Tree-sitter in Guix
I’m impartial to syntax highlighting in code since it can be a source
of distraction more often than not, however, I tend to use the favored
major mode for the language I’m writing in Emacs paired with
eglot. Lately though, this has become a pain point when working with
all-things JavaScript on large files. My quick solution was to forego
eglot
and web-mode, which improved the editing speed tremendously.
It looks like the latter is a common reason for the slowdown when
working with TSX
files. I figured this is a good reason to finally get
tree-sitter in my Emacs setup working as I’ve failed previously.
Tree-sitter is a parser generator tool that can build a concrete syntax tree for a source file and efficiently update the tree during edits. Syntax highlighting is one of those features that can leverage this tool. Code navigation is another, though we’ll only talk about syntax highlighting.
Syntax highlighting tools usually rely on custom regular expressions, so using Tree-sitter is faster and has better highlighting since it’s more context-aware.
Installation
I’ve had trouble installing the language grammars manually before on my Guix system, so I figured it’s better to install the packages from Guix.
I use Guix Profiles to group package installations together e.g., a default profile, an Emacs profile, a Common Lisp profile etc. and make them available on login.
In this case I’m adding the relevant packages to my default profile:
;; guix-default-manifest.scm
;; default packages but example only includes Tree-sitter ones
(specifications->manifest
'("tree-sitter"
"tree-sitter-bash"
"tree-sitter-css"
"tree-sitter-dockerfile"
"tree-sitter-go"
"tree-sitter-html"
"tree-sitter-javascript"
"tree-sitter-json"
"tree-sitter-python"
"tree-sitter-typescript"))
Then I run:
guix package --manifest=/home/boogs/.package-lists/guix-default-manifest.scm --profile=/home/boogs/.guix-extra-profiles/default/default
to update my default profile to include these packages.
Emacs configuration
Now we’ve installed the tool and the language grammars. Next, we need to tweak our Emacs configuration slightly to know where to find the language grammars.
(setq treesit-extra-load-path '("~/.guix-extra-profiles/default/default/lib/tree-sitter"))
(add-to-list 'auto-mode-alist '("\\.js\\'" . js-ts-mode))
(add-to-list 'auto-mode-alist '("\\.json\\'" . json-ts-mode))
(add-to-list 'auto-mode-alist '("\\.ts\\'" . typescript-ts-mode))
(add-to-list 'auto-mode-alist '("\\.tsx\\'" . tsx-ts-mode))
(add-to-list 'auto-mode-alist '("\\.html\\'" . html-ts-mode))
(add-to-list 'auto-mode-alist '("\\.css\\'" . css-ts-mode))
(add-to-list 'auto-mode-alist '("\\.go\\'" . go-ts-mode))
The load path may vary depending on how you install the packages. If
you install them to the current profile, then the path starts with
"~/.guix-profile/lib/tree-sitter"
.
Conclusion
With Tree-sitter set up via Guix, editing large JavaScript,
TypeScript
, or TSX
files in Emacs should feel snappier, thanks to
efficient parsing and context-aware highlighting. This setup not only
resolves slowdowns from modes like web-mode
but also opens the door to
advanced features like structural editing.
If you encounter issues (e.g., missing grammars or incompatible Emacs versions), check the Tree-sitter GitHub repository or the Guix Codeberg repository. Happy hacking!