[インデックス 18009] ファイルの概要
このコミットは、Go言語のVim用インデントスクリプト misc/vim/indent/go.vim
における改善です。具体的には、Vimのインデント幅を決定する際に、より新しい shiftwidth()
関数が利用可能であればそれを使用し、そうでなければ従来の &shiftwidth
オプションを使用するように変更されました。これにより、Vimのバージョンによる挙動の違いを吸収し、より堅牢なインデント処理を実現しています。
コミット
commit e962f8f1c6f69845130374cb040dd0284f78a943
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Mon Dec 16 20:05:48 2013 -0500
misc/vim: use shiftwidth() instead of &sw if available.
Fixes #6841.
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/43010044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/e962f8f1c6f69845130374cb040dd0284f78a943
元コミット内容
misc/vim: use shiftwidth() instead of &sw if available.
Fixes #6841.
変更の背景
この変更は、Go言語のVimインデントスクリプトが、Vimのインデント幅を正しく取得できない場合があるという問題(Issue 6841)を解決するために行われました。従来のスクリプトでは、インデント幅の取得にVimのオプションである &shiftwidth
を直接参照していました。しかし、Vimの新しいバージョンでは、インデント幅をより正確に、かつ柔軟に取得できる shiftwidth()
関数が導入されていました。
&shiftwidth
は、ユーザーが設定したインデント幅を示すオプションですが、Vimの自動インデント機能やファイルタイプごとの設定によっては、実際のインデント幅が &shiftwidth
の値と異なる場合があります。特に、expandtab
や tabstop
などの他のオプションとの組み合わせによって、期待通りのインデント幅にならないことがありました。
shiftwidth()
関数は、現在のバッファの実際のインデント幅を計算して返すため、より信頼性の高い値を提供します。このコミットは、shiftwidth()
関数が利用可能な環境ではそちらを優先的に使用することで、インデントの不整合を解消し、より正確なGoコードのインデントをVimで実現することを目的としています。
前提知識の解説
Vimのインデント設定
Vimにおけるインデントは、複数のオプションによって制御されます。
shiftwidth
(&sw
): 自動インデントや>>
、<<
コマンドでインデントされる幅を設定します。例えば、set shiftwidth=4
とすると、インデント幅が4スペースになります。tabstop
(&ts
): タブ文字 (\t
) が表示される幅を設定します。例えば、set tabstop=8
とすると、タブ文字が8スペース幅で表示されます。expandtab
(&et
): タブ文字を入力した際に、shiftwidth
で指定された数のスペースに展開するかどうかを設定します。set expandtab
とすると、タブがスペースに変換されます。autoindent
(&ai
): 新しい行を開始したときに、前の行のインデントレベルを自動的に引き継ぐかどうかを設定します。cindent
(&ci
): C言語のような構文に基づいて自動的にインデントを行うかどうかを設定します。Go言語のインデントスクリプトもこれに類するものです。
Vimscriptの関数とオプション
Vimscriptでは、Vimの内部状態や設定にアクセスするために、オプション(&option_name
)と関数(function_name()
)が提供されています。
- オプション (
&option_name
): Vimの設定値を直接参照します。例えば、&shiftwidth
はshiftwidth
オプションの現在の値を取得します。 - 関数 (
function_name()
): 特定の処理を実行したり、計算された値を返したりします。shiftwidth()
関数は、現在のバッファの実際のインデント幅を計算して返します。これは、shiftwidth
オプションだけでなく、tabstop
やexpandtab
などの他の関連オプションも考慮に入れた上で決定されます。
Issue 6841
Go言語のIssueトラッカーにおける Issue 6841: misc/vim: go.vim indent script doesn't respect shiftwidth は、このコミットの直接的な原因となった問題です。このIssueでは、VimのGoインデントスクリプトが shiftwidth
オプションを正しく尊重せず、期待通りのインデントが行われないという報告がされていました。特に、shiftwidth
が tabstop
と異なる値に設定されている場合に問題が発生することが指摘されていました。
技術的詳細
このコミットの技術的な核心は、Vimscriptにおけるインデント幅の取得方法の改善にあります。
従来の misc/vim/indent/go.vim
スクリプトでは、インデント幅を計算する際に、Vimのグローバルオプションである &shiftwidth
を直接使用していました。これは、Vimのインデント設定の基本的な値を取得する一般的な方法です。
しかし、Vimのインデントは shiftwidth
だけでなく、tabstop
や expandtab
といった他のオプション、さらにはファイルタイプごとの設定やユーザーのカスタマイズによって複雑に影響を受けます。特に、shiftwidth
と tabstop
が異なる値に設定されている場合や、expandtab
が有効になっている場合、&shiftwidth
が示す値と、Vimが実際に適用するインデント幅との間に乖離が生じることがありました。
Vim 7.3以降で導入された shiftwidth()
関数は、このような複雑な状況に対応するために設計されました。この関数は、現在のバッファのコンテキスト(shiftwidth
、tabstop
、expandtab
、およびその他の関連設定)を総合的に考慮し、Vimが実際に使用するインデント幅を正確に計算して返します。これにより、スクリプトがVimのインデント挙動と完全に同期し、より正確なインデントを提供できるようになります。
このコミットでは、shiftwidth()
関数がVimのバージョンで利用可能かどうかを exists('*shiftwidth')
でチェックし、利用可能であれば shiftwidth()
を使用するヘルパー関数 s:sw()
を定義しています。利用可能でなければ、フォールバックとして従来の &shiftwidth
を使用します。これにより、古いVimバージョンとの互換性を保ちつつ、新しいVimバージョンではより正確なインデント幅を取得できるようになりました。
コアとなるコードの変更箇所
変更は misc/vim/indent/go.vim
ファイルに集中しています。
-
s:sw()
ヘルパー関数の追加: ファイルの冒頭部分に、shiftwidth()
関数が存在するかどうかをチェックし、それに応じてインデント幅を返すs:sw()
という新しいVimscript関数が追加されました。if exists('*shiftwidth') func s:sw() return shiftwidth() endfunc else func s:sw() return &shiftwidth endfunc endif
-
&sw
からs:sw()
への置き換え:GoIndent
関数内でインデント幅を計算する際に、これまで直接&sw
(または&shiftwidth
) を参照していた箇所が、新しく定義されたs:sw()
関数呼び出しに置き換えられました。let ind += &sw
がlet ind += s:sw()
に変更。let ind -= &sw
がlet ind -= s:sw()
に変更。
具体的には、以下の行が変更されています。
--- a/misc/vim/indent/go.vim +++ b/misc/vim/indent/go.vim @@ -40,17 +52,17 @@ function! GoIndent(lnum) if prevl =~ '[({]\s*$' " previous line opened a block - let ind += &sw + let ind += s:sw() endif if prevl =~# '^\\s*\\(case .*\\|default\\):$' " previous line is part of a switch statement - let ind += &sw + let ind += s:sw() endif " TODO: handle if the previous line is a label. if thisl =~ '^\\s*[)}]' " this line closed a block - let ind -= &sw + let ind -= s:sw() endif " Colons are tricky. @@ -58,7 +70,7 @@ function! GoIndent(lnum) " We ignore trying to deal with jump labels because (a) they're rare, and " (b) they're hard to disambiguate from a composite literal key. if thisl =~# '^\\s*\\(case .*\\|default\\):$' - let ind -= &sw + let ind -= s:sw() endif return ind
コアとなるコードの解説
このコミットの核となる変更は、Vimのインデントスクリプトがインデント幅を決定するロジックを改善した点にあります。
misc/vim/indent/go.vim
は、Go言語のソースコードをVimで編集する際に、適切なインデントを自動的に適用するためのスクリプトです。GoIndent(lnum)
関数は、指定された行番号 lnum
のインデントレベルを計算し、その値を返します。
変更前は、この関数内でインデントの増減を行う際に、&shiftwidth
というVimのオプションの値を直接使用していました。例えば、ブロックの開始を示す {
や (
が前の行にある場合、現在の行のインデントを &shiftwidth
分だけ増やす、といった処理が行われていました。
変更後は、まず s:sw()
というヘルパー関数が導入されました。この関数は、Vimの組み込み関数である exists('*shiftwidth')
を使用して、shiftwidth()
関数が現在のVim環境で利用可能かどうかをチェックします。
- もし
shiftwidth()
が利用可能であれば、s:sw()
はshiftwidth()
の戻り値を返します。shiftwidth()
は、Vimの現在のインデント設定(shiftwidth
、tabstop
、expandtab
など)を総合的に考慮した上で、実際に適用されるべきインデント幅を計算して返します。これにより、より正確でVimの挙動に即したインデント幅が得られます。 - もし
shiftwidth()
が利用可能でなければ(古いVimバージョンなど)、s:sw()
はフォールバックとして従来の&shiftwidth
の値を返します。これにより、古いVimバージョンとの互換性が維持されます。
そして、GoIndent
関数内のすべての &sw
への参照が s:sw()
の呼び出しに置き換えられました。これにより、スクリプトはVimのバージョンに応じて最適なインデント幅の取得方法を自動的に選択し、Goコードのインデントをより正確かつ堅牢に行えるようになりました。
この変更は、Vimのインデント機能の進化に対応し、ユーザーがどのようなVim設定を使用していても、Go言語のコーディングスタイルガイドラインに沿った一貫したインデントを提供するための重要な改善と言えます。
関連リンク
- Go Issue 6841: misc/vim: go.vim indent script doesn't respect shiftwidth
- Go CL 43010044: misc/vim: use shiftwidth() instead of &sw if available.
- Vim documentation for
shiftwidth()
::h shiftwidth()
(Vimエディタ内で:h shiftwidth()
と入力して参照)
参考にした情報源リンク
- Vim documentation (特に
:h shiftwidth
,:h tabstop
,:h expandtab
,:h autoindent
,:h cindent
,:h exists()
) - Go Issue Tracker
- Go Code Review (Goのコードレビュープロセスに関する情報)
- Vimscript: Functions (Vimscriptの関数に関する一般的な情報)
- Vimscript: Options (Vimscriptのオプションに関する一般的な情報)I have generated the detailed explanation of the commit as requested, following all the specified instructions and chapter structure. The output is in Markdown format and is printed to standard output. I used web search to gather information about Vim's
shiftwidth()
function,&shiftwidth
option, and the context of Go Issue 6841.
I believe the task is complete.