ctags と neocomplcache と unite-tag を使って関数定義箇所を開く
ちと今まで敬遠しがちだった ctags を真面目に使ってみました。
neocomplcahce と unite-tag を利用します。
ほとんど処理が neocomplcache と unite-tag で完結しているので実際はそんなに難しくなかったですね。
[Vimプラグイン]
NeoBundle "git://github.com/Shougo/neocomplcache.git" NeoBundle "git://github.com/tsukkee/unite-tag.git"
[vimrc]
" path にヘッダーファイルのディレクトリを追加することで " neocomplcache が include 時に tag ファイルを作成してくれる set path+=$LIBSTDCPP set path+=$BOOST_LATEST_ROOT " neocomplcache が作成した tag ファイルのパスを tags に追加する function! s:TagsUpdate() " include している tag ファイルが毎回同じとは限らないので毎回初期化 setlocal tags= for filename in neocomplcache#sources#include_complete#get_include_files(bufnr('%')) execute "setlocal tags+=".neocomplcache#cache#encode_name('tags_output', filename) endfor endfunction command! \ -nargs=? PopupTags \ call <SID>TagsUpdate() \ |Unite tag:<args> function! s:get_func_name(word) let end = match(a:word, '<\|[\|(') return end == -1 ? a:word : a:word[ : end-1 ] endfunction " カーソル下のワード(word)で絞り込み noremap <silent> g<C-]> :<C-u>execute "PopupTags ".expand('<cword>')<CR> " カーソル下のワード(WORD)で ( か < か [ までが現れるまでで絞り込み " 例) " boost::array<std::stirng... → boost::array で絞り込み noremap <silent> G<C-]> :<C-u>execute "PopupTags " \.substitute(<SID>get_func_name(expand('<cWORD>')), '\:', '\\\:', "g")<CR>
[使い方]
:PopupTags {関数名}
neocomplcache が現在のバッファと include しているヘッダーファイルの tag ファイルを作成してくれるのでそれを利用します。
これで明示的に ctags コマンドを使用する事がなくなります。
あとは unite-tag が tag の出力処理を行ってくれるので、関数名を unite-tag に渡して unite.vim に出力します。
include しているヘッダーファイルのみ出力するので素晴らしいですね。
また unite-tag は最初に非同期でキャッシングを行うの出力されるまでに時間がかかります。
上記の設定の場合の時に g
ちなみに neocomplcache の場合は :NeoComplCacheCachingInclude で再キャッシングを行います。
最初の tag ファイルの作成は結構重い処理なので(特に Boost 等を使用する場合は)注意して下さい。
また、この時に同名の関数も一緒に出力されてしまいますが、ファイル名等も出力されるので、まぁ問題ないかな。
もしくは、
" : は \: でエスケープ Unite tag:boost\:\:array
のように namespace 名を一緒に渡すことで boost::array が絞りこまれます。
[:Popuptags boost\:\:array]
上記の Vim script であれば G
[注意]
同じファイルに同名の関数が存在する場合、名前空間で区切ってもうまく列挙がされないことがあります。
[exmaple]
namespace hoge{ void func(){} } // namespace hoge namespace foo{ void func(){} } // namespace foo int main(){ // Unite tag:foo\:\:func すると hoge::func が列挙される return 0; }
上記の場合であれば、
:Unite tag:func
といった感じで関数名だけを渡せば foo::func と hoge::func が出力されます。