(let ((completion-ignore-case (if (memq tags-case-fold-search '(t nil))
tags-case-fold-search
case-fold-search))
- (pattern (funcall (or find-tag-default-function
- (get major-mode 'find-tag-default-function)
- #'find-tag-default)))
+ (pattern (find-tag--default))
beg)
(when pattern
(save-excursion
- (forward-char (1- (length pattern)))
+ ;; Avoid end-of-buffer error.
+ (goto-char (+ (point) (length pattern) -1))
;; The find-tag function might be overly optimistic.
(when (search-backward pattern nil t)
(setq beg (point))
(let* ((completion-ignore-case (if (memq tags-case-fold-search '(t nil))
tags-case-fold-search
case-fold-search))
- (default (funcall (or find-tag-default-function
- (get major-mode 'find-tag-default-function)
- 'find-tag-default)))
+ (default (find-tag--default))
(spec (completing-read (if default
(format "%s (default %s): "
(substring string 0 (string-match "[ :]+\\'" string))
(or default (user-error "There is no default tag"))
spec)))
+(defun find-tag--default ()
+ (funcall (or find-tag-default-function
+ (get major-mode 'find-tag-default-function)
+ 'find-tag-default)))
+
(defvar last-tag nil
"Last tag found by \\[find-tag].")
(point-min) (point-max))))
(save-excursion
(goto-char (point-min))
- ;; This monster regexp matches an etags tag line.
- ;; \1 is the string to match;
- ;; \2 is not interesting;
- ;; \3 is the guessed tag name; XXX guess should be better eg DEFUN
- ;; \4 is not interesting;
- ;; \5 is the explicitly-specified tag name.
- ;; \6 is the line to start searching at;
- ;; \7 is the char to start searching at.
+ ;; This regexp matches an explicit tag name or the place where
+ ;; it would start.
(while (re-search-forward
- "^\\(\\([^\177]*[^-a-zA-Z0-9_+*$:\177]+\\)?\
-\\([-a-zA-Z0-9_+*$?:]+\\)[^-a-zA-Z0-9_+*$?:\177]*\\)\177\
-\\(\\([^\n\001]+\\)\001\\)?\\([0-9]+\\)?,\\([0-9]+\\)?\n"
+ "[\f\t\n\r()=,; ]?\177\\\(?:\\([^\n\001]+\\)\001\\)?"
nil t)
- (push (prog1 (if (match-beginning 5)
+ (push (prog1 (if (match-beginning 1)
;; There is an explicit tag name.
- (buffer-substring (match-beginning 5) (match-end 5))
- ;; No explicit tag name. Best guess.
- (buffer-substring (match-beginning 3) (match-end 3)))
+ (buffer-substring (match-beginning 1) (match-end 1))
+ ;; No explicit tag name. Backtrack a little,
+ ;; and look for the implicit one.
+ (goto-char (match-beginning 0))
+ (skip-chars-backward "^\f\t\n\r()=,; ")
+ (prog1
+ (buffer-substring (point) (match-beginning 0))
+ (goto-char (match-end 0))))
(progress-reporter-update progress-reporter (point)))
table)))
table))
(defvar etags-xref-find-definitions-tag-order '(tag-exact-match-p
tag-implicit-name-match-p)
- "Tag order used in `etags-xref-find' to look for definitions.")
+ "Tag order used in `xref-backend-definitions' to look for definitions.")
;;;###autoload
-(defun etags-xref-find (action id)
- (pcase action
- (`definitions (etags--xref-find-definitions id))
- (`references (etags--xref-find-references id))
- (`apropos (etags--xref-find-definitions id t))))
-
-(defun etags--xref-find-references (symbol)
- ;; TODO: Merge together with the Elisp impl.
- (cl-mapcan
- (lambda (dir)
- (xref-collect-references symbol dir))
- (let ((pr (project-current t)))
- (append
- (project-roots pr)
- (project-library-roots pr)))))
+(defun etags--xref-backend () 'etags)
+
+(cl-defmethod xref-backend-identifier-at-point ((_backend (eql etags)))
+ (find-tag--default))
+
+(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql etags)))
+ (tags-lazy-completion-table))
+
+(cl-defmethod xref-backend-definitions ((_backend (eql etags)) symbol)
+ (etags--xref-find-definitions symbol))
+
+(cl-defmethod xref-backend-apropos ((_backend (eql etags)) symbol)
+ (etags--xref-find-definitions symbol t))
(defun etags--xref-find-definitions (pattern &optional regexp?)
;; This emulates the behaviour of `find-tag-in-order' but instead of
(with-slots (tag-info) l
(nth 1 tag-info)))
-(defun etags-library-roots ()
- (mapcar #'file-name-directory tags-table-list))
-
\f
(provide 'etags)