Clojure の開発で gtags を使う
えっと Emacs/Cider ユーザーにはあまり関係ないですね。あと他のエディタや IDE で定義ジャンプ出来る人はいらないと思う。
僕はこの前から inf-clojure を使っているので、これが欲しかった。あと例えば他のエディタや IDE で defxxxx なマクロを使っていると定義ジャンプ出来ないシーンがある気がしたので*1、どうせなのでそのへんまとめていい感じにしようかなと思った。
必要なもの
- Exuberant Ctags
- GNU GLOBAL v6.3.2 以降
以下の記事が詳しいので、参照してインストールしましょう。
gtags - GNU GLOBALの対応言語を大幅に増やすPygmentsパーサーを導入する - Qiita
ctags の設定
Exuberant Ctags は Clojure に対応していないので、このまま使うと定義タグの生成が出来ずに定義ジャンプが出来ない。シンボルタグだけは上記の記事の通りにやれば生成出来るのだけど、検索対象が山のようになるだけで使い勝手悪いどころの騒ぎではないので、定義タグを作れるようにする。
~/.ctags を作って以下の設定を書く。
--langdef=Clojure --langmap=Clojure:.clj --langmap=Clojure:+.cljs --langmap=Clojure:+.cljx --regex-clojure=/\([ \t]*create-ns[ \t]+([-[:alnum:]*+!_:\/.?]+)/\1/n,namespace/ --regex-clojure=/\([ \t]*def[ \t]+([-[:alnum:]*+!_:\/.?]+)/\1/d,definition/ --regex-clojure=/\([ \t]*def[a-z]*[ \t]+([-[:alnum:]*+!_:\/.?]+)/\1/d,definition/ --regex-clojure=/\([ \t]*defn[ \t]+([-[:alnum:]*+!_:\/.?]+)/\1/f,function/ --regex-clojure=/\([ \t]*defn-[ \t]+([-[:alnum:]*+!_:\/.?]+)/\1/p,private function/ --regex-clojure=/\([ \t]*defmacro[ \t]+([-[:alnum:]*+!_:\/.?]+)/\1/m,macro/ --regex-clojure=/\([ \t]*definline[ \t]+([-[:alnum:]*+!_:\/.?]+)/\1/i,inline/ --regex-clojure=/\([ \t]*defmulti[ \t]+([-[:alnum:]*+!_:\/.?]+)/\1/a,multimethod definition/ --regex-clojure=/\([ \t]*defmethod[ \t]+([-[:alnum:]*+!_:\/.?]+)/\1/b,multimethod instance/ --regex-clojure=/\([ \t]*defonce[ \t]+([-[:alnum:]*+!_:\/.?]+)/\1/c,definition (once)/ --regex-clojure=/\([ \t]*defstruct[ \t]+([-[:alnum:]*+!_:\/.?]+)/\1/s,struct/ --regex-clojure=/\([ \t]*intern[ \t]+([-[:alnum:]*+!_:\/.?]+)/\1/v,intern/ --regex-clojure=/\([ \t]*ns[ \t]+([-[:alnum:]*+!_:\/.?]+)/\1/n,namespace/
元ネタは以下の設定だけど、元のやつだと defxxxx マクロで定義したシンボルを定義タグとして作成してくれないので少しだけ細工した。
my .ctags(exuberant-ctags) for Clojure
gtags の設定
以下の記事では Lisp の設定を乗っ取る形で実現しているけど、 GLOBAL の v3.6.2 以降だとデフォルトで Clojure サポートがあるはずなのでそちらを修正するようにする。
gtagsでClojureのコードのタグ付け - iwasakimsの日記
$ cp /usr/local/share/gtags/gtags.conf ~/.globalrc
とコピーしたら .globalrc を以下のように修正する
$ diff /usr/local/share/gtags/gtags.conf ~/.globalrc 28c28 < :tc=native: --- > :tc=native:tc=pygments: 170c170 < :langmap=Clojure\:.clj:\ --- > :langmap=Clojure\:.clj.cljs.cljx:\
ふたつ変更点があって、ひとつは default でも pygments を使う設定、ふたつめは cljs/cljx という拡張子に対応するため。
これだけ設定したら後はプロジェクトルートで gtags と実行するだけでいいわけです*2。
おまけ
Emacs ユーザーなら helm-gtags.el を使って幸せになりましょう。
syohex/emacs-helm-gtags · GitHub
むしろこれがあるから gtags を使えるようにしようと思ったくらい。
余談
Exuberant Ctags の後続プロジェクトというか fork した(?)プロジェクトで Universal Ctags というのがあるらしくて、それはデフォルトで Clojure をサポートしているんだけどパーサーが適当すぎて ns, defn, quote しかサポートしてないという。
これを使った場合でも同様に .ctags に設定書けば解決するんだけど、まぁ結局同じような内容書くならどっちでもいいよねという感じはある。
universal-ctags/ctags · GitHub