• 作成:

EmacsのMagitでコミットメッセージを書く時にGitHub Copilotがある程度効くようにしました

GitHub Copilotが無償配布されるようになりました

弊社pluszeroでは生産性向上のために、希望者にはGitHub Copilotを無料で配布するようになりました。

自分は拡張版のGitHub Copilot Xが、 Visual Studio CodeVisual Studio以外の、具体的にはNeovim向けにも提供されるまで様子見して、提供されたら一ヶ月の試用期間で使ってみて継続して契約するか決めようかと様子見していました。

そんなことを考えていた理由は、私はEmacsを使っていて、ここから離されると生産性が落ちることが目に見えていたためです。

GitHub CopilotはEmacsには公式には対応していないのですが、 zerolfx/copilot.el: An unofficial Copilot plugin for Emacs.で非公式サポートされています。

これの実装方法はNeovim向けのクライアントに依存しています。 GitHub Copilotは嘆かわしいことにクライアントすらプロプライエタリです。 GitHubに投稿されたコードを利用しているのですから、クライアントぐらいフリーソフトウェアにするのが望ましいと思うのですが。せめてドキュメント化されたAPIを提供してほしい。

ともかくそういう事情があるのでNeovim向けにはどうもlsp(少なくともNode.jsとJSON RPCしている)で接続しているようで、 Emacsの非公式クライアントはNeovimのクライアントをコピーしてくる形で実装されています。

なのでEmacs向けにCopilot Xを実装するにはNeovim向けのクライアントがCopilot Xを待つ必要があったわけです。

一回しか無料の試用期間は使えないのでCopilot Xが実装できそうな雰囲気が出たら使ってみて、コントリビュートも考えていました。一ヶ月1500円ぐらいはそこそこ高いですからねえ。

しかし会社が無料で配布してくれるならXじゃない範囲でも使います。補完はGPT-3の性能的にあんまり期待してなかったのですがそれなりに便利です。どちらかと言うとリファクタリングやドキュメントコメント生成に期待してたのでCopilot Xを待っていましたが、補完だけでも使う価値がかなりありますね。

Gitのコミットメッセージでも補完を効かせたい

copilot.elのドキュメント的にはprog-mode-hookcopilot-modeを追加するのが推奨で、それで概ね動きます。

ただもちろんそれだとプログラミング言語のモードでしか動きません。

Gitのコミットメッセージこそdiffをソースにかなり自動化できそうですね。

EmacsにはMagitというEmacs以外を入れても最強に近いGitクライアントが存在するので、私はこれを使っています。

なのでgit-commit-setup-hookcopilot-modeを追加してやれば当然EmacsのGitのコミットメッセージ編集画面でCopilotは動きます。

しかしMagitのコミット画面ではコミットメッセージ編集画面は簡素になっていて、 diff画面とコミットメッセージ画面が横に2分割されてdiffを見ながらコミットを書くことが出来るようになっています。これは通常の使い方では特に文句はないのですが、 copilot.elは今のバッファとファイルしか読まないようなので、この状態ではcopilotはfeat: add init.elのようなざっくりとしすぎている上に間違っているコミットメッセージしか作れません。どのファイルに変更があったかぐらいしか見れないからですね。

コミットメッセージバッファに情報を入れます

バッファの内容を読むのであれば当然バッファに入れる情報を増やしてやれば良いわけです。 Magitでコミットする時--verboseオプションを有効にしてやればコミットメッセージ入力バッファにdiffも入力されるので、 feat: add git-commit-setup-hook to copilotのようなそれっぽいコミットメッセージが生成されるようになってくれます。

--verboseをデフォルトにしたい

さて--verboseを毎回有効にするのは面倒なのでデフォルトにしたいですね。

How can I make --verbose flag be enabled by default in magit commit screen? - Emacs Stack Exchange の作者による回答を参考にすると、 --verboseを有効にしてC-x C-sを実行すれば(magit-popup-save-default-arguments)が実行されてデフォルトになるようですね。実際の動作を辿ると.emacs.d/transientディレクトリに永続化されるようですね。

transient全然わからん

それでもうだいたい目的は達成されているのですが、複数端末での利用や.emacs.dgit cloneだけでの再構築を考えると、自動で変更される部分ではなく、手動で書くGitマネージドなコード部分にデフォルト値は書いておきたいですね。

昔はmagit-commit-argumentsは単なるリストだったようなのですが、今はmagit-popup -> transientの管轄になっているようなので単純に--verboseをリストに追加する方法では対応できません。

Git自体の設定で解決することにしました

MagitではなくGit自体の設定でgit config --global commit.verbose trueのように設定すれば表示されるようになるので、実用的にはこれでも良いかなと思いました。

Magitのフラグ表示と実際の挙動が異なるのはかなり気持ちが悪いですが、 Transient User and Developer Manualを見たり、 forgeの使用例を見ても解決策が思いつきませんでした。

多少汚いですがadviceで(magit-commit-arguments)をaroundして解決しようかと思いましたが、構築段階ではなくコミット生成段階で閲覧するためGit自体の設定で解決するのと結果は変わらないですね。

transientの複雑性と真面目に向き合う必要性を今の所感じないのでこれで良いとしてしまいます。

一応Emacs以外(コマンドラインとか)からコミットを開いたときも設定の有効性を得られるメリットもあります。