Function: imenu--generic-function

imenu--generic-function is a byte-compiled function defined in imenu.el.gz.

Signature

(imenu--generic-function PATTERNS)

Documentation

Return an index alist of the current buffer based on PATTERNS.

PATTERNS should be an alist of the same form as imenu-generic-expression.

If imenu-generic-skip-comments-and-strings is non-nil, this ignores text inside comments and strings.

If imenu-case-fold-search is non-nil, this ignores case.

The return value is an alist of the form
 (INDEX-NAME . INDEX-POSITION)
or
 (INDEX-NAME INDEX-POSITION FUNCTION ARGUMENTS...)
The return value may also consist of nested index alists like:
 (INDEX-NAME . INDEX-ALIST)
depending on PATTERNS.

Source Code

;; Defined in /usr/src/emacs/lisp/imenu.el.gz
;; This function can be called with quitting disabled,
;; so it needs to be careful never to loop!
(defun imenu--generic-function (patterns)
  "Return an index alist of the current buffer based on PATTERNS.
PATTERNS should be an alist of the same form as `imenu-generic-expression'.

If `imenu-generic-skip-comments-and-strings' is non-nil, this ignores
text inside comments and strings.

If `imenu-case-fold-search' is non-nil, this ignores case.

The return value is an alist of the form
 (INDEX-NAME . INDEX-POSITION)
or
 (INDEX-NAME INDEX-POSITION FUNCTION ARGUMENTS...)
The return value may also consist of nested index alists like:
 (INDEX-NAME . INDEX-ALIST)
depending on PATTERNS."
  (let ((index-alist (list 'dummy))
        (case-fold-search (if (or (local-variable-p 'imenu-case-fold-search)
				  (not (local-variable-p 'font-lock-defaults)))
			      imenu-case-fold-search
			    (nth 2 font-lock-defaults)))
        (start-time (float-time))
        (old-table (syntax-table))
        (table (copy-syntax-table (syntax-table)))
        (slist imenu-syntax-alist))
    ;; Modify the syntax table used while matching regexps.
    (dolist (syn slist)
      ;; The character(s) to modify may be a single char or a string.
      (if (numberp (car syn))
	  (modify-syntax-entry (car syn) (cdr syn) table)
        (mapc (lambda (c)
                (modify-syntax-entry c (cdr syn) table))
              (car syn))))
    (goto-char (point-max))
    (unwind-protect			; For syntax table.
	(save-match-data
	  (set-syntax-table table)

	  ;; Map over the elements of imenu-generic-expression
	  ;; (typically functions, variables ...).
	  (dolist (pat patterns)
	    (let ((menu-title (car pat))
		  (regexp (nth 1 pat))
		  (index (nth 2 pat))
		  (function (nth 3 pat))
		  (rest (nthcdr 4 pat))
		  start beg)
	      ;; Go backwards for convenience of adding items in order.
	      (goto-char (point-max))
	      (while (and (if (functionp regexp)
			      (funcall regexp)
			    (and
			     (re-search-backward regexp nil t)
			     ;; Do not count invisible definitions.
			     (let ((invis (invisible-p (point))))
			       (or (not invis)
				   (progn
				     (while (and invis
						 (not (bobp)))
				       (setq invis (not (re-search-backward
							 regexp nil 'move))))
				     (not invis))))))
			  ;; Exit the loop if we get an empty match,
			  ;; because it means a bad regexp was specified.
			  (not (= (match-beginning 0) (match-end 0)))
                          ;; Don't take an excessive amount of time.
                          (or (< (- (float-time) start-time)
                                 imenu-max-index-time)
                              (progn
                                (message "`imenu-max-index-time' exceeded")
                                nil)))
		(setq start (point))
		;; Record the start of the line in which the match starts.
		;; That's the official position of this definition.
		(goto-char (match-beginning index))
		(beginning-of-line)
		(setq beg (point))
		;; Add this sort of submenu only when we've found an
		;; item for it, avoiding empty, duff menus.
		(unless (assoc menu-title index-alist)
		  (push (list menu-title) index-alist))
		(if imenu-use-markers
		    (setq beg (copy-marker beg)))
		(let ((item
		       (if function
			   (nconc (list (match-string-no-properties index)
					beg function)
				  rest)
			 (cons (match-string-no-properties index)
			       beg)))
		      ;; This is the desired submenu,
		      ;; starting with its title (or nil).
		      (menu (assoc menu-title index-alist)))
		  ;; Insert the item unless it is already present.
		  (unless (or (member item (cdr menu))
                              (and imenu-generic-skip-comments-and-strings
                                   (save-excursion
                                     (goto-char start) (nth 8 (syntax-ppss)))))
		    (setcdr menu
			    (cons item (cdr menu)))))
		;; Go to the start of the match, to make sure we
		;; keep making progress backwards.
		(goto-char start))))
	  (set-syntax-table old-table)))
    ;; Sort each submenu by position.
    ;; This is in case one submenu gets items from two different regexps.
    (dolist (item index-alist)
      (when (listp item)
	(setcdr item (sort (cdr item) 'imenu--sort-by-position))))
    ;; Remove any empty menus.  That can happen because of skipping
    ;; things inside comments or strings.
    (setq index-alist (cl-delete-if
                       (lambda (it) (and (consp it) (null (cdr it))))
                       index-alist))
    (let ((main-element (assq nil index-alist)))
      (nconc (delq main-element (delq 'dummy index-alist))
             (cdr main-element)))))