ctagsと連携するように環境を構築する

[実践Vim](http://tatsu-zine.com/books/practical-vim)読みました。
達人出版会さんからpdf版が発売されてるのでそちらがおすすめです。何やらAmazonと比べて600円ぐらい安いようですね。

その中の

> 第6部 ツール
> 第16章 ctagsを使ってソースコードのインデックスを作成し、ナビゲーションを行う
> TIP102： ctagsと連携するようにVimを構成する

の所を掘り下げて見ようと。元々は「Vimを構成する」ですがすでにvimを使いこなす時の環境構築になってしまうのかなと思い少しタイトルを広くとらえる形にしました。

# ctagsってなに
まずctagsの説明ですが、実践vimの言葉を引用すると

> ctagsは、コードベースを走査し、キーワードのインデックスを作成する外部プログラムだ。

てやつで、そのctagsを使って生成されたtagsファイルを使う事によってキーワードの宣言元へ移動したりキーワードの補完をする事が出来ます。IDEで標準的に実装されてる機能が当たり前に使えるようになります。

# ctagsのインストール

debian系

    sudo apt-get install exuberant-ctags

mac

    brew install ctags

macでは標準でctagsが入っているけどBSD版なので対応言語が少なかったりオプションが違ったりするのでインストールしておきましょう。

# ctagsの実行方法

    ctags -R

でカレントディレクトリにtagsファイルが作成されます。
これをvimで読み込む設定にしておけばジャンプできたり補完できたりと便利になるしろもの。

# 今回考察すること

[実践Vim](http://tatsu-zine.com/books/practical-vim)の方ではプチまとめとしての`考察`の項では以下のように書かれている。

> コミットするたびにコードベースのインデックスを再作成するのがちょうどよいところを突いている。確かに、作業中のローカルコピーと、tagsファイルが分離されるが、エラーはなんとかなる。アクティブに作業しているコードは、タグを使ってナビゲーションを行いたくなることはあまりないコードだ。

僕もそう思う。

しかしそれはバージョン管理を使っていて、なおかつ分散バージョン管理、例えばGitを使っているプロジェクトにしか適応されないという問題を抱えている。

バージョン管理使うようにしたりgit使うようにすればいいじゃんって、そう思うけどもそうじゃないじゃん？やりたいこととやることが離れすぎちゃうじゃん？やる気無くなっちゃうじゃん？技術ってそうじゃないじゃん？もっと簡単に出来るようにしてインターネットでいい気分したいじゃん？いい気分してる人と仲良くしたいじゃん？なかよしインターネットしたいじゃん？もっと世界良くして行きたいじゃん？

という訳でsvn使ってる弊社でも使えるように環境構築をしてきて培ったノウハウを出して行こうかなというのが本記事の目的になります(前置き長過ぎ..)

svn使うとコミットしてもhookがホストリポジトリでしか実行されないのでローカルではctags実行できないのでそれ対応です。

# 目次

- gitのhookを利用してctags実行
- vimでファイル保存した時にctagsをバックグラウンド実行

とりあえずgitのhookを利用してのctags実行と、vimでファイル保存時にctags実行の二段構えで行くという考え。git使ってるならhook使えば良いしvimで保存時に作るようにしちゃえばどの環境でも大抵使えるからいいっすよねって感じで〜感じで〜

## gitのhookを利用してctags実行

vim強であるtpope氏のブログ記事が参考になる。
[Effortless Ctags with Git](http://tbaggery.com/2011/08/08/effortless-ctags-with-git.html)

というかこれだけだと解りづらいので自分が過去に書いた記事を引用
[gitのhookでtags作成](http://qiita.com/soramugi/items/9a3687bb81ce35e3f99a)

`git checkout`したり`git clone`したり`git merge`したり`git commit`した時にctagsのコマンド実行をさせる

まずはhookで実行させるスクリプトの作成

    mkdir -p .git_tmp/hooks
    touch .git_tmp/hooks/post-commit # git commit hook
    touch .git_tmp/hooks/post-merge # git merge, git pull hook
    touch .git_tmp/hooks/post-checkout # git checkout hook
    touch .git_tmp/hooks/ctags
    chmod +x .git_tmp/hooks/*

```post-系
#!/bin/sh
.git/hooks/ctags >/dev/null 2>&1 &
```

```ctags
rm tags
/usr/local/bin/ctags --tag-relative --recurse --sort=yes  --append=no
```

とする。ctagsのパスとかは別途設定してくだしあ。

ctagsのオプションを軽く説明すると
- `--tag-relative` 作成されるtagsファイル内のキーワードのパスが相対パスに
- `--recurse` ディレクトリを再起的に
- `--sort=yes` 作成されたキーワードをsortする
- `--append=no` 既存のタグファイルに追加しない

あとはgitを使う時に作成したhookを共通して使うように設定してあげる

    git config --global init.templatedir '.git_tmp'

これで、次からcloneするgitリポジトリはhookが反映される。
vimを開けばタグジャンプだったり補完だったりが「vimの標準機能のみで」実行することができる。


ここからは好みだが`.git`ディレクトリ下にtagsファイルを作成する方法もある。
そうすればいちいち`.gitignore`の指定をしなくてすんだり、tagsの変更分をコミットしたりしなくてすむ。
`.git`以下に作ってしまうともし閲覧する必要が出てきた時に別のファイルを削除してしまった場合等を考えて設定してみてほしい。考え過ぎかもしれないが。

その場合は以下になる

```ctags
rm .git/tags
/usr/local/bin/ctags --tag-relative --recurse --sort=yes  --append=no -f .git/tags
```

あとは`.vimrc`に以下のようにtagsファイルを指定してあげる

```.vimrc
set tags+=.git/tags
```

[fugitive.vim](https://github.com/tpope/vim-fugitive)を使っていれば標準で`.git/tags`を見るように設定されている。

## ファイル保存時にctags実行

`.vimrc`にファイル保存時に作成する設定をしても良いが、あまりにもソースコードの行数が多かったりするとctagsプロセスが終了する時間がかかってしまう。
なのでバックグラウンドで実行する設定にする必要がある、なおかつバックグラウンドで実行したとしても、頻繁に保存した時にctagsプロセスが多重起動してしまった時が厄介で作成されるtagsファイルのフォーマットが崩れてしまうので作成しなおす必要が出てくる。ああ厄介だーどうしようー

と、そんなこともあろうかとctagsを保存時に実行する[auto-ctags.vim](https://github.com/soramugi/auto-ctags.vim)というプラグインを作成しておいたので問題はなかった。(宣伝)

インストールをして

```.vimrc
NeoBundle 'soramugi/auto-ctags.vim'
```

vimを開いて以下のコマンドを打ち込めばtagsファイルが作成される

    :Ctags

`.vimrc`に以下の設定をしてやれば保存時に勝手にtagsファイルが作成されます。

```.vimrc
let g:auto_ctags = 1
```

格納ディレクトリも指定できます

```.vimrc
let g:auto_ctags_directory_list = ['.git', '.svn']
```

tagsファイルを読み込む設定はしていないので、自分が設定したディレクトリパスを指定してあげてください。こんな感じで

```.vimrc
set tags+=.svn/tags
```

使い方はここら辺とかに乗ってるんじゃないかな(ほじ(宣伝))
[tagsファイルを作成する「auto-ctags.vim」作った](http://soramugi.hateblo.jp/entry/2013/12/01/150433)


# まとめ

結構長くなった。。

以上でgitを使っていてコミットした時にtagsファイルを作成したり、ファイルを保存した時にtagsファイルを作成する環境を構築する方法でした。

元々は自分が過去に書いた記事
[ctagsをちゃんと使う](http://qiita.com/soramugi/items/7014c866b705e2cd0b95)が結構見られてるみたいで、そういう需要があるのではないかと思いまとめてみた次第です。書いた時から色々得た知識もありますしね。
でもあんまりctagsの記事を見ないのですが他のvim強の方達は他の方法を取っているのかも？あんまりタグジャンプしないのかな。

タグジャンプはすげー便利な機能だと思っているのでもっと簡単に使えればいいなと思いプラグイン作った次第です。よければ使ってやって下せえ。

あと実践vim面白いよ！

enjoy the vim!