この記事は 初心者C++er Advent Calendar 2017、20日目の記事です。
VimでC++のコードリーディング
私はC++の開発にVimを使用しています。
IDEにはさすがに負けるかもしれませんが、Vimでも結構快適にコードを読むことができます。
以下にVimを使用してC++のコードリーディングを行う際のTipsについて記載していきたいと思いますー。
環境
Windows 7
VIM - Vi IMproved 8.0 (2016 Sep 12, compiled May 2 2017 12:56:41)
MS-Windows 64 ビット GUI 版
適用済パッチ: 1-596
デフォルトで使用できるキーマップ
多用するのは以下です。
map | 説明 |
---|---|
[# | カーソルが#if-#endif 内ならば#if or #else にジャンプ |
]# | カーソルが#if-#endif 内ならば#else of #endif にジャンプ |
gd | 変数の定義位置にジャンプ(大抵うまくジャンプできるらしい) |
gD | 変数(global)の定義位置にジャンプ(大抵うまくジャンプできるらしい) |
[[ | 一桁目が{ の行(大抵関数の開始位置(?))にジャンプ |
]] | 一桁目が} の行(大抵関数の終了位置(?))にジャンプ |
[* or [/ | C コメントの始まり(/* )に移動します。 |
]* or ]/ | C コメントの終わり(*/ )に移動します。 |
gf | カーソル下のファイルを開く(環境によってpath の設定が必要です) |
<C-^> or <C-6> | 直前に開いたファイルを開く(厳密には違います。詳細は:h CTRL-6 ) |
このあたりのマップは実はC++用ではなくC言語用のマップかもしれません。
ただ、C++でも問題なく使用できます。
定義位置ジャンプ、参照元ジャンプ
ctags
とcscope
を使用します
Windowsの場合にctagsはここから、cscopeはここからバイナリをダウンロードできます。
ダウンロード後はパスが通っている場所に配置すればよいだけ。
あとは以下のような設定をvimrc内に記載して、少し便利にします。
(一部vim-submodeというプラグインを使用して、<C-t>と逆方向への移動を楽にしてます。)
" cscope show/killをマッピングnnoremap<Leader>zs :<C-u>cscope show<CR>nnoremap<Leader>zk :<C-u>cscope kill -1<CR>" :cscope find c <関数名> " 指定した関数を呼び出している関数を検索" :cscope find f <ファイル名> " ファイルを検索" :cscope find s <Cのシンボル> " シンボルを検索" 最後に指定する文字を大文字にするとクリップボード内の文字列を使用して:cscope findを実行します。" NOTE: @+ についてはclipboardの設定により、適宜変更してくださいnnoremap<Leader>zfc :<C-u>cscope find c<C-r>=expand('<cword>')<CR><CR>nnoremap<Leader>zfC :<C-u>cscope find c<C-r>=@+<CR><CR>nnoremap<Leader>zfs :<C-u>cscope find s <C-r>=expand('<cword>')<CR><CR>nnoremap<Leader>zfS :<C-u>cscope find s <C-r>=@+<CR><CR>nnoremap<Leader>zff :<C-u>cscope find f<C-r>=expand('<cfile>')<CR><CR>nnoremap<Leader>zfF :<C-u>cscope find f<C-r>=@+<CR><CR>" 定義位置へのジャンプ時に複数候補表示" クリップボード内の文字列使って:tjumpnnoremap<C-]>g<C-]>nnoremapg<C-]> :<C-u>tjump<C-r>=@+<CR><CR>" <C-t>と逆方向への移動をg<C-t>tttt..とできるよう設定" NOTE: <C-t>は定義への移動前にいた場所にジャンプ。" NOTE: vimデフォルトだと<C-t>の逆方向への移動用マップはない(<C-o>で逆移動っぽい動作はするが、少し違う)ので、定義call submode#enter_with('tag','n','','g<C-t>',':<C-u>tag<CR>')call submode#map('tag','n','','t',':<C-u>tag<CR>')
私の場合にはSVNの各ブランチのルートディレクトリ(.svn
or .git
ディレクトリがある場所)でctags, cscopeを実行したかったので、
以下のような設定も追加しています。
" 特定のファイルを開いた場合にはカレントディレクトリをルートディレクトリに変更function! s:root_dir() abortlet search_dir_names = ['.svn','.git']for dir_name in search_dir_nameslet ret_dir = finddir(dir_name, expand('%:p:h') . ';')if ret_dir !=''return substitute(fnamemodify(ret_dir,':p:h'), dir_name . '$','','g')endifendforreturn''endfunction
augroup cd_project_root
autocmd!
autocmd BufEnter *.cpp,*.h,*.c,silent execute 'lcd' s:root_dir()
augroup END" do ctagsfunction! s:do_ctags() abortif isdirectory('.svn')|| isdirectory('.git')if input('now: ' . getcwd() . "\nrun ctags? (y)es or (n)o : ")=~'^y$\|^yes$'silent!start ctags -Rendifelse
echohl ErrorMsg | echo 'check current dir!'| echohl noneendifendfunction" cscope build/addfunction! s:cscope_build() abortif isdirectory('.svn')|| isdirectory('.git')if input('now: ' . getcwd() . "\nrun cscope -Rb? (y)es or (n)o : ")=~'^y$\|^yes$'silent!startcscope-Rbendifelse
echohl ErrorMsg | echo 'check current dir!'| echohl noneendifendfunctionfunction! s:cscope_add() abortif(isdirectory('.svn')|| isdirectory('.git'))&& filereadable('cscope.out')cscope add cscope.out
echo "cscope add cscope.out!"else
echohl ErrorMsg | echo 'check current dir!'| echohl noneendifendfunction" ctags, cscope build/add用のマップ
nmap <Leader>ct :<C-u>call<SID>do_ctags()<CR>
nmap <Leader>zb :<C-u>call<SID>cscope_build()<CR>
nmap <Leader>za :<C-u>call<SID>cscope_add()<CR>
cscopeについて
記事を書いていく中で知ったのですが、cscopeはC言語用のパーサとして作られているようですね。。
c++でも大抵動くらしいですが、以下のような記載もあり油断は禁物らしいです。
The fuzzy parser supports C, but is flexible enough to be useful for C++ and Java, and for use as a generalized 'grep database'
現状はrtagsというのが流行っているそうですね。
どなたかWindowsでrtagsを使う方法をまとめてください(切実)
まとめ
いかがだったでしょうか?
Vimをつかえば設定しなくとも快適にコードを読めますし、設定すれば更に快適にコードを読むことができます!他のIDEの使い方がわからないだけとは言えない
また、ここでは紹介しませんが、Vimのプラグインであるunite.vimのmru, bookmark, file機能をつかえば
ファイルを開くまでの時間を短縮できますし、unite-outlineを使用すれば
ファイル内の定義の一覧を常に表示でき、VimをIDEっぽくすることもできます。
皆様もいろいろ試してみて、Vimで快適なコードリーディングを行ってみましょー!
Happy C++ Life!