X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/d5dc920668a85c56c4d3e54a6898bbd43bcb64a1..d21d2e9a67b654e308dc2a8770b82c48a0539365:/lisp/imenu.el diff --git a/lisp/imenu.el b/lisp/imenu.el index a210b39c60..65213ef1b2 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, 2001, 2002, 2003, 2004, +;; 2005, 2006, 2007, 2008 Free Software Foundation, Inc. ;; Author: Ake Stenhoff ;; Lars Lindberg @@ -11,10 +11,10 @@ ;; This file is part of GNU Emacs. -;; GNU Emacs is free software; you can redistribute it and/or modify +;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -22,9 +22,7 @@ ;; GNU General Public License for more details. ;; 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., 51 Franklin Street, Fifth Floor, -;; Boston, MA 02110-1301, USA. +;; along with GNU Emacs. If not, see . ;;; Commentary: @@ -78,7 +76,7 @@ :link '(custom-manual "(elisp)Imenu")) (defcustom imenu-use-markers t - "*Non-nil means use markers instead of integers for Imenu buffer positions. + "Non-nil means use markers instead of integers for Imenu buffer positions. Setting this to nil makes Imenu work a little faster but editing the buffer will make the generated index positions wrong. @@ -89,18 +87,18 @@ This might not yet be honored by all index-building functions." (defcustom imenu-max-item-length 60 - "*If a number, truncate Imenu entries to that length." + "If a number, truncate Imenu entries to that length." :type '(choice integer (const :tag "Unlimited")) :group 'imenu) (defcustom imenu-auto-rescan nil - "*Non-nil means Imenu should always rescan the buffers." + "Non-nil means Imenu should always rescan the buffers." :type 'boolean :group 'imenu) (defcustom imenu-auto-rescan-maxout 60000 - "*Imenu auto-rescan is disabled in buffers larger than this size (in bytes). + "Imenu auto-rescan is disabled in buffers larger than this size (in bytes). This variable is buffer-local." :type 'integer :group 'imenu) @@ -130,7 +128,7 @@ If `on-mouse' use a popup menu when `imenu' was invoked with the mouse." :version "22.1") (defcustom imenu-after-jump-hook nil - "*Hooks called after jumping to a place in the buffer. + "Hooks called after jumping to a place in the buffer. Useful things to use here include `reposition-window', `recenter', and \(lambda () (recenter 0)) to show at top of screen." @@ -139,7 +137,7 @@ Useful things to use here include `reposition-window', `recenter', and ;;;###autoload (defcustom imenu-sort-function nil - "*The function to use for sorting the index mouse-menu. + "The function to use for sorting the index mouse-menu. Affects only the mouse index menu. @@ -158,7 +156,7 @@ element should come before the second. The arguments are cons cells; :group 'imenu) (defcustom imenu-max-items 25 - "*Maximum number of elements in a mouse menu for Imenu." + "Maximum number of elements in a mouse menu for Imenu." :type 'integer :group 'imenu) @@ -175,14 +173,14 @@ element should come before the second. The arguments are cons cells; ;; :group 'imenu) (defcustom imenu-space-replacement "." - "*The replacement string for spaces in index names. + "The replacement string for spaces in index names. Used when presenting the index in a completion buffer to make the names work as tokens." :type '(choice string (const nil)) :group 'imenu) (defcustom imenu-level-separator ":" - "*The separator between index names of different levels. + "The separator between index names of different levels. Used for making mouse-menu titles and for flattening nested indexes with name concatenation." :type 'string @@ -208,18 +206,13 @@ during matching.") ;;;###autoload (defvar imenu-create-index-function 'imenu-default-create-index-function - "The function to use for creating a buffer index. + "The function to use for creating an index alist of the current buffer. -It should be a function that takes no arguments and returns an index -of the current buffer as an alist. +It should be a function that takes no arguments and returns +an index alist of the current buffer. The function is +called within a `save-excursion'. -Simple elements in the alist look like (INDEX-NAME . INDEX-POSITION). -Special elements look like (INDEX-NAME INDEX-POSITION FUNCTION ARGUMENTS...). -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'.") +See `imenu--index-alist' for the format of the buffer index alist.") ;;;###autoload (make-variable-buffer-local 'imenu-create-index-function) @@ -431,15 +424,27 @@ Don't move point." ;; The latest buffer index. ;; Buffer local. (defvar imenu--index-alist nil - "The buffer index computed for this buffer in Imenu. -Simple elements in the alist look like (INDEX-NAME . INDEX-POSITION). -Special elements look like (INDEX-NAME INDEX-POSITION FUNCTION ARGUMENTS...). -A nested sub-alist element looks like (INDEX-NAME SUB-ALIST).") + "The buffer index alist computed for this buffer in Imenu. + +Simple elements in the alist look like (INDEX-NAME . POSITION). +POSITION is the buffer position of the item; to go to the item +is simply to move point to that position. + +Special elements look like (INDEX-NAME POSITION FUNCTION ARGUMENTS...). +To \"go to\" a special element means applying FUNCTION +to INDEX-NAME, POSITION, and the ARGUMENTS. + +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. + +There is one simple element with negative POSITION; selecting that +element recalculates the buffer's index alist.") (make-variable-buffer-local 'imenu--index-alist) (defvar imenu--last-menubar-index-alist nil - "The latest buffer index used to update the menu bar menu.") + "The latest buffer index alist used to update the menu bar menu.") (make-variable-buffer-local 'imenu--last-menubar-index-alist) @@ -478,6 +483,8 @@ A nested sub-alist element looks like (INDEX-NAME SUB-ALIST).") ;; Split LIST into sublists of max length N. ;; Example (imenu--split '(1 2 3 4 5 6 7 8) 3)-> '((1 2 3) (4 5 6) (7 8)) +;; +;; The returned list DOES NOT share structure with LIST. (defun imenu--split (list n) (let ((remain list) (result '()) @@ -499,10 +506,15 @@ A nested sub-alist element looks like (INDEX-NAME SUB-ALIST).") ;;; Split the alist MENULIST into a nested alist, if it is long enough. ;;; In any case, add TITLE to the front of the alist. +;;; If IMENU--RESCAN-ITEM is present in MENULIST, it is moved to the +;;; beginning of the returned alist. +;;; +;;; The returned alist DOES NOT share structure with MENULIST. (defun imenu--split-menu (menulist title) - (let (keep-at-top tail) + (let ((menulist (copy-sequence menulist)) + keep-at-top tail) (if (memq imenu--rescan-item menulist) - (setq keep-at-top (cons imenu--rescan-item nil) + (setq keep-at-top (list imenu--rescan-item) menulist (delq imenu--rescan-item menulist))) (setq tail menulist) (dolist (item tail) @@ -510,7 +522,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 (copy-sequence menulist) imenu-sort-function))) + (setq menulist (sort menulist imenu-sort-function))) (if (> (length menulist) imenu-max-items) (setq menulist (mapcar @@ -522,6 +534,9 @@ A nested sub-alist element looks like (INDEX-NAME SUB-ALIST).") ;;; Split up each long alist that are nested within ALIST ;;; into nested alists. +;;; +;;; Return a split and sorted copy of ALIST. The returned alist DOES +;;; NOT share structure with ALIST. (defun imenu--split-submenus (alist) (mapcar (function (lambda (elt) @@ -547,19 +562,12 @@ A nested sub-alist element looks like (INDEX-NAME SUB-ALIST).") (defun imenu--make-index-alist (&optional noerror) - "Create an index-alist for the definitions in the current buffer. - + "Create an index alist for the definitions in the current buffer. +This works by using the hook function `imenu-create-index-function'. Report an error if the list is empty unless NOERROR is supplied and non-nil. -Simple elements in the alist look like (INDEX-NAME . INDEX-POSITION). -Special elements look like (INDEX-NAME FUNCTION ARGUMENTS...). -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. - -There is one simple element with negative POSITION; that's intended -as a way for the user to ask to recalculate the buffer's index alist." +See `imenu--index-alist' for the format of the index alist." (or (and imenu--index-alist (or (not imenu-auto-rescan) (and imenu-auto-rescan @@ -657,11 +665,15 @@ and speed-up matching.") (make-variable-buffer-local 'imenu-syntax-alist) (defun imenu-default-create-index-function () - "*Wrapper for index searching functions. + "Default function to create an index alist of the current buffer. -Moves point to end of buffer and then repeatedly calls +The most general method is to move point to end of buffer, then repeatedly call `imenu-prev-index-position-function' and `imenu-extract-index-name-function'. -Their results are gathered into an index alist." +All the results returned by the latter are gathered into an index alist. +This method is used if those two variables are non-nil. + +The alternate method, which is the one most often used, is to call +`imenu--generic-function' with `imenu-generic-expression' as argument." ;; These should really be done by setting imenu-create-index-function ;; in these major modes. But save that change for later. (cond ((and imenu-prev-index-position-function @@ -687,27 +699,6 @@ Their results are gathered into an index alist." (t (error "This buffer cannot use `imenu-default-create-index-function'")))) -;; Not used and would require cl at run time -;; (defun imenu--flatten-index-alist (index-alist &optional concat-names prefix) -;; ;; Takes a nested INDEX-ALIST and returns a flat index alist. -;; ;; If optional CONCAT-NAMES is non-nil, then a nested index has its -;; ;; name and a space concatenated to the names of the children. -;; ;; Third argument PREFIX is for internal use only. -;; (mapcan -;; (lambda (item) -;; (let* ((name (car item)) -;; (pos (cdr item)) -;; (new-prefix (and concat-names -;; (if prefix -;; (concat prefix imenu-level-separator name) -;; name)))) -;; (cond -;; ((or (markerp pos) (numberp pos)) -;; (list (cons new-prefix pos))) -;; (t -;; (imenu--flatten-index-alist pos new-prefix))))) -;; index-alist)) - ;;; ;;; Generic index gathering function. ;;; @@ -724,7 +715,7 @@ for modes which use `imenu--generic-function'. If it is not set, but ;; 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. + "Return an index alist of the current buffer based on PATTERNS. PATTERNS is an alist with elements that look like this: (MENU-TITLE REGEXP INDEX) @@ -732,9 +723,8 @@ 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'. +special element of the form (INDEX-NAME POSITION-MARKER FUNCTION +ARGUMENTS...) with FUNCTION and ARGUMENTS copied from PATTERNS. MENU-TITLE is a string used as the title for the submenu or nil if the entries are not nested. @@ -745,7 +735,7 @@ 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. +true and set `match-data' if 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 @@ -928,9 +918,8 @@ select from ALIST. With no index alist ALIST, it calls `imenu--make-index-alist' to create the index alist. -If `imenu-use-popup-menu' is non-nil, then the -completion buffer is always used, no matter if the mouse was used or -not. +If `imenu-use-popup-menu' is nil, then the completion buffer +is always used, no matter if the mouse was used or not. The returned value is of the form (INDEX-NAME . INDEX-POSITION)." (let (index-alist @@ -973,7 +962,8 @@ See the command `imenu' for more information." `(menu-item ,name ,(make-sparse-keymap "Imenu"))) (use-local-map newmap) (add-hook 'menu-bar-update-hook 'imenu-update-menubar)) - (error "The mode `%s' does not support Imenu" mode-name))) + (error "The mode `%s' does not support Imenu" + (format-mode-line mode-name)))) ;;;###autoload (defun imenu-add-menubar-index () @@ -986,15 +976,15 @@ 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'.") + "The value of (buffer-chars-modified-tick) as of the last call +to `imenu-update-menubar'.") (make-variable-buffer-local 'imenu-menubar-modified-tick) (defun imenu-update-menubar () (when (and (current-local-map) (keymapp (lookup-key (current-local-map) [menu-bar index])) - (not (eq (buffer-modified-tick) - imenu-menubar-modified-tick))) - (setq imenu-menubar-modified-tick (buffer-modified-tick)) + (/= (buffer-chars-modified-tick) imenu-menubar-modified-tick)) + (setq imenu-menubar-modified-tick (buffer-chars-modified-tick)) (let ((index-alist (imenu--make-index-alist t))) ;; Don't bother updating if the index-alist has not changed ;; since the last time we did it.