[インデックス 17125] ファイルの概要
このコミットは、Go言語のEmacsメジャーモードであるgo-mode.el
に対する変更です。go-mode.el
は、Emacsエディタ内でGo言語のコードを編集する際に、シンタックスハイライト、インデント、コード補完、そしてこのコミットが関連するコードカバレッジ情報の表示など、Go言語に特化した機能を提供します。
コミット
このコミットは、go-mode.el
において、新しいオーバーレイを追加する前に既存のオーバーレイをクリアするように修正するものです。これにより、コードカバレッジ情報などの表示が正しく行われ、以前の表示が残ってしまう問題が解決されます。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/8a9045634905c8777a3b6acd5eb78a8eee7828c6
元コミット内容
misc/emacs: clear previous overlays before adding new ones
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/12578044
変更の背景
go-mode.el
は、Go言語のテストツールが生成するコードカバレッジ情報をEmacs上で視覚的に表示する機能を持っています。この機能は、go test -coverprofile
コマンドによって生成されたカバレッジプロファイルファイルを読み込み、カバレッジのある行やない行をEmacsの「オーバーレイ」機能を使ってハイライトすることで実現されます。
しかし、このコミットが行われる前は、新しいカバレッジ情報を表示する際に、以前に適用されたオーバーレイが適切にクリアされていませんでした。このため、ユーザーが異なるカバレッジプロファイルを読み込んだり、コードを変更してカバレッジ情報が更新されたりした場合に、古いハイライトが画面上に残り続け、表示が乱れたり、誤解を招く情報が表示されたりする問題が発生していました。
この変更は、この表示上の問題を解決し、go-mode.el
が常に最新かつ正確なカバレッジ情報を表示できるようにするために導入されました。
前提知識の解説
EmacsとEmacs Lisp
- Emacs: GNU Emacsは、非常に強力で拡張性の高いテキストエディタです。その最大の特徴は、Emacs Lispというプログラミング言語で記述された豊富な機能と、ユーザーがEmacs Lispを使ってエディタの動作を自由にカスタマイズ・拡張できる点にあります。
- Emacs Lisp (Elisp): Emacsの内部で動作するLisp方言です。Emacsのほぼ全ての機能はEmacs Lispで実装されており、ユーザーはEmacs Lispのコードを記述することで、新しいコマンドの追加、既存のコマンドの変更、キーバインドのカスタマイズなど、多岐にわたる拡張が可能です。
go-mode.el
もEmacs Lispで書かれたファイルです。
Emacsのオーバーレイ (Overlays)
Emacsのオーバーレイは、バッファ(Emacsで開いているファイルの内容)の特定の領域に、一時的な視覚的属性(色、フォント、下線など)や動作(クリック可能にするなど)を適用するための強力なメカニズムです。オーバーレイはバッファの内容そのものを変更するわけではなく、その上に「重ねて」表示されるため、元のテキストはそのまま保持されます。
コードエディタの文脈では、オーバーレイは以下のような用途で広く利用されます。
- シンタックスハイライト
- スペルチェックの誤りを示す下線
- デバッガの現在の実行行のハイライト
- コードカバレッジ情報の表示(このコミットのケース)
- Linterや静的解析ツールの警告・エラー表示
オーバーレイは、その適用範囲(開始位置と終了位置)、表示属性、優先度などを持つオブジェクトとして扱われます。
go-mode.el
go-mode.el
は、EmacsでGo言語のソースコードを編集するための主要なメジャーモードです。Go言語の構文解析に基づいたシンタックスハイライト、自動インデント、Goツールチェーンとの連携(例: go fmt
の実行、go test
の結果表示、コードカバレッジの視覚化)など、Go開発を効率化するための多くの機能を提供します。
go test -coverprofile
Go言語の標準テストツールであるgo test
には、コードカバレッジ情報を収集する機能があります。
go test -coverprofile=output.txt
: このコマンドは、テストを実行し、そのテストによって実行されたコードの割合(カバレッジ)に関する詳細な情報をoutput.txt
というファイルに書き出します。このファイルは、どのファイルのどの行が実行されたか、あるいは実行されなかったかを示すテキストベースのプロファイルです。go tool cover
:go test -coverprofile
で生成されたプロファイルは、go tool cover
コマンドを使ってHTMLレポートとして生成したり、特定の形式に変換したりすることができます。go-mode.el
はこのプロファイルファイルを直接読み込み、Emacsバッファ上で視覚化します。
技術的詳細
このコミットの技術的詳細の中心は、Emacs Lispにおけるオーバーレイの管理です。
go-mode.el
のコードカバレッジ表示機能は、go test -coverprofile
によって生成されたカバレッジプロファイルの内容を解析し、カバレッジのある行とない行を特定します。その後、これらの行に対してEmacsのオーバーレイ機能を使って、異なる背景色やテキスト属性を適用することで、視覚的にカバレッジ情報を表現します。
問題は、新しいカバレッジプロファイルが読み込まれたり、カバレッジ情報が更新されたりする際に、以前に作成されたオーバーレイがバッファ上に残り続けてしまうことでした。Emacsのオーバーレイは、明示的に削除されない限り、バッファ上に存在し続けます。
このコミットでは、remove-overlays
というEmacs Lisp関数が導入されました。この関数は、現在のバッファに存在する全てのオーバーレイを削除します。これにより、新しいカバレッジ情報を表示する前に、古いカバレッジ表示によるオーバーレイが完全にクリアされ、常に最新かつ正確な情報のみが表示されるようになります。
save-excursion
ブロック内でremove-overlays
が呼び出されている点も重要です。save-excursion
は、そのブロック内の処理が完了した後、カーソル位置(ポイント)とマーク(選択範囲の開始点)をブロック実行前の状態に戻すEmacs Lispのマクロです。これにより、オーバーレイの操作がユーザーのカーソル位置に影響を与えないように配慮されています。
コアとなるコードの変更箇所
--- a/misc/emacs/go-mode.el
+++ b/misc/emacs/go-mode.el
@@ -998,6 +998,7 @@ coverage information gathered via go test -coverprofile=INPUT.\"\n (get-buffer gocov-buffer-name)\n (clone-indirect-buffer gocov-buffer-name nil))\n (save-excursion\n+ (remove-overlays)\n (overlay-put\n (make-overlay\n (point-min)\n```
## コアとなるコードの解説
変更は`misc/emacs/go-mode.el`ファイルの1箇所に、1行の追加のみです。
追加された行:
```elisp
(remove-overlays)
この行は、go-mode.el
がコードカバレッジ情報を表示するロジックの一部である(save-excursion ...)
ブロックの内部に追加されました。
(save-excursion ...)
: このEmacs Lispマクロは、その内部のコードが実行される間、現在のカーソル位置(ポイント)とマークを一時的に保存し、ブロックの実行が終了した後に元の位置に戻します。これにより、オーバーレイの操作がユーザーの編集作業に影響を与えないようにします。(remove-overlays)
: これはEmacs Lispの組み込み関数で、現在のバッファに存在する全てのオーバーレイを削除します。この関数が呼び出されることで、以前に適用されたカバレッジハイライトなどのオーバーレイが全て消去されます。
この変更により、go-mode.el
が新しいカバレッジ情報を処理するたびに、まず既存の全てのオーバーレイをクリアし、その後に新しいカバレッジ情報に基づいたオーバーレイを適用するようになります。これにより、表示の重複や古い情報の残存が解消され、ユーザーは常に正確なカバレッジ情報を視覚的に確認できるようになりました。
関連リンク
- Go CL 12578044: https://golang.org/cl/12578044
参考にした情報源リンク
- GNU Emacs Manual - Overlays: https://www.gnu.org/software/emacs/manual/html_node/elisp/Overlays.html
- Go Programming Language -
go test
command: https://pkg.go.dev/cmd/go#hdr-Test_packages - Go Programming Language -
go tool cover
: https://pkg.go.dev/cmd/go#hdr-Go_tool_cover - Emacs Lisp Reference Manual -
save-excursion
: https://www.gnu.org/software/emacs/manual/html_node/elisp/Excursions.html - Emacs Lisp Reference Manual -
remove-overlays
: https://www.gnu.org/software/emacs/manual/html_node/elisp/Overlay-Properties.html go-mode.el
source code (for context, though not directly referenced for this explanation): https://github.com/golang/go/blob/master/misc/emacs/go-mode.el