【vim】ctagsでクラスや関数の定義箇所へ移動する
問題
VSCodeやeclipseにある、クラス名や関数から定義元を開く機能はvimにはないですか。
答え
ctagsを利用する。
ctags コマンドは、関数の定義元などを解析してインデックス(タグファイル tags)を作成してくれる。vimはこのtagsを利用できる。
インストール
Debian、Ubuntu
apt install universal-ctags ← こちらを推奨
apt install exuberant-ctags ← 使えるが開発が2009年で止まっている
CentOS
yum install ctags
ctagsコマンドの設定
exuberant-ctags なら ~/.ctags
universal-ctags なら ~/.config/ctags/*.ctags を作成して、以下のような形で設定(オプション)を書く。
--recurse=yes --php-kinds=cfd
デフォルトで -R(--recurse=yes 再帰的に)などが指定されていないらしいので、.ctagsで設定するか、都度コマンドラインオプションで指定する。
プログラムの言語、タグにする種別など設定する。--php-kinds=cfd とすると、phpのときclassとfunctionとdefineを拾ってくれる。
対応している言語、kindの確認方法。
ctags --list-kinds
php だとデフォルトで以下が有効。
c classes d constant definitions f functions
対応している拡張子は以下で確認可能。
ctags --list-maps
解析不要なファイルは拡張子で除外が可能。
--exclude=*.js --exclude=*.css
ctagsコマンドの使い方
対象のディレクトリにて以下のコマンドを実行する(~/.ctags の設定が使われる)
ctags
tags というファイルができる。
プログラムや言語、状況に応じて、都度オプションを指定してもよい。
ctags --recurse=yes --php-kinds=cfd --exclude=*.css
vimでtagsファイルを利用する
vimで :set tags コマンドで tags オプションの設定値を確認すると、初期値で ./tags,tags などになっている。
tags=./tags,./TAGS,tags,TAGS
ctags はデフォルトで tags のファイル名でタグファイルを作ってくれるが、そのままでよいということ。
あえて違うタグファイル名にするなら :set tags=違うファイル名 で指定するとよい。
vimで定義箇所へジャンプ
ここまでくれば後は使うだけ。
- Ctrl + ]
- g + Ctrl + ](複数から選択)
- :ts (複数から選択)
- :tags タグリストを表示
- :tn 次のタグ
- :tp 前のタグ
- :ta N番目のタグ
:ta :ta[g][!] {tag} {tag}で指定したタグにジャンプ
:ta :[count]ta[g][!] タグリストの[count]番目に新しいタグにジャンプ
CTRL-] CTRL-] 変更がされていない限り、カーソル位置にあるタ
グにジャンプ
:ts :ts[elect][!] [tag] タグに合致する一覧を表示し、ジャンプ先を選択
:tjump :tj[ump][!] [tag] 指定のタグ [tag] にジャンプ。もし、合致する
タグが複数ある時は一覧から選択
:ltag :lt[ag][!] [tag] タグ [tag] にジャンプし、マッチしたタグを
locationリストに加える
:tags :tags タグリストを一覧表示
CTRL-T N CTRL-T タグリストの N 番目に古いタグにジャンプ
:po :[count]po[p][!] タグリストの [count] 番目に古いタグにジャンプ
:tnext :[count]tn[ext][!] [count] 個分、次のタグにジャンプ
:tp :[count]tp[revious][!] [count]個分、前のタグにジャンプ
:tr :[count]tr[ewind][!] [count]番目に一致するタグにジャンプ
:tl :tl[ast][!] 直前に一致したタグにジャンプ
タグの更新
とりあえず手動で実行すればtagsファイルは更新される。都度 :!ctags で実行してもよい。
自動、半自動、プログラムを書き換えた都度、vimの中から実行などでタグファイルを再構築させたい場合は、ctags関連のプラグインを探すとよい。 → vim-tagsプラグイン
プラグインを使わないでタグを自動更新
phpファイルを保存するたびに ctags コマンドを実行させたい場合、以下のように書ける。
:autocmd BufWritePost *.php silent !ctags
カレントディレクトリにtagsファイルが存在するときに限定してctagsを実行してもらうようにした例。.vimrc に書く。
if filewritable('./tags')
augroup myautocmd
autocmd!
autocmd BufWritePost *.php silent !ctags --recurse=yes &
augroup END
endif