Vim script で namespace る
この記事は Vim Advent Calendar 2012 279日目の記事になります。
さて、Vim script の autoload 関数を使用(定義)する場合、次のような名前空間(ディレクトリパス)を # で区切って使用します。
call unite#custom#default_action('directory' , 'tabvimfiler') call unite#custom#default_action('qfixhowm' , 'tabopen') call unite#custom#source('qfixhowm', 'sorters', ['sorter_qfixhowm_updatetime', 'sorter_reverse']) call unite#custom#source('quickfix', 'converters', 'converter_quickfix_highlight') call unite#custom#source('location_list', 'converters', 'converter_quickfix_highlight')
これは他のプラグインと関数名を重複してしまうのを抑制する事ができるので便利なのですが、関数名が長くなってしまいます。
こんな時に C++ の namespace のような機能があれば…っていう事で簡単に書いてみました。
[ソース]
function! s:function() let tmpfile = tempname() let tmp = &verbosefile let &verbosefile = tmpfile try redir => flist silent function redir END finally call delete(tmpfile) let &verbosefile = tmp endtry return split(flist, "\n") endfunction function! Namespace(target, using_sharp) let target = a:target . "#" let result = {} for name in map(filter(s:function(), 'v:val =~ target'), "matchstr(v:val, '.* \\zs.*\\ze(')") if a:using_sharp let result[substitute(substitute(name, target, "", ""), '#', '_', "g")] = function(name) else let result[substitute(name, target, "", "")] = function(name) endif endfor return result endfunction command! -nargs=* -bang \ Namespace \ execute 'let ' . [<f-args>][0] . ' = Namespace([<f-args>][1], <bang>0)' function! s:main() " namespace なし call unite#custom#default_action('directory' , 'tabvimfiler') call unite#custom#default_action('qfixhowm' , 'tabopen') call unite#custom#source('qfixhowm', 'sorters', ['sorter_qfixhowm_updatetime', 'sorter_reverse']) call unite#custom#source('quickfix', 'converters', 'converter_quickfix_highlight') call unite#custom#source('location_list', 'converters', 'converter_quickfix_highlight') " namespace あり Namespace u unite#custom call u.default_action('directory' , 'tabvimfiler') call u.default_action('qfixhowm' , 'tabopen') call u.source('qfixhowm', 'sorters', ['sorter_qfixhowm_updatetime', 'sorter_reverse']) call u.source('quickfix', 'converters', 'converter_quickfix_highlight') call u.source('location_list', 'converters', 'converter_quickfix_highlight') endfunction call s:main()
:Namespace に展開する変数名と関数のプレフィックスを渡して、その変数にプレフィックス以下の関数を展開します。
ただし、# は変数名として使えなかったので _ に置き換えられています。
[注意1]
ぶっちゃけ処理速度が遅いです。
なのでどうしても必要でない場合以外は使用しないほうが無難です。
[注意2]
既に読み込まれた autoload 関数にしか使用できません。
なので使用するタイミングによっては関数が呼び出せない事があります。
[まとめ]
勢いでつくってみたんですが微妙な感じ。
コードはスッキリとするんですが多用すると遅くなってしまうのがネック…。
使うとしたらスクリプトローカルに展開するとかかなぁ。
それなら1度しか呼ばれないのでパフォーマンスもそこまで気にならないかもしれない。