そう簡単に行かないのが Vim の恐ろしいところ。
とんでもない落とし穴があります。
書き換えた関数でスクリプトローカルな変数にアクセスしようとすると、関数の ID に関係なく関数を定義したファイルのスクリプトローカルな変数を見てしまいます。
a.vim
let s:value1 = 'a.vim:value1' let s:value2 = 'a.vim:value2' function! s:get_value() return s:value1 endfunction " A wrapper to call from other scope. function! GetValue() return s:get_value() endfunction
b.vim
source hookfunc.vim source a.vim let s:value1 = 'b.vim:value1' let s:value2 = 'b.vim:value2' function! s:get_value() return s:value2 endfunction echo GetValue() " => a.vim:value1 call HookFunc(GetFunc(fnamemodify("a.vim", ":p"), "get_value"), GetFunc(expand("%:p"), "get_value")) echo GetValue() " => b.vim:value2 (not "a.vim:value2")
これではスクリプトローカルな変数を参照する関数は外から書き換えられない。非常に残念。
もっと簡単に書き換えようと以下のような物まで書いてたのに(書いてる途中でこの事実に気付いた)。
" hookfunc.vim command! -nargs=+ Hookfunc execute s:hookfunc(<q-args>) function! s:get_script_id(fname) let snlist = '' redir => snlist silent! scriptnames redir END for line in split(tolower(substitute(snlist, '\\', '/', 'g')), "\n") if line =~? '\V' . a:fname . '\$' return matchstr(line, '^\s*\zs\d\+') endif endfor endfunction function! s:hookfunc(args) let [file, func] = split(a:args, ':') return 'function! <SNR>' . s:get_script_id(file) . '_' . func endfunction " ------------------------------------------------------------------ function! s:hoge(text) echo "Hello, " . a:text endfunction call s:hoge('world.') " => Hello, world. Hookfunc hookfunc.vim:hoge(text) echo "Goodbye, " . a:text endfunction call s:hoge('world.') " => Goodbye, world.
Vim の深淵は深すぎて覗き込もうとすると思わぬ怪我をするので気を付けましょう。