[インデックス 16022] ファイルの概要
このコミットは、EmacsのGo言語モード(go-mode.el
)におけるgofmt
のエラーバッファ表示に関する修正です。具体的には、gofmt
のエラーを表示する際に、バッファをcompilation-mode
に設定するタイミングを、バッファを表示する前(display-buffer
)に変更することで、popwin.el
のようなEmacsパッケージがバッファのモードに基づいて表示動作を変更する際に正しく機能するようにします。
コミット
commit 0104cea6c8f25ced6f5944a810ccaadab1cbf4e6
Author: Dominik Honnef <dominik.honnef@gmail.com>
Date: Sat Mar 30 09:54:08 2013 -0700
misc/emacs: Enable compilation-mode for gofmt error buffer before displaying it.
Some packages, like popwin.el, change display behaviour based on
the buffer's mode, so we should enable compilation-mode before
displaying the buffer.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/8155043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/0104cea6c8f25ced6f5944a810ccaadab1cbf4e6
元コミット内容
misc/emacs: Enable compilation-mode for gofmt error buffer before displaying it.
Some packages, like popwin.el, change display behaviour based on
the buffer's mode, so we should enable compilation-mode before
displaying the buffer.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/8155043
変更の背景
この変更の背景には、Emacsの特定のパッケージ、特にpopwin.el
のようなものが、バッファの表示方法をそのバッファのメジャーモードに基づいて動的に調整するという挙動があります。
gofmt
はGo言語のコードフォーマッタであり、コードの整形に失敗した場合やエラーが発生した場合に、その情報をEmacsのバッファに出力します。このエラー情報を表示するバッファは、通常、コンパイルエラーやリンターの警告などを表示するために設計されたcompilation-mode
に設定されることが期待されます。compilation-mode
は、エラーメッセージをクリック可能にするなど、エラーナビゲーションのための特別な機能を提供します。
しかし、このコミット以前の実装では、gofmt
のエラーバッファがdisplay-buffer
関数によって表示された後にcompilation-mode
が有効にされていました。この順序が問題を引き起こしていました。popwin.el
のようなパッケージは、バッファが表示される「前」にそのモードをチェックし、それに基づいて表示ウィンドウのサイズや位置などを決定します。もしバッファが表示される時点でまだcompilation-mode
が有効になっていない場合、これらのパッケージはバッファを通常のテキストバッファとして扱い、compilation-mode
に特化した表示設定を適用できませんでした。
このため、ユーザー体験が損なわれ、gofmt
のエラーバッファが意図した通りに表示されない、あるいはpopwin.el
の機能が正しく適用されないという問題が発生していました。このコミットは、この表示のタイミングの問題を解決し、gofmt
のエラーバッファが常に正しくcompilation-mode
として認識され、関連するEmacsパッケージの恩恵を受けられるようにすることを目的としています。
前提知識の解説
このコミットを理解するためには、以下のEmacsおよびGo言語関連の概念について理解しておく必要があります。
-
Emacs:
- Emacs Lisp (Elisp): Emacsの拡張言語であり、Emacsのほぼ全ての機能がElispで記述されています。ユーザーはElispを使ってEmacsをカスタマイズしたり、新しい機能を追加したりできます。
go-mode.el
もElispで書かれたファイルです。 - バッファ (Buffer): Emacsがテキストを保持する基本的な単位です。ファイルの内容、シェルコマンドの出力、ヘルプメッセージなど、Emacsで表示される全ての情報はバッファに格納されます。
- メジャーモード (Major Mode): バッファの編集動作を定義するものです。例えば、
text-mode
は一般的なテキスト編集用、prog-mode
はプログラミング言語用、go-mode
はGo言語用です。メジャーモードは、シンタックスハイライト、インデント、特定のコマンドの挙動などを制御します。 compilation-mode
: Emacsのメジャーモードの一つで、コンパイラやリンター、その他の外部ツールからの出力を表示するために特化しています。このモードでは、エラーメッセージや警告がハイライトされ、それらのメッセージをクリックすることで、対応するソースコードの行にジャンプできる機能(next-error
、previous-error
)が提供されます。これは、開発者がエラーを効率的にナビゲートするために非常に重要です。display-buffer
: Emacs Lispの関数で、指定されたバッファをユーザーに表示するために使用されます。この関数は、新しいウィンドウを開いたり、既存のウィンドウの内容を置き換えたりして、バッファを可視化します。popwin.el
: Emacsの拡張パッケージの一つで、特定のバッファ(例えば、ヘルプバッファ、コンパイル出力バッファ、ミニバッファなど)を一時的にポップアップウィンドウとして表示し、作業中のメインウィンドウを邪魔しないようにする機能を提供します。popwin.el
は、バッファのメジャーモードを認識し、それに基づいてポップアップウィンドウの表示方法(サイズ、位置、自動クローズなど)を調整することがあります。
- Emacs Lisp (Elisp): Emacsの拡張言語であり、Emacsのほぼ全ての機能がElispで記述されています。ユーザーはElispを使ってEmacsをカスタマイズしたり、新しい機能を追加したりできます。
-
Go言語関連:
gofmt
: Go言語の公式なコードフォーマッタです。Goのソースコードを標準的なスタイルに自動的に整形します。gofmt
は、コードの可読性を高め、Goコミュニティ全体で一貫したコーディングスタイルを維持するために広く使用されています。gofmt
がコードを整形できない場合や、構文エラーがある場合には、エラーメッセージを出力します。go-mode.el
: EmacsでGo言語のソースコードを編集するためのメジャーモードです。シンタックスハイライト、インデント、gofmt
の実行、Go言語特有のコマンド(例:go-play-buffer
)の提供など、Go開発をサポートする機能を提供します。
これらの概念を理解することで、コミットが解決しようとしている問題と、その解決策がどのように機能するのかを深く把握できます。
技術的詳細
このコミットの技術的な核心は、Emacsにおけるバッファのモード設定と表示のタイミングに関するものです。
Emacsでは、バッファのメジャーモードは、そのバッファがどのように振る舞い、どのように表示されるかを決定する上で非常に重要な役割を果たします。compilation-mode
は、エラーメッセージの解析、ハイライト、そしてエラー箇所へのジャンプ機能を提供するため、gofmt
のエラー出力のような構造化されたメッセージを表示するバッファには不可欠です。
popwin.el
のようなEmacsパッケージは、バッファが表示される際に、そのバッファの現在のメジャーモードを「検査」します。この検査は、display-buffer
関数が実際にバッファを画面に描画する前、またはその処理の非常に早い段階で行われることが一般的です。
コミット前のコードでは、gofmt
のエラーバッファが作成された後、以下の順序で処理が行われていました。
display-buffer errbuf)
: エラーバッファ(errbuf
)をEmacsのウィンドウに表示します。この時点では、errbuf
はまだcompilation-mode
に設定されておらず、おそらくデフォルトのfundamental-mode
やtext-mode
のような汎用モードになっています。(compilation-mode)
:errbuf
のメジャーモードをcompilation-mode
に設定します。
この順序の問題点は、popwin.el
がdisplay-buffer
の呼び出しに応答してバッファのモードをチェックする際に、まだcompilation-mode
が有効になっていないため、popwin.el
がerrbuf
を通常のテキストバッファとして扱ってしまうことにありました。その結果、popwin.el
はcompilation-mode
に特化した表示ルール(例えば、特定のポップアップウィンドウのサイズや位置、自動クローズの挙動など)を適用できず、ユーザーは期待通りの表示を得られませんでした。
このコミットでは、この順序を単純に反転させています。
(compilation-mode)
: まず、errbuf
のメジャーモードをcompilation-mode
に設定します。これにより、バッファはcompilation-mode
の全ての特性と機能を持つようになります。(display-buffer errbuf)
: 次に、errbuf
をEmacsのウィンドウに表示します。この時点では、errbuf
は既にcompilation-mode
として認識されているため、popwin.el
のようなパッケージは、バッファのモードを正しく検出し、compilation-mode
に特化した表示ルールを適用できるようになります。
この変更は、Emacsのバッファ管理と表示メカニズムの深い理解に基づいています。バッファのモードは、そのバッファがどのように「振る舞う」かだけでなく、他のEmacsコンポーネントや拡張機能がそのバッファをどのように「認識し、扱う」かにも影響を与えるため、モード設定のタイミングは非常に重要です。この修正により、gofmt
のエラー表示がより堅牢になり、Emacsの様々な拡張機能との互換性が向上しました。
コアとなるコードの変更箇所
変更はmisc/emacs/go-mode.el
ファイル内で行われています。
--- a/misc/emacs/go-mode.el
+++ b/misc/emacs/go-mode.el
@@ -565,8 +565,8 @@ buffer."
(insert "gofmt errors:\n")
(while (search-forward-regexp (concat "^\\(" (regexp-quote tmpfile) "\\):") nil t)
(replace-match (file-name-nondirectory filename) t t nil 1))
- (display-buffer errbuf)
- (compilation-mode)))
+ (compilation-mode)
+ (display-buffer errbuf)))
コアとなるコードの解説
このコミットで変更されたのは、gofmt
のエラー出力を表示するEmacs Lisp関数内の2行の順序です。
元のコード:
(display-buffer errbuf)
(compilation-mode))
このコードでは、まずerrbuf
(gofmt
のエラーメッセージを含むバッファ)がdisplay-buffer
関数によってEmacsのウィンドウに表示されます。その後、compilation-mode
関数が呼び出され、そのバッファのメジャーモードがcompilation-mode
に設定されます。
変更後のコード:
(compilation-mode)
(display-buffer errbuf)))
変更後では、この2つの行の順序が入れ替わっています。まず、compilation-mode
関数が呼び出され、errbuf
のメジャーモードがcompilation-mode
に設定されます。この時点で、errbuf
はcompilation-mode
の全ての特性(例えば、エラーメッセージのハイライトやクリック可能なリンクなど)を持つようになります。その後、display-buffer
関数が呼び出され、既にcompilation-mode
であるerrbuf
がEmacsのウィンドウに表示されます。
この順序の変更が重要な理由は、前述の「技術的詳細」で述べた通り、popwin.el
のようなEmacsパッケージがバッファの表示時にそのモードをチェックするためです。モードが先に設定されていれば、これらのパッケージはバッファを正しくcompilation-mode
として認識し、それに応じた表示動作を適用できます。これにより、gofmt
のエラーバッファが期待通りに表示され、Emacsの拡張機能との互換性が向上します。
関連リンク
参考にした情報源リンク
- Emacs Lisp Reference Manual (特にBuffer, Major Mode, display-buffer, compilation-modeに関するセクション)
popwin.el
のドキュメントやソースコードgofmt
の公式ドキュメントgo-mode.el
のソースコード- https://www.gnu.org/software/emacs/manual/html_node/elisp/Displaying-Buffers.html
- https://www.gnu.org/software/emacs/manual/html_node/emacs/Compilation-Mode.html
- https://github.com/nonsequitur/popwin
- https://pkg.go.dev/cmd/gofmt