function's scope ?.txt
vim script を書いてて学んだことのまとめ。って最近これ多いな。まぁいいか。関数は何もつけずに定義すると global になるんだけど以下の prefix をつけると script file 内のみから見えるように出来るらしい。http://d.hatena.ne.jp/thinca/20090310/1236657469 でツッコミもらった。 :help script-local をちゃんと読めということに落ち着いてしまった。 thinca さんいつもありがとう。
- "s:"
- :help local-function
- script local な変数と同じ。なんだけどこれをつけるとホントに外から見えなくなるので、 vimrc や
:command で定義する ex command からや autocmdcommand line 経由で呼びたいなんてときはつけてはいけない。後述する <SID> を伴っての呼び出しの場合でもこっちをつけておけばいいみたい。
- "<SID>"
- :help <SID>
- script id の略かな。
たとえば上記の例だけど script 内で local function を呼ぶ :command を定義する場合には関数定義と :command での呼び出し時にこれをつけると内部で勝手に script number に展開されてよしなにしてくれる、と。map もしくは menu から呼び出される関数にはこれをつけないといけないらしい。他は :command や :autocmd にもつけることができるけど必須ではない、と。ただ既存の script を見ている限りでは <SID> 付きで :command から呼び出していたりするんだけどこれはたぶんその command がどこで定義されているかを :command による一覧から把握しやすくするための tips みたいなもんよね。 - vim 側がその
ex commandmap や menu を解釈していくときに global な function じゃないと関数本体が見つからなくて実行のしようがないと思うんだけど、展開された script number があればそれを辿っていくことで関数定義を見つけることができる、ということかな。そういう意味では script local というよりは vim 内部限定で global という認識が正解ぽいね。 - 一応使うだけならこれだけ知ってればいいみたいだけど command の挙動がおかしいとかいう場合の調査や debug にはもうちょっと知っとくと便利。 <SID> は内部で "<SNR>{script number}_" という形式に展開されるみたいなんだけど、このときの script number が :scriptnames で参照できる一番左側の番号と一致してるらしい。
- 試しに :command とうって定義されてる ex command 群をつらつらと眺めていくと <SNR>26_Autodate とか書いてあるのを発見。とりあえず番号の 26 を生体 register に記憶して :scriptnames で 26 番目に読み込まれている script を確認すると $VIMRUNTIME/plugin/autodate.vim だとわかる。したっけ autodate.vim を開いて Autodate という関数を検索してみると :command での呼び出しも含めて見つかる、という具合。
ちなみに以下のような file を ~/.vim/plguin/ 以下においておくと :SIDSample command が使えるようになる、と。でもこれあんまりいい例じゃないな。まぁこんな感じで複雑な command sequence を関数として定義してそれを command として登録するのが流儀なのかなぁと思ったり思わなかったり。
" in SIDSample.vim function! s:SIDSample() echo '<SID> sample' sleep endfunction command! SIDSample call <SID>SIDSample()
で、ひとつ疑問に思ったんだけど vim は名前空間ていう概念がないからほいほい global に関数定義していくとマズイわけよねいろいろと。てことは関数はなるべく script local にすべきということなのはわかるんだけどじゃあ :command による定義はどうなんだというハナシになるわけで。 :command の場合は問答無用で global になるのでそのうちぶつかるんじゃね ? と思うんだけどそこらへんの記述が help にないんだよな…。というあたりを考えると別に関数も scope とか考えない文化なのか ? とか何とか。まぁ imap + <C-r>=
経由で insert mode で呼ばれるとか以外は local にするのが礼儀というか行儀というかしつけ ? みたいな ?
にしても vim って prefix や postfix で修飾するの好きよね。慣れるとわかりやすいんだけどやっぱり初期導入 cost は高い ( そもそも prefix の概念を知っているかとか prefix であると気付くかとかその :help を適切にひけるかとかそれぞれの prefix の意味を覚えないと他人の書いた script とか読んでられないとか ) よなー。