reformatter.elを使って色々な言語のフォーマッターを一元管理する
はじめに
プログラムを書いてセーブ時にフォーマットを実行する。当たり前にやってることと思いますが複数のプログラミング言語を使う環境で言語ごとにフォーマッターを設定していくのは大変です。そこで最近 Emacs の reformatter.el というパッケージを使って複数のフォーマッターを一元管理する方法を見つけたので紹介します。
emacs-reformatter
今回利用するパッケージはこちらです。
reformatterという名前ですがパスの通ったCLIコマンドであればフォーマッターに限らずなんでも使えそうです。use-packageを使った設定方法
普段、私はGoとTypeScriptとPythonを使っています。以下のコード例は3つの言語(Go/TS/Python)のフォーマッターを設定する例です。
(use-package reformatter
:ensure t
:config
(reformatter-define go-format
:program "goimports")
(reformatter-define web-format
:program "prettier"
:args `("--write" "--stdin-filepath" ,buffer-file-name))
(reformatter-define python-format
:program "ruff"
:args `("format" "--stdin-filename" ,buffer-file-name))
:hook
(go-ts-mode . go-format-on-save-mode)
(tsx-ts-mode . web-format-on-save-mode)
(json-ts-mode . web-format-on-save-mode)
(python-ts-mode . python-format-on-save-mode))
各種プログラミング言語のフォーマッターはお手持ちの環境で先にインストールしてパスが通るようにしておいてください。コード例では、それぞれGoはgoimport、TypeScript(jsonとtsx含む)はprettier、Pythonはruffを使ってセーブ時にフォーマットをかけています。
elispの説明
:config
の reformatter-define で言語ごとに利用するフォーマッターのCLIコマンドを指定と(:program
)、実行に必要なコマンドライン引数の設定をしています(:args
)。reformatter-define の設定を追加することで *-on-save-mode というマイナーモードが自動生成されます(*にはreformatter-defineで定義したフォーマッターの名前が入ります)。あとはhook:
を使って各種言語のモードと reformatter-define で生成したマイナーモードを関連づけてやればOKです。
biomeを使う場合
TypeScript のフォーマッターに prettier じゃなくて biome を使いたいという場合は reformatter-define 部分を以下に変更してください。
(reformatter-define web-format
:program "biome"
:args `("format" "--stdin-file-path" ,(buffer-file-name)))
[補足]プログラミング言語ごとのモードの設定
reformatter の hooks に各種言語のモードを関連づけましたが、こちらは最近流行りの Tree-Sitter 対応のモードを利用しています。設定方法はこちらを参照してください。
Tree-Sitter を使わない場合は:hook
の部分を以下のように変更してください。
:hook
(go-mode . go-format-on-save-mode)
(tsx-mode . web-format-on-save-mode)
(json-mode . web-format-on-save-mode)
(python-mode . python-format-on-save-mode)
今回紹介したコードのリポジトリはこちら
Discussion