Function: find-tag-in-order

find-tag-in-order is a byte-compiled function defined in etags.el.gz.

Signature

(find-tag-in-order PATTERN SEARCH-FORWARD-FUNC ORDER NEXT-LINE-AFTER-FAILURE-P MATCHING FIRST-SEARCH)

Documentation

Internal tag-finding function.

PATTERN is a string to pass to arg SEARCH-FORWARD-FUNC, and to any member of the function list ORDER. If ORDER is nil, use saved state to continue a previous search.

Arg NEXT-LINE-AFTER-FAILURE-P is non-nil if after a failed match, point should be moved to the next line.

Arg MATCHING is a string, an English -ing word, to be used in an error message.

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/etags.el.gz
  "Matches remembered between calls.") ; Doc string: calls to what?

(defun find-tag-in-order (pattern
			  search-forward-func
			  order
			  next-line-after-failure-p
			  matching
			  first-search)
  "Internal tag-finding function.
PATTERN is a string to pass to arg SEARCH-FORWARD-FUNC, and to any
member of the function list ORDER.  If ORDER is nil, use saved state
to continue a previous search.

Arg NEXT-LINE-AFTER-FAILURE-P is non-nil if after a failed match,
point should be moved to the next line.

Arg MATCHING is a string, an English `-ing' word, to be used in an
error message."
;; Algorithm is as follows:
;; For each qualifier-func in ORDER, go to beginning of tags file, and
;; perform inner loop: for each naive match for PATTERN found using
;; SEARCH-FORWARD-FUNC, qualify the naive match using qualifier-func.  If
;; it qualifies, go to the specified line in the specified source file
;; and return.  Qualified matches are remembered to avoid repetition.
;; State is saved so that the loop can be continued.
  (let (file				;name of file containing tag
	tag-info			;where to find the tag in FILE
	(first-table t)
	(tag-order order)
	(match-marker (make-marker))
	goto-func
	(case-fold-search (if (memq tags-case-fold-search '(nil t))
			      tags-case-fold-search
			    case-fold-search))
        (cbuf (current-buffer))
	)
    (save-excursion

      (if first-search
	  ;; This is the start of a search for a fresh tag.
	  ;; Clear the list of tags matched by the previous search.
	  ;; find-tag-noselect has already put us in the first tags table
	  ;; buffer before we got called.
	  (setq tag-lines-already-matched nil)
	;; Continuing to search for the tag specified last time.
	;; tag-lines-already-matched lists locations matched in previous
	;; calls so we don't visit the same tag twice if it matches twice
	;; during two passes with different qualification predicates.
	;; Switch to the current tags table buffer.
	(visit-tags-table-buffer 'same))

      ;; Get a qualified match.
      (catch 'qualified-match-found

	;; Iterate over the list of tags tables.
	(while (or first-table (visit-tags-table-buffer t cbuf))

	  (and first-search first-table
	       ;; Start at beginning of tags file.
	       (goto-char (point-min)))

	  (setq first-table nil)

	  ;; Iterate over the list of ordering predicates.
	  (while order
	    (while (funcall search-forward-func pattern nil t)
	      ;; Naive match found.  Qualify the match.
	      (and (funcall (car order) pattern)
		   ;; Make sure it is not a previous qualified match.
                   (not (member (set-marker match-marker (line-beginning-position))
				tag-lines-already-matched))
		   (throw 'qualified-match-found nil))
	      (if next-line-after-failure-p
		  (forward-line 1)))
	    ;; Try the next flavor of match.
	    (setq order (cdr order))
	    (goto-char (point-min)))
	  (setq order tag-order))
	;; We throw out on match, so only get here if there were no matches.
	;; Clear out the markers we use to avoid duplicate matches so they
	;; don't slow down editing and are immediately available for GC.
	(while tag-lines-already-matched
	  (set-marker (car tag-lines-already-matched) nil nil)
	  (setq tag-lines-already-matched (cdr tag-lines-already-matched)))
	(set-marker match-marker nil nil)
	(user-error "No %stags %s %s" (if first-search "" "more ")
                    matching pattern))

      ;; Found a tag; extract location info.
      (beginning-of-line)
      (setq tag-lines-already-matched (cons match-marker
					    tag-lines-already-matched))
      ;; Expand the filename, using the tags table buffer's default-directory.
      ;; We should be able to search for file-name backwards in file-of-tag:
      ;; the beginning-of-line is ok except when positioned on a "file-name" tag.
      (setq file (expand-file-name
		  (if (memq (car order) '(tag-exact-file-name-match-p
					  tag-file-name-match-p
					  tag-partial-file-name-match-p))
                      (save-excursion (forward-line 1)
                                      (file-of-tag))
                    (file-of-tag)))
	    tag-info (funcall snarf-tag-function))

      ;; Get the local value in the tags table buffer before switching buffers.
      (setq goto-func goto-tag-location-function)
      (tag-find-file-of-tag-noselect file)
      (widen)
      (push-mark)
      (funcall goto-func tag-info)

      ;; Return the buffer where the tag was found.
      (current-buffer))))