タグファイルの階層化

上のエントリの最後に書きました様に、XEmacs では find-tag の際に、カレントディレクトリからルートディレクトリに向って、TAGS ファイルを探してくれます。そして、見付かった全ての TAGS ファイルの中から tag を探してくれます。
そのため、私の環境では、C 言語向けの TAGS ファイルについて、先ず自分の home ディレクトリに、システムのインクルードファイルを入力にして作成した TAGS ファイルを置いておき、実際に C のコードを書いたディレクトリでは、適宜、そのディレクトリ近辺の *.[ch] を入力にした TAGS が置いてあります。

システムのインクルードファイルについては、カレントディレクトリの TAGS に tag が無くても、カレントディレクトリが自分の home ディレクトリ配下であれば、どこからでも同じ TAGS ファイルを参照してタグジャンプできるという訳です。

さて、この find-tag の際の `buffer-tag-table-list' なんですが、実は、非常に嫌な問題を抱えています。上で紹介している様に、ディレクトリを遡って TAGS ファイルを探してくれるのは良いのですが、探す対象となる `TAGS' というファイル名を、何とハードコードして抱えてしまっているのです。

そうです、そのために Ruby のコードで M-. などしてタグジャンプしようとしたときに、直近の TAGS に存在しないと home ディレクトリに置いてある *C 言語の* TAGS を見て、そこに tag があるとそこに飛んでしまうのです。これがまた結構あるのですよ。

しかし、それを回避する方法もありました。鍵を握るのは `tag-table-alist' という連想リストです。
このリストに、

("\\.rb$" . "~/TAGS.d/ruby")

の様な cons cell を設定しておくことで、該当するファイル名を開いているバッファに於いては、上位ディレクトリを辿るだけではなく、指定されたディレクトリを TAGS ファイルの検索パスとして扱う様になります。

この仕組みを利用して、home ディレクトリ直下に TAGS を置くことを避け、各言語ごとに用意した特定のディレクトリにそれぞれの TAGS を置いておけば、異なる言語の TAGS ファイルを参照してしまうことを避けることができます。
私の場合はこんな感じですね。

(eval-after-load "etags"
  '(progn
     (add-to-list  'tag-table-alist
                   '("\\.rb$" . "~/TAGS.d/ruby"))
     (add-to-list  'tag-table-alist
                   '("\\.[ch]$" . "~/TAGS.d/c"))
     (add-to-list  'tag-table-alist
                   '("\\.scm$" . "~/TAGS.d/gauche"))
     (add-to-list  'tag-table-alist
                   '("\\.p[lm]$" . "~/TAGS.d/perl"))))

ふむ、もっとスマートに設定できないもんですかね。

ともあれ、この様にすることで、各言語ごとに階層化した TAGS ファイルを活用することができています。

しかし、C なんかは良いんですけど、RubyPerl などは、/usr/lib/{ruby,perl} 配下に置いてある様なファイルへの tag があったとしても、適切な tag にジャンプできることは少ないんですよね。find-tag が class や module を意識できないことには、数ある同名のメソッドを順に M-, で探して行かなければなりません。
RubyPerl では、オブジェクトの型を識別するのは無理でしょうから、せめて require や include, use などを見て、バッファ上のコードに関連するファイルを拾うとかでしょうかね。
こいつが解決できたら随分と快適になるとは思うのですが……

今のところは思っているだけです。