Introduce Tree Sitter to Emacs
近年、テキストエディタ/IDEの機能はますます複雑となり、プログラミング言語の数は増え、その組み合わせは膨大なものとなっています。元来テキストエディタはそれぞれがそれぞれの実装でそれらの組み合わせを実現してきましたが、自動補完、定義ジャンプ、ドキュメントの表示など、概ねその基本的な機能は同じであるにもかかわらず、すべてのエディタ開発者はそれぞれが車輪の再発明を行う必要があったのです。その問題を解決するために設計開発されたのがLanguage Server Protocol(LSP)であり、ここ数年で多くのテキストエディタが採用したことにより名前くらいは知っているという人も多いのではないでしょうか。 Tree-sitter はある意味でLSPあるいはLanguage Serverと呼ばれるものに似ています。Tree-sitterは、プログラミング言語の文法から構文解析器を自動生成するパーサージェネレーターツールであり、またそれを使用した構文解析ライブラリです。 Tree-sitterは任意の言語を解析できる汎用的なツールで、動作が速く、依存が少ないツールです。2018年にGitHubからリリースされ、emacs 29.1ではbuilt-inの機能として使えるようになりました。 Emacs x Tree-sitterの仕組みと導入 emacsでTree-sitterを使うには、2つの条件があります: 使用したい言語のパーサーが実装されている Tree-sitterに対応したmajor modeが実装されている 使用したい言語のパーサーが実装されている 当然のことながら、Tree-sitter用に文法が定義されている必要があります。使用したい言語のパーサーが既に誰かによって実装されているかは、available-parsers のリストを参照すると良いでしょう。概ね、メジャーどころの言語は実装されておりほとんどの場合困ることはないと思います。各言語の文法定義(grammar)はJavaScriptで定義し、tree-sitter CLIを使用してC言語のソースコードに変換し、最終的にはそれをコンパイルして使用します。 emacsの場合、~/.emacs.d/tree-sitter/ディレクトリにコンパイルされたダイナミックリンクライブラリを置くことで読み込むことができます。予めコンパイルされたものを置く、でも良いのですが、treesit-install-language-grammarを使用すると文法をダウンロードしてきて配置してくれるため簡単です。treesit-install-language-grammarを使用するには、まずtreesit-language-source-alistに言語とgitリポジトリのペアを定義します。その後treesit-install-language-grammarに言語を渡すことでgit cloneからコンパイル、配置まで行ってくれます。 例えば、YAML用の文法を導入するには次の様に定義します: 1 2 (setq treesit-language-source-alist '((yaml "https://github.com/ikatyang/tree-sitter-yaml"))) そして、(treesit-install-language-grammar yaml)(もちろんM-xでやっても良いと思います)とするとYAML用の文法がインストールされます。私はこの手のものはemacsの起動時に自動で導入されてほしいので、次の様にしました: 1 2 3 4 5 6 7 8 9 (setq treesit-language-source-alist '((yaml "https://github.com/ikatyang/tree-sitter-yaml"))) (dolist (element treesit-language-source-alist) (let* ((lang (car element))) (if (treesit-language-available-p lang) (message "tree-sistter: %s is already installed" lang) (message "tree-sitter: %s is not installed" lang) (treesit-install-language-grammar lang)))) Tree-sitterに対応したmajor modeが実装されている emacsでTree-sitterを使用したい場合、残念ながら、LSPを使用するときのように、単純にパッケージを追加すればすべての言語でよしなに動く・・・という風にはなりません。emacsでは今までのところ、major modeがシンタックスハイライトを提供するためには主に正規表現などが使用されてきました。正規表現を利用したシンタックスハイライトと、Tree-sitterを使用したシンタックスハイライトは大きく違うため、ほとんどのmajor modeではそのままTree-sitterを採用する形にはならず、Tree-sitter専用のmajor modeが提供される形になっています。emacs29ではメジャーどころの言語に対するTree-sitter対応モードが提供されています 。 手動でこれらのモードを拡張子ごとに設定しても良いのですが、major-mode-remap-alistを設定することで、従来のmajor modeをそのままTree-sitter対応のモードに切り替えることができます。 例えば、yaml-modeの代わりにyaml-ts-modeを使用する場合次の様に設定します: 1 2 3 4 5 6 (add-to-list 'major-mode-remap-alist '(yaml-mode . yaml-ts-mode)) ;; or (setq major-mode-remap-alist '((yaml-mode . yaml-ts-mode))) この設定によって、yaml-modeでバッファが開かれる場面ではすべてyaml-ts-modeが使用されるようになります。今のところ、hookなどの設定は移行されないため、これらは個別に設定を移行する必要があります。 ...