>

A quick setup guide for .heex files on Emacs. At the time of writing, Doom Emacs only supports up to 28, and 29+ are not supported yet. This guide could become irrelevent once Emacs 29 becomes stable.

Since I'm using Doom Emacs, this will provide steps to get .heex working on it as well.

We'll need to install the tree-sitter-cli before proceeding.

Rust version

git clone https://github.com/tree-sitter/tree-sitter
cd tree-sitter/cli

cargo build --release           # Build tree-sitter in release mode

cd ../
cp ./target/release/tree-sitter /path/for/bin
NOTE: You'll need the v0.19.5 since v0.20 has some breaking changes

There's a NPM package as well so this can be used if Rust is not installed in your system.

NPM version

npm i -g tree-sitter-cli@19
NOTE: I did not try this but it should work

Verify with the following command.

> ~/bin/tree-sitter
tree-sitter 0.19.5 (8d8690538ef0029885c7ef1f163b0e32f256a5aa)
Max Brunsfeld <[email protected]>
Generates and tests parsers

USAGE:
    tree-sitter <SUBCOMMAND>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

SUBCOMMANDS:
    build-wasm        Compile a parser to WASM
    dump-languages    Print info about all known language parsers
    generate          Generate a parser
    help              Prints this message or the help of the given subcommand(s)
    highlight         Highlight a file
    init-config       Generate a default config file
    parse             Parse files
    query             Search files using a syntax tree query
    tags
    test              Run a parser's tests
    web-ui            Test a parser interactively in the browser
Check if tree-sitter-cli is installed properly

Build

Let's start with retrieving the tree-sitter code for heex.

The repo for tree-sitter-heex is provided by the Phoenix team and is available at phoenixframework/tree-sitter-heex.

git clone https://github.com/phoenixframework/tree-sitter-heex.git
Clone repository to local workstation

At the time of writting, tree-sitter-heex comes with src/parser.c, but since it was generated with v0.20 of the CLI, we'll need to use the v0.19 version to regenerate it.

tree-sitter generate
Generate parser.c with tree-sitter-cli

You should see some diffs after the command which you can ignore.

> git status
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   src/parser.c
        modified:   src/tree_sitter/parser.h

no changes added to commit (use "git add" and/or "git commit -a")
cc -shared -fPIC -fno-exceptions -g -I src src/parser.c -o ./heex.so -O2

You should see a heex.so file now.

Emacs

Now that heex.so is available, it's time to get it loaded into Emacs.

Tree-sitter Emacs looks for custom built libraries in tree-sitter-load-path, which is a list of strings. You can run Alt x => describe-variable in Emacs to check for the current values. In my case, $HOME/.tree-sitter-/bin was already included in the variable so I'll be placing the built heex.so there.

mkdir -p ~/.tree-sitter/bin
mv ./heex.so ~/.tree-sitter/bin/

Next step will be to instruct Emacs to load heex.so when it opened a file with .heex extension.

Add the following to ~/.doom.d/config.el

;; Elixir
;; Add heex-mode for modifying .heex files
(define-derived-mode heex-mode web-mode "HEEx" "Major mode for editing HEEx files")
(add-to-list 'auto-mode-alist '("\\.heex?\\'" . heex-mode))
(add-to-list 'tree-sitter-major-mode-language-alist '(heex-mode . heex))

(add-hook 'heex-mode-hook #'tree-sitter-hl-mode)
(add-hook 'heex-mode-hook
          (lambda()
            ;; Ask tree-sitter to load 'heex.so'
            (tree-sitter-load 'heex)
            ;; Auto format .heex files on save, requires liveview 0.18+
            (add-hook 'before-save-hook 'elixir-format nil t)))
Add a new heex mode and load it with .heex files

Restart/reload Emacs and this should now show up.

heex.png
HEEx mode activated for .heex files

Notes

Syntax highlighting itself is not really working for me at the moment, so will probably update this post after I figure that out. Might have to deal with web-mode directly.