emacs29でビルドインされたtree-sitterとtsx-ts-modeでtypescriptの開発環境を構築する

2024年5月16日
thumbnail
emacs29からビルドインでtree-sitterとtypescript-ts-modeが入ったことで、飛躍的にtypescript環境の構築が楽らになりました。
これまでEmacsでtypescriptの開発環境を整えるには苦労と工夫が必要でした。
1番の問題は、TSXがうまく機能しない点です。3rd partyのtypescript-modeは標準でTSXをサポートしておらず、TSXのDOM部分のシンタックスがうまくいかなかったり、インデントがずれたりしました。
TSXの解決策としてweb-modeを併用して使うのが一般的でした。ただ、web-modeを使ったとしても、typescript-modeとtideで使える機能を無理やりweb-modeで使おうとすると、設定が複雑になり意図しない挙動が現れたりしました。
mmm-modeを組み合わせてTSX部分だけをweb-modeにして、それ以外をtypescript-modeで動かす方法が考えられました。一見良さそうな挙動をするのですが、DOMの中の型推論がうまくいかなかったり、mmm-modeの正規表現でweb-modeとtypescript-modeの切り分けるがうまくいかず、意図しないところでメジャーモードが切り替わってしまう問題がありました。
多くの問題点もemacsにtrees-sitterとtypescript-ts-modeが入ったことで、環境構築が楽になりました。
この記事ではサードバーティのtypescript-modeを使うのではなく、emacsにビルドインされているtypescript-ts-modeを使います。
emacsは29より上のバージョンを利用してください。
こちらが全ての設定になります。
(use-package typescript-ts-mode
  :mode (("\\\\.tsx\\\\'" . tsx-ts-mode)
         ("\\\\.ts\\\\'" . tsx-ts-mode))
  :config
  (setq typescript-ts-mode-indent-offset 2))

(use-package treesit
  :config
  (setq treesit-font-lock-level 4))

(use-package treesit-auto
  :ensure t
  :init
  (require 'treesit-auto)
  (global-treesit-auto-mode)
  :config
  (setq treesit-auto-install t))

(use-package tree-sitter
  :ensure t
  :hook ((typescript-ts-mode . tree-sitter-hl-mode)
         (tsx-ts-mode . tree-sitter-hl-mode))
  :config
  (global-tree-sitter-mode))

(use-package tree-sitter-langs
  :ensure t
  :after tree-sitter
  :config
  (tree-sitter-require 'tsx)
  (add-to-list 'tree-sitter-major-mode-language-alist '(tsx-ts-mode . tsx)))

(use-package tide
  :ensure t
  :hook (tsx-ts-mode . setup-tide-mode)
  :config
  (defun setup-tide-mode ()
    (interactive)
    (tide-setup)
    (flycheck-mode +1)
    (setq flycheck-check-syntax-automatically '(save mode-enabled))
    (eldoc-mode +1)
    (tide-hl-identifier-mode +1)
    (company-mode +1))
  (setq company-tooltip-align-annotations t))

typescript-ts-mode

ビルドインされたパッケージの設定から見ていきましょう。
(use-package typescript-ts-mode
  :mode (("\\\\.tsx\\\\'" . tsx-ts-mode)
         ("\\\\.ts\\\\'" . tsx-ts-mode))
  :config
  (setq typescript-ts-mode-indent-offset 2))
tsx-ts-modetypescript-ts-modeを継承したTSX対応のメジャーモードです。拡張子が.tsx.tsでtsx-ts-modeを開くようにしています。理由は分けると設定をそれぞれ記述することになり、面倒だからです。

treesit

(use-package treesit
  :config
  (setq treesit-font-lock-level 4))
内蔵されたtree-sitter(treesit)では、構文解析のハイライトするレベルを設定できます。数字を大きくするとカラーリングが深くなります。小さくするとカラーリングが浅くなり、色合いがシンプルになります。1〜4の数字が設定できます。

treesit-auto

(use-package treesit-auto
  :ensure t
  :init
  (require 'treesit-auto)
  (global-treesit-auto-mode)
  :config
  (setq treesit-auto-install t))
tree-sitterは各プログラム言語毎にパーサーがあり、自分で用意します。 それだと面倒なので、treesit-autoを使って自動的にパーサーをダウンロードし、各言語ごとに読み込みを行います。

tree-sitter

(use-package tree-sitter
  :ensure t
  :hook ((typescript-ts-mode . tree-sitter-hl-mode)
         (tsx-ts-mode . tree-sitter-hl-mode))
  :config
  (global-tree-sitter-mode))
typescript-ts-modetsx-ts-modeのメジャーモードでtree-sitterのハイライトモードを有効にします。さらに、サポートされているすべてのバッファでtree-sitterのグローバルモードを有効にしておきます。

tree-sitter-langs

(use-package tree-sitter-langs
  :ensure t
  :after tree-sitter
  :config
  (tree-sitter-require 'tsx)
  (add-to-list 'tree-sitter-major-mode-language-alist '(tsx-ts-mode . tsx)))
tsx-ts-modeとtree-sitterの構文ルールを結合させます。tree-sitter-requireで下記のURL先にあるtsxのルールを読み込みます。その後tsx-ts-modetsxの構文ルールを明示的に紐付けます。

tide

(use-package tide
  :ensure t
  :hook (tsx-ts-mode . setup-tide-mode)
  :config
  (defun setup-tide-mode ()
    (interactive)
    (tide-setup)
    (flycheck-mode +1)
    (setq flycheck-check-syntax-automatically '(save mode-enabled))
    (eldoc-mode +1)
    (tide-hl-identifier-mode +1)
    (company-mode +1))
  (setq company-tooltip-align-annotations t))
tideはtypescriptの開発をサポートしてくれるパッケージです。一通りのtypescript開発で必要な型推論(eldoc)、入力補完(company)、型のエラー(flycheck)を提供してくれます。

使い方

設定を記述したら、emacsを再起動してください。必要なパッケージがインストールされます。
なんでも良いので.tsxファイルを開いてください。typescriptに必要なtree-sitterのパーサーがダウンロードされます。正常にtree-sitterやtide flycheckが動いているとこのような画面が表示されます。
article image

まとめ

いかがだったでしょうか? ぜひEmacsで本格的なtypescript開発に取り組んでみてください。
profile image
Ted
大学でコンセンサスアルゴリズムを研究。卒業後ベンチャー企業に入社してフルスタックでWebサービスを開発。現在は大手IT企業に転職し、プログラミングを行っている。AIにプログラマーの仕事を奪って欲しいと願っている。