ctags
南極を含む7大陸で使用されていると評判(?)のexuberant ctagsは、
generates an index (or tag) file of language objects found in source files that allows these items to be quickly and easily located by a text editor or other utility.
とあるように、関数やクラス定義のインデックスを生成し、エディタ機能で容易にその定義位置にジャンプしたり、定義ファイルを開いたりするためのユーティリティです。
41の言語にデフォルトで対応しているとのことですが、Elixirは入っていません。
が、インデックスしたい定義の正規表現を登録することで、(大雑把になら)簡単に別言語ファイルに対応できます。
使い方
$ cd project_root
$ ctags -R [paths]
tags
というファイルが生成され、中に関数やクラスが列挙されていればOK.
設定ファイルは~/.ctags
という名前でホームディレクトリにおきます。
Elixir
mmorearty/elixir-ctagsで公開されています。
--langdef=Elixir
--langmap=Elixir:.ex.exs
--regex-Elixir=/^[ \t]*def(p?)[ \t]+([a-z_][a-zA-Z0-9_?!]*)/\2/f,functions,functions (def ...)/
...
--regex-<langdef>
の行は、/<regex>/<capture>/<label>/
という構造になっているようです。ドキュメントはあまり詳細ではないですが、生成されたtags
ファイルを見るとなんとなくわかります。
上記例の場合、(p?)
と([a-z_][a-zA-Z0-9_?!]*)
でキャプチャが2箇所あり、実際にインデックスされて欲しい関数名の方は2番めなので、<capture>
項に\2
を指定します。
Atom Editorで「定義にジャンプ」
ビルトインのsymbols-viewパッケージが担当しています。
単語を選択(OSXならcmd-d
、あるいはctrl-shift-W
)して、alt-cmd-down
でジャンプできます。alt-cmd-up
で元のファイルの元の位置に戻れます。
が、このストロークは複雑なのと、選択した単語がインデックスに存在していても、ジャンプが効かないケースがあります。
(例えばNested.Module
でNested
部分を選択してジャンプしようとする場合。symbols-view側の仕様?)
どちらかと言うと、ファイル内であればcmd-r
、プロジェクト全体であればshift-cmd-R
を使って、検索モーダルから探すほうが直観的かもしれません。個人的にはこちらを多用しています。
goto
ctagsを使わず独自にインデックスを(in-memoryで)自動構築してジャンプを行うgotoというパッケージもあり、symbols-viewを代替できるようです。手動でctagsコマンドを叩く手間が省けてお手軽ですが、まだ試してはいません。
ただ、ctagsを介しておけばvimやEmacsでも同じインデックスを使い回せる利点があるので、どちらが良いかは好みと状況によるでしょう。
Tips
以下おまけ。
インデックス生成
たまに手動でコマンドを叩くだけですが、面倒ですよね。自動でやらせたい。"ctagsと連携するように環境を構築する"も参考に。
- git hookで好きなタイミングで実行させる。
-
post-commit
,post-merge
,post-checkout
あたりか。
-
- npm scriptsやgulpでwatchしているプロジェクトであれば、適当なスクリプトに
ctags
呼び出しを絡ませておく。- ctags自体は単純なシロモノなので高速ですが、走査するファイル量によるので、
[paths]
引数で適宜範囲指定。 -
deps
とか、node_modules
とかは最初から含めないのがよさげ。
- ctags自体は単純なシロモノなので高速ですが、走査するファイル量によるので、
-
mix-test.watchを使っているのなら、
System.cmd/3
とかでctagsを呼び出すMix taskを作っておいて、configで指定する。- 試してはいません。でもできるはず。
- ファイル保存時にコマンドを実行する系のAtomパッケージでフックする。
- save-autorunやsave-commandsなどがある模様。試してみる予定。
エディタ等ローカル開発環境周りの設定事項はできればGitに入ってプロジェクトで共有されるファイルでは設定したくないので、1か4が有望そうです。
tags
ファイルはglobal ignore
同様に、頻繁に更新されることになるtags
ファイルもGitには入れたくありません。が、同名のファイルが複数プロジェクトで生成されるので、いちいち.gitignore
に書かせてもらうのは忍びない。
global ignoreに入れておくのがよさそうです。
Scala
他の未対応言語ももちろんカバーできます。
Scalaならこちらのgistが参考になります。
--langdef=scala
--langmap=scala:.scala
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*(private|protected)?[ \t]*class[ \t]+([a-zA-Z0-9_]+)/\4/c,classes/
...
SBTを使っている場合、sbt-ctagsというプラグインを使うとビルド時に生成可能のようです。~/.ctags
は必要です。
筆者設定
gistで公開しています。skirino/cromaのdefun
シリーズにも対応。