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()などでスコープへアクセス出来るため、聖域はほとんど無い
正直今でも理解出来ていない。
