[インデックス 17846] ファイルの概要
このコミットは、Go言語のEmacsメジャーモードであるgo-mode.el
に対する変更です。具体的には、misc/emacs/go-mode.el
ファイルが修正されています。このファイルは、EmacsエディタでGo言語のコードを編集する際に、シンタックスハイライト、インデント、コード補完、定義へのジャンプなどの機能を提供するLispコードを含んでいます。
コミット
- コミットハッシュ:
3b0e6c21aef32c5439fdcdaff44418a875565fcc
- Author: Dominik Honnef dominik.honnef@gmail.com
- Date: Tue Oct 29 11:14:56 2013 -0400
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/3b0e6c21aef32c5439fdcdaff44418a875565fcc
元コミット内容
misc/emacs: support godef-jump on import statements
The newest version of godef supports jumping to a package's source
directory if point is on an import statement.
R=adonovan
CC=golang-dev
https://golang.org/cl/18230043
変更の背景
このコミットの背景には、Go言語の定義ジャンプツールであるgodef
の機能拡張があります。以前のgodef
は、変数、関数、型などの定義元にジャンプする機能を提供していましたが、Goのimport
ステートメント(パッケージのインポート宣言)上では、そのパッケージのソースディレクトリに直接ジャンプする機能は持っていませんでした。
新しいバージョンのgodef
が、この「import
ステートメントからパッケージのソースディレクトリへジャンプする」機能を追加しました。これに伴い、Emacsのgo-mode.el
も、この新しいgodef
の出力を適切に解釈し、ユーザーを目的のディレクトリまたはファイルに誘導できるように更新する必要が生じました。
具体的には、godef
がパッケージのソースディレクトリを指す場合、その出力はファイル名や行番号、列番号を含まない単なるディレクトリパスになる可能性があります。go-mode.el
は、このような新しい形式のgodef
の出力を処理できるように、既存のgo-goto-location
関数を修正する必要がありました。また、godef
がインポートパスを見つけられなかった場合のエラーメッセージも適切に処理できるように変更されています。
前提知識の解説
Emacs
Emacsは、拡張性とカスタマイズ性に優れたテキストエディタです。その機能の多くはEmacs Lisp(Elisp)というプログラミング言語で記述されており、ユーザーはElispを使ってEmacsの動作を自由にカスタマイズしたり、新しい機能を追加したりできます。
go-mode.el
go-mode.el
は、EmacsでGo言語のコードを編集するためのメジャーモードです。Go言語特有のシンタックスハイライト、自動インデント、コードフォーマット、そして外部ツール(godef
など)との連携機能を提供します。これにより、EmacsユーザーはGo言語の開発を効率的に行うことができます。
godef
godef
は、Go言語のソースコード内で識別子(変数名、関数名、型名など)がどこで定義されているかを特定し、その定義元のファイルパス、行番号、列番号を出力するコマンドラインツールです。開発者がコードを読み解く際に、定義元に素早くジャンプできるため、非常に便利なツールとして広く利用されています。
定義へのジャンプ (Jump to Definition)
プログラミングエディタにおける「定義へのジャンプ」機能は、カーソルが置かれている識別子(変数、関数、型など)の定義が記述されているソースコードの場所に、エディタの表示を移動させる機能です。これにより、開発者はコードベースを効率的にナビゲートし、特定の要素がどのように定義されているかを素早く理解できます。
importステートメントとパッケージのソースディレクトリ
Go言語では、import "path/to/package"
という形式で他のパッケージをインポートします。このpath/to/package
は、通常、Goのワークスペース(GOPATH
)内のsrc
ディレクトリ以下に存在するパッケージのソースコードへのパスに対応します。例えば、import "fmt"
であれば、標準ライブラリのfmt
パッケージのソースコードディレクトリを指します。
技術的詳細
このコミットの技術的な核心は、go-mode.el
内のgo-goto-location
関数の変更にあります。この関数は、godef
コマンドの出力(定義元の場所を示す文字列)を解析し、Emacsでその場所にジャンプする役割を担っています。
従来のgodef
の出力は、filename:line:column
という形式でした。go-goto-location
関数は、この形式を正規表現でマッチングし、ファイル名、行番号、列番号を抽出して、該当するファイルを開き、指定された行と列にカーソルを移動させていました。
しかし、新しいgodef
は、import
ステートメント上で実行された場合、filename:line:column
形式ではなく、単にパッケージのソースディレクトリのパスを返すようになりました。このコミットでは、この新しい出力形式に対応するために、go-goto-location
関数が以下のように変更されました。
-
ディレクトリパスの直接処理:
godef
の出力がfilename:line:column
の形式にマッチしない場合、それはディレクトリパスであると判断し、そのディレクトリをEmacsで開くように変更されました。これは、funcall (if other-window #'find-file-other-window #'find-file) specifier)
という行で実現されています。find-file
はファイルを開く関数ですが、ディレクトリパスが与えられた場合はそのディレクトリのDiredバッファ(ファイル一覧)を開きます。 -
新しいエラーメッセージの処理:
godef
がインポートパスを見つけられなかった場合に返す可能性のある新しいエラーメッセージ"error finding import path for "
を認識し、それをEmacsのメッセージバッファに表示するように追加されました。これにより、ユーザーはgodef
がなぜジャンプできなかったのかを理解できるようになります。
これらの変更により、go-mode.el
は、godef
の新しい機能(import
ステートメントからのパッケージソースディレクトリへのジャンプ)を完全にサポートし、より堅牢なエラーハンドリングを提供するようになりました。
コアとなるコードの変更箇所
diff --git a/misc/emacs/go-mode.el b/misc/emacs/go-mode.el
index 6cc03edb06..b74bc45e8d 100644
--- a/misc/emacs/go-mode.el
+++ b/misc/emacs/go-mode.el
@@ -950,11 +950,12 @@ will be commented, otherwise they will be removed completely."
"Given a file name in the format of `filename:line:column',
visit FILENAME and go to line LINE and column COLUMN."
(if (not (string-match "\\(.+\\):\\([0-9]+\\):\\([0-9]+\\)" specifier))
- (error "Unexpected godef output: %s" specifier)
+ ;; We've only been given a directory name
+ (funcall (if other-window #'find-file-other-window #'find-file) specifier)
(let ((filename (match-string 1 specifier))
(line (string-to-number (match-string 2 specifier)))
(column (string-to-number (match-string 3 specifier))))
- (with-current-buffer (funcall (if other-window 'find-file-other-window 'find-file) filename)
+ (with-current-buffer (funcall (if other-window #'find-file-other-window #'find-file) filename)
(go--goto-line line)
(beginning-of-line)
(forward-char (1- column))))))
@@ -1008,6 +1009,8 @@ description at POINT."
(message "%s" file))
((go--string-prefix-p "godef: no declaration found for " file)
(message "%s" file))
+ ((go--string-prefix-p "error finding import path for " file)
+ (message "%s" file))
(t
(push-mark)
(ring-insert find-tag-marker-ring (point-marker))
コアとなるコードの解説
go-goto-location
関数の変更
(if (not (string-match "\\(.+\\):\\([0-9]+\\):\\([0-9]+\\)" specifier))
- (error "Unexpected godef output: %s" specifier)
+ ;; We've only been given a directory name
+ (funcall (if other-window #'find-file-other-window #'find-file) specifier)
(let ((filename (match-string 1 specifier))
(line (string-to-number (match-string 2 specifier)))
(column (string-to-number (match-string 3 specifier))))
- (with-current-buffer (funcall (if other-window 'find-file-other-window 'find-file) filename)
+ (with-current-buffer (funcall (if other-window #'find-file-other-window #'find-file) filename)
(go--goto-line line)
(beginning-of-line)
(forward-char (1- column))))))
- 変更前:
(error "Unexpected godef output: %s" specifier)
godef
の出力specifier
がfilename:line:column
の形式にマッチしない場合、Emacsは「予期しないgodef
出力」というエラーを発生させていました。これは、godef
がディレクトリパスを返した場合にエラーとなることを意味します。
- 変更後:
(funcall (if other-window #'find-file-other-window #'find-file) specifier)
- 正規表現にマッチしない場合、
specifier
はディレクトリパスであると仮定し、find-file
関数(またはfind-file-other-window
関数)を呼び出してそのパスを開くように変更されました。find-file
は、ファイルパスが与えられればそのファイルを開き、ディレクトリパスが与えられればそのディレクトリのDiredバッファ(ファイル一覧)を開くというEmacsの標準的な動作を利用しています。 other-window
は、現在のウィンドウではなく別のウィンドウでファイルを開くかどうかを制御する変数です。#'
は、関数を引用符で囲む(quote)ためのElispの構文で、関数をデータとして扱うことを示します。
- 正規表現にマッチしない場合、
エラーメッセージ処理の追加
((go--string-prefix-p "godef: no declaration found for " file)
(message "%s" file))
+ ((go--string-prefix-p "error finding import path for " file)
+ (message "%s" file))
(t
(push-mark)
(ring-insert find-tag-marker-ring (point-marker))
- 追加:
((go--string-prefix-p "error finding import path for " file) (message "%s" file))
- これは、
godef
からの出力file
が文字列"error finding import path for "
で始まる場合に、そのメッセージをEmacsのミニバッファ(メッセージ領域)に表示するための条件分岐が追加されたことを示します。 go--string-prefix-p
は、文字列が特定のプレフィックスで始まるかどうかをチェックするヘルパー関数です。- これにより、
godef
がインポートパスを解決できなかった場合に、ユーザーにその旨が明確に通知されるようになりました。
- これは、
これらの変更により、go-mode.el
はgodef
の新しい動作に適切に対応し、ユーザーエクスペリエンスが向上しました。
関連リンク
- Go言語の
godef
ツール: https://pkg.go.dev/golang.org/x/tools/cmd/godef - Emacs Lispの
find-file
関数に関するドキュメント: https://www.gnu.org/software/emacs/manual/html_node/elisp/Visiting-Files.html
参考にした情報源リンク
- Go言語の公式ドキュメント
- Emacs Lispの公式ドキュメント
godef
のソースコード(Go言語リポジトリ内)go-mode.el
のソースコード(Go言語リポジトリ内)- 一般的なEmacs Lispプログラミングの知識