imenu.el 36.7 KB
Newer Older
1
;;; imenu.el --- framework for mode-specific buffer indexes
Richard M. Stallman's avatar
Richard M. Stallman committed
2

Glenn Morris's avatar
Glenn Morris committed
3
;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 2001, 2002, 2003, 2004,
Glenn Morris's avatar
Glenn Morris committed
4
;;   2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Richard M. Stallman's avatar
Richard M. Stallman committed
5 6 7

;; Author: Ake Stenhoff <etxaksf@aom.ericsson.se>
;;         Lars Lindberg <lli@sypro.cap.se>
Richard M. Stallman's avatar
Richard M. Stallman committed
8
;; Maintainer: FSF
Richard M. Stallman's avatar
Richard M. Stallman committed
9
;; Created: 8 Feb 1994
Dan Nicolaescu's avatar
Dan Nicolaescu committed
10
;; Keywords: tools convenience
Erik Naggum's avatar
Erik Naggum committed
11 12 13

;; This file is part of GNU Emacs.

14
;; GNU Emacs is free software: you can redistribute it and/or modify
Richard M. Stallman's avatar
Richard M. Stallman committed
15
;; it under the terms of the GNU General Public License as published by
16 17
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
Erik Naggum's avatar
Erik Naggum committed
18 19

;; GNU Emacs is distributed in the hope that it will be useful,
Richard M. Stallman's avatar
Richard M. Stallman committed
20 21 22
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.
Erik Naggum's avatar
Erik Naggum committed
23

Richard M. Stallman's avatar
Richard M. Stallman committed
24
;; You should have received a copy of the GNU General Public License
25
;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
Richard M. Stallman's avatar
Richard M. Stallman committed
26 27

;;; Commentary:
Erik Naggum's avatar
Erik Naggum committed
28

Richard M. Stallman's avatar
Richard M. Stallman committed
29 30 31 32 33
;; Purpose of this package:
;;   To present a framework for mode-specific buffer indexes.
;;   A buffer index is an alist of names and buffer positions.
;;   For instance all functions in a C-file and their positions.
;;
34 35
;;   It is documented in the Emacs Lisp manual.
;;
Richard M. Stallman's avatar
Richard M. Stallman committed
36 37 38 39 40 41 42 43
;; How it works:

;;   A mode-specific function is called to generate the index.  It is
;;   then presented to the user, who can choose from this index.
;;
;;   The package comes with a set of example functions for how to
;;   utilize this package.

44 45 46 47
;;   There are *examples* for index gathering functions/regular
;;   expressions for C/C++ and Lisp/Emacs Lisp but it is easy to
;;   customize for other modes.  A function for jumping to the chosen
;;   index position is also supplied.
Richard M. Stallman's avatar
Richard M. Stallman committed
48

49 50
;;; History:
;;  Thanks go to
Richard M. Stallman's avatar
Richard M. Stallman committed
51 52
;;  [simon] - Simon Leinen simon@lia.di.epfl.ch
;;  [dean] - Dean Andrews ada@unison.com
53
;;  [alon] - Alon Albert al@mercury.co.il
54
;;  [greg] - Greg Thompson gregt@porsche.visix.COM
55
;;  [wolfgang] - Wolfgang Bangerth zcg51122@rpool1.rus.uni-stuttgart.de
56
;;  [kai] - Kai Grossjohann grossjoh@linus.informatik.uni-dortmund.de
57
;;  [david] - David M. Smith dsmith@stats.adelaide.edu.au
58 59 60
;;  [christian] - Christian Egli Christian.Egli@hcsd.hac.com
;;  [karl] - Karl Fogel kfogel@floss.life.uiuc.edu

61
;;; Code:
Erik Naggum's avatar
Erik Naggum committed
62

63
(eval-when-compile (require 'cl))
Richard M. Stallman's avatar
Richard M. Stallman committed
64 65 66 67 68 69

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Customizable variables
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
70

71 72 73
(defgroup imenu nil
  "Mode-specific buffer indexes."
  :group 'matching
74
  :group 'frames
Dan Nicolaescu's avatar
Dan Nicolaescu committed
75
  :group 'convenience
76
  :link '(custom-manual "(elisp)Imenu"))
77 78

(defcustom imenu-use-markers t
Lute Kamstra's avatar
Lute Kamstra committed
79
  "Non-nil means use markers instead of integers for Imenu buffer positions.
80 81 82

Setting this to nil makes Imenu work a little faster but editing the
buffer will make the generated index positions wrong.
83

84 85 86 87
This might not yet be honored by all index-building functions."
  :type 'boolean
  :group 'imenu)

88

89
(defcustom imenu-max-item-length 60
Lute Kamstra's avatar
Lute Kamstra committed
90
  "If a number, truncate Imenu entries to that length."
91 92
  :type '(choice integer
		 (const :tag "Unlimited"))
93
  :group 'imenu)
94

95
(defcustom imenu-auto-rescan nil
Lute Kamstra's avatar
Lute Kamstra committed
96
  "Non-nil means Imenu should always rescan the buffers."
97 98
  :type 'boolean
  :group 'imenu)
99

100
(defcustom imenu-auto-rescan-maxout 60000
Lute Kamstra's avatar
Lute Kamstra committed
101
  "Imenu auto-rescan is disabled in buffers larger than this size (in bytes).
102 103 104
This variable is buffer-local."
  :type 'integer
  :group 'imenu)
Richard M. Stallman's avatar
Richard M. Stallman committed
105

106 107
(defvar imenu-always-use-completion-buffer-p nil)
(make-obsolete-variable 'imenu-always-use-completion-buffer-p
108
			'imenu-use-popup-menu "22.1")
109 110 111 112 113 114 115 116 117 118 119

(defcustom imenu-use-popup-menu
  (if imenu-always-use-completion-buffer-p
      (not (eq imenu-always-use-completion-buffer-p 'never))
    'on-mouse)
  "Use a popup menu rather than a minibuffer prompt.
If nil, always use a minibuffer prompt.
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)
120 121
		 (other :tag "Always" t))
  :group 'imenu)
122 123 124 125

(defcustom imenu-eager-completion-buffer
  (not (eq imenu-always-use-completion-buffer-p 'never))
  "If non-nil, eagerly popup the completion buffer."
126 127
  :type 'boolean
  :group 'imenu
128
  :version "22.1")
Richard M. Stallman's avatar
Richard M. Stallman committed
129

130
(defcustom imenu-after-jump-hook nil
Lute Kamstra's avatar
Lute Kamstra committed
131
  "Hooks called after jumping to a place in the buffer.
132 133 134 135 136 137

Useful things to use here include `reposition-window', `recenter', and
\(lambda () (recenter 0)) to show at top of screen."
  :type 'hook
  :group 'imenu)

138
;;;###autoload
139
(defcustom imenu-sort-function nil
Lute Kamstra's avatar
Lute Kamstra committed
140
  "The function to use for sorting the index mouse-menu.
Richard M. Stallman's avatar
Richard M. Stallman committed
141 142 143 144 145 146 147

Affects only the mouse index menu.

Set this to nil if you don't want any sorting (faster).
The items in the menu are then presented in the order they were found
in the buffer.

148
Set it to `imenu--sort-by-name' if you want alphabetic sorting.
Richard M. Stallman's avatar
Richard M. Stallman committed
149

150
The function should take two arguments and return t if the first
Richard M. Stallman's avatar
Richard M. Stallman committed
151
element should come before the second.  The arguments are cons cells;
152
\(NAME . POSITION).  Look at `imenu--sort-by-name' for an example."
153
  :type '(choice (const :tag "No sorting" nil)
154
		 (const :tag "Sort by name" imenu--sort-by-name)
155
		 (function :tag "Another function"))
156
  :group 'imenu)
Richard M. Stallman's avatar
Richard M. Stallman committed
157

158
(defcustom imenu-max-items 25
Lute Kamstra's avatar
Lute Kamstra committed
159
  "Maximum number of elements in a mouse menu for Imenu."
160 161
  :type 'integer
  :group 'imenu)
Richard M. Stallman's avatar
Richard M. Stallman committed
162

163 164 165 166 167 168 169 170 171 172 173
;; 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)
Richard M. Stallman's avatar
Richard M. Stallman committed
174

175
(defcustom imenu-space-replacement "."
Lute Kamstra's avatar
Lute Kamstra committed
176
  "The replacement string for spaces in index names.
177
Used when presenting the index in a completion buffer to make the
178
names work as tokens."
179
  :type '(choice string (const nil))
180
  :group 'imenu)
Richard M. Stallman's avatar
Richard M. Stallman committed
181

182
(defcustom imenu-level-separator ":"
Lute Kamstra's avatar
Lute Kamstra committed
183
  "The separator between index names of different levels.
Richard M. Stallman's avatar
Richard M. Stallman committed
184
Used for making mouse-menu titles and for flattening nested indexes
185 186 187
with name concatenation."
  :type 'string
  :group 'imenu)
Richard M. Stallman's avatar
Richard M. Stallman committed
188

189
;;;###autoload
190
(defvar imenu-generic-expression nil
191 192
  "The regex pattern to use for creating a buffer index.

193 194 195
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.
196

197
For example, see the value of `fortran-imenu-generic-expression' used by
198 199 200
`fortran-mode' with `imenu-syntax-alist' set locally to give the
characters which normally have \"symbol\" syntax \"word\" syntax
during matching.")
201

202
;;;###autoload
203
(make-variable-buffer-local 'imenu-generic-expression)
204

Richard M. Stallman's avatar
Richard M. Stallman committed
205 206
;;;; Hooks

207
;;;###autoload
Richard M. Stallman's avatar
Richard M. Stallman committed
208
(defvar imenu-create-index-function 'imenu-default-create-index-function
209
  "The function to use for creating an index alist of the current buffer.
Richard M. Stallman's avatar
Richard M. Stallman committed
210

211 212 213
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'.
214

215
See `imenu--index-alist' for the format of the buffer index alist.")
216
;;;###autoload
Richard M. Stallman's avatar
Richard M. Stallman committed
217 218
(make-variable-buffer-local 'imenu-create-index-function)

219
;;;###autoload
220
(defvar imenu-prev-index-position-function 'beginning-of-defun
Richard M. Stallman's avatar
Richard M. Stallman committed
221 222
  "Function for finding the next index position.

223 224
If `imenu-create-index-function' is set to
`imenu-default-create-index-function', then you must set this variable
Richard M. Stallman's avatar
Richard M. Stallman committed
225 226 227 228
to a function that will find the next index, looking backwards in the
file.

The function should leave point at the place to be connected to the
229
index and it should return nil when it doesn't find another index.")
230
;;;###autoload
231
(make-variable-buffer-local 'imenu-prev-index-position-function)
Richard M. Stallman's avatar
Richard M. Stallman committed
232

233
;;;###autoload
234
(defvar imenu-extract-index-name-function nil
235
  "Function for extracting the index item name, given a position.
236 237 238

This function is called after `imenu-prev-index-position-function'
finds a position for an index item, with point at that position.
239
It should return the name for that index item.")
240
;;;###autoload
241
(make-variable-buffer-local 'imenu-extract-index-name-function)
Richard M. Stallman's avatar
Richard M. Stallman committed
242

243 244 245 246 247 248 249 250 251 252
;;;###autoload
(defvar imenu-name-lookup-function nil
  "Function to compare string with index item.

This function will be called with two strings, and should return
non-nil if they match.

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
253
arguments match\".")
254 255 256
;;;###autoload
(make-variable-buffer-local 'imenu-name-lookup-function)

257
;;;###autoload
258 259 260
(defvar imenu-default-goto-function 'imenu-default-goto-function
  "The default function called when selecting an Imenu item.
The function in this variable is called when selecting a normal index-item.")
261
;;;###autoload
262 263 264
(make-variable-buffer-local 'imenu-default-goto-function)


265 266
(defun imenu--subalist-p (item)
  (and (consp (cdr item)) (listp (cadr item))
267
       (not (eq (car (cadr item)) 'lambda))))
268

269 270 271 272 273
;; Macro to display a progress message.
;; RELPOS is the relative position to display.
;; If RELPOS is nil, then the relative position in the buffer
;; is calculated.
;; PREVPOS is the variable in which we store the last position displayed.
274
(defmacro imenu-progress-message (prevpos &optional relpos reverse)
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290

;; 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)))))
)
291 292 293 294 295 296 297 298 299


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
;;;; Some examples of functions utilizing the framework of this
;;;; package.
;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

300 301 302
;; 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.
303
(defun imenu-example--name-and-position ()
304 305
  "Return the current/previous sexp and its (beginning) location.
Don't move point."
306 307
  (save-excursion
    (forward-sexp -1)
308 309 310
    ;; [ydi] modified for imenu-use-markers
    (let ((beg (if imenu-use-markers (point-marker) (point)))
	  (end (progn (forward-sexp) (point))))
311
      (cons (buffer-substring beg end)
312
	    beg))))
313 314
(make-obsolete 'imenu-example--name-and-position
	       "use your own function instead." "23.2")
315 316 317

;;;
;;; Lisp
318
;;;
319 320 321 322 323 324 325 326 327 328 329 330 331 332

(defun imenu-example--lisp-extract-index-name ()
  ;; Example of a candidate for `imenu-extract-index-name-function'.
  ;; This will generate a flat index of definitions in a lisp file.
  (save-match-data
    (and (looking-at "(def")
	 (condition-case nil
	     (progn
	       (down-list 1)
	       (forward-sexp 2)
	       (let ((beg (point))
		     (end (progn (forward-sexp -1) (point))))
		 (buffer-substring beg end)))
	   (error nil)))))
333
(make-obsolete 'imenu-example--lisp-extract-index-name "your own" "23.2")
334 335 336 337 338 339 340 341 342 343 344 345 346 347

(defun imenu-example--create-lisp-index ()
  ;; Example of a candidate for `imenu-create-index-function'.
  ;; It will generate a nested index of definitions.
  (let ((index-alist '())
	(index-var-alist '())
	(index-type-alist '())
	(index-unknown-alist '())
	prev-pos)
    (goto-char (point-max))
    (imenu-progress-message prev-pos 0)
    ;; Search for the function
    (while (beginning-of-defun)
      (imenu-progress-message prev-pos nil t)
348 349 350
	  (save-match-data
	    (and (looking-at "(def")
		 (save-excursion
351
	       (down-list 1)
352
		   (cond
353
		((looking-at "def\\(var\\|const\\)")
354 355 356
		     (forward-sexp 2)
		     (push (imenu-example--name-and-position)
			   index-var-alist))
357
		((looking-at "def\\(un\\|subst\\|macro\\|advice\\)")
358 359 360
		     (forward-sexp 2)
		     (push (imenu-example--name-and-position)
			   index-alist))
361
		((looking-at "def\\(type\\|struct\\|class\\|ine-condition\\)")
362
		     (forward-sexp 2)
363
 		 (if (= (char-after (1- (point))) ?\))
364
			 (progn
365
 		       (forward-sexp -1)
366
			   (down-list 1)
367
 		       (forward-sexp 1)))
368 369 370 371 372
		     (push (imenu-example--name-and-position)
			   index-type-alist))
		    (t
		     (forward-sexp 2)
		     (push (imenu-example--name-and-position)
373 374 375
		       index-unknown-alist)))))))
    (imenu-progress-message prev-pos 100)
    (and index-var-alist
376
	 (push (cons "Variables" index-var-alist)
377 378
	       index-alist))
    (and index-type-alist
379
 	 (push (cons "Types" index-type-alist)
380 381
  	       index-alist))
    (and index-unknown-alist
382
	 (push (cons "Syntax-unknown" index-unknown-alist)
383 384
	       index-alist))
    index-alist))
385
(make-obsolete 'imenu-example--create-lisp-index "your own" "23.2")
386 387 388

;; Regular expression to find C functions
(defvar imenu-example--function-name-regexp-c
389
  (concat
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
   "^[a-zA-Z0-9]+[ \t]?"		; type specs; there can be no
   "\\([a-zA-Z0-9_*]+[ \t]+\\)?"	; more than 3 tokens, right?
   "\\([a-zA-Z0-9_*]+[ \t]+\\)?"
   "\\([*&]+[ \t]*\\)?"			; pointer
   "\\([a-zA-Z0-9_*]+\\)[ \t]*("	; name
   ))

(defun imenu-example--create-c-index (&optional regexp)
  (let ((index-alist '())
	prev-pos char)
    (goto-char (point-min))
    (imenu-progress-message prev-pos 0)
    ;; Search for the function
    (save-match-data
      (while (re-search-forward
	      (or regexp imenu-example--function-name-regexp-c)
	      nil t)
	(imenu-progress-message prev-pos)
	(backward-up-list 1)
	(save-excursion
	  (goto-char (scan-sexps (point) 1))
	  (setq char (following-char)))
	;; Skip this function name if it is a prototype declaration.
	(if (not (eq char ?\;))
	    (push (imenu-example--name-and-position) index-alist))))
    (imenu-progress-message prev-pos 100)
    (nreverse index-alist)))
417
(make-obsolete 'imenu-example--create-c-index "your own" "23.2")
418

Richard M. Stallman's avatar
Richard M. Stallman committed
419 420 421 422 423 424 425 426 427 428 429
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Internal variables
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; The item to use in the index for rescanning the buffer.
(defconst imenu--rescan-item '("*Rescan*" . -99))

;; The latest buffer index.
;; Buffer local.
430
(defvar imenu--index-alist nil
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
  "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
446
element recalculates the buffer's index alist.")
447

Richard M. Stallman's avatar
Richard M. Stallman committed
448 449
(make-variable-buffer-local 'imenu--index-alist)

450
(defvar imenu--last-menubar-index-alist nil
451
  "The latest buffer index alist used to update the menu bar menu.")
452

453 454
(make-variable-buffer-local 'imenu--last-menubar-index-alist)

Richard M. Stallman's avatar
Richard M. Stallman committed
455
;; History list for 'jump-to-function-in-buffer'.
456
;; Making this buffer local caused it not to work!
Richard M. Stallman's avatar
Richard M. Stallman committed
457 458 459 460 461 462 463 464 465 466 467
(defvar imenu--history-list nil)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Internal support functions
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;
;;; Sort function
;;; Sorts the items depending on their index name.
468
;;; An item looks like (NAME . POSITION).
Richard M. Stallman's avatar
Richard M. Stallman committed
469 470 471 472
;;;
(defun imenu--sort-by-name (item1 item2)
  (string-lessp (car item1) (car item2)))

473 474 475
(defun imenu--sort-by-position (item1 item2)
  (< (cdr item1) (cdr item2)))

Richard M. Stallman's avatar
Richard M. Stallman committed
476 477 478 479 480 481 482 483 484 485 486 487 488 489
(defun imenu--relative-position (&optional reverse)
  ;; Support function to calculate relative position in buffer
  ;; Beginning of buffer is 0 and end of buffer is 100
  ;; If REVERSE is non-nil then the beginning is 100 and the end is 0.
  (let ((pos (point))
	(total (buffer-size)))
    (and reverse (setq pos (- total pos)))
    (if (> total 50000)
	;; Avoid overflow from multiplying by 100!
	(/ (1- pos) (max (/ total 100) 1))
      (/ (* 100 (1- pos)) (max total 1)))))

;; 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))
490 491
;;
;; The returned list DOES NOT share structure with LIST.
Richard M. Stallman's avatar
Richard M. Stallman committed
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
(defun imenu--split (list n)
  (let ((remain list)
	(result '())
	(sublist '())
	(i 0))
    (while remain
      (push (pop remain) sublist)
      (incf i)
      (and (= i n)
	   ;; We have finished a sublist
	   (progn (push (nreverse sublist) result)
		  (setq i 0)
		  (setq sublist '()))))
    ;; There might be a sublist (if the length of LIST mod n is != 0)
    ;; that has to be added to the result list.
    (and sublist
	 (push (nreverse sublist) result))
    (nreverse result)))

511 512
;;; Split the alist MENULIST into a nested alist, if it is long enough.
;;; In any case, add TITLE to the front of the alist.
513 514 515 516
;;; 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.
Richard M. Stallman's avatar
Richard M. Stallman committed
517
(defun imenu--split-menu (menulist title)
518 519
  (let ((menulist (copy-sequence menulist))
        keep-at-top tail)
520
    (if (memq imenu--rescan-item menulist)
521
	(setq keep-at-top (list imenu--rescan-item)
522 523
	      menulist (delq imenu--rescan-item menulist)))
    (setq tail menulist)
524
    (dolist (item tail)
525 526 527
      (when (imenu--subalist-p item)
	(push item keep-at-top)
	(setq menulist (delq item menulist))))
528
    (if imenu-sort-function
529
	(setq menulist (sort menulist imenu-sort-function)))
530
    (if (> (length menulist) imenu-max-items)
531 532 533 534 535
	(setq menulist
	      (mapcar
	       (lambda (menu)
		 (cons (format "From: %s" (caar menu)) menu))
	       (imenu--split menulist imenu-max-items))))
536 537
    (cons title
	  (nconc (nreverse keep-at-top) menulist))))
538 539 540

;;; Split up each long alist that are nested within ALIST
;;; into nested alists.
541 542 543
;;;
;;; Return a split and sorted copy of ALIST. The returned alist DOES
;;; NOT share structure with ALIST.
544
(defun imenu--split-submenus (alist)
545 546 547 548 549 550 551
  (mapcar (function
	   (lambda (elt)
	     (if (and (consp elt)
		      (stringp (car elt))
		      (listp (cdr elt)))
		 (imenu--split-menu (cdr elt) (car elt))
	       elt)))
552
	  alist))
Richard M. Stallman's avatar
Richard M. Stallman committed
553

554 555
;;; Truncate all strings in MENULIST to imenu-max-item-length
(defun imenu--truncate-items (menulist)
556 557 558 559 560
  (mapcar (function
	   (lambda (item)
	     (cond
	      ((consp (cdr item))
	       (imenu--truncate-items (cdr item)))
561 562 563 564
	      ;; 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))))))
565
	  menulist))
566 567


568
(defun imenu--make-index-alist (&optional noerror)
569 570
  "Create an index alist for the definitions in the current buffer.
This works by using the hook function `imenu-create-index-function'.
571 572 573
Report an error if the list is empty unless NOERROR is supplied and
non-nil.

574
See `imenu--index-alist' for the format of the index alist."
575 576 577 578
  (or (and imenu--index-alist
	   (or (not imenu-auto-rescan)
	       (and imenu-auto-rescan
		    (> (buffer-size)  imenu-auto-rescan-maxout))))
579 580 581 582 583 584 585 586
      ;; Get the index; truncate if necessary
      (progn
	(setq imenu--index-alist
	      (save-excursion
		(save-restriction
		  (widen)
		  (funcall imenu-create-index-function))))
	(imenu--truncate-items imenu--index-alist)))
587
  (or imenu--index-alist noerror
588
      (error "No items suitable for an index found in this buffer"))
589 590
  (or imenu--index-alist
      (setq imenu--index-alist (list nil)))
Richard M. Stallman's avatar
Richard M. Stallman committed
591 592
  ;; Add a rescan option to the index.
  (cons imenu--rescan-item imenu--index-alist))
593

594 595
;;; Find all markers in alist and makes
;;; them point nowhere.
596 597 598 599
;;; The top-level call uses nil as the argument;
;;; non-nil arguments are in recursivecalls.
(defvar imenu--cleanup-seen)

600
(defun imenu--cleanup (&optional alist)
601
  ;; If alist is provided use that list.
602 603 604 605 606 607
  ;; If not, empty the table of lists already seen
  ;; and use imenu--index-alist.
  (if alist
      (setq imenu--cleanup-seen (cons alist imenu--cleanup-seen))
    (setq alist imenu--index-alist imenu--cleanup-seen (list alist)))

608
  (and alist
609 610 611 612 613 614 615 616 617
       (mapc
	(lambda (item)
	  (cond
	   ((markerp (cdr item))
	    (set-marker (cdr item) nil))
	   ;; Don't process one alist twice.
	   ((memq (cdr item) imenu--cleanup-seen))
	   ((imenu--subalist-p item)
	    (imenu--cleanup (cdr item)))))
618
	alist)
619 620
       t))

621 622 623 624 625 626 627 628 629 630 631 632
(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)))
633 634 635 636 637 638

(defun imenu--in-alist (str alist)
  "Check whether the string STR is contained in multi-level ALIST."
  (let (elt head tail res)
    (setq res nil)
    (while alist
639
      (setq elt (car alist)
640
	    tail (cdr elt)
641 642
	    alist (cdr alist)
	    head (car elt))
643 644 645 646 647 648 649 650 651
      ;; A nested ALIST element looks like
      ;;   (INDEX-NAME (INDEX-NAME . INDEX-POSITION) ...)
      ;; while a bottom-level element looks like
      ;;   (INDEX-NAME . INDEX-POSITION)
      ;; We are only interested in the bottom-level elements, so we need to
      ;; recurse if TAIL is a list.
      (cond ((listp tail)
	     (if (setq res (imenu--in-alist str tail))
		 (setq alist nil)))
652 653 654
	    ((if imenu-name-lookup-function
                 (funcall imenu-name-lookup-function str head)
               (string= str head))
655
	     (setq alist nil res elt))))
656 657
    res))

658
(defvar imenu-syntax-alist nil
659
  "Alist of syntax table modifiers to use while in `imenu--generic-function'.
660 661

The car of the assocs may be either a character or a string and the
Glenn Morris's avatar
Glenn Morris committed
662
cdr is a syntax description appropriate for `modify-syntax-entry'.  For
663 664 665
a string, all the characters in the string get the specified syntax.

This is typically used to give word syntax to characters which
Dave Love's avatar
Dave Love committed
666
normally have symbol syntax to simplify `imenu-expression'
667
and speed-up matching.")
668
;;;###autoload
669 670
(make-variable-buffer-local 'imenu-syntax-alist)

Richard M. Stallman's avatar
Richard M. Stallman committed
671
(defun imenu-default-create-index-function ()
Lute Kamstra's avatar
Lute Kamstra committed
672
  "Default function to create an index alist of the current buffer.
Richard M. Stallman's avatar
Richard M. Stallman committed
673

674
The most general method is to move point to end of buffer, then repeatedly call
675
`imenu-prev-index-position-function' and `imenu-extract-index-name-function'.
676 677 678 679 680
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."
681 682
  ;; These should really be done by setting imenu-create-index-function
  ;; in these major modes.  But save that change for later.
683 684
  (cond ((and imenu-prev-index-position-function
	      imenu-extract-index-name-function)
685
	 (let ((index-alist '())
686
	       prev-pos name)
687
	   (goto-char (point-max))
688
	   (imenu-progress-message prev-pos 0 t)
689
	   ;; Search for the function
690
	   (while (funcall imenu-prev-index-position-function)
691
	     (imenu-progress-message prev-pos nil t)
692 693 694
	     (save-excursion
	       (setq name (funcall imenu-extract-index-name-function)))
	     (and (stringp name)
695 696 697
 		  ;; [ydi] updated for imenu-use-markers
		  (push (cons name (if imenu-use-markers (point-marker) (point)))
			index-alist)))
698
	   (imenu-progress-message prev-pos 100 t)
699 700 701
	   index-alist))
	;; Use generic expression if possible.
	((and imenu-generic-expression)
702
	 (imenu--generic-function imenu-generic-expression))
703
	(t
704
	 (error "This buffer cannot use `imenu-default-create-index-function'"))))
Richard M. Stallman's avatar
Richard M. Stallman committed
705

706 707 708
;;;
;;; Generic index gathering function.
;;;
709

710 711 712
(defvar imenu-case-fold-search t
  "Defines whether `imenu--generic-function' should fold case when matching.

713
This variable should be set (only) by initialization code
714 715
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.")
716
;;;###autoload
717 718
(make-variable-buffer-local 'imenu-case-fold-search)

719 720
;; This function can be called with quitting disabled,
;; so it needs to be careful never to loop!
721
(defun imenu--generic-function (patterns)
722
  "Return an index alist of the current buffer based on PATTERNS.
723

724
PATTERNS is an alist with elements that look like this:
725
 (MENU-TITLE REGEXP INDEX)
726 727
or like this:
 (MENU-TITLE REGEXP INDEX FUNCTION ARGUMENTS...)
728 729
with zero or more ARGUMENTS.  The former format creates a simple
element in the index alist when it matches; the latter creates a
730 731
special element of the form (INDEX-NAME POSITION-MARKER FUNCTION
ARGUMENTS...) with FUNCTION and ARGUMENTS copied from PATTERNS.
732 733 734 735 736 737 738 739 740 741

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
742
true and set `match-data' if it finds another element.
743 744 745 746

INDEX points to the substring in REGEXP that contains the
name (of the function, variable or type) that is to appear in the
menu.
747

748 749 750
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.
751

752
See `lisp-imenu-generic-expression' for an example of PATTERNS.
753

754
Returns an index of the current buffer as an alist.  The elements in
755 756 757 758
the alist look like:
 (INDEX-NAME . INDEX-POSITION)
or like:
 (INDEX-NAME INDEX-POSITION FUNCTION ARGUMENTS...)
759
They may also be nested index alists like:
760 761
 (INDEX-NAME . INDEX-ALIST)
depending on PATTERNS."
762 763

  (let ((index-alist (list 'dummy))
764
	prev-pos
765 766 767 768
        (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)))
769 770 771 772
        (old-table (syntax-table))
        (table (copy-syntax-table (syntax-table)))
        (slist imenu-syntax-alist))
    ;; Modify the syntax table used while matching regexps.
773
    (dolist (syn slist)
774
      ;; The character(s) to modify may be a single char or a string.
775 776
      (if (numberp (car syn))
	  (modify-syntax-entry (car syn) (cdr syn) table)
777 778 779
        (mapc (lambda (c)
                (modify-syntax-entry c (cdr syn) table))
              (car syn))))
780 781
    (goto-char (point-max))
    (imenu-progress-message prev-pos 0 t)
782 783 784
    (unwind-protect			; for syntax table
	(save-match-data
	  (set-syntax-table table)
785

786 787
	  ;; map over the elements of imenu-generic-expression
	  ;; (typically functions, variables ...)
788 789 790 791 792
	  (dolist (pat patterns)
	    (let ((menu-title (car pat))
		  (regexp (nth 1 pat))
		  (index (nth 2 pat))
		  (function (nth 3 pat))
793
		  (rest (nthcdr 4 pat))
794
		  start beg)
795 796
	      ;; Go backwards for convenience of adding items in order.
	      (goto-char (point-max))
797 798 799
	      (while (and (if (functionp regexp)
			      (funcall regexp)
			    (re-search-backward regexp nil t))
800 801 802
			  ;; Exit the loop if we get an empty match,
			  ;; because it means a bad regexp was specified.
			  (not (= (match-beginning 0) (match-end 0))))
803
		(setq start (point))
804
		;; Record the start of the line in which the match starts.
805
		;; That's the official position of this definition.
806 807 808
		(goto-char (match-beginning index))
		(beginning-of-line)
		(setq beg (point))
809 810 811 812 813 814
		(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
815
		    (setq beg (copy-marker beg)))
816 817 818
		(let ((item
		       (if function
			   (nconc (list (match-string-no-properties index)
819
					beg function)
820 821
				  rest)
			 (cons (match-string-no-properties index)
822
			       beg)))
823 824 825 826 827 828
		      ;; 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
829 830 831 832
			    (cons item (cdr menu)))))
		;; Go to the start of the match, to make sure we
		;; keep making progress backwards.
		(goto-char start))))
833
	  (set-syntax-table old-table)))
834
    (imenu-progress-message prev-pos 100 t)
835 836
    ;; Sort each submenu by position.
    ;; This is in case one submenu gets items from two different regexps.
837 838 839
    (dolist (item index-alist)
      (when (listp item)
	(setcdr item (sort (cdr item) 'imenu--sort-by-position))))
840
    (let ((main-element (assq nil index-alist)))
841 842
      (nconc (delq main-element (delq 'dummy index-alist))
	     (cdr main-element)))))
843

Richard M. Stallman's avatar
Richard M. Stallman committed
844 845 846 847 848 849
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; The main functions for this package!
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

850 851 852 853 854 855 856 857 858 859 860 861 862
;; See also info-lookup-find-item
(defun imenu-find-default (guess completions)
  "Fuzzily find an item based on GUESS inside the alist COMPLETIONS."
  (catch 'found
    (let ((case-fold-search t))
      (if (assoc guess completions) guess
	(dolist (re (list (concat "\\`" (regexp-quote guess) "\\'")
			  (concat "\\`" (regexp-quote guess))
			  (concat (regexp-quote guess) "\\'")
			  (regexp-quote guess)))
	  (dolist (x completions)
	    (if (string-match re (car x)) (throw 'found (car x)))))))))

Richard M. Stallman's avatar
Richard M. Stallman committed
863 864 865
(defun imenu--completion-buffer (index-alist &optional prompt)
  "Let the user select from INDEX-ALIST in a completion buffer with PROMPT.

866
Return one of the entries in index-alist or nil."
Richard M. Stallman's avatar
Richard M. Stallman committed
867
  ;; Create a list for this buffer only when needed.
868 869 870
  (let ((name (thing-at-point 'symbol))
	choice
	(prepared-index-alist
871 872 873
	 (if (not imenu-space-replacement) index-alist
	   (mapcar
	    (lambda (item)
874
	      (cons (subst-char-in-string ?\s (aref imenu-space-replacement 0)
875 876 877
					  (car item))
		    (cdr item)))
	    index-alist))))
878 879
    (when (stringp name)
      (setq name (or (imenu-find-default name prepared-index-alist) name)))
880 881 882 883
    (cond (prompt)
	  ((and name (imenu--in-alist name prepared-index-alist))
	   (setq prompt (format "Index item (default %s): " name)))
	  (t (setq prompt "Index item: ")))
884 885 886 887 888 889 890
    (let ((minibuffer-setup-hook minibuffer-setup-hook))
      ;; Display the completion buffer.
      (if (not imenu-eager-completion-buffer)
	  (add-hook 'minibuffer-setup-hook 'minibuffer-completion-help))
      (setq name (completing-read prompt
				  prepared-index-alist
				  nil t nil 'imenu--history-list name)))
891

892 893 894 895 896
    (when (stringp name)
      (setq choice (assoc name prepared-index-alist))
      (if (imenu--subalist-p choice)
	  (imenu--completion-buffer (cdr choice) prompt)
	choice))))
897

Richard M. Stallman's avatar
Richard M. Stallman committed
898 899 900 901 902
(defun imenu--mouse-menu (index-alist event &optional title)
  "Let the user select from a buffer index from a mouse menu.

INDEX-ALIST is the buffer index and EVENT is a mouse event.

903
Returns t for rescan and otherwise an element or subelement of INDEX-ALIST."
904
  (setq index-alist (imenu--split-submenus index-alist))
905
  (let* ((menu (imenu--split-menu index-alist (or title (buffer-name))))
906 907 908 909
	 (map (imenu--create-keymap (car menu)
				    (cdr (if (< 1 (length (cdr menu)))
					     menu
					   (car (cdr menu)))))))
910
    (popup-menu map event)))
Richard M. Stallman's avatar
Richard M. Stallman committed
911

Richard M. Stallman's avatar
Richard M. Stallman committed
912
(defun imenu-choose-buffer-index (&optional prompt alist)
Richard M. Stallman's avatar
Richard M. Stallman committed
913 914 915 916 917 918
  "Let the user select from a buffer index and return the chosen index.

If the user originally activated this function with the mouse, a mouse
menu is used.  Otherwise a completion buffer is used and the user is
prompted with PROMPT.