emacs-tree-sitter を導入してみる

前置き

久々に lsp-mode のドキュメントを眺めていたら、 see-also の節に emacs-tree-sitter なるパッケージが追加されていることに気がついた。このパッケージを導入することで、バッファ中のソースコードに対してより意味論的なハイライトを行うことが出来るらしい。バックエンドに Tree-sitter という Rust 実装のインクリメンタルな構文解析ツールが使用されており、このツールによる構文解析の結果にアクセスするための API も提供されている。

このあたりは全然詳しくないのだが、 Tree-sitter はいわゆる抽象構文木(Abstract Syntax tree)を生成するのではなく、構想構文木(Concrete Syntax Tree)と呼ばれる粒度のより小さい構文木を生成するらしい。

インストール

さて、早速インストールしてみる。インストール手順は emacs-tree-sitter のドキュメントの Installation に記載されている。私は leaf.el を使っているため、 init.el に以下のような記述を追加した。

(leaf emacs-tree-sitter
  :url "https://github.com/ubolonton/emacs-tree-sitter"
  :init
  (straight-register-package
   '(tsc :host github :repo "ubolonton/emacs-tree-sitter" :files
         ("core/*.el")))
  (straight-use-package
   '(tree-sitter :host github :repo "ubolonton/emacs-tree-sitter" :files
                 ("lisp/*.el")))
  (straight-use-package
   '(tree-sitter-langs :host github :repo "ubolonton/emacs-tree-sitter" :files
                       ("langs/*.el" "langs/queries")))
  :require tree-sitter-langs
  :config
  (global-tree-sitter-mode)
  (add-hook 'tree-sitter-after-on-hook #'tree-sitter-hl-mode))

全バッファで tree-sitter-mode を起動するようにして、これの起動後に tree-sitter-hl-mode が起動するように hook している。この tree-sitter-hl-mode がハイライトを行う minor mode である。

leaf.el で straight.el を使う際のお作法がよく分かっていない (:straight キーワードが用意されているようだが…) ので、 leaf-convert の力を借りて適当に変換した。ここで straight.el がないよ〜と言われる場合は、

(leaf straight
  :defvar bootstrap-version
  :config
  (let ((bootstrap-file (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
        (bootstrap-version 5))
    (unless (file-exists-p bootstrap-file)
      (with-current-buffer (url-retrieve-synchronously "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el" 'silent 'inhibit-cookies)
        (goto-char (point-max))
        (eval-print-last-sexp)))
    (load bootstrap-file nil 'nomessage)))

を追記して straight.el をインストールしておく。このインストール方法は STRAIGHT.EL で ORG MODE をインストールする を参考にしているが、もう少しスマートなやり方があるかもしれない。

動作

転がっていた競プロのソースコード(C++)で動作の様子を確認した(競プロは久しくやってないが、他にちょうど良いソースコードがなかったので…)。

tree-sitter-hl-mode 適用前
tree-sitter-hl-mode 適用後

マクロや関数の呼び出しが太文字になったり、クラスのメンバが斜体になったりしている。また、オペレータに色が付くようになった。他に大きな違いとして、型の色が auto 以外の予約語とその他で変わるようになった。

しばらく眺めて気がついたのだが、どうやら color-identifiers-mode.el (変数名ごとに色を割り当てるパッケージ)と中途半端に両立してしまっているらしい。変数に対して代入を行っている箇所の色が tree-sitter-hl-mode によって上書きされてしまっている。それ以外、すなわち参照を行っている箇所は color-identifiers-mode.el によって引き続きハイライトされている。ただ、これに関しては、 lsp-mode のハイライト機能symbol-overlay.el (カーソルが変数の上になくてもハイライトし続けるパッケージ。とても便利。)で代用出来るのでそこまで不自由ではないと思う(color-identifiers-mode.el を無効にした方がいいかもしれない)。また、ハイライトのカスタマイズが可能となっているので、何かしら回避する手段がありそうにも思える。

おわりに

Tree-sitter 自体が軽いこともあって快適に使えそう。emacs-tree-sitter の API を使うことでハイライト以外にも色々出来る気がする。

参考

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です