X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/38357a23f4887991726185607297a98a82680ea8..3db571c0d71c8d568ff54786606cccad2b138ddc:/lisp/imenu.el diff --git a/lisp/imenu.el b/lisp/imenu.el index 238adfe950..1a107ed8ae 100644 --- a/lisp/imenu.el +++ b/lisp/imenu.el @@ -1,7 +1,7 @@ ;;; imenu.el --- framework for mode-specific buffer indexes -;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 2003, 2004 -;; Free Software Foundation, Inc. +;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 2002, 2003, 2004, +;; 2005 Free Software Foundation, Inc. ;; Author: Ake Stenhoff ;; Lars Lindberg @@ -23,8 +23,8 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. ;;; Commentary: @@ -107,7 +107,7 @@ This variable is buffer-local." (defvar imenu-always-use-completion-buffer-p nil) (make-obsolete-variable 'imenu-always-use-completion-buffer-p - 'imenu-use-popup-menu "21.4") + 'imenu-use-popup-menu "22.1") (defcustom imenu-use-popup-menu (if imenu-always-use-completion-buffer-p @@ -119,12 +119,15 @@ If t, always use a popup menu, If `on-mouse' use a popup menu when `imenu' was invoked with the mouse." :type '(choice (const :tag "On Mouse" on-mouse) (const :tag "Never" nil) - (other :tag "Always" t))) + (other :tag "Always" t)) + :group 'imenu) (defcustom imenu-eager-completion-buffer (not (eq imenu-always-use-completion-buffer-p 'never)) "If non-nil, eagerly popup the completion buffer." - :type 'boolean) + :type 'boolean + :group 'imenu + :version "22.1") (defcustom imenu-after-jump-hook nil "*Hooks called after jumping to a place in the buffer. @@ -159,16 +162,17 @@ element should come before the second. The arguments are cons cells; :type 'integer :group 'imenu) -(defcustom imenu-scanning-message "Scanning buffer for index (%3d%%)" - "*Progress message during the index scanning of the buffer. -If non-nil, user gets a message during the scanning of the buffer. - -Relevant only if the mode-specific function that creates the buffer -index use `imenu-progress-message', and not useful if that is fast, in -which case you might as well set this to nil." - :type '(choice string - (const :tag "None" nil)) - :group 'imenu) +;; No longer used. KFS 2004-10-27 +;; (defcustom imenu-scanning-message "Scanning buffer for index (%3d%%)" +;; "*Progress message during the index scanning of the buffer. +;; If non-nil, user gets a message during the scanning of the buffer. +;; +;; Relevant only if the mode-specific function that creates the buffer +;; index use `imenu-progress-message', and not useful if that is fast, in +;; which case you might as well set this to nil." +;; :type '(choice string +;; (const :tag "None" nil)) +;; :group 'imenu) (defcustom imenu-space-replacement "." "*The replacement string for spaces in index names. @@ -188,34 +192,9 @@ with name concatenation." (defvar imenu-generic-expression nil "The regex pattern to use for creating a buffer index. -If non-nil this pattern is passed to `imenu--generic-function' -to create a buffer index. - -The value should be an alist with elements that look like this: - (MENU-TITLE REGEXP INDEX) -or like this: - (MENU-TITLE REGEXP INDEX FUNCTION ARGUMENTS...) -with zero or more ARGUMENTS. The former format creates a simple element in -the index alist when it matches; the latter creates a special element -of the form (NAME POSITION-MARKER FUNCTION ARGUMENTS...) -with FUNCTION and ARGUMENTS copied from `imenu-generic-expression'. - -MENU-TITLE is a string used as the title for the submenu or nil if the -entries are not nested. - -REGEXP is a regexp that should match a construct in the buffer that is -to be displayed in the menu; i.e., function or variable definitions, -etc. It contains a substring which is the name to appear in the -menu. See the info section on Regexps for more information. - -INDEX points to the substring in REGEXP that contains the name (of the -function, variable or type) that is to appear in the menu. - -The variable is buffer-local. - -The variable `imenu-case-fold-search' determines whether or not the -regexp matches are case sensitive, and `imenu-syntax-alist' can be -used to alter the syntax table for the search. +If non-nil this pattern is passed to `imenu--generic-function' to +create a buffer index. Look there for the documentation of this +pattern's structure. For example, see the value of `fortran-imenu-generic-expression' used by `fortran-mode' with `imenu-syntax-alist' set locally to give the @@ -240,9 +219,7 @@ A nested sub-alist element looks like (INDEX-NAME SUB-ALIST). The function `imenu--subalist-p' tests an element and returns t if it is a sub-alist. -This function is called within a `save-excursion'. - -The variable is buffer-local.") +This function is called within a `save-excursion'.") ;;;###autoload (make-variable-buffer-local 'imenu-create-index-function) @@ -302,16 +279,22 @@ The function in this variable is called when selecting a normal index-item.") ;; is calculated. ;; PREVPOS is the variable in which we store the last position displayed. (defmacro imenu-progress-message (prevpos &optional relpos reverse) - `(and - imenu-scanning-message - (let ((pos ,(if relpos - relpos - `(imenu--relative-position ,reverse)))) - (if ,(if relpos t - `(> pos (+ 5 ,prevpos))) - (progn - (message imenu-scanning-message pos) - (setq ,prevpos pos)))))) + +;; Made obsolete/empty, as computers are now faster than the eye, and +;; it had problems updating the messages correctly, and could shadow +;; more important messages/prompts in the minibuffer. KFS 2004-10-27. + +;; `(and +;; imenu-scanning-message +;; (let ((pos ,(if relpos +;; relpos +;; `(imenu--relative-position ,reverse)))) +;; (if ,(if relpos t +;; `(> pos (+ 5 ,prevpos))) +;; (progn +;; (message imenu-scanning-message pos) +;; (setq ,prevpos pos))))) +) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -321,9 +304,12 @@ The function in this variable is called when selecting a normal index-item.") ;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Return the current/previous sexp and the location of the sexp (its -;; beginning) without moving the point. +;; FIXME: This is the only imenu-example-* definition that's actually used, +;; and it seems to only be used by cperl-mode.el. We should just move it to +;; cperl-mode.el and remove the rest. (defun imenu-example--name-and-position () + "Return the current/previous sexp and its (beginning) location. +Don't move point." (save-excursion (forward-sexp -1) ;; [ydi] modified for imenu-use-markers @@ -524,7 +510,7 @@ A nested sub-alist element looks like (INDEX-NAME SUB-ALIST).") (push item keep-at-top) (setq menulist (delq item menulist)))) (if imenu-sort-function - (setq menulist (sort menulist imenu-sort-function))) + (setq menulist (sort (copy-sequence menulist) imenu-sort-function))) (if (> (length menulist) imenu-max-items) (setq menulist (mapcar @@ -553,12 +539,10 @@ A nested sub-alist element looks like (INDEX-NAME SUB-ALIST).") (cond ((consp (cdr item)) (imenu--truncate-items (cdr item))) - (t - ;; truncate if necessary - (if (and (numberp imenu-max-item-length) - (> (length (car item)) imenu-max-item-length)) - (setcar item (substring (car item) 0 - imenu-max-item-length))))))) + ;; truncate if necessary + ((and (numberp imenu-max-item-length) + (> (length (car item)) imenu-max-item-length)) + (setcar item (substring (car item) 0 imenu-max-item-length)))))) menulist)) @@ -737,27 +721,39 @@ for modes which use `imenu--generic-function'. If it is not set, but ;;;###autoload (make-variable-buffer-local 'imenu-case-fold-search) -;; Originally "Built on some ideas that Erik Naggum -;; once posted to comp.emacs" but since substantially re-written. +;; 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 of the current buffer as an alist. PATTERNS is an alist with elements that look like this: - (MENU-TITLE REGEXP INDEX). + (MENU-TITLE REGEXP INDEX) or like this: (MENU-TITLE REGEXP INDEX FUNCTION ARGUMENTS...) -with zero or more ARGUMENTS. +with zero or more ARGUMENTS. The former format creates a simple +element in the index alist when it matches; the latter creates a +special element of the form (NAME POSITION-MARKER FUNCTION +ARGUMENTS...) with FUNCTION and ARGUMENTS copied from +`imenu-generic-expression'. + +MENU-TITLE is a string used as the title for the submenu or nil +if the entries are not nested. + +REGEXP is a regexp that should match a construct in the buffer +that is to be displayed in the menu; i.e., function or variable +definitions, etc. It contains a substring which is the name to +appear in the menu. See the info section on Regexps for more +information. REGEXP may also be a function, called without +arguments. It is expected to search backwards. It shall return +true and set `match-data' iff it finds another element. + +INDEX points to the substring in REGEXP that contains the +name (of the function, variable or type) that is to appear in the +menu. -MENU-TITLE is a string used as the title for the submenu or nil if the -entries are not nested. - -REGEXP is a regexp that should match a construct in the buffer that is -to be displayed in the menu; i.e., function or variable definitions, -etc. It contains a substring which is the name to appear in the -menu. See the info section on Regexps for more information. - -INDEX points to the substring in REGEXP that contains the name (of the -function, variable or type) that is to appear in the menu. +The variable `imenu-case-fold-search' determines whether or not the +regexp matches are case sensitive, and `imenu-syntax-alist' can be +used to alter the syntax table for the search. See `lisp-imenu-generic-expression' for an example of PATTERNS. @@ -766,12 +762,12 @@ the alist look like: (INDEX-NAME . INDEX-POSITION) or like: (INDEX-NAME INDEX-POSITION FUNCTION ARGUMENTS...) -They may also be nested index alists like: +They may also be nested index alists like: (INDEX-NAME . INDEX-ALIST) depending on PATTERNS." (let ((index-alist (list 'dummy)) - prev-pos beg + prev-pos (case-fold-search (if (or (local-variable-p 'imenu-case-fold-search) (not (local-variable-p 'font-lock-defaults))) imenu-case-fold-search @@ -792,6 +788,7 @@ depending on PATTERNS." (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) @@ -799,12 +796,23 @@ depending on PATTERNS." (regexp (nth 1 pat)) (index (nth 2 pat)) (function (nth 3 pat)) - (rest (nthcdr 4 pat))) + (rest (nthcdr 4 pat)) + start beg) ;; Go backwards for convenience of adding items in order. (goto-char (point-max)) - (while (re-search-backward regexp nil t) + (while (and (if (functionp regexp) + (funcall regexp) + (re-search-backward regexp nil t)) + ;; Exit the loop if we get an empty match, + ;; because it means a bad regexp was specified. + (not (= (match-beginning 0) (match-end 0)))) + (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)) (imenu-progress-message prev-pos nil t) - (setq beg (match-beginning index)) ;; Add this sort of submenu only when we've found an ;; item for it, avoiding empty, duff menus. (unless (assoc menu-title index-alist) @@ -824,7 +832,10 @@ depending on PATTERNS." ;; Insert the item unless it is already present. (unless (member item (cdr menu)) (setcdr menu - (cons item (cdr 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))) (imenu-progress-message prev-pos 100 t) ;; Sort each submenu by position. @@ -858,7 +869,7 @@ depending on PATTERNS." (defun imenu--completion-buffer (index-alist &optional prompt) "Let the user select from INDEX-ALIST in a completion buffer with PROMPT. -Returns t for rescan and otherwise a position number." +Return one of the entries in index-alist or nil." ;; Create a list for this buffer only when needed. (let ((name (thing-at-point 'symbol)) choice @@ -866,7 +877,7 @@ Returns t for rescan and otherwise a position number." (if (not imenu-space-replacement) index-alist (mapcar (lambda (item) - (cons (subst-char-in-string ?\ (aref imenu-space-replacement 0) + (cons (subst-char-in-string ?\s (aref imenu-space-replacement 0) (car item)) (cdr item))) index-alist)))) @@ -884,13 +895,11 @@ Returns t for rescan and otherwise a position number." prepared-index-alist nil t nil 'imenu--history-list name))) - (cond ((not (stringp name)) nil) - ((string= name (car imenu--rescan-item)) t) - (t - (setq choice (assoc name prepared-index-alist)) - (if (imenu--subalist-p choice) - (imenu--completion-buffer (cdr choice) prompt) - choice))))) + (when (stringp name) + (setq choice (assoc name prepared-index-alist)) + (if (imenu--subalist-p choice) + (imenu--completion-buffer (cdr choice) prompt) + choice)))) (defun imenu--mouse-menu (index-alist event &optional title) "Let the user select from a buffer index from a mouse menu. @@ -941,9 +950,9 @@ The returned value is of the form (INDEX-NAME . INDEX-POSITION)." (or (eq imenu-use-popup-menu t) mouse-triggered)) (imenu--mouse-menu index-alist last-nonmenu-event) (imenu--completion-buffer index-alist prompt))) - (and (eq result t) + (and (equal result imenu--rescan-item) (imenu--cleanup) - (setq imenu--index-alist nil))) + (setq result t imenu--index-alist nil))) result)) ;;;###autoload @@ -977,8 +986,7 @@ A trivial interface to `imenu-add-to-menubar' suitable for use in a hook." (defvar imenu-buffer-menubar nil) (defvar imenu-menubar-modified-tick 0 - "The value of (buffer-modified-tick) as of last call to `imenu-update-menubar'. -This value becomes local in every buffer when it is set.") + "The value of (buffer-modified-tick) as of last call to `imenu-update-menubar'.") (make-variable-buffer-local 'imenu-menubar-modified-tick) (defun imenu-update-menubar () @@ -1019,7 +1027,7 @@ This value becomes local in every buffer when it is set.") nil)) (defun imenu-default-goto-function (name position &optional rest) - "Move the point to the given position. + "Move to the given position. NAME is ignored. POSITION is where to move. REST is also ignored. The ignored args just make this function have the same interface as a @@ -1059,5 +1067,5 @@ for more information." (provide 'imenu) -;;; arch-tag: 98a2f5f5-4b91-4704-b18c-3aacf77d77a7 +;; arch-tag: 98a2f5f5-4b91-4704-b18c-3aacf77d77a7 ;;; imenu.el ends here