目的
vterm内でgitコマンドを操作していると、git commitのたびにターミナル上でNeovimやnanoが起動していた。
これをmagitと同様に、Emacs自身のバッファでコミットメッセージを編集できるようにしたい。
with-editorはこの用途のために作られたパッケージであり、shell-modeやeshell-modeだけでなくvterm-modeにも公式に対応している1。
設定自体は数行で済むはずだったが、実際には二つのつまずきがあった。
use-packageの:customに紛れ込んだフック登録
最初の設定では、次のようにフックの登録を:customブロックの中に書いていた。
:custom
...
(add-hook 'vterm-mode-hook 'with-editor-export-editor)
:customは(変数名 値 [コメント])という3つ組を受け取り、内部でcustomize-set-variableを呼ぶための場所であり、任意のLispコードを実行する場所ではない。
この行はadd-hookという名前の変数に'vterm-mode-hookという値を設定しようとする形に解釈されてしまい、フックの登録としては機能していなかった。
修正は単純で、この行を:hookブロックへ移すだけでよい。
:hook
(vterm-mode . (lambda ()
(with-editor-export-editor)))
core.editorがEDITORより優先されていた
しかし、フックの登録を直しても、vterm内でgit commitを打つと相変わらずNeovimが開いた。
そこでvterm内で次の2つを確認したところ、core.editorにnvimが設定されていることがわかった。
git config --get core.editor
echo $GIT_EDITOR
Gitがエディタを選ぶ優先順位は次の通りであり、GIT_EDITOR環境変数が最優先、次にcore.editor、その次にVISUAL、最後にEDITORという順になる。
GIT_EDITOR > core.editor > VISUAL > EDITOR
with-editor-export-editorはEDITORしか書き換えないため、core.editorの設定がある限り無視され続ける。
原因は当初疑っていたzshのログインシェル起動時のタイミング競合ではなく、この優先順位の問題だった。
with-editorにはGIT_EDITORを直接書き換えるwith-editor-export-git-editorという関数が用意されており、これに切り替えることでcore.editorより優先させられる。
:hook
(vterm-mode . (lambda ()
(with-editor-export-git-editor)))
現在の設定
最終的に、vtermパッケージの設定は次のようになった。
(use-package vterm
:custom
(vterm-max-scrollback 100000)
(vterm-kill-buffer-on-exit t)
(vterm-copy-exclude-prompt t)
(vterm-disable-bold-font nil)
(vterm-shell (concat shell-file-name " -l"))
:hook
(vterm-mode . (lambda ()
(with-editor-export-git-editor)))
:bind
("C-c v t" . vterm))
動作確認の方法
新しくC-c v tでvtermバッファを開き、echo $GIT_EDITORを実行する。
nvimではなく、with-editorが用意する仲介スクリプトへのパスが表示されていれば、環境変数の書き換えは成功している。
-
対応するバッファの種類ごとに、
export EDITOR=...という文字列をキー入力として直接送り込む実装になっている。 ↩