Hung-Yi’s Journal

Front-end Developer, Emacs Adventurer, Home Cook

13 Oct 2020

Use Emacs-Tree-Sitter for Highlighting in Doom Emacs

Tree-sitter is a general programming language parser that efficiently builds and updates Abstract Syntax Trees (AST) for your code. Basically, it can read programming languages and understand the structure and meaning of code without having to execute it. Among many amazing things, one of its best and simplest features to take advantage of is richer syntax highlighting, which is what I use it for in Emacs. Today I'll show you how to set up emacs-tree-sitter in Doom Emacs1 so you can quickly get prettier code with next to no effort.

First, add these lines to packages.el:

(package! tree-sitter)
(package! tree-sitter-langs)

Update [2020-10-26 Mon]: It seems emacs-tree-sitter is now on MELPA, so the packages.el config above has been simplified accordingly. There's no longer any need to specify a tsc package2 or write a manual straight.el recipe to fetch it from GitHub.

Then in config.el, you'll need:

(use-package! tree-sitter
  :config
  (require 'tree-sitter-langs)
  (global-tree-sitter-mode)
  (add-hook 'tree-sitter-after-on-hook #'tree-sitter-hl-mode))

Now run doom sync in a terminal, restart Doom Emacs with SPC q R and explore some code to see the new highlighting. You'll notice some of these changes:

  • Things that are harder to detect with regex are now highlighted and differentiated (e.g. function names, properties on objects, template strings)

  • More use of italics and bold font weights to help with the above

  • Potential speed and stability improvements, since AST parsing should be faster and more robust than regex parsing.

Caveats

Web-Mode

Emacs-tree-sitter highlighting works by mapping each major mode in Emacs to a language-specific parser. This falls apart when a major mode happens to support multiple or mixed languages in the one file, for example web-mode which handles HTML, JavaScript and CSS.

Personally, I tried mapping web-mode to html in tree-sitter-major-mode-language-alist, but it complained and didn't work when I tried to turn on highlighting. This seems to be a dead end for now.

SCSS-Mode

One other thing I found missing from the standard setup was SCSS support, which I've added by putting the following in my :config section of use-package! tree-sitter:

(pushnew! tree-sitter-major-mode-language-alist
          '(scss-mode . css))

This seems to work OK for now, however it's not officially supported and may be unstable.


1

If you're using vanilla Emacs instead of Doom, you can follow the official emacs-tree-sitter installation instructions and the corresponding syntax highlighting setup.

2

tsc has nothing to do with the TypeScript Compiler of the same name. That confused me for a while this morning when Doom was complaining about non-existent packages in recipes.