at posts/single.html

ソースコードを快適に読むための GNU GLOBAL 入門 (中編)

前編では GNU GLOBAL のインストールからコマンドラインでの global コマンドの使い方までを説明した。 中編ではエディタ (vim) と連携させる方法について。 Emacs を使っている人は「gtags emacs」で検索してみてください。ごめんなさい。

使い方 (3) - vim エディタから使う

事前の準備

vim から GNU GLOBAL を呼び出すためのプラグイン (gtags.vim) を設定する。 プラグインはGNU GLOBAL の share ディレクトリに入っている。 MacPort を使った場合は /opt/local/share/gtags。 Linuxだと /usr/share/gtags かな。 gtags.vim を、ホームディレクトリの .vim/plugin にコピーする。

$ mkdir -p $HOME/.vim/plugin
$ cp /opt/local/share/gtags/gtags.vim $HOME/.vim/plugin

これで準備完了。

基本的な使い方 (:Gtagsコマンド)

vim から GNU GLOBAL を呼び出すには :Gtags コマンドを使う。 先ほどと同じように ruby-1.9.1 のソースコードディレクトリに移動し、 vim を起動する。 ファイルは開いていても、開いていなくてもどちらでも OK 。

試しに、 rb_str_length 関数へジャンプしてみる。 vim で「:Gtags rb_str_length」と入力する。

GNU GLOBAL with vim (1)

エンターキーを押すと、 rb_str_length 関数が定義されている scring.c が自動的に開いて、さらに関数の位置までジャンプしてくれる。

GNU GLOBAL with vim (2)

この関数が使われている箇所へジャンプするには、 -r オプションを付けて「:Gtags -r rb_str_length」と入力する。

GNU GLOBAL with vim (3)

気がついたかもしれないけど、 vim での :Gtags コマンドの使い方は、コマンドラインの global と同じ。

:Gtags 関数名関数名 → ソースコード(定義)
:Gtags -r 関数名関数名 → ソースコード(参照)
:Gtags -f ファイル名ソースコード → 関数一覧
:Gtags -g 検索文字列ソースコードの grep

正規表現も使えるので、「:Gtags rb_str+」で rb_str で始まる関数の一覧を表示できる。

GNU GLOBAL with vim (4)

また、「:Gtags -f string.c」で、 string.c で定義されている関数一覧が表示される。 すでに string.c を開いていれば「:Gtags -f %」で OK (% は現在開いているファイル名に置き換えられる)。

GNU GLOBAL with vim (5)

検索結果から複数のファイルへ次々とジャンプする (Quickfixリスト)

Gtags コマンドの検索結果は、 vim エディタの下に表示されている。

これは、 Quickfix リストという vim エディタの機能を使っている。 以下の方法で、検索結果からファイルへジャンプできる。

  1. CTRL キーを押しながら w キーを2回押すと、カーソルキーが Quickfix リストに移動する
  2. Quickfix リストで目的のソースへカーソルを移動してエンターキーを押すと、上部のウインドウにその箇所が表示される

Quickfix ウインドウへカーソルを切り替えるのが面倒な場合は、 :cn と :cp コマンドが使える。

:cn次の検索結果へジャンプする
:cp前の検索結果へジャンプする

でも、 :cp や :cp と入力するのも面倒なので、 $HOME/.vimrc に以下のように設定しておく。

map <C-n> :cn<CR>
map <C-p> :cp<CR>

<C-n> は Ctrl + n を表している。 Ctrl + n キーを押すと、 :cn と入力してエンターキーを押すよっていう意味。 これで、 Ctrl + n で次の検索結果へジャンプし、 Ctrl + p で前の検索結果にジャンプできるので快適になった。

カーソル位置の関数を検索する (:GtagsCursorコマンド)

基本的な使い方を覚えたので、次はもっと便利な :GtagsCursor コマンドについて。:GtagsCursor はカーソル位置の単語で検索して、検索結果へジャンプしてくれるコマンド。 「Eclipse の F3 キー」みたいなことができるようになる。

たとえば、 rb_str_length 関数の中では str_strlen 関数が呼ばれている。 この関数へジャンプしたいと思ったら、 str_strlen にカーソルを合わせて「:GtagsCursor」と入力する。

GNU GLOBAL with vim (6)

すると、 str_strlen 関数の定義箇所へジャンプしてくれる。

GNU GLOBAL with vim (7)

関数の定義箇所で :GtagsCursor コマンドを実行すると、こんどはその関数が参照されている箇所へとジャンプする。

GNU GLOBAL with vim (8)

つまり「定義→参照」と「参照→定義」という動作になっている。

いちいち「:GtagsCursor」と入力するのは面倒なので、やっぱり $HOME/.vimrc にショートカットを定義しておく。 ここでは、 Ctrl+J に割り振ってみた。

map <C-j> :GtagsCursor<CR>
ショートカットのまとめ

僕は .vim に以下のように指定している。

map <C-g> :Gtags 
map <C-i> :Gtags -f %<CR>
map <C-j> :GtagsCursor<CR>
map <C-n> :cn<CR>
map <C-p> :cp<CR>

ショートカットは以下のようになる。

Ctrl+G:Gtags と入力する
Ctrl+I開いているファイルに定義されている関数の一覧を表示
Ctrl+Jカーソル位置の関数へジャンプ
Ctrl+N次の検索結果へジャンプする
Ctrl+P前の検索結果へジャンプする

ソースを読むときは、以下のようにしている。

  1. 読みたいファイルを開く
  2. Ctrl+I でそのファイルの関数一覧を表示し、 Ctrl+N や Ctrl+P を使って関数単位で移動する
  3. ソースコードの中で知らない関数があったら、 Ctrl+J を使って定義箇所へジャンプする
  4. より詳しく調べたい場合は「:Gtags -g 検索文字列」を使う (:Gtags は Ctrl+G で入力)

これまでの「grepで検索してソースファイルを特定」→「vim でソースファイルを開く」→「vim 内で検索して目的の行へ移動」→「vim を閉じる」→「grepで検索してソースファイルを特定」…のループに比べたら格段に効率がアップしたよ。

つづき

関連する日記