Use existing *-ts-mode
package
First, install packages in package.el
.
(package! tree-sitter-langs
:pin "3a3ad0527d5f8c7768678878eb5cfe399bedf703")
(package! typst-ts-mode
:recipe (:host sourcehut :repo "l2dy/typst-ts-mode")
:pin "39a9e63c019bd5498c8f0e5a7ee8cb9d6bb53fd0")
If package depends on treesit
instead of tree-sitter
, it’s required to copy and rename parser library files.
;; config.el
(defun treesit-copy-langs-lib-if-newer (lang)
"Copy treesit libraries from tree-sitter-langs"
(require 'tree-sitter-langs)
(let* ((ts-lib-path (car (file-expand-wildcards (concat (tree-sitter-langs--bin-dir) lang ".*"))))
(ts-lib-name (file-name-nondirectory ts-lib-path))
(ts-lib-user-dir (concat user-emacs-directory (file-name-as-directory "tree-sitter")))
(ts-lib-user-path (concat ts-lib-user-dir "libtree-sitter-" ts-lib-name)))
(when (or (not (file-exists-p ts-lib-user-path))
(time-less-p (file-attribute-modification-time (file-attributes ts-lib-user-path))
(file-attribute-modification-time (file-attributes ts-lib-path))))
(make-directory ts-lib-user-dir t)
(delete-file ts-lib-user-path)
(copy-file ts-lib-path ts-lib-user-path nil t))))
(use-package! typst-ts-mode
:mode "\\.typ\\'"
:config
(treesit-copy-langs-lib-if-newer "typst"))
Using pre-compiled language grammars
You can find them on his Github releases page. You can also download the
tree-sitter-langs
package from MELPA, but I recommend you just download the shared libs directly instead, as you’ll in any event have to rename them and place the grammar libraries somewhere else.The names of the files are
<LANGUAGE>.so
(or with your platform’s equivalent extension) which is not in keeping with the expected naming style in Emacs. You must first rename them so they’re namedlibtree-sitter-<LANGUAGE>.so
. This is as good a time as any to learn how to bulk rename them with Emacs’sM-x dired
and the editable dired buffers feature.
Define your own new major mode for highlighting
Supported languages: https://github.com/emacs-tree-sitter/tree-sitter-langs/tree/master/queries
- Ensure
(package! tree-sitter-langs ...)
pins to the right commit (or a later commit) inpackages.el
and tree-sitter module is enabled ininit.el
. - Run
doom sync
if pin is updated, and verify that updates are applied to local Straight directories. - Define the major mode in
config.el
, or a custom Doom module withdefine-derived-mode
split intoautoload.el
.
;;;###autoload
(define-derived-mode typst-mode text-mode "Typst"
"Major mode for editing Typst documents."
(set-tree-sitter-lang! 'typst-mode 'typst) ;; only required if not in tree-sitter-langs--init-major-mode-alist
(add-hook 'typst-mode-local-vars-hook #'tree-sitter! 'append))
(add-to-list 'auto-mode-alist '("\\.typ\\'" . typst-mode))
To enable LSP instead, replace #'tree-sitter!
with #'lsp!
.
For Elisp gurus: Doom provides MAJOR-MODE-local-vars-hook, and we use it instead of MAJOR-MODE-hook because it runs later in the mode’s startup process (giving other functionality or packages — like
direnv
— time to configure the LSP client).
Lazy loading
Check if tsc-dyn-get-ensure
is defined on start to verify lazy loading.
Linux AArch64 support
See also https://github.com/emacs-tree-sitter/elisp-tree-sitter/issues/166#issuecomment-1522766887.
Add the following to config.el
, which is equivalent to use-package
’s :init
.
;; No binaries are provided for tree-sitter on AArch64 Linux
(setq tsc-dyn-get-from '(:compilation))
This does not fix missing binaries of tree-sitter-langs, so you need to build them yourself.