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

[インデックス 15581] ファイルの概要

このコミットは、Go言語のEmacsメジャーモードである go-mode.el に関連する変更です。具体的には、godoc コマンドのタブ補完機能を追加し、インストール済みのGoパッケージ名から補完できるようにするものです。

misc/emacs/go-mode.el は、EmacsエディタでGo言語のソースコードを編集する際に使用される主要なLispファイルです。シンタックスハイライト、インデント、Goツールとの連携(go build, go run, godoc など)といった機能を提供し、Go開発者の生産性を向上させます。

コミット

commit a969f3c247b45ab5557aff1a8777751360b9c0a4
Author: Dominik Honnef <dominik.honnef@gmail.com>
Date:   Mon Mar 4 15:31:57 2013 -0500

    misc/emacs: Add tab completion for godoc command, completing from known installed packages
    
    R=golang-dev, adonovan, bradfitz, cw, patrick.allen.higgins, sameer, ugorji
    CC=golang-dev
    https://golang.org/cl/7373051

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/a969f3c247b45ab5557aff1a8777751360b9c0a4

元コミット内容

misc/emacs: Add tab completion for godoc command, completing from known installed packages

R=golang-dev, adonovan, bradfitz, cw, patrick.allen.higgins, sameer, ugorji
CC=golang-dev
https://golang.org/cl/7373051

変更の背景

このコミットの背景には、Emacsの go-mode を利用してGo言語のドキュメントを参照する際のユーザーエクスペリエンスの向上が挙げられます。以前は、godoc コマンドをEmacs内で実行する際に、ドキュメントを参照したいパッケージ名をユーザーが手動で入力する必要がありました。この手動入力は、特にパッケージ名が長い場合や、正確な名前を覚えていない場合に、タイプミスや手間を伴うものでした。

この変更は、godoc コマンドの引数としてパッケージ名を入力する際に、Emacsの強力な補完機能(タブ補完)を利用できるようにすることで、この問題を解決しようとしています。これにより、ユーザーはインストール済みのGoパッケージのリストから、目的のパッケージ名を簡単に選択できるようになり、入力の手間とミスを大幅に削減できます。これは、開発ワークフローの効率化に直接貢献する改善です。

前提知識の解説

Emacs

Emacsは、非常に強力で拡張性の高いテキストエディタであり、統合開発環境(IDE)としても機能します。その特徴は、Emacs Lispというプログラミング言語で記述された豊富なカスタマイズ機能と拡張性です。ユーザーはEmacs Lispを使って、エディタの動作を細かく制御したり、新しい機能を追加したりすることができます。

go-mode.el

go-mode.el は、EmacsでGo言語のソースコードを編集するための「メジャーモード」です。メジャーモードは、特定のプログラミング言語やファイルタイプに特化した編集機能(シンタックスハイライト、自動インデント、コメントの切り替え、特定のコマンド実行など)を提供します。go-mode.el は、Go言語の構文を理解し、go buildgo rungodoc といったGoツールチェインのコマンドをEmacs内から直接実行するためのインターフェースを提供します。

godocコマンド

godoc は、Go言語の標準ツールチェインに含まれるドキュメンテーションツールです。Goのソースコードに記述されたコメントや宣言からドキュメントを生成し、表示します。通常、コマンドラインから godoc <package_path> のように実行され、指定されたパッケージのドキュメントを表示します。例えば、godoc fmt と入力すると、標準ライブラリの fmt パッケージのドキュメントが表示されます。

Emacs Lispの主要な関数

  • read-string PROMPT &optional INITIAL-INPUT HISTORY DEFAULT-VALUE: ユーザーに PROMPT を表示し、文字列入力を受け取る基本的な関数です。この関数は、入力補完機能を提供しません。

  • completing-read PROMPT COLLECTION &optional PREDICATE REQUIRE-MATCH INITIAL-INPUT HISTORY DEFAULT-VALUE: ユーザーに PROMPT を表示し、文字列入力を受け取りますが、COLLECTION で指定された候補リストからの入力補完機能を提供します。ユーザーが入力するにつれて、COLLECTION 内の候補が絞り込まれ、タブキーを押すことで補完候補を表示したり、選択したりできます。

    • PROMPT: ユーザーに表示するプロンプト文字列。
    • COLLECTION: 補完の候補となる文字列のリスト、または候補を返す関数。
    • HISTORY: 入力履歴を保存するための変数。これにより、以前に入力した値を再利用できます。
  • defvar SYMBOL &optional INITIAL-VALUE DOCSTRING: Emacs Lispでグローバル変数を定義するために使用されます。SYMBOL は変数名、INITIAL-VALUE は初期値、DOCSTRING は変数の説明です。

  • defun NAME ARGLIST &rest BODY: Emacs Lispで関数を定義するために使用されます。NAME は関数名、ARGLIST は引数リスト、BODY は関数の本体です。

  • format FORMAT-STRING &rest ARGS: C言語の printf に似た機能を提供し、FORMAT-STRING に基づいて文字列をフォーマットします。

  • buffer-substring-no-properties START END: 現在のバッファの START から END までの範囲のテキストを、テキストプロパティなしの文字列として返します。

  • car LIST: リストの最初の要素を返します。

  • cdr LIST: リストの最初の要素を除いた残りの部分(リスト)を返します。

Go言語のパッケージシステム

Go言語では、コードは「パッケージ」という単位で整理されます。パッケージは、関連する機能の集合であり、再利用可能なコードのモジュール化を促進します。godoc コマンドは、これらのパッケージのドキュメントを参照するために使用されます。Goの標準ライブラリには fmt, net/http, io など多くのパッケージが含まれており、ユーザーが作成したアプリケーションも独自のパッケージとして構成されます。

技術的詳細

このコミットの主要な技術的変更は、godoc コマンドのクエリを読み取る godoc-read-query 関数において、ユーザー入力の取得方法を read-string から completing-read へと変更した点です。

  1. read-string から completing-read への移行:

    • 変更前は read-string を使用していたため、ユーザーは godoc コマンドの引数(通常はパッケージ名)を完全に手動で入力する必要がありました。
    • 変更後は completing-read を使用することで、Emacsの強力な補完フレームワークが利用可能になります。これにより、ユーザーが入力するにつれて、利用可能なGoパッケージのリストから候補が提示され、タブキーで補完できるようになります。
  2. 補完候補の提供 (go-packages):

    • completing-read の第2引数には、補完の候補となるリストが必要です。このコミットでは、go-packages という関数がその役割を担っています。この関数は、システムにインストールされている(またはGoの環境変数 GOPATHGOROOT から認識できる)Goパッケージのリストを動的に生成して返すと推測されます。これにより、常に最新かつ正確なパッケージリストに基づいて補完が行われます。
  3. 入力履歴の管理 (go-godoc-history):

    • completing-read の引数として go-godoc-history という新しい変数が導入されています。これは、godoc コマンドで過去に入力されたパッケージ名を記憶するための履歴変数です。これにより、ユーザーは以前に検索したパッケージ名を簡単に再利用できるようになり、利便性がさらに向上します。defvar go-godoc-history nil で初期化されており、Emacsセッション間で履歴が保持されるようになります。

これらの変更により、godoc コマンドの使い勝手が大幅に向上し、Go開発者はより効率的にドキュメントを参照できるようになります。

コアとなるコードの変更箇所

--- a/misc/emacs/go-mode.el
+++ b/misc/emacs/go-mode.el
@@ -35,6 +35,7 @@
 (defconst go-type-name-regexp (concat "\\(?:[*(]\\)*\\(?:" go-identifier-regexp "\\.\\)?\\(" go-identifier-regexp "\\)\"))
 
 (defvar go-dangling-cache)
+(defvar go-godoc-history nil)
 
 (defgroup go nil
   "Major mode for editing Go code"
@@ -476,10 +477,10 @@ you save any file, kind of defeating the point of autoloading.\"\n          (symbol (if bounds\n                       (buffer-substring-no-properties (car bounds)\n                                                       (cdr bounds)))))\n-    (read-string (if symbol\n-                     (format "godoc (default %s): " symbol)\n-                   "godoc: ")\n-                 nil nil symbol)))\n+    (completing-read (if symbol\n+                         (format "godoc (default %s): " symbol)\n+                       "godoc: ")\n+                     (go-packages) nil nil nil 'go-godoc-history symbol)))\n \n (defun godoc--get-buffer (query)\n   "Get an empty buffer for a godoc query."\n```

## コアとなるコードの解説

このコミットで変更されたのは、`misc/emacs/go-mode.el` ファイル内の `godoc-read-query` 関数です。この関数は、`godoc` コマンドを実行する際にユーザーからクエリ(通常はパッケージ名)を読み取る役割を担っています。

1.  **`go-godoc-history` 変数の追加 (行 36)**:
    ```elisp
    (defvar go-godoc-history nil)
    ```
    `defvar` を使用して、`go-godoc-history` という新しい変数が定義されました。この変数は、`godoc` コマンドの入力履歴を保存するために使用されます。初期値は `nil` (空) です。

2.  **`godoc-read-query` 関数の変更 (行 479-484)**:
    変更の核心は、`read-string` 関数呼び出しが `completing-read` 関数呼び出しに置き換えられた点です。

    *   **変更前**:
        ```elisp
        (read-string (if symbol
                         (format "godoc (default %s): " symbol)
                       "godoc: ")
                     nil nil symbol)))
        ```
        ここでは `read-string` が使用されており、ユーザーはプロンプトに対して文字列を直接入力するだけでした。補完機能はありません。

    *   **変更後**:
        ```elisp
        (completing-read (if symbol
                             (format "godoc (default %s): " symbol)
                           "godoc: ")
                         (go-packages) nil nil nil 'go-godoc-history symbol)))
        ```
        `completing-read` 関数が使用されるようになりました。
        *   **第1引数**: `(if symbol ... "godoc: ")` は、以前と同様にユーザーに表示されるプロンプト文字列を生成します。`symbol` が存在する場合(例えば、カーソル下の単語がデフォルト値として提案される場合)、その単語を含むプロンプトが表示されます。
        *   **第2引数**: `(go-packages)` が補完の候補リストを提供します。この関数は、Goのインストール済みパッケージのリストを返すと推測されます。
        *   **第3引数 (`nil`)**: `PREDICATE` 引数で、候補をフィルタリングするための述語関数を指定できますが、ここでは `nil` なので使用されていません。
        *   **第4引数 (`nil`)**: `REQUIRE-MATCH` 引数で、入力が候補リストと完全に一致する必要があるかどうかを指定できますが、ここでは `nil` なので必須ではありません。
        *   **第5引数 (`nil`)**: `INITIAL-INPUT` 引数で、初期入力文字列を指定できますが、ここでは `nil` です。
        *   **第6引数 (`'go-godoc-history`)**: `HISTORY` 引数に、新しく定義された `go-godoc-history` 変数が渡されています。これにより、`completing-read` はユーザーの入力をこの変数に保存し、次回の呼び出し時に履歴として利用できるようになります。
        *   **第7引数 (`symbol`)**: `DEFAULT-VALUE` 引数に `symbol` が渡されています。これは、カーソル下の単語など、デフォルトの入力値として提案されるものです。

この変更により、`godoc` コマンドの実行時に、ユーザーはGoパッケージ名を効率的に補完入力できるようになり、操作性が大幅に向上しました。

## 関連リンク

*   **Go言語公式サイト**: [https://go.dev/](https://go.dev/)
*   **Emacs公式サイト**: [https://www.gnu.org/software/emacs/](https://www.gnu.org/software/emacs/)
*   **Go言語のドキュメンテーションツール `godoc`**: [https://pkg.go.dev/cmd/godoc](https://pkg.go.dev/cmd/godoc)
*   **Emacs Lisp Manual - Completing Read**: [https://www.gnu.org/software/emacs/manual/html_node/elisp/Completing-Read.html](https://www.gnu.org/software/emacs/manual/html_node/elisp/Completing-Read.html)
*   **Go言語の `go-mode.el` リポジトリ (Goプロジェクト内)**: [https://github.com/golang/go/tree/master/misc/emacs](https://github.com/golang/go/tree/master/misc/emacs)

## 参考にした情報源リンク

*   Go言語の公式ドキュメント
*   Emacs Lispの公式ドキュメント
*   GitHub上のGo言語リポジトリのコミット履歴
*   Emacs Lispの `completing-read` および `read-string` 関数の一般的な使用例に関する情報