Vim プラグイン紹介第四弾です。どうですか、飽きてきましたか? 私は飽きてきましよ(ぉ。
Quickfix の次は Cscope です。例によってソースは以下に。
https://bitbucket.org/anyakichi/vim-csutil
内容としてもたいしたことはないです。だいたい以下の通り。
- ファイルのあるパスから cscope.out の自動検索(tags=./tags;/ 的な)
- 各種キーマッピングの定義
似たようなものに autoload_cscope.vim というのも既にあるんですが、中身を近代的な感じにしつつちょっと拡張したくらいのものです。
cscope の説明に入る前に、まずは私の .vimrc の cscope 周辺を掲載しておきます。前回紹介した qfutil も少し絡んでいます(cscope の結果を quickfix や location list に出せる機能があるのだが、これをトグル対象にできるようにしている)。
set cscopetag
set cscopetagorder=1
set cscopequickfix=s-,c-,d-,i-,t-,e-
nmap <C-\><C-\> <Plug>(csutil-toggle-csto)
for type in ['s', 'g', 'd', 'c', 't', 'e']
let mapping = '<C-\>' . type
let target = ':<C-u>call csutil#find("<cword>", "' . type .
\ '", qfutil#_mode())<CR>'
execute 'nnoremap' '<silent>' mapping target
endfor
for type in ['f', 'i']
let mapping = '<C-\>' . type
let target = ':<C-u>call csutil#find("<cfile>", "' . type .
\ '", qfutil#_mode())<CR>'
execute 'nnoremap' '<silent>' mapping target
endfor
cscope は、ソースコードを静的解析して、簡単に関数や変数の定義にジャンプするためのものです。ctags とも少なからず役割が被ります。
ctags と比較した cscope の利点としては、
- 関数の定義位置だけでなく呼び出し元のへのジャンプなどもできる
- 検索インデックスを使用した高速な検索
というあたりでしょうか。C(C++ も?)を対象に絞っているだけに、より詳細なソースコード解析をしている・・・ということだと思います。ただしジャンプは速いには速いのですが、構造体の定義の検索などでは思ったところに飛んでくれないことも多く、私の場合最近はマシンがそれほど遅くない場合には ctags の方を使ってしまっています(cscopetagorder=1 にしている)。
以下、簡単なチュートリアルをば。例によって NetBSD ソースツリーの sys 以下にいるとしましょう。ここで以下のようなコマンドを叩くと、このディレクトリ以下のファイルのデータベースを作ってくれます。

次に、netinet ディレクトリに移動して、tcp_usrreq.c というファイルを開いてみます。

ここで、1 階層手前の cscope.out を自動的に読み込んでくれるため、ファイルを開いた後はすぐに cscope の機能を使用することができます。

で、まあ例えば、ソースコードを眺めているうちに soisconnecting() という関数がここ以外にどんな文脈で使用されているのか(関数の呼び出し元)が見たいとしましょう。関数名にカーソルがある状態で C-\ c とタイプします。

すると uipc_usrreq.c という関数内の、soisconnecting() の呼び出し位置にジャンプしました。ここで q. で location list window を開いてみます。

あとは前回 qfutil で書いたのと同様、C-j/C-k でリストの各位置を移動できます(このマッピング自体は私のカスタムですが)。
ということで、cscope は使える状態になっていればたまに役に立つのですが、標準的な状態では cscope.out の読み込み等が自動で行われないため使える状態になく、宝の持ち腐れになる率が高い機能です。csutil はこれを多少使える状態にしておくのに役立つプラグインです。