Moving to Emacs Tree Sitter Modes
Tags: emacs, treesitter
Published: 2024-06-06 15:20:56

---
title: Moving to Emacs Tree Sitter Modes
published: true
date: 2024-05-22 04:30:15 UTC
tags: emacs,treesitter
canonical_url: https://erick.navarro.io/blog/moving-to-emacs-tree-sitter-modes/
---

I'm currently using emacs 30 and this version has support for more languages using the new `ts-modes`, I've been using [emacs-tree-sitter](https://github.com/emacs-tree-sitter/elisp-tree-sitter/) package since Emacs added dynamic modules feature.

Now using `emacs 30` I give a try to use only `ts-modes` and maybe delete some external packages I was using.

# How to install grammars

Emacs doesn't have a built-in way to install automatically most common grammar so we're going to use a package that can handle that, we use [tree-sitter-langs](https://github.com/emacs-tree-sitter/tree-sitter-langs/) package, which is a repository for grammars.

When we install it it download and install all the available grammars in its own directory but to be used by emacs `ts-modes` we need to put them inside `/.emacs.d/tree-sitter` directory. I write a helper function to accomplish this:

```emacs-lisp
(defun my/copy-grammars-to-emacs-tree-sitter-dir ()
  "Copy tree-sitter grammar files to native Emacs dir."
  (interactive)
  (let* ((files (directory-files (tree-sitter-langs--bin-dir) nil "\\.dylib$")))
    (dolist (grammar-file files)
      (copy-file (concat (tree-sitter-langs--bin-dir) grammar-file) (concat (expand-file-name user-emacs-directory) "tree-sitter/" "libtree-sitter-" grammar-file) t)
      (message "%s grammar files copied" (length files)))))
```

# The migration

I use `straight.el` to manage my packages so I'm going to use it to configure built-in `ts-modes`, by now I only migrated a few modes.

For `elixir`:

```emacs-lisp
(use-package elixir-ts-mode
  :straight (:type built-in)
  :mode (("\\.ex\\'" . elixir-ts-mode)
         ("\\.exs\\'" . elixir-ts-mode)
         ("\\mix.lock\\'" . elixir-ts-mode)))
```

For `docker`:

```emacs-lisp
(use-package dockerfile-ts-mode
  :straight (:type built-in)
  :defer t
  :mode (("\\Dockerfile\\'" . dockerfile-ts-mode)
         ("\\.dockerignore\\'" . dockerfile-ts-mode)))
```

For `typescript`

```emacs-lisp
(use-package typescript-ts-mode
  :straight (:type built-in)
  :defer t
  :mode "\\.tsx?\\'")
```

For `toml`

```emacs-lisp
(use-package toml-ts-mode
  :straight (:type built-in)
  :mode "\\.toml\\'"
  :defer t)
```

For `yaml`

```emacs-lisp
(use-package yaml-ts-mode
  :straight (:type built-in)
  :mode "\\.ya?ml\\'")
```

With this now I have 5 dependencies less in my configuration :).


# Conclusion

I'm in the process to migrate others modes like `python-mode`, `go-mode` and so on but in some cases syntax highlighting is not the best. For example `shell-script-mode` has better highlight than `bash-ts-mode`. I'm been using these "new" `ts-modes` for a few weeks and everything is working well.


<a id="org624b87d"></a>

# Bonus

I also updated a [package](https://github.com/erickgnavar/tree-sitter-ispell.el/) I use to run `ispell` on text nodes to support built-in tree-sitter support. Now it supports `tree-sitter.el` and `treesit` packages.