Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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言語関連の概念について理解しておく必要があります。

  1. 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-errorprevious-error)が提供されます。これは、開発者がエラーを効率的にナビゲートするために非常に重要です。
    • display-buffer: Emacs Lispの関数で、指定されたバッファをユーザーに表示するために使用されます。この関数は、新しいウィンドウを開いたり、既存のウィンドウの内容を置き換えたりして、バッファを可視化します。
    • popwin.el: Emacsの拡張パッケージの一つで、特定のバッファ(例えば、ヘルプバッファ、コンパイル出力バッファ、ミニバッファなど)を一時的にポップアップウィンドウとして表示し、作業中のメインウィンドウを邪魔しないようにする機能を提供します。popwin.elは、バッファのメジャーモードを認識し、それに基づいてポップアップウィンドウの表示方法(サイズ、位置、自動クローズなど)を調整することがあります。
  2. 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のエラーバッファが作成された後、以下の順序で処理が行われていました。

  1. display-buffer errbuf): エラーバッファ(errbuf)をEmacsのウィンドウに表示します。この時点では、errbufはまだcompilation-modeに設定されておらず、おそらくデフォルトのfundamental-modetext-modeのような汎用モードになっています。
  2. (compilation-mode): errbufのメジャーモードをcompilation-modeに設定します。

この順序の問題点は、popwin.eldisplay-bufferの呼び出しに応答してバッファのモードをチェックする際に、まだcompilation-modeが有効になっていないため、popwin.elerrbufを通常のテキストバッファとして扱ってしまうことにありました。その結果、popwin.elcompilation-modeに特化した表示ルール(例えば、特定のポップアップウィンドウのサイズや位置、自動クローズの挙動など)を適用できず、ユーザーは期待通りの表示を得られませんでした。

このコミットでは、この順序を単純に反転させています。

  1. (compilation-mode): まず、errbufのメジャーモードをcompilation-modeに設定します。これにより、バッファはcompilation-modeの全ての特性と機能を持つようになります。
  2. (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))

このコードでは、まずerrbufgofmtのエラーメッセージを含むバッファ)がdisplay-buffer関数によってEmacsのウィンドウに表示されます。その後、compilation-mode関数が呼び出され、そのバッファのメジャーモードがcompilation-modeに設定されます。

変更後のコード:

    (compilation-mode)
    (display-buffer errbuf)))

変更後では、この2つの行の順序が入れ替わっています。まず、compilation-mode関数が呼び出され、errbufのメジャーモードがcompilation-modeに設定されます。この時点で、errbufcompilation-modeの全ての特性(例えば、エラーメッセージのハイライトやクリック可能なリンクなど)を持つようになります。その後、display-buffer関数が呼び出され、既にcompilation-modeであるerrbufがEmacsのウィンドウに表示されます。

この順序の変更が重要な理由は、前述の「技術的詳細」で述べた通り、popwin.elのようなEmacsパッケージがバッファの表示時にそのモードをチェックするためです。モードが先に設定されていれば、これらのパッケージはバッファを正しくcompilation-modeとして認識し、それに応じた表示動作を適用できます。これにより、gofmtのエラーバッファが期待通りに表示され、Emacsの拡張機能との互換性が向上します。

関連リンク

参考にした情報源リンク