(tcl-do-fill-paragraph): New function.
[emacs.git] / lisp / imenu.el
blob3fedade04e77249018ff5072b931c0657d63f282
1 ;;; imenu.el --- Framework for mode-specific buffer indexes.
3 ;; Copyright (C) 1994 Free Software Foundation, Inc.
5 ;; Author: Ake Stenhoff <etxaksf@aom.ericsson.se>
6 ;; Lars Lindberg <lli@sypro.cap.se>
7 ;; Created: 8 Feb 1994
8 ;; Version: 1.17
9 ;; Keywords: tools
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; any later version.
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with this program; if not, write to the Free Software
23 ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 ;;; Commentary:
27 ;; Purpose of this package:
28 ;; To present a framework for mode-specific buffer indexes.
29 ;; A buffer index is an alist of names and buffer positions.
30 ;; For instance all functions in a C-file and their positions.
32 ;; How it works:
34 ;; A mode-specific function is called to generate the index. It is
35 ;; then presented to the user, who can choose from this index.
37 ;; The package comes with a set of example functions for how to
38 ;; utilize this package.
40 ;; There are *examples* for index gathering functions/regular
41 ;; expressions for C/C++ and Lisp/Emacs Lisp but it is easy to
42 ;; customize for other modes. A function for jumping to the chosen
43 ;; index position is also supplied.
45 ;;; Thanks goes to
46 ;; [simon] - Simon Leinen simon@lia.di.epfl.ch
47 ;; [dean] - Dean Andrews ada@unison.com
48 ;; [alon] - Alon Albert al@mercury.co.il
49 ;; [greg] - Greg Thompson gregt@porsche.visix.COM
50 ;; [wolfgang] - Wolfgang Bangerth zcg51122@rpool1.rus.uni-stuttgart.de
51 ;; [kai] - Kai Grossjohann grossjoh@linus.informatik.uni-dortmund.de
52 ;; [david] - David M. Smith dsmith@stats.adelaide.edu.au
53 ;; [christian] - Christian Egli Christian.Egli@hcsd.hac.com
54 ;; [karl] - Karl Fogel kfogel@floss.life.uiuc.edu
56 ;;; Code
57 (eval-when-compile (require 'cl))
59 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
60 ;;;
61 ;;; Customizable variables
62 ;;;
63 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
64 (defvar imenu-use-keymap-menu nil
65 "* Set this to non-nil for using a keymap when making
66 the mouse menu.")
68 (defvar imenu-auto-rescan nil
69 "* T if we always should rescan the buffers, nil to disable
70 automatic rescan.")
72 (defvar imenu-auto-rescan-maxout 60000
73 "* auto-rescan is disabled in buffers larger than this.
74 This variable is buffer-local.")
76 (defvar imenu-always-use-completion-buffer-p nil
77 "*Set this to non-nil for displaying the index in a completion buffer.
79 Non-nil means always display the index in a completion buffer.
80 Nil means display the index as a mouse menu when the mouse was
81 used to invoke `imenu'.
82 `never' means never automatically display a listing of any kind.")
84 (defvar imenu-sort-function nil
85 "*The function to use for sorting the index mouse-menu.
87 Affects only the mouse index menu.
89 Set this to nil if you don't want any sorting (faster).
90 The items in the menu are then presented in the order they were found
91 in the buffer.
93 Set it to `imenu--sort-by-name' if you want alphabetic sorting.
95 The function should take two arguments and return T if the first
96 element should come before the second. The arguments are cons cells;
97 \(NAME . POSITION). Look at `imenu--sort-by-name' for an example.")
99 (defvar imenu-max-items 25
100 "*Maximum number of elements in an index mouse-menu.")
102 (defvar imenu-scanning-message "Scanning buffer for index. (%3d%%)"
103 "*Progress message during the index scanning of the buffer.
104 If non-nil, user gets a message during the scanning of the buffer
106 Relevant only if the mode-specific function that creates the buffer
107 index use `imenu-progress-message'.")
109 (defvar imenu-space-replacement "^"
110 "*The replacement string for spaces in index names.
111 Used when presenting the index in a completion-buffer to make the
112 names work as tokens.")
114 (defvar imenu-level-separator ":"
115 "*The separator between index names of different levels.
116 Used for making mouse-menu titles and for flattening nested indexes
117 with name concatenation.")
119 (defvar imenu-submenu-name-format "%s..."
120 "*The format for making a submenu name.")
122 ;;;###autoload
123 (defvar imenu-generic-expression nil
124 "The regex pattern to use for creating a buffer index.
126 If non-nil this pattern is passed to `imenu-create-index-with-pattern'
127 to create a buffer index.
129 It is an alist with elements that look like this: (MENU-TITLE
130 REGEXP INDEX).
132 MENU-TITLE is a string used as the title for the submenu or nil if the
133 entries are not nested.
135 REGEXP is a regexp that should match a construct in the buffer that is
136 to be displayed in the menu i.e. function or variable definitions,
137 etc. It contains a substring which is the name to appear in the
138 menu. See the info section on Regexps for more information.
140 INDEX points to the substring in REGEXP that contains the name (of the
141 function, variable or type) that is to appear in the menu.
143 For emacs-lisp-mode for example PATTERN would look like:
145 '((nil \"^\\s-*(def\\(un\\|subst\\|macro\\|advice\\)\\s-+\\([-A-Za-z0-9+]+\\)\" 2)
146 (\"*Vars*\" \"^\\s-*(def\\(var\\|const\\)\\s-+\\([-A-Za-z0-9+]+\\)\" 2)
147 (\"*Types*\" \"^\\s-*(def\\(type\\|struct\\|class\\|ine-condition\\)\\s-+\\([-A-Za-z0-9+]+\\)\" 2))
149 The variable is buffer-local.")
151 ;;;###autoload
152 (make-variable-buffer-local 'imenu-create-index-pattern)
154 ;; make sure the default is nil
155 (setq-default imenu-create-index-pattern nil)
157 ;;;; Hooks
159 (defvar imenu-create-index-function 'imenu-default-create-index-function
160 "The function to use for creating a buffer index.
162 It should be a function that takes no arguments and returns an index
163 of the current buffer as an alist. The elements in the alist look
164 like: (INDEX-NAME . INDEX-POSITION). You may also nest index list like
165 \(INDEX-NAME . INDEX-ALIST).
167 This function is called within a `save-excursion'.
169 The variable is buffer-local.")
170 (make-variable-buffer-local 'imenu-create-index-function)
172 (defvar imenu-prev-index-position-function 'beginning-of-defun
173 "Function for finding the next index position.
175 If `imenu-create-index-function' is set to
176 `imenu-default-create-index-function', then you must set this variable
177 to a function that will find the next index, looking backwards in the
178 file.
180 The function should leave point at the place to be connected to the
181 index and it should return nil when it doesn't find another index. ")
182 (make-variable-buffer-local 'imenu-prev-index-position-function)
184 (defvar imenu-extract-index-name-function nil
185 "Function for extracting the index name.
187 This function is called after the function pointed out by
188 `imenu-prev-index-position-function'.")
189 (make-variable-buffer-local 'imenu-extract-index-name-function)
192 ;;; Macro to display a progress message.
193 ;;; RELPOS is the relative position to display.
194 ;;; If RELPOS is nil, then the relative position in the buffer
195 ;;; is calculated.
196 ;;; PREVPOS is the variable in which we store the last position displayed.
197 (defmacro imenu-progress-message (prevpos &optional relpos reverse)
198 (` (and
199 imenu-scanning-message
200 (let ((pos (, (if relpos
201 relpos
202 (` (imenu--relative-position (, reverse)))))))
203 (if (, (if relpos t
204 (` (> pos (+ 5 (, prevpos))))))
205 (progn
206 (message imenu-scanning-message pos)
207 (setq (, prevpos) pos)))))))
210 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
211 ;;;;
212 ;;;; Some examples of functions utilizing the framework of this
213 ;;;; package.
214 ;;;;
215 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
217 ;; Return the current/previous sexp and the location of the sexp (it's
218 ;; beginning) without moving the point.
219 (defun imenu-example--name-and-position ()
220 (save-excursion
221 (forward-sexp -1)
222 (let ((beg (point))
223 (end (progn (forward-sexp) (point)))
224 (marker (make-marker)))
225 (set-marker marker beg)
226 (cons (buffer-substring beg end)
227 marker))))
230 ;;; Lisp
231 ;;;
233 (defun imenu-example--lisp-extract-index-name ()
234 ;; Example of a candidate for `imenu-extract-index-name-function'.
235 ;; This will generate a flat index of definitions in a lisp file.
236 (save-match-data
237 (and (looking-at "(def")
238 (condition-case nil
239 (progn
240 (down-list 1)
241 (forward-sexp 2)
242 (let ((beg (point))
243 (end (progn (forward-sexp -1) (point))))
244 (buffer-substring beg end)))
245 (error nil)))))
247 (defun imenu-example--create-lisp-index ()
248 ;; Example of a candidate for `imenu-create-index-function'.
249 ;; It will generate a nested index of definitions.
250 (let ((index-alist '())
251 (index-var-alist '())
252 (index-type-alist '())
253 (index-unknown-alist '())
254 prev-pos)
255 (goto-char (point-max))
256 (imenu-progress-message prev-pos 0)
257 ;; Search for the function
258 (while (beginning-of-defun)
259 (imenu-progress-message prev-pos nil t)
260 (save-match-data
261 (and (looking-at "(def")
262 (save-excursion
263 (down-list 1)
264 (cond
265 ((looking-at "def\\(var\\|const\\)")
266 (forward-sexp 2)
267 (push (imenu-example--name-and-position)
268 index-var-alist))
269 ((looking-at "def\\(un\\|subst\\|macro\\|advice\\)")
270 (forward-sexp 2)
271 (push (imenu-example--name-and-position)
272 index-alist))
273 ((looking-at "def\\(type\\|struct\\|class\\|ine-condition\\)")
274 (forward-sexp 2)
275 (if (= (char-after (1- (point))) ?\))
276 (progn
277 (forward-sexp -1)
278 (down-list 1)
279 (forward-sexp 1)))
280 (push (imenu-example--name-and-position)
281 index-type-alist))
283 (forward-sexp 2)
284 (push (imenu-example--name-and-position)
285 index-unknown-alist)))))))
286 (imenu-progress-message prev-pos 100)
287 (and index-var-alist
288 (push (cons (imenu-create-submenu-name "Variables") index-var-alist)
289 index-alist))
290 (and index-type-alist
291 (push (cons (imenu-create-submenu-name "Types") index-type-alist)
292 index-alist))
293 (and index-unknown-alist
294 (push (cons (imenu-create-submenu-name "Syntax-unknown") index-unknown-alist)
295 index-alist))
296 index-alist))
298 (defvar imenu-generic-lisp-expression
300 (nil
301 "^\\s-*(def\\(un\\|subst\\|macro\\|advice\\)\\s-+\\([-A-Za-z0-9+]+\\)" 2)
302 ("Variables"
303 "^\\s-*(def\\(var\\|const\\)\\s-+\\([-A-Za-z0-9+]+\\)" 2)
304 ("Types"
305 "^\\s-*(def\\(type\\|struct\\|class\\|ine-condition\\)\\s-+\\([-A-Za-z0-9+]+\\)"
308 "imenu generic expression for Lisp mode in the form
309 (PATTERN), where PATTERN is a list containing entries of the form
310 (MENU-TITLE REGEXP INDEX). See `imenu-generic-expression'.")
313 ;;; C++
315 ;; Example of an imenu-generic-expression
317 (defvar imenu-generic-c++-expression
319 ((nil
321 (concat
322 "^" ; beginning of line is required
323 "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>"
324 "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; type specs; there can be no
325 "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; more than 3 tokens, right?
327 "\\(" ; last type spec including */&
328 "[a-zA-Z0-9_:]+"
329 "\\([ \t]*[*&]+[ \t]*\\|[ \t]+\\)" ; either pointer/ref sign or whitespace
330 "\\)?" ; if there is a last type spec
331 "\\(" ; name; take that into the imenu entry
332 "[a-zA-Z0-9_:~]+" ; member function, ctor or dtor...
333 ; (may not contain * because then
334 ; "a::operator char*" would become "char*"!)
335 "\\|"
336 "\\([a-zA-Z0-9_:~]*::\\)?operator"
337 "[^a-zA-Z1-9_][^(]*" ; ...or operator
338 " \\)"
339 "[ \t]*([^)]*)[ \t\n]*[^ ;]" ; require something other than a ; after
340 ; the (...) to avoid prototypes. Can't
341 ; catch cases with () inside the parentheses
342 ; surrounding the parameters
343 ; (like "int foo(int a=bar()) {...}"
345 )) 6)
346 ("Class"
347 (, (concat
348 "^" ; beginning of line is required
349 "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>"
350 "class[ \t]+"
351 "\\([a-zA-Z0-9_]+\\)" ; this is the string we want to get
352 "[ \t]*[:{]"
353 )) 2)
354 ;; Example of generic expression for finding prototypes, structs, unions, enums.
355 ;; Uncomment if You want to find these too. It will be at bit slower gathering
356 ;; the indexes.
357 ; ("Prototypes"
358 ; (,
359 ; (concat
360 ; "^" ; beginning of line is required
361 ; "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>"
362 ; "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; type specs; there can be no
363 ; "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; more than 3 tokens, right?
365 ; "\\(" ; last type spec including */&
366 ; "[a-zA-Z0-9_:]+"
367 ; "\\([ \t]*[*&]+[ \t]*\\|[ \t]+\\)" ; either pointer/ref sign or whitespace
368 ; "\\)?" ; if there is a last type spec
369 ; "\\(" ; name; take that into the imenu entry
370 ; "[a-zA-Z0-9_:~]+" ; member function, ctor or dtor...
371 ; ; (may not contain * because then
372 ; ; "a::operator char*" would become "char*"!)
373 ; "\\|"
374 ; "\\([a-zA-Z0-9_:~]*::\\)?operator"
375 ; "[^a-zA-Z1-9_][^(]*" ; ...or operator
376 ; " \\)"
377 ; "[ \t]*([^)]*)[ \t\n]*;" ; require ';' after
378 ; ; the (...) Can't
379 ; ; catch cases with () inside the parentheses
380 ; ; surrounding the parameters
381 ; ; (like "int foo(int a=bar());"
382 ; )) 6)
383 ; ("Struct"
384 ; (, (concat
385 ; "^" ; beginning of line is required
386 ; "\\(static[ \t]+\\)?" ; there may be static or const.
387 ; "\\(const[ \t]+\\)?"
388 ; "struct[ \t]+"
389 ; "\\([a-zA-Z0-9_]+\\)" ; this is the string we want to get
390 ; "[ \t]*[{]"
391 ; )) 3)
392 ; ("Enum"
393 ; (, (concat
394 ; "^" ; beginning of line is required
395 ; "\\(static[ \t]+\\)?" ; there may be static or const.
396 ; "\\(const[ \t]+\\)?"
397 ; "enum[ \t]+"
398 ; "\\([a-zA-Z0-9_]+\\)" ; this is the string we want to get
399 ; "[ \t]*[{]"
400 ; )) 3)
401 ; ("Union"
402 ; (, (concat
403 ; "^" ; beginning of line is required
404 ; "\\(static[ \t]+\\)?" ; there may be static or const.
405 ; "\\(const[ \t]+\\)?"
406 ; "union[ \t]+"
407 ; "\\([a-zA-Z0-9_]+\\)" ; this is the string we want to get
408 ; "[ \t]*[{]"
409 ; )) 3)
411 "imenu generic expression for C++ mode in the form
412 (PATTERN), where PATTERN is a list containing entries of the form
413 (MENU-TITLE REGEXP INDEX). See `imenu-generic-expression'.")
416 ;;; C
419 (defvar imenu-generic-c-expression
420 ;; Use the C++ expression above.
421 imenu-generic-c++-expression
422 "imenu generic expression for C mode in the form
423 (PATTERN), where PATTERN is a list containing entries of the form
424 (MENU-TITLE REGEXP INDEX). See `imenu-generic-expression'.")
426 ;; Regular expression to find C functions
427 (defvar imenu-example--function-name-regexp-c
428 (concat
429 "^[a-zA-Z0-9]+[ \t]?" ; type specs; there can be no
430 "\\([a-zA-Z0-9_*]+[ \t]+\\)?" ; more than 3 tokens, right?
431 "\\([a-zA-Z0-9_*]+[ \t]+\\)?"
432 "\\([*&]+[ \t]*\\)?" ; pointer
433 "\\([a-zA-Z0-9_*]+\\)[ \t]*(" ; name
436 (defun imenu-example--create-c-index (&optional regexp)
437 (let ((index-alist '())
438 prev-pos char)
439 (goto-char (point-min))
440 (imenu-progress-message prev-pos 0)
441 ;; Search for the function
442 (save-match-data
443 (while (re-search-forward
444 (or regexp imenu-example--function-name-regexp-c)
445 nil t)
446 (imenu-progress-message prev-pos)
447 (backward-up-list 1)
448 (save-excursion
449 (goto-char (scan-sexps (point) 1))
450 (setq char (following-char)))
451 ;; Skip this function name if it is a prototype declaration.
452 (if (not (eq char ?\;))
453 (push (imenu-example--name-and-position) index-alist))))
454 (imenu-progress-message prev-pos 100)
455 (nreverse index-alist)))
459 ;; Ada
461 ;; Written by Christian Egli <Christian.Egli@hcsd.hac.com>
463 (defvar imenu-generic-ada-expression
464 '((nil "^\\s-*\\(procedure\\|function\\)\\s-+\\([A-Za-z0-9_]+\\)" 2)
465 ("Type Defs" "^\\s-*\\(sub\\)?type\\s-+\\([A-Za-z0-9_]+\\)" 2))
467 "imenu generic expression for Ada mode in the form
468 (PATTERN), where PATTERN is a list containing entries of the form
469 (MENU-TITLE REGEXP INDEX). See `imenu-generic-expression'.")
471 ;;;
472 ;;; TexInfo
473 ;;;
474 ;; Written by Wolfgang Bangerth <zcg51122@rpool1.rus.uni-stuttgart.de>
477 (defvar imenu-generic-texinfo-expression
478 '((nil "^@node[ \t]+\\([^,\n]*\\)" 1)
479 ("Chapters" "^@chapter[ \t]+\\(.*\\)$" 1))
481 "imenu generic expression for TexInfo mode in the form
482 (PATTERN), where PATTERN is a list containing entries of the form
483 (MENU-TITLE REGEXP INDEX). See `imenu-generic-expression'.
485 To overide this example, Either set 'imenu-generic-expression
486 or 'imenu-create-index-function")
488 ;;;
489 ;;; LaTex
490 ;;;
491 ;; Written by Wolfgang Bangerth <zcg51122@rpool1.rus.uni-stuttgart.de>
494 (defvar imenu-generic-latex-expression
496 ("Part" "\\\\part{\\([^}]*\\)}" 1)
497 ("Chapter" "\\\\chapter{\\([^}]*\\)}" 1)
498 ("Section" "\\\\[a-zA-Z]*section{\\([^}]*\\)}" 1)
499 ;; i put numbers like 3.15 before my
500 ;; \begin{equation}'s which tell me
501 ;; the number the equation will get when
502 ;; being printed.
503 ("Equations" "%[ \t]*\\([0-9]+\\.[0-9]+\\)[,;]?[ \t]?" 1))
505 "imenu generic expression for LaTex mode in the form
506 (PATTERN), where PATTERN is a list containing entries of the form
507 (MENU-TITLE REGEXP INDEX). See `imenu-generic-expression'.")
509 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
511 ;;; Internal variables
513 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
515 ;; The item to use in the index for rescanning the buffer.
516 (defconst imenu--rescan-item '("*Rescan*" . -99))
518 ;; The latest buffer index.
519 ;; Buffer local.
520 (defvar imenu--index-alist nil)
521 (make-variable-buffer-local 'imenu--index-alist)
523 ;; History list for 'jump-to-function-in-buffer'.
524 ;; Buffer local.
525 (defvar imenu--history-list nil)
526 (make-variable-buffer-local 'imenu--history-list)
528 (defvar imenu--scanning-method-alist
529 '((emacs-lisp-mode imenu-generic-lisp-expression)
530 (lisp-mode imenu-example--create-lisp-index)
531 (c++-mode imenu-generic-c++-expression)
532 (c-mode imenu-generic-c-expression)
533 (latex-mode imenu-generic-latex-expression)
534 (texinfo-mode imenu-generic-texinfo-expression)
535 (ada-mode imenu-generic-ada-expression))
537 "Alist of major mode and imenu scanning methods.
539 Each item should be a list of the form: (MAJOR-MODE
540 IMENU-SCANNING-METHOD) where both MAJOR-MODE and IMENU-SCANNING-METHOD
541 are symbols. If IMENU-SCANNING-METHOD is a function then it is called
542 to create an index. If it is a `pattern' (See `imenu-generic-expression')
543 it is passed to imenu--generic-function to create an index.")
545 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
547 ;;; Internal support functions
549 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
552 ;;; Sort function
553 ;;; Sorts the items depending on their index name.
554 ;;; An item look like (NAME . POSITION).
556 (defun imenu--sort-by-name (item1 item2)
557 (string-lessp (car item1) (car item2)))
559 (defun imenu--relative-position (&optional reverse)
560 ;; Support function to calculate relative position in buffer
561 ;; Beginning of buffer is 0 and end of buffer is 100
562 ;; If REVERSE is non-nil then the beginning is 100 and the end is 0.
563 (let ((pos (point))
564 (total (buffer-size)))
565 (and reverse (setq pos (- total pos)))
566 (if (> total 50000)
567 ;; Avoid overflow from multiplying by 100!
568 (/ (1- pos) (max (/ total 100) 1))
569 (/ (* 100 (1- pos)) (max total 1)))))
572 ;;; Function for suporting general looking submenu names.
573 ;;; Uses `imenu-submenu-name-format' for creating the name.
574 ;;; NAME is the base of the new submenu name.
576 (defun imenu-create-submenu-name (name)
577 (format imenu-submenu-name-format name))
579 ;; Split LIST into sublists of max length N.
580 ;; Example (imenu--split '(1 2 3 4 5 6 7 8) 3)-> '((1 2 3) (4 5 6) (7 8))
581 (defun imenu--split (list n)
582 (let ((remain list)
583 (result '())
584 (sublist '())
585 (i 0))
586 (while remain
587 (push (pop remain) sublist)
588 (incf i)
589 (and (= i n)
590 ;; We have finished a sublist
591 (progn (push (nreverse sublist) result)
592 (setq i 0)
593 (setq sublist '()))))
594 ;; There might be a sublist (if the length of LIST mod n is != 0)
595 ;; that has to be added to the result list.
596 (and sublist
597 (push (nreverse sublist) result))
598 (nreverse result)))
601 ;;; Split a menu in to several menus.
603 (defun imenu--split-menu (menulist title)
604 (cons "Index menu"
605 (mapcar
606 (function
607 (lambda (menu)
608 (cons (format "(%s)" title) menu)))
609 (imenu--split menulist imenu-max-items))))
612 ;;; Find all items in this buffer that should be in the index.
613 ;;; Returns an alist on the form
614 ;;; ((NAME . POSITION) (NAME . POSITION) ...)
617 (defun imenu--make-index-alist ()
618 ;; Create a list for this buffer only when needed.
619 (or (and imenu--index-alist
620 (or (not imenu-auto-rescan)
621 (and imenu-auto-rescan
622 (> (buffer-size) imenu-auto-rescan-maxout))))
623 ;; Get the index
624 (setq imenu--index-alist
625 (save-excursion
626 (funcall imenu-create-index-function))))
627 (or imenu--index-alist
628 (error "No items suitable for an index found in this buffer."))
629 ;; Add a rescan option to the index.
630 (cons imenu--rescan-item imenu--index-alist))
632 ;;; Find all markers in alist and makes
633 ;;; them point nowhere.
635 (defun imenu--cleanup (&optional alist)
636 ;; Sets the markers in imenu--index-alist
637 ;; point nowhere.
638 ;; if alist is provided use that list.
639 (or alist
640 (setq alist imenu--index-alist))
641 (and alist
642 (mapcar
643 (function
644 (lambda (item)
645 (cond
646 ((markerp (cdr item))
647 (set-marker (cdr item) nil))
648 ((consp (cdr item))
649 (imenu--cleanup (cdr item))))))
650 alist)
653 (defun imenu--create-keymap-2 (alist counter)
654 (let ((map nil))
655 (mapcar
656 (function
657 (lambda (item)
658 (cond
659 ((listp (cdr item))
660 (append (list (incf counter) (car item) 'keymap (car item))
661 (imenu--create-keymap-2 (cdr item) (+ counter 10))))
663 (let ((end (cons '(nil) t)))
664 (cons (car item)
665 (cons (car item) end))))
667 alist)))
669 (defun imenu--create-keymap-1 (title alist)
670 (append (list 'keymap title) (imenu--create-keymap-2 alist 0)))
673 (defun imenu--in-alist (str alist)
674 "Check whether the string STR is contained in multi-level ALIST."
675 (let (elt head tail res)
676 (setq res nil)
677 (while alist
678 (setq elt (car alist)
679 tail (cdr elt)
680 alist (cdr alist)
681 head (car elt))
682 (if (string= str head)
683 (setq alist nil res elt)
684 (if (and (listp tail)
685 (setq res (imenu--in-alist str tail)))
686 (setq alist nil))))
687 res))
689 (defun imenu-default-create-index-function ()
690 "*Wrapper for index searching functions.
692 Moves point to end of buffer and then repeatedly calls
693 `imenu-prev-index-position-function' and `imenu-extract-index-name-function'.
694 Their results are gathered into an index alist."
695 ;; These should really be done by setting imenu-create-index-function
696 ;; in these major modes. But save that change for later.
697 (cond ((and (fboundp imenu-prev-index-position-function)
698 (fboundp imenu-extract-index-name-function))
699 (let ((index-alist '())
700 prev-pos name)
701 (goto-char (point-max))
702 (imenu-progress-message prev-pos 0 t)
703 ;; Search for the function
704 (while (funcall imenu-prev-index-position-function)
705 (imenu-progress-message prev-pos nil t)
706 (save-excursion
707 (setq name (funcall imenu-extract-index-name-function)))
708 (and (stringp name)
709 (push (cons name (point)) index-alist)))
710 (imenu-progress-message prev-pos 100 t)
711 index-alist))
712 ;; Use generic expression if possible.
713 ((and imenu-generic-expression)
714 (imenu--generic-function imenu-generic-expression))
715 ;; Use supplied example functions or expressions
716 ((assq major-mode imenu--scanning-method-alist)
717 (let ((method (cadr (assq major-mode imenu--scanning-method-alist))))
718 ;; is it a function?
719 (if (fboundp method)
720 ;; ... then call it
721 (funcall method)
722 ;; ...otherwise pass the pattern to imenu--generic-function
723 (imenu--generic-function (eval method)))))
725 (error "The mode \"%s\" does not take full advantage of imenu.el yet."
726 mode-name))))
728 (defun imenu--replace-spaces (name replacement)
729 ;; Replace all spaces in NAME with REPLACEMENT.
730 ;; That second argument should be a string.
731 (mapconcat
732 (function
733 (lambda (ch)
734 (if (char-equal ch ?\ )
735 replacement
736 (char-to-string ch))))
737 name
738 ""))
740 (defun imenu--flatten-index-alist (index-alist &optional concat-names prefix)
741 ;; Takes a nested INDEX-ALIST and returns a flat index alist.
742 ;; If optional CONCAT-NAMES is non-nil, then a nested index has its
743 ;; name and a space concatenated to the names of the children.
744 ;; Third argument PREFIX is for internal use only.
745 (mapcan
746 (function
747 (lambda (item)
748 (let* ((name (car item))
749 (pos (cdr item))
750 (new-prefix (and concat-names
751 (if prefix
752 (concat prefix imenu-level-separator name)
753 name))))
754 (cond
755 ((or (markerp pos) (numberp pos))
756 (list (cons new-prefix pos)))
758 (imenu--flatten-index-alist pos new-prefix))))))
759 index-alist))
762 ;;; Generic index gathering function.
765 (defun imenu--generic-function (patterns)
766 ;; Built on some ideas that Erik Naggum <erik@naggum.no> once posted
767 ;; to comp.emacs
768 "Return an index of the current buffer as an alist.
770 PATTERN is an alist with elements that look like this: (MENU-TITLE
771 REGEXP INDEX).
773 MENU-TITLE is a string used as the title for the submenu or nil if the
774 entries are not nested.
776 REGEXP is a regexp that should match a construct in the buffer that is
777 to be displayed in the menu i.e. function or variable definitions,
778 etc. It contains a substring which is the name to appear in the
779 menu. See the info section on Regexps for more information.
781 INDEX points to the substring in REGEXP that contains the name (of the
782 function, variable or type) that is to appear in the menu.
784 For emacs-lisp-mode for example PATTERN would look like:
786 '((nil \"^\\s-*(def\\(un\\|subst\\|macro\\|advice\\)\\s-+\\([-A-Za-z0-9]+\\)\" 2)
787 (\"*Vars*\" \"^\\s-*(def\\(var\\|const\\)\\s-+\\([-A-Za-z0-9]+\\)\" 2)
788 (\"*Types*\" \"^\\s-*(def\\(type\\|struct\\|class\\|ine-condition\\)\\s-+\\([-A-Za-z0-9]+\\)\" 2))'
790 Returns an index of the current buffer as an alist. The elements in
791 the alist look like: (INDEX-NAME . INDEX-POSITION). They may also be
792 nested index lists like (INDEX-NAME . INDEX-ALIST) depending on
793 pattern.
795 \(imenu--generic-function PATTERN\)."
797 (let ((index-alist (list 'dummy))
798 (found nil)
799 (global-regexp
800 (concat "\\("
801 (mapconcat
802 (function (lambda (pattern) (identity (cadr pattern))))
803 patterns "\\)\\|\\(")
804 "\\)"))
805 prev-pos)
807 (goto-char (point-max))
808 (imenu-progress-message prev-pos 0 t)
809 (save-match-data
810 (while (re-search-backward global-regexp nil t)
811 (imenu-progress-message prev-pos nil t)
812 (setq found nil)
813 (save-excursion
814 (goto-char (match-beginning 0))
815 (mapcar
816 (function
817 (lambda (pat)
818 (let ((menu-title (car pat))
819 (regexp (cadr pat))
820 (index (caddr pat)))
821 (if (and (not found) ; Only allow one entry;
822 (looking-at regexp))
823 (let ((beg (match-beginning index))
824 (end (match-end index)))
825 (setq found t)
826 (push
827 (cons (buffer-substring beg end) beg)
828 (cdr
829 (or (if (not (stringp menu-title)) index-alist)
830 (assoc
831 (imenu-create-submenu-name menu-title)
832 index-alist)
833 (car (push
834 (cons
835 (imenu-create-submenu-name menu-title)
836 '())
837 index-alist))))))))))
838 patterns))))
839 (imenu-progress-message prev-pos 100 t)
840 (delete 'dummy index-alist)))
842 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
844 ;;; The main functions for this package!
846 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
848 (defun imenu--completion-buffer (index-alist &optional prompt)
849 "Let the user select from INDEX-ALIST in a completion buffer with PROMPT.
851 Returns t for rescan and otherwise a position number."
852 ;; Create a list for this buffer only when needed.
853 (let (name choice
854 (prepared-index-alist
855 (mapcar
856 (function
857 (lambda (item)
858 (cons (imenu--replace-spaces (car item) imenu-space-replacement)
859 (cdr item))))
860 index-alist)))
861 (if (eq imenu-always-use-completion-buffer-p 'never)
862 (setq name (completing-read (or prompt "Index item: ")
863 prepared-index-alist
864 nil t nil 'imenu--history-list))
865 (save-window-excursion
866 ;; Display the completion buffer
867 (with-output-to-temp-buffer "*Completions*"
868 (display-completion-list
869 (all-completions "" prepared-index-alist )))
870 (let ((minibuffer-setup-hook
871 (function (lambda ()
872 (let ((buffer (current-buffer)))
873 (save-excursion
874 (set-buffer "*Completions*")
875 (setq completion-reference-buffer buffer)))))))
876 ;; Make a completion question
877 (setq name (completing-read (or prompt "Index item: ")
878 prepared-index-alist
879 nil t nil 'imenu--history-list)))))
880 (cond ((not (stringp name))
881 nil)
882 ((string= name (car imenu--rescan-item))
885 (setq choice (assoc name prepared-index-alist))
886 (if (listp (cdr choice))
887 (imenu--completion-buffer (cdr choice) prompt)
888 choice)))))
890 (defun imenu--mouse-menu (index-alist event &optional title)
891 "Let the user select from a buffer index from a mouse menu.
893 INDEX-ALIST is the buffer index and EVENT is a mouse event.
895 Returns t for rescan and otherwise a position number."
896 (let* ((menu (imenu--split-menu
897 (if imenu-sort-function
898 (sort
899 (let ((res nil)
900 (oldlist index-alist))
901 ;; Copy list method from the cl package `copy-list'
902 (while (consp oldlist) (push (pop oldlist) res))
903 (prog1 (nreverse res) (setcdr res oldlist)))
904 imenu-sort-function)
905 index-alist)
906 (or title (buffer-name))))
907 position)
908 (and imenu-use-keymap-menu
909 (setq menu (imenu--create-keymap-1 (car menu)
910 (if (< 1 (length (cdr menu)))
911 (cdr menu)
912 (cdr (cadr menu))))))
913 (setq position (x-popup-menu event menu))
914 (if imenu-use-keymap-menu
915 (progn
916 (cond
917 ((and (listp position)
918 (numberp (car position))
919 (stringp (nth (1- (length position)) position)))
920 (setq position (nth (1- (length position)) position)))
921 ((and (stringp (car position))
922 (null (cdr position)))
923 (setq position (car position))))))
924 (cond
925 ((eq position nil)
926 position)
927 ((listp position)
928 (imenu--mouse-menu position event
929 (if title
930 (concat title imenu-level-separator
931 (car (rassq position index-alist)))
932 (car (rassq position index-alist)))))
933 ((stringp position)
934 (or (string= position (car imenu--rescan-item))
935 (imenu--in-alist position index-alist)))
936 ((or (= position (cdr imenu--rescan-item))
937 (and (stringp position)
938 (string= position (car imenu--rescan-item))))
941 (rassq position index-alist)))))
943 (defun imenu-choose-buffer-index (&optional prompt alist)
944 "Let the user select from a buffer index and return the chosen index.
946 If the user originally activated this function with the mouse, a mouse
947 menu is used. Otherwise a completion buffer is used and the user is
948 prompted with PROMPT.
950 If you call this function with index alist ALIST, then it lets the user
951 select from ALIST.
953 With no index alist ALIST, it calls `imenu--make-index-alist' to
954 create the index alist.
956 If `imenu-always-use-completion-buffer-p' is non-nil, then the
957 completion buffer is always used, no matter if the mouse was used or
958 not.
960 The returned value is on the form (INDEX-NAME . INDEX-POSITION)."
961 (let (index-alist
962 (mouse-triggered (listp last-nonmenu-event))
963 (result t) )
964 ;; If selected by mouse, see to that the window where the mouse is
965 ;; really is selected.
966 (and mouse-triggered
967 (not (equal last-nonmenu-event '(menu-bar)))
968 (let ((window (posn-window (event-start last-nonmenu-event))))
969 (or (framep window) (select-window window))))
970 ;; Create a list for this buffer only when needed.
971 (while (eq result t)
972 (setq index-alist (if alist alist (imenu--make-index-alist)))
973 (setq result
974 (if (and mouse-triggered
975 (not imenu-always-use-completion-buffer-p))
976 (imenu--mouse-menu index-alist last-nonmenu-event)
977 (imenu--completion-buffer index-alist prompt)))
978 (and (eq result t)
979 (imenu--cleanup)
980 (setq imenu--index-alist nil)))
981 result))
983 ;;;###autoload
984 (defun imenu-add-to-menubar (name)
985 "Adds an \"imenu\" entry to the menubar for the
986 current local keymap.
987 NAME is the string naming the menu to be added.
988 See 'imenu' for more information."
989 (interactive "sMenu name: ")
990 (and window-system
991 (define-key (current-local-map) [menu-bar index]
992 (cons name 'imenu))))
994 ;;;###autoload
995 (defun imenu ()
996 "Jump to a place in the buffer chosen using a buffer menu or mouse menu.
997 See `imenu-choose-buffer-index' for more information."
998 (interactive)
999 (let ((index-item (save-restriction
1000 (widen)
1001 (imenu-choose-buffer-index))))
1002 (and index-item
1003 (progn
1004 (push-mark)
1005 (cond
1006 ((markerp (cdr index-item))
1007 (if (or ( > (marker-position (cdr index-item)) (point-min))
1008 ( < (marker-position (cdr index-item)) (point-max)))
1009 ;; widen if outside narrowing
1010 (widen))
1011 (goto-char (marker-position (cdr index-item))))
1013 (if (or ( > (cdr index-item) (point-min))
1014 ( < (cdr index-item) (point-max)))
1015 ;; widen if outside narrowing
1016 (widen))
1017 (goto-char (cdr index-item))))))))
1019 (provide 'imenu)
1021 ;;; imenu.el ends here