Exuberant CtagsのJavaScript解析能力を向上させたので、それをvimのtaglist.vimに適用してみた

id:eel3:20090326:1238028321 の続編。

コードを書く時は基本的にvim*1なので、関数などのオブジェクトを一覧表示してくれるtaglist.vimを愛用している。

taglist.vimは背後でExuberant Ctagsを使っているので、ctagsの解析能力が向上すれば関数一覧に表示されるものも増えるはず……なんだけど、そこは現実社会ほどではないけど事前の根回しが重要、ということらしい。

ctagsで解析されていても、taglist.vim側で表示しないオブジェクトがある

id:m-hiyama:20080627:1214549228 にsample.jsというサンプルソースがあるけど、試しに手元のExuberant Ctags 5.7J1で「ctags sample.js」でタグを生成させたら、こんな結果になった*2

!_TAG_FILE_FORMAT	2	/extended format; --format=1 will not append ;" to lines/
!   =中略=
!_TAG_PROGRAM_VERSION	5.7J1	//
Baz	sample.js	/^function Baz(n) {$/;"	c
Baz.f5	sample.js	/^Baz.prototype.f5 = function() {$/;"	m
f1	sample.js	/^function f1() {$/;"	f
f2	sample.js	/^var f2 = function() {$/;"	f
f4	sample.js	/^  f4: function() {$/;"	m
foo.f3	sample.js	/^foo.f3 = function() {$/;"	f
g	sample.js	/^var g = 1;$/;"	v

後半に注目。行の末尾にアルファベットが1文字あるけど、これはタグ付けしたオブジェクトの種類を表すフラグ。このフラグの意味は「--list-kinds」で取得できる。

D:\temp>ctags --list-kinds=javascript
f  functions
c  classes
m  methods
v  global variables
m  methods

D:\temp>

taglist.vimは、標準だとJavaScriptのソースでは上記のfにあたるオブジェクトしか表示しない*3。それ以外も表示したい場合.vimrcないし_vimrcに設定を追加する必要があるらしい。例えばc、f、mに該当するオブジェクトを表示したい場合、.vimrcに次のように追記する。

" taglist.vim: JavaScriptの表示対象を変更
let g:tlist_javascript_settings = 'javascript;c:class;m:method;f:function'

tlist_javascript_settingsという変数を宣言して初期化している。変数名と値のフォーマットについては、taglist.vim ver.4.5の348行目以降が参考になりそう。

ctagsの「--regex-」でマッチしたオブジェクトに割り振るフラグに注意する

「--regex-」オプションのフォーマットをもう一度見てみる。

--regex-<LANG>=/regexp/replacement/[kind-spec/][flags]

この中の「kind-spec」は、「regexp」にマッチしたオブジェクトに割り振るフラグ文字を指定する。

例えばctagsで「--regex-javascript」を使う場合、

--regex-javascript=/^[ \t]*(.*)[ \t]*:[ \t]*function/\1/m,methods/

末尾側の「/m,methods/」は、

  • 正規表現にマッチしたオブジェクトのタグには、フラグ文字としてmを付加する。
  • このmはmethodsのm。

という意味になる。指定した正規表現にマッチするオブジェクトがあると、生成されるタグのフラグ文字はmになる。

なので、taglist.vimで表示するようになっていないフラグ文字を指定してしまうと、ctaqgsは該当するオブジェクトへのタグを生成するけどtaglist.vimで表示されない。

「kind-spec」には、taglist.vimで表示する設定になっているフラグを指定すること。

ctagsで同一オブジェクトへのタグを複数生成すると、taglist.vimでも同じオブジェクトが複数表示される

「--regex-」で正規表現を指定する時、ctags本体側でタグを生成するオブジェクトにもマッチしてしまうことがある。そうなると、taglist.vimの一覧表示に、同じオブジェクトが複数表示されてしまう。非常にうざい。

解決策としては2通りが思いつく。

  1. ctagsのデフォルトの機能では解析できないオブジェクトにのみマッチする正規表現を指定する。
  2. デフォルトでマッチするオブジェクトはtaglist.vim側で表示しないようにする。その代わりに、
    1. 「--regex-javascript」の正規表現でマッチするオブジェクトには、独自のフラグを指定する。
    2. taglist.vim側は、その独自のフラグがついているオブジェクトのみを表示する。

*1:でもCommon LispRubySchemeNTEmacs

*2:前のエントリで書いた「--regex-javascript」な方法を適用しているので、ノーマルなctagsとは結果が異なっているので注意。

*3:ver.4.5で確認。