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

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

このコミットは、Go言語のEmacsメジャーモードであるgo-mode.elにおいて、prog-modeの定義方法をGNU Emacs 24の挙動に合わせるように修正したものです。これにより、prog-modeが存在しない古いEmacsバージョンやXEmacs環境での互換性が向上し、Go言語のソースコード編集時の挙動がより一貫したものになります。

コミット

  • コミットハッシュ: 5f199f2d5a6054cffbea5a869004a3af55b4f401
  • Author: Dominik Honnef dominik.honnef@gmail.com
  • Date: Thu Aug 15 20:40:38 2013 -0700

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

https://github.com/golang/go/commit/5f199f2d5a6054cffbea5a8669004a3af55b4f401

元コミット内容

misc/emacs: when defining prog-mode, define it like GNU Emacs 24 would

Fixes #6156.

R=adonovan
CC=golang-dev
https://golang.org/cl/13035043

変更の背景

この変更の背景には、Emacsのバージョン間の互換性の問題があります。GNU Emacs 24ではprog-modeというメジャーモードが導入されましたが、それ以前のバージョンやXEmacsにはこのprog-modeが存在しませんでした。go-mode.elはGo言語のソースコードを編集するためのメジャーモードであり、通常、プログラミング言語のモードはprog-modeから派生することが一般的です。

しかし、prog-modeが存在しない環境でgo-mode.elを使用しようとすると、prog-modeが未定義であるためにエラーが発生したり、期待通りの挙動を示さない可能性がありました。このコミットは、prog-modeが存在しない場合に、GNU Emacs 24がprog-modeを定義するのと同様の方法でprog-modeを定義することで、この互換性の問題を解決し、Go言語の編集体験をより安定させることを目的としています。

具体的には、Go issue #6156で報告された問題に対応しています。この問題は、prog-modeが利用できない環境でgo-mode.elが正しく動作しないことに関連していると考えられます。

前提知識の解説

このコミットを理解するためには、以下のEmacs Lispに関する基本的な概念を理解しておく必要があります。

  • Emacs: 高度にカスタマイズ可能なテキストエディタであり、プログラミングIDEとしても広く利用されています。Emacsの機能の多くはEmacs Lispというプログラミング言語で記述されています。
  • メジャーモード (Major Mode): Emacsにおける編集モードの一種で、特定の種類のファイル(例: Go言語のソースコード、Markdownファイル、プレーンテキストなど)を編集するために特化した機能を提供します。各バッファ(開いているファイル)には常に1つのメジャーモードがアクティブになります。メジャーモードは、構文ハイライト、インデント、特定のコマンドなどを定義します。
  • prog-mode: GNU Emacs 24で導入されたメジャーモードで、一般的なプログラミング言語のモードの基盤となることを意図しています。prog-modeは、プログラミング言語に共通する基本的な機能(コメントの扱い、インデントの挙動など)を提供し、他の言語固有のモードがそこから派生することで、コードの重複を減らし、一貫した挙動を実現します。
  • fundamental-mode: Emacsで最も基本的なメジャーモードです。特別な機能はほとんど提供せず、他の多くのメジャーモードの基盤となります。
  • define-derived-mode: Emacs Lispの関数で、既存のメジャーモードから新しいメジャーモードを派生させるために使用されます。これにより、親モードの機能を継承しつつ、新しいモード固有の機能を追加できます。
  • fboundp: Emacs Lispの関数で、シンボルが関数として定義されているかどうかをチェックします。このコミットでは、prog-modeが関数として定義されているか(つまり、prog-modeが存在するか)をチェックするために使用されています。
  • make-local-variable: Emacs Lispの関数で、指定された変数を現在のバッファのローカル変数にします。これにより、その変数の値は現在のバッファにのみ影響し、他のバッファには影響しません。
  • require-final-newline: Emacsの変数で、ファイルの最後に改行があるべきかどうかを制御します。多くのプログラミング言語のスタイルガイドでは、ファイルの最後に改行があることを推奨しています。
  • parse-sexp-ignore-comments: Emacsの変数で、S式(Symbolic Expression)のパース時にコメントを無視するかどうかを制御します。プログラミングモードでは、通常コメントを無視してコード構造を解析します。
  • bidi-paragraph-direction: Emacsの変数で、双方向テキスト(例: アラビア語やヘブライ語のように右から左に書かれる言語と左から右に書かれる言語が混在するテキスト)の段落の方向を制御します。プログラミングモードでは、通常左から右への記述が基本となります。

技術的詳細

このコミットの核心は、go-mode.elprog-modeに依存しているにもかかわらず、古いEmacsバージョンやXEmacsにはprog-modeが組み込まれていないという問題に対処することです。

元のコードでは、prog-modeが関数として定義されていない場合(つまり、prog-modeが存在しない場合)に、define-derived-modeを使ってprog-modefundamental-modeから派生させていました。しかし、この定義は非常に簡素なもので、GNU Emacs 24のprog-modeが持つべき重要なプロパティや挙動を模倣していませんでした。

新しいコードでは、prog-modeが存在しない場合に、GNU Emacs 24のprog-modeの定義をより忠実に再現するように変更されています。具体的には、以下の設定が追加されています。

  1. "Prog": モードラインに表示されるモード名。
  2. "Major mode for editing source code.": モードのドキュメンテーション文字列。
  3. (set (make-local-variable 'require-final-newline) mode-require-final-newline): require-final-newline変数を現在のバッファのローカル変数として設定し、その値をmode-require-final-newline(通常はt、つまりファイルの最後に改行を要求する)に設定します。これにより、プログラミングモードとして適切なファイルの終端挙動が保証されます。
  4. (set (make-local-variable 'parse-sexp-ignore-comments) t): parse-sexp-ignore-comments変数を現在のバッファのローカル変数として設定し、その値をt(真)に設定します。これにより、S式をパースする際にコメントが無視され、コードの構造解析が正確に行われます。
  5. (setq bidi-paragraph-direction 'left-to-right): bidi-paragraph-direction変数を'left-to-rightに設定します。これは、プログラミングコードが通常左から右に記述されることを前提とした設定です。

これらの追加設定により、prog-modeが存在しない環境でも、go-mode.elが期待するprog-modeの基本的な挙動がエミュレートされ、Go言語のソースコード編集時の機能がより安定し、一貫性を持つようになります。

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

--- a/misc/emacs/go-mode.el
+++ b/misc/emacs/go-mode.el
@@ -67,14 +67,14 @@
 (defun go--old-completion-list-style (list)\n   (mapcar (lambda (x) (cons x nil)) list))\n \n-;; GNU Emacs 24 has prog-mode, older GNU Emacs and XEmacs do not.\n-;; Ideally we\'d use defalias instead, but that breaks in XEmacs.\n-;;\n-;; TODO: If XEmacs decides to add prog-mode, change this to use\n-;; defalias to alias prog-mode or fundamental-mode to go--prog-mode\n-;; and use that in define-derived-mode.\n+;; GNU Emacs 24 has prog-mode, older GNU Emacs and XEmacs do not, so\n+;; copy its definition for those.\n (if (not (fboundp \'prog-mode))\n-    (define-derived-mode prog-mode fundamental-mode \"\" \"\"))\n+    (define-derived-mode prog-mode fundamental-mode \"Prog\"\n+      \"Major mode for editing source code.\"\n+      (set (make-local-variable \'require-final-newline) mode-require-final-newline)\n+      (make-local-variable \'parse-sexp-ignore-comments) t)\n+      (setq bidi-paragraph-direction \'left-to-right)))\n \n (defun go--regexp-enclose-in-symbol (s)\n   ;; XEmacs does not support \\_<, GNU Emacs does. In GNU Emacs we make\n```

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

変更の中心は、`if (not (fboundp 'prog-mode))`という条件分岐の中身です。

**変更前:**

```elisp
(if (not (fboundp 'prog-mode))
    (define-derived-mode prog-mode fundamental-mode "" ""))

このコードは、prog-modeが関数として定義されていない場合(つまり、prog-modeが存在しない場合)に、prog-modefundamental-modeから派生させて定義していました。しかし、モード名とドキュメンテーション文字列が空文字列""となっており、prog-modeが持つべき他の重要なプロパティが設定されていませんでした。

変更後:

(if (not (fboundp 'prog-mode))
    (define-derived-mode prog-mode fundamental-mode "Prog"
      "Major mode for editing source code."
      (set (make-local-variable 'require-final-newline) mode-require-final-newline)
      (set (make-local-variable 'parse-sexp-ignore-comments) t)
      (setq bidi-paragraph-direction 'left-to-right)))

この変更により、prog-modeが存在しない場合に定義されるprog-modeが、GNU Emacs 24のprog-modeの定義に近づけられました。

  • "Prog": モードラインに表示されるモード名が設定されました。
  • "Major mode for editing source code.": モードのドキュメンテーション文字列が追加され、モードの目的が明確になりました。
  • (set (make-local-variable 'require-final-newline) mode-require-final-newline): ファイルの最後に改行を要求する設定が追加されました。これはプログラミングモードで一般的に推奨される挙動です。
  • (set (make-local-variable 'parse-sexp-ignore-comments) t): S式をパースする際にコメントを無視する設定が追加されました。これにより、コードの構造解析がより正確になります。
  • (setq bidi-paragraph-direction 'left-to-right): 双方向テキストの段落方向が左から右に設定されました。これはプログラミングコードの記述方向と一致します。

これらの変更により、prog-modeが存在しない環境でも、go-mode.elがより適切に機能し、Go言語のソースコード編集時の挙動が改善されます。

関連リンク

参考にした情報源リンク