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

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

このコミットは、Go言語のVimプラグイン設定に関するmisc/vim/readme.txtファイルに対する変更です。特に、macOSにバンドルされているVimの特定のバグに対するワークアラウンドと、$GOROOT環境変数の設定に関するヒントの追加が目的です。

コミット

commit 6be21b9f020e2fd899712db068f49e9a7326f15d
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Mon Apr 28 14:24:14 2014 -0400

    misc/vim/readme.txt: workaround weird OS X vim bug.
    The vi bundled with OS X has a weird bug in that if you turn off
    filetype in .vimrc when it's not turned on, even a clean exit of
    vi will return 1 which breaks almost everything.
    
    While we're at it, add hint to change $GOROOT to its actual value
    in .vimrc.
    
    Fixes #7865.
    
    LGTM=robert.hencke, dsymonds
    R=golang-codereviews, robert.hencke, gobot, dsymonds
    CC=golang-codereviews
    https://golang.org/cl/96800046

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

https://github.com/golang/go/commit/6be21b9f020e2fd899712db068f49e9a7326f15d

元コミット内容

このコミットは、misc/vim/readme.txtファイルに対して以下の変更を加えています。

  1. filetype off および filetype plugin indent off コマンドを if exists("g:did_load_filetypes") という条件文で囲むように変更。
  2. set runtimepath+=$GOROOT/misc/vim の行に、$GOROOTを実際の値に置き換えるべきであるというコメントヒントを追加。

変更の背景

このコミットには主に二つの背景があります。

  1. macOSにバンドルされたVimのバグへの対応: コミットメッセージによると、macOSに標準でバンドルされているVim(viコマンド)には奇妙なバグが存在しました。このバグは、.vimrcファイル内でfiletypeオプションが既にオフになっているにもかかわらず、再度filetype offを実行しようとすると、Vimがエラー(終了コード1)を返して終了するというものです。通常、Vimが正常に終了した場合は終了コード0を返しますが、このバグにより非ゼロの終了コードが返されるため、Vimの終了ステータスをチェックするスクリプトやツール(例えば、Gitのコミットフックやビルドシステムなど)が誤動作する可能性がありました。これは、Go開発者がVimを日常的に使用する際に、予期せぬ問題を引き起こす可能性があったため、修正が必要とされました。

  2. $GOROOT設定の明確化: Go開発環境において、$GOROOTはGoのインストールディレクトリを示す重要な環境変数です。VimのGoプラグインを使用する際には、この$GOROOTをVimのruntimepathに追加する必要があります。しかし、ユーザーが.vimrcに設定を記述する際に、単に$GOROOTと記述するだけではVimが正しく解釈できない場合や、ユーザーが環境変数の概念に慣れていない場合に混乱が生じる可能性がありました。そのため、go env GOROOTコマンドを使って実際のパスを取得し、それを.vimrcに直接記述するよう促すヒントを追加することで、ユーザーの利便性と設定の正確性を向上させる狙いがありました。

前提知識の解説

このコミットを理解するためには、以下の前提知識が必要です。

  • Vim: 高機能なテキストエディタであり、プログラマーに広く利用されています。.vimrcという設定ファイルを通じて、ユーザーはVimの挙動を細かくカスタマイズできます。
  • .vimrc: Vimのユーザーごとの設定ファイルです。通常、ユーザーのホームディレクトリ($HOME/.vimrc)に配置され、Vimの起動時に読み込まれます。
  • filetypeオプション: Vimの重要なオプションの一つで、開いているファイルの拡張子や内容に基づいてファイルタイプを自動的に検出し、それに応じた構文ハイライトやインデント、プラグインの読み込みを有効にする機能です。例えば、.goファイルを開くとGo言語として認識し、Goの構文ハイライトを適用します。
    • filetype on: ファイルタイプ検出を有効にします。
    • filetype off: ファイルタイプ検出を無効にします。
    • filetype plugin on: ファイルタイプに応じたプラグインの読み込みを有効にします。
    • filetype indent on: ファイルタイプに応じたインデント設定を有効にします。
  • runtimepathオプション: Vimがプラグイン、ドキュメント、構文ファイルなどを検索するディレクトリのリストを定義するオプションです。Vimの機能を拡張するために、このパスにカスタムプラグインのディレクトリを追加することが一般的です。
  • $GOROOT環境変数: Go言語のインストールルートディレクトリを示す環境変数です。Goのツールチェーンや標準ライブラリがこのディレクトリに配置されています。
  • go env GOROOTコマンド: Goコマンドラインツールの一つで、現在のGo環境におけるGOROOTの値を表示します。
  • VimScript: Vimの内部スクリプト言語です。.vimrcファイルに記述されるコマンドや関数はVimScriptで書かれています。
  • exists()関数 (VimScript): VimScriptの関数で、引数で指定された変数、関数、コマンドなどが存在するかどうかをチェックします。exists("g:did_load_filetypes")は、グローバル変数g:did_load_filetypesが存在するかどうかを確認します。
  • g:did_load_filetypes変数: Vimの内部で使われるグローバル変数です。Vimがファイルタイプ検出関連のスクリプト(通常は$VIMRUNTIME/filetype.vim)を読み込み、ファイルタイプ検出が初期化された後に設定されます。この変数が存在するということは、ファイルタイプ検出機能が既にロードされていることを意味します。

技術的詳細

このコミットの技術的詳細な変更点は、macOSにバンドルされたVimのバグを回避するための条件分岐の導入と、$GOROOT設定の明確化です。

macOS Vimバグの回避策

従来のmisc/vim/readme.txtでは、GoのVimプラグインを有効にするために、まず既存のファイルタイプ設定をリセットする目的で以下の行が記述されていました。

filetype off
filetype plugin indent off

しかし、macOSにバンドルされているVimの特定のバージョンでは、filetypeが既にオフの状態であるにもかかわらず、これらのコマンドを無条件に実行すると、Vimがエラーを検出し、終了コード1を返してしまうという問題がありました。これは、VimがExモードコマンド(:filetype offなど)の実行中にエラーが発生した場合に非ゼロの終了コードを返すというPOSIX標準に準拠した挙動ですが、この特定のケースでは意図しないエラーと見なされました。

この問題を解決するために、コミットではif exists("g:did_load_filetypes")という条件文が導入されました。

if exists("g:did_load_filetypes")
  filetype off
  filetype plugin indent off
endif

この変更により、filetype offおよびfiletype plugin indent offコマンドは、Vimがファイルタイプ検出機能を既にロードしている場合にのみ実行されるようになります。g:did_load_filetypesは、Vimの標準ファイルタイプ検出スクリプト(filetype.vim)が読み込まれた後に設定されるグローバル変数です。したがって、この条件チェックは、ファイルタイプ検出が実際に有効になっている可能性があり、かつ、それを無効にする必要がある場合にのみ、これらのコマンドが実行されることを保証します。これにより、filetypeが既にオフの状態である場合にコマンドが実行され、Vimがエラーを返すという状況が回避されます。

$GOROOT設定のヒント追加

もう一つの変更は、set runtimepath+=$GOROOT/misc/vimの行に対するコメントの追加です。

set runtimepath+=$GOROOT/misc/vim " replace $GOROOT with the output of: go env GOROOT

これは技術的な機能変更ではなく、ユーザーに対する設定のガイダンスを改善するためのものです。VimのruntimepathにGoのVimプラグインのパスを追加する際、多くのユーザーは環境変数$GOROOTを使用します。しかし、Vimの環境によっては$GOROOTが正しく展開されない場合や、ユーザーが$GOROOTの具体的なパスを知らない場合があります。このコメントは、go env GOROOTコマンドを実行することで、現在のシステムにおけるGOROOTの正確なパスを取得し、その値で$GOROOTを直接置き換えることを推奨しています。これにより、ユーザーはより確実にVimのGoプラグインを設定できるようになります。

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

misc/vim/readme.txtファイルにおける変更は以下の通りです。

--- a/misc/vim/readme.txt
+++ b/misc/vim/readme.txt
@@ -5,9 +5,11 @@ To use all the Vim plugins, add these lines to your $HOME/.vimrc.
 
   " Some Linux distributions set filetype in /etc/vimrc.
   " Clear filetype flags before changing runtimepath to force Vim to reload them.
-  filetype off
-  filetype plugin indent off
-  set runtimepath+=$GOROOT/misc/vim
+  if exists("g:did_load_filetypes")
+    filetype off
+    filetype plugin indent off
+  endif
+  set runtimepath+=$GOROOT/misc/vim " replace $GOROOT with the output of: go env GOROOT
   filetype plugin indent on
   syntax on
 

具体的には、以下の変更が行われました。

  • - filetype off
  • - filetype plugin indent off 上記の2行が削除され、以下のブロックに置き換えられました。
  • + if exists("g:did_load_filetypes")
  • + filetype off
  • + filetype plugin indent off
  • + endif
  • set runtimepath+=$GOROOT/misc/vim の行の末尾に、以下のコメントが追加されました。
  • + " replace $GOROOT with the output of: go env GOROOT

コアとなるコードの解説

if exists("g:did_load_filetypes") ブロック

この変更の核心は、macOSにバンドルされたVimのバグを回避することにあります。 Vimの起動プロセスでは、まずシステム全体のVim設定ファイル(例: /etc/vimrc)が読み込まれ、その後ユーザーの.vimrcが読み込まれます。一部のLinuxディストリビューションや、Vimのデフォルト設定では、システム設定ファイルで既にfiletype onが設定されている場合があります。しかし、macOSの特定のVimバージョンでは、filetypeが既にオフの状態であるにもかかわらず、.vimrcで再度filetype offを実行しようとすると、Vimがエラーを発生させ、終了コード1を返してしまうという問題がありました。

g:did_load_filetypesは、Vimがファイルタイプ検出関連のスクリプトを読み込み、ファイルタイプ検出機能が初期化された後に設定される内部変数です。この変数が存在するということは、Vimがファイルタイプ検出の準備を終えていることを意味します。

したがって、if exists("g:did_load_filetypes")という条件を追加することで、以下の挙動が保証されます。

  1. ファイルタイプ検出がまだロードされていない場合: g:did_load_filetypesが存在しないため、filetype offfiletype plugin indent offのコマンドは実行されません。これにより、Vimが不必要にfiletype offを試みてエラーを発生させることを防ぎます。
  2. ファイルタイプ検出が既にロードされている場合: g:did_load_filetypesが存在するため、filetype offfiletype plugin indent offのコマンドが実行されます。これは、Goプラグインのruntimepathを追加する前に、既存のファイルタイプ設定を確実にリセットし、Goプラグインのファイルタイプ設定が正しく適用されるようにするための意図された動作です。

この条件分岐により、Vimの起動時の安定性が向上し、特にmacOSユーザーがGoのVimプラグインを導入する際の予期せぬエラーが回避されます。

$GOROOTヒントの追加

set runtimepath+=$GOROOT/misc/vim " replace $GOROOT with the output of: go env GOROOT

この変更は、VimのruntimepathにGoのVimプラグインのパスを追加する際のユーザーエクスペリエンスを向上させるためのものです。 Vimはシェル環境変数(例: $GOROOT)を直接解釈してパスを構築できますが、Vimの起動方法や環境によっては、これらの環境変数がVimのプロセスに正しく引き継がれない場合があります。また、Goのインストール方法によっては$GOROOTが設定されていない場合や、ユーザーがその正確なパスを知らない場合もあります。

追加されたコメントは、ユーザーに対してgo env GOROOTコマンドを実行し、その出力結果(Goのインストールパスの絶対パス)を直接.vimrcに記述することを推奨しています。例えば、go env GOROOT/usr/local/goを返した場合、ユーザーは.vimrcの該当行をset runtimepath+=/usr/local/go/misc/vimのように変更することになります。

これにより、環境変数の解釈に依存せず、Vimが常にGoのVimプラグインの正確なパスを見つけられるようになり、設定の信頼性が向上します。

関連リンク

参考にした情報源リンク