Someone on gnu.emacs.help asked if there was a way to browse through multiple matching tags for an identifier and choose a specific one (as opposed to tags-loop-continue). This is helpful when you have overloaded function names and want to go to the right one. I am using an aspect-oriented language (Specman) that extends methods all over the place, so this was something I’ve been thinking about doing for a while. So I finally took a couple hours and did it.
I have integrated this patch after having used it for a month and it works fine imo. It adds TAB completion just like find-tag has. - MartinNordholts
Tag completion been updated to work on Emacs/XEmacs. - ScottFrazer
On Emacs 22.2.1, I get “Buffer is read-only error” when I press return. - bvk-chaitanya
Do you have some hook or minor-mode that overrides ‘return’ for all modes? - ScottFrazer
I ran into the “Buffer is read-only error” also, on Emacs 24.1.1, but only when launching Emacs in the terminal (emacs-nox), not in an X-window. The difference must be in how the terminal passes input events to emacs. It turns out that the RETURN key was not recognized in etags-select’s mode-map. It’s the same “error” you would receive by pressing a non-mapped key such as “z” in the etags-select window. I fixed it by changing the following:
(define-key map (kbd "RET") 'etags-select-goto-tag)
(define-key map (kbd "M-RET") 'etags-select-goto-tag-other-window)
To find tags in a included tags file, such as TAGS-LISP for Emacs Lisp, re-define
(defun etags-select-get-tag-files () "Get tag files." (if etags-select-use-xemacs-etags-p (buffer-tag-table-list) (mapcar 'tags-expand-table-name tags-table-list) (tags-table-check-computed-list) tags-table-computed-list))
I was running into an error “wrong-type-argument stringp t” only the first time per session that I followed a tag. It turned out to originate from tags-table-computed-list having an element that was t, not a proper filename. Apparently t is used as an initial placeholder for unloaded tables (I use an externally-referenced TAGS table.) See the documentation for tags-table-extend-computed-list for more details. So I added the following line to the extended version of etags-select-get-tag-files above:
etags-select.el provide a bottom window for select
But sometimes, the select info is too short (e.g. struct abc under different #define condition). So a preview window besides select window will be helpful.
Vim has a nice feature where you can indicate that you would like the editor to search up the directory tree from the current working directory for a file named “tags”. These two functions provide that for etags-select.el, searching up the filesystem from the buffer-file-name of the current buffer. (Modified version from EmacsTags)
;;load the etags-select.el source code (load-file "path/to/etags-select.el") ;;binding the key (global-set-key "\M-?" 'etags-select-find-tag-at-point) (global-set-key "\M-." 'etags-select-find-tag) (defun jds-find-tags-file () "recursively searches each parent directory for a file named 'TAGS' and returns the path to that file or nil if a tags file is not found. Returns nil if the buffer is not visiting a file" (progn (defun find-tags-file-r (path) "find the tags file from the parent directories" (let* ((parent (file-name-directory path)) (possible-tags-file (concat parent "TAGS"))) (cond ((file-exists-p possible-tags-file) (throw 'found-it possible-tags-file)) ((string= "/TAGS" possible-tags-file) (error "no tags file found")) (t (find-tags-file-r (directory-file-name parent)))))) (if (buffer-file-name) (catch 'found-it (find-tags-file-r (buffer-file-name))) (error "buffer is not visiting a file")))) (defun jds-set-tags-file-path () "calls `jds-find-tags-file' to recursively search up the directory tree to find a file named 'TAGS'. If found, set 'tags-table-list' with that path as an argument otherwise raises an error." (interactive) (setq tags-table-list (cons (jds-find-tags-file) tags-table-list))) ;; delay search the TAGS file after open the source file (add-hook 'emacs-startup-hook '(lambda () (jds-set-tags-file-path)))
I love etags-select, but I also really like ido’s fuzzy matching, so I mixed the two. Based on a contribution on the InteractivelyDoThings page, I came up with this function:
;; Use ido to list tags, but then select via etags-select (best of both worlds!) (defun my-ido-find-tag () "Find a tag using ido" (interactive) (tags-completion-table) (let (tag-names) (mapatoms (lambda (x) (push (prin1-to-string x t) tag-names)) tags-completion-table) (etags-select-find (ido-completing-read "Tag: " tag-names)))) (global-set-key (kbd "M-.") 'my-ido-find-tag)
See Also: Icicles command
‘icicle-search-tag’. You can browse matching tags (including duplicates) in any order, and not necessarily consecutively. Very easy to filter tags to those you want to visit, using regexps; you can filter the source files to search also. Tag completion is also available.