Vim中級者を脱する スコープ編
個人的に、Vimで一番ハマったのがスコープの問題でした。
vimrcのコピペばかりの、あなた。
せめて、よく登場するスコープだけでも理解してみましょう。
よく見るスコープ一覧
- グローバルスコープ
g:
- 関数内スコープ
a:
- スクリプトスコープ
s:
- バッファスコープ
b:
- 接頭辞なし
let huga=...
など
グローバル(g:)スコープ
どこからでも参照できます。
プラグインの設定で見慣れたスコープですね。
let g:neocomplete#enable_at_startup = 1
変数を初期化するには、次のようにします。 大量のエラーコードによって操作できなくなるので、嫌いな人のvimrcの末尾に書き込んでください。
for key in keys(g:)
execute 'unlet g:' . key
endfor
関数内(a:)スコープ
関数内で、引数を参照するときに使用するスコープ
個人的に一番理解しがたいスコープです。
こんな感じで使います。他言語から移ってきた人には、正直使いづらい。
function! Huga(first, second)
echo a:first
"=> 'a'
echo a:
"=> {'0': 0, '000': [], 'second': 'b', 'first': 'a', 'firstline': 5, 'lastline': 5}
endfunction
call Huga('a', 'b')
「あーなるほど、関数内でだけ有効なスコープなのか。」
と、思っていたらそれは間違い。
下記のようにすると、グローバルスコープとして参照できます。
function! a:huga()
echo 'Global!?!?!?'
endfunction
call a:huga() " => Global!?!?!?
実は、これ関数名に:
が許可されているだけです。
なので実際はa:
スコープは関係ないんだけど、分かりづらい。
スクリプト(s:)スコープ
ファイル内でのみ有効なスコープです。
プラグインで、プライベートなメソッドや定数を作るときによく使います。
let s:script_scope = '外部からは参照できない'
function! s:script_scope_method()
" プライベートメソッドとしてよく使われる
endfunction
このs:
は、スクリプトがsourceされるときに置き換えられ、<SNR>1_...
という感じの形になります。
えぇ、そうです。すると、グローバルなスコープとして参照できます。
この<SNR>
の後にどの数値が割り振られているかは、:scriptnames
で参照できます。
また、s:
は<SID>
として使えばスコープを超えて使用できるようになります。
マッピングの時に、scriptスコープを使う時などは必須ですね。
nnoremap s :echo <SID>SID()<CR>
ただし、変数は基本的には聖域です。
バッファ(b:)スコープ
バッファ単位のスコープです。
ファイルタイプによる設定や、一時バッファによる変数などに使います。
- ファイルタイプの変更で、
b:current_syntax
などが初期化&格納されます - Uniteを起動で、
b:unite
にデータが格納されます。
Uniteのデバッグするときには、echo b:unite.candidates
などを参照しましょう。
あぁ、ようやくまともなスコープだ。
接頭辞なし(let huga=
)変数
えぇ。グローバルなスコープです。
お前もか!
マナーとしては、やはりg:
で宣言したいところですが、
Vimにデフォルトで入っているプラグインは、容赦なくこの変数を使ってきます。
:echo loaded_*<Tab>
などすれば、奴らを見つけられるはずです。
細かいことを言えば、関数内ならばローカルスコープです。。。
スコープのまとめ
- スコープはほとんどグローバルで参照できる
- VimLは枠にハマらない素敵な言語仕様を持っている
- getbufvar()などでスコープへアクセス出来るため、聖域はほとんど無い
正直今でも理解出来ていない。