;;; imenu.el --- framework for mode-specific buffer indexes
-;; Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 2003, 2004
+;; Free Software Foundation, Inc.
;; Author: Ake Stenhoff <etxaksf@aom.ericsson.se>
;; Lars Lindberg <lli@sypro.cap.se>
;;; Code:
+(require 'newcomment)
+
(eval-when-compile (require 'cl))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(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 "21.4")
(defcustom imenu-after-jump-hook nil
"*Hooks called after jumping to a place in the buffer.
: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.
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.
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)
file.
The function should leave point at the place to be connected to the
-index and it should return nil when it doesn't find another index.
-
-This variable is local in all buffers.")
+index and it should return nil when it doesn't find another index.")
;;;###autoload
(make-variable-buffer-local 'imenu-prev-index-position-function)
This function is called after `imenu-prev-index-position-function'
finds a position for an index item, with point at that position.
-It should return the name for that index item.
-
-This variable is local in all buffers.")
+It should return the name for that index item.")
;;;###autoload
(make-variable-buffer-local 'imenu-extract-index-name-function)
If nil, comparison is done with `string='.
Set this to some other function for more advanced comparisons,
such as \"begins with\" or \"name matches and number of
-arguments match\".
-
-This variable is local in all buffers.")
+arguments match\".")
;;;###autoload
(make-variable-buffer-local 'imenu-name-lookup-function)
;; 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)))))
+)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; 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
"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).
-
-This variable is local in all buffers, once set.")
+A nested sub-alist element looks like (INDEX-NAME SUB-ALIST).")
(make-variable-buffer-local 'imenu--index-alist)
menulist (delq imenu--rescan-item menulist)))
(setq tail menulist)
(dolist (item tail)
- (if (imenu--subalist-p item)
- (setq keep-at-top (cons item keep-at-top)
- menulist (delq item menulist))))
+ (when (imenu--subalist-p item)
+ (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)
- (let ((count 0))
- (setq menulist
- (mapcar
- (function
- (lambda (menu)
- (cons (format "From: %s" (caar menu)) menu)))
- (imenu--split menulist imenu-max-items)))))
+ (setq menulist
+ (mapcar
+ (lambda (menu)
+ (cons (format "From: %s" (caar menu)) menu))
+ (imenu--split menulist imenu-max-items))))
(cons title
(nconc (nreverse keep-at-top) menulist))))
(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))
alist)
t))
-(defun imenu--create-keymap-1 (title alist)
- (let ((counter 0))
- (list* 'keymap title
- (mapcar
- (lambda (item)
- (list* (car item) (car item)
- (cond
- ((imenu--subalist-p item)
- (imenu--create-keymap-1 (car item) (cdr item)))
- (t
- `(lambda () (interactive)
- (imenu--menubar-select ',item))))))
- alist))))
+(defun imenu--create-keymap (title alist &optional cmd)
+ (list* 'keymap title
+ (mapcar
+ (lambda (item)
+ (list* (car item) (car item)
+ (cond
+ ((imenu--subalist-p item)
+ (imenu--create-keymap (car item) (cdr item) cmd))
+ (t
+ `(lambda () (interactive)
+ ,(if cmd `(,cmd ',item) (list 'quote item)))))))
+ alist)))
(defun imenu--in-alist (str alist)
"Check whether the string STR is contained in multi-level ALIST."
(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))
+;; (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.
"Defines whether `imenu--generic-function' should fold case when matching.
This variable should be set (only) by initialization code
-for modes which use `imenu--generic-function'. If it is not set, that
-function will use the current value of `case-fold-search' to match
-patterns.")
+for modes which use `imenu--generic-function'. If it is not set, but
+`font-lock-defaults' is set, then font-lock's setting is used.")
;;;###autoload
(make-variable-buffer-local 'imenu-case-fold-search)
PATTERNS is 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.
MENU-TITLE is a string used as the title for the submenu or nil if the
entries are not nested.
See `lisp-imenu-generic-expression' for an example of PATTERNS.
Returns an index of the current buffer as an alist. The elements in
-the alist look like: (INDEX-NAME . INDEX-POSITION). They may also be
-nested index lists like (INDEX-NAME . INDEX-ALIST) depending on
-PATTERNS."
+the alist look like:
+ (INDEX-NAME . INDEX-POSITION)
+or like:
+ (INDEX-NAME INDEX-POSITION FUNCTION ARGUMENTS...)
+They may also be nested index alists like:
+ (INDEX-NAME . INDEX-ALIST)
+depending on PATTERNS."
(let ((index-alist (list 'dummy))
prev-pos beg
- (case-fold-search imenu-case-fold-search)
+ (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)))
(old-table (syntax-table))
(table (copy-syntax-table (syntax-table)))
(slist imenu-syntax-alist))
(regexp (nth 1 pat))
(index (nth 2 pat))
(function (nth 3 pat))
- (rest (nthcdr 4 pat)))
+ (rest (nthcdr 4 pat))
+ start
+ cs)
;; Go backwards for convenience of adding items in order.
(goto-char (point-max))
(while (re-search-backward regexp nil t)
- (imenu-progress-message prev-pos nil t)
+ (setq start (point))
+ (goto-char (match-end index))
(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)
- (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 (member item (cdr menu))
- (setcdr menu
- (cons item (cdr menu))))))))
+ (setq cs (and comment-start-skip
+ (save-match-data (comment-beginning))))
+ (if cs
+ (goto-char (min cs beg)) ; skip this one, it's in a comment
+ (goto-char beg)
+ (imenu-progress-message prev-pos nil t)
+ ;; 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 (member item (cdr menu))
+ (setcdr menu
+ (cons item (cdr menu)))))
+ ;; Move to the start of the entire match,
+ ;; to ensure we keep moving backwards
+ ;; as long as the match is nonempty.
+ (goto-char start)))))
(set-syntax-table old-table)))
(imenu-progress-message prev-pos 100 t)
;; Sort each submenu by position.
(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
(setq name (completing-read prompt
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.
Returns t for rescan and otherwise an element or subelement of INDEX-ALIST."
(setq index-alist (imenu--split-submenus index-alist))
(let* ((menu (imenu--split-menu index-alist (or title (buffer-name))))
- (map (imenu--create-keymap-1 (car menu)
- (if (< 1 (length (cdr menu)))
- (cdr menu)
- (cdr (car (cdr menu)))))))
+ (map (imenu--create-keymap (car menu)
+ (cdr (if (< 1 (length (cdr menu)))
+ menu
+ (car (cdr menu)))))))
(popup-menu map event)))
(defun imenu-choose-buffer-index (&optional prompt alist)
(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
(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 ()
(setq index-alist (imenu--split-submenus index-alist))
(setq menu (imenu--split-menu index-alist
(buffer-name)))
- (setq menu1 (imenu--create-keymap-1 (car menu)
- (if (< 1 (length (cdr menu)))
- (cdr menu)
- (cdr (car (cdr menu))))))
+ (setq menu1 (imenu--create-keymap (car menu)
+ (cdr (if (< 1 (length (cdr menu)))
+ menu
+ (car (cdr menu))))
+ 'imenu--menubar-select))
(setq old (lookup-key (current-local-map) [menu-bar index]))
(setcdr old (cdr menu1)))))))
(if (equal item imenu--rescan-item)
(progn
(imenu--cleanup)
+ ;; Make sure imenu-update-menubar redoes everything.
+ (setq imenu-menubar-modified-tick -1)
(setq imenu--index-alist nil)
+ (setq imenu--last-menubar-index-alist nil)
(imenu-update-menubar)
t)
(imenu item)
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
(provide 'imenu)
+;; arch-tag: 98a2f5f5-4b91-4704-b18c-3aacf77d77a7
;;; imenu.el ends here