auto-complete-etags.el をいじってみた。

どうもりんこ。アモバン半錠とワイパックス半錠飲んで寝たら,
3時間で起きて,で口の中が苦いので,まじぃと思ったので,
かっとなってやってみた。やってみたら,できた。


パッチ充てるのが面倒臭い人用に,最後の方に丸ごと貼り付けておきます。

TAGS ファイルから補完されている様子

  • 補完候補がどばどばと。

  • 別のタグファイル内の補完もでる。

  • 補完元の TAGS の中身を一部抜粋。きちんと補完されていますね。

  • 別のタグファイルの中身。


何をしたか?

以前は,タグファイルを指定してない状況だとタグファイルはどこだごらぁと
怒られていました。
なので,現在のバッファでタグファイルを訪れているかどうかを,
tags-file-name によって判定して補完候補を出しているだけです。
作者の Yen-Chin,Lee さんの設定色は,私の環境とは相性が悪かったので,
自分で設定しました。
そして,この tags-file-name による判定は微妙かなぁと

その理由

調べてみると,etags.el で重要そうな変数は以下。

  • tags-table-list
    • タグファイル名のリスト
    • M-x visit-tags-table してタグファイルを指定していく。
    • 再度実行して,別のタグファイルを指定するときに[y]esと答えると,リストにタグファイルが追加される。
  • tags-table-set-list
    • タグファイル名のリストのリスト。
    • 上記の指定の際に,[n]o と答えると新たなリストを作って使用するっぽい。
    • たぶん,バッファとかによって,タグファイルのリストを切り替えたりするのが想定されている使い方かな?
  • tags-file-name
    • 現在有効なタグファイル名。
      • つまり,M-. or M-x find-tag で使用するタグファイル。

さて。

auto-complete-etags.el に手を入れて,いけるじゃんこれで,
と思ったとき,ふと複数のタグファイルを持っているときには
どうなる? と思ってしまったのが,災いのもと。
複数のタグファイルを持っているとは,
tags-table-list に2個以上のファイル名が入っているということ。

今,tags-table-list => ("OLDTAGS")
で,M-x visit-tags-table NEWTAGS して,
tags-table-list => ("NEWTAGS" "OLDTAGS")
となったとします。
この状態で補完すると,あろうことか,OLDTAGS の方から補完候補がでてきてしまったのです!!
アイヤー。

どうしましょ?

ソースみましょ。ということで,etags.el を覗いてみる。
覗きが趣味の変態whitypigさんは(なんでやねん!),覗くのは好きなのです。
auto-complete-etags.el 内で使用している関数は,
tags-completion-table で,これはどばっとタグ内のエントリのテーブル返しているようです。
一部を抜粋して,ほいで,ちょっとコメントを追加したのを引用します。

;; Build tags-completion-table on demand.  The single current tags table
;; and its included tags tables (and their included tables, etc.) have
;; their tags included in the completion table.
(defun tags-completion-table ()
  (or tags-completion-table ;; <-- こいつが non-nil なのが原因。
      ;; No cached value for this buffer.
      ;; ...色々と処理がある
            (setq tags-completion-table combined-table))
        (quit (message "Tags completion table construction aborted.")
              (setq tags-completion-table nil)))))

tags-completion-table がすでに作られている場合には,あとからタグファイルをvisit
しても,効果がでないようです。
なので,let de kurunde nil nishita なんかフランス語っぽい?
すみません。
let でくるんで nil にしちゃいました。性能とかオレよくわかんねぇし。
これで,複数のタグファイルを指定してある場合に,
いいか悪いかは判断できないけども,補完候補にでてくるようになりました。
でも,どうなんだろうなぁ。果てしてこれでいいのか?
あかん気がしてきた。なので,あとで考える。
どんな状況でどんな風に使うかを考えれば,答えは出そう。

diff

--- auto-complete-etags.el	2010/03/25 00:54:05	1.1
+++ auto-complete-etags.el	2010/03/25 03:34:27	1.3
@@ -3,7 +3,7 @@
 ;; Copyright 2009 Yen-Chin,Lee
 ;;
 ;; Author: Yen-Chin,Lee
-;; Version: $Id: auto-complete-etags.el,v 1.1 2010/03/25 00:54:05 whitypig Exp $
+;; Version: $Id: auto-complete-etags.el,v 1.3 2010/03/25 03:34:27 whitypig Exp $
 ;; Keywords: 
 ;; X-URL: not distributed yet
 
@@ -30,12 +30,10 @@
 
 ;;; Code:
 
-(provide 'auto-complete-etags)
 (require 'auto-complete)
 (eval-when-compile
   (require 'cl))
 
-
 ;;;;##########################################################################
 ;;;;  User Options, Variables
 ;;;;##########################################################################
@@ -48,13 +46,18 @@
   '((t (:background "deep sky blue" :foreground "white")))
   "Face for the etags selected candidate.")
 
+(defun ac-etags-candidate ()
+  (when tags-file-name
+    (ignore-errors
+      (let ((tags-completion-table nil))
+        (all-completions ac-target (tags-completion-table))))))
+
 (defvar ac-source-etags
-  '((candidates . (lambda () 
-         (all-completions ac-target (tags-completion-table))))
+  '((candidates . ac-etags-candidate)
     (candidate-face . ac-etags-candidate-face)
     (selection-face . ac-etags-selection-face)
     (requires . 3))
   "Source for etags.")
 
-
+(provide 'auto-complete-etags)
 ;;; auto-complete-etags.el ends here

疑問

M-x visit-tags-table して NEWTAGS を同じリストに追加して,
M-. しても,NEWTAGS 内の定義にはジャンプできないんだね。
とすると,同じリストに突っ込むのはどんな状況なんだろうか。
追加しても意味がない気が・・・。
あ,1つ気付いた。

バグ

これ,別のリストにタグを突っ込んだときには,auto-complete の補完候補に
でてこないね。なんでだろ。どうすれば実現できるかな?
また,考えてみる。

まとめ

もうちょっとよく調べて,まとめてから,日記を書き始めましょう。
じゃないと書いていて,色々思いついたりするので大変です。

設定

昨日だか一昨日とほぼかぶってしまいますが。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; auto-complete mode
;; http://www.emacswiki.org/emacs/AutoComplete
;; http://cx4a.org/repo/auto-complete.git
(when (and (require 'auto-complete nil t) (require 'auto-complete-config nil t))
  (require 'ac-dabbrev)
  (require 'auto-complete-etags) ;; <-- これ追加した
  (global-auto-complete-mode t)
  (setq ac-auto-start 2)
  (set-default 'ac-sources '(ac-source-abbrev ac-source-words-in-buffer))
  (setq ac-modes (append ac-modes '(jde-mode)))
  (define-key ac-completing-map "\C-n" 'ac-next)
  (define-key ac-completing-map "\C-p" 'ac-previous)
  (define-key ac-mode-map "\C-c\C-i" 'auto-complete)
  (add-to-list 'ac-gtags-modes 'jde-mode t)
  (custom-set-faces  '(pulldown-default-face ((t (:background "slate gray" :foreground "white"))))
                     '(pulldown-default-selection-face ((t (:background "blue" :foreground "white"))))
                     '(ac-completion-face ((t (:background "blue" :foreground "white"))))
                     '(ac-candidate-face ((t (:background "slate gray" :foreground "white"))))
                     '(ac-selection-face ((t (:background "blue" :foreground "white"))))
                     '(ac-dabbrev-menu-face ((t (:background "slate gray" :foreground "white"))))
                     '(ac-dabbrev-selection-face ((t (:background "firebrick4" :foreground "white"))))
                     '(ac-gtags-candidate-face ((t (:background "slate gray" :foreground "white"))))
                     '(ac-gtags-selection-face ((t (:background "indian red" :foreground "white"))))
                     ;; この下2行でetags補完の際の色を設定
                     '(ac-etags-candidate-face ((t (:background "slate gray" :foreground "white"))))
                     '(ac-etags-selection-face ((t (:background "sienna" :foreground "white")))))
  )

まるごと(長いので注意)

;;; auto-complete-etags.el --- 

;; Copyright 2009 Yen-Chin,Lee
;;
;; Author: Yen-Chin,Lee
;; Version: $Id: auto-complete-etags.el,v 1.3 2010/03/25 03:34:27 whitypig Exp $
;; Keywords: 
;; X-URL: not distributed yet

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; if not, write to the Free Software
;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

;;; Commentary:

;; 

;; Put this file into your load-path and the following into your ~/.emacs:
;;   (require 'auto-complete-etags)

;;; Code:

(require 'auto-complete)
(eval-when-compile
  (require 'cl))

;;;;##########################################################################
;;;;  User Options, Variables
;;;;##########################################################################

(defface ac-etags-candidate-face
  '((t (:background "gainsboro" :foreground "deep sky blue")))
  "Face for etags candidate")

(defface ac-etags-selection-face
  '((t (:background "deep sky blue" :foreground "white")))
  "Face for the etags selected candidate.")

(defun ac-etags-candidate ()
  (when tags-file-name
    (ignore-errors
      (let ((tags-completion-table nil))
        (all-completions ac-target (tags-completion-table))))))

(defvar ac-source-etags
  '((candidates . ac-etags-candidate)
    (candidate-face . ac-etags-candidate-face)
    (selection-face . ac-etags-selection-face)
    (requires . 3))
  "Source for etags.")

(provide 'auto-complete-etags)
;;; auto-complete-etags.el ends here