Vim で関数の呼び出し元のスクリプト番号を取得する
最近教えてもらった黒魔術を覚書。
と、いうかだいぶ改造したので原型があまり残っていない(基本的なロジックはそのままだけど。
簡単に説明すると g:SID() をつくりました。
とりあえず、こんな感じで使えます。
[使い方]
function! s:main() " 呼び出し元の関数名を返す echo g:call_funcname() " => <SNR>290_main " SID 付きスクリプト関数の prefix を返す echo g:SID_function_prefix() " => <SNR>290_ " SID を返す echo g:SID() " => 281 " スクリプト関数の参照を返す echo g:script_function("s:plus")(1, 2) " => 3 endfunction call s:main()
これで s:SID() を作成する必要はなくなった…はず。
[注意]
上記のように g:SID() を使用するためには制限があり、スクリプトローカル関数から呼び出した場合しか使えません。
どういう事かというとグローバル空間やグローバル関数から呼び出した場合は使えない。
" グローバル空間では使えないや echo g:SID() function! g:global() " グローバル関数内では使えない echo g:SID() " => '' " こっちは動作する call s:main() endfunction call g:global()
あとはまだあんまりアグレッシブなテストを行なっていないのでまだ何か問題があるかも。
[ソース]
function! s:SCaller(...) try throw 'abc' catch /^abc$/ if a:0 let prefunc = a:1 let result = matchstr(v:throwpoint, '^.*\.\.\zs.*\ze\.\.'.prefunc) if empty(result) let result = matchstr(v:throwpoint, '^function \zs.*\ze\.\.'.prefunc) endif return result else return matchstr(v:throwpoint, '^function \zs.\{-}\ze\.\.') endif endtry endfunction function! g:call_funcname() return s:SCaller("g:call_funcname") endfunction function! g:SID_function_prefix() return matchstr(s:SCaller("g:SID_function_prefix"), '^\zs<SNR>\d\+_\ze.*$') endfunction function! g:SID() return matchstr(s:SCaller("g:SID"), '^<SNR>\zs\d\+\ze.*$') endfunction function! g:script_function(name) let SID = matchstr(s:SCaller("g:script_function"), '^\zs<SNR>\d\+_\ze.*$') let funcname = substitute(a:name, "s:", SID, "g") return function(funcname) endfunction