aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman1995-06-27 06:23:43 +0000
committerRichard M. Stallman1995-06-27 06:23:43 +0000
commit2d24227e430bf2d911cbde60b52ab285b572a823 (patch)
treefd9889f2b6d31fac583e0daab5aac78bbfa528ba
parent7e8696590861bee6fb2f04b31e4dbd3f5e5ab61f (diff)
downloademacs-2d24227e430bf2d911cbde60b52ab285b572a823.tar.gz
emacs-2d24227e430bf2d911cbde60b52ab285b572a823.zip
(imenu-use-keymap-menu): New variable.
(imenu-auto-rescan): New variable. (imenu-auto-rescan-maxout): New variable. (imenu-generic-expression): Doc changes. (imenu-generic-lisp-expression): New variable. (imenu-generic-c-expression): New variable. (imenu-example--generic-c++-expression): Changed the name to imenu-generic-c++-expression. (imenu-example--generic-texinfo-expression): Changed the name to imenu-generic-texinfo-expression. (imenu-example--generic-latex-expression): Changed the name to imenu-generic-latex-expression. (imenu--scanning-method-alist): New variable. (imenu--split-menu): Changed it to make the title "Index menu" instead of "Function menus". (imenu--make-index-alist): Changed to handle auto rescan. (imenu--create-keymap-2): New function to create a keymap. (imenu--create-keymap-1): New function. (imenu--in-alist): New function. (imenu-default-create-index-function): Changed to handle imenu--scanning-method-alist). (imenu--generic-extract-name): Removed. (imenu--generic-function): Rewritten to handle submenus. (imenu--mouse-menu): Changed to handle keymaps.
-rw-r--r--lisp/imenu.el521
1 files changed, 372 insertions, 149 deletions
diff --git a/lisp/imenu.el b/lisp/imenu.el
index f35116d840c..315e2caf599 100644
--- a/lisp/imenu.el
+++ b/lisp/imenu.el
@@ -5,7 +5,7 @@
5;; Author: Ake Stenhoff <etxaksf@aom.ericsson.se> 5;; Author: Ake Stenhoff <etxaksf@aom.ericsson.se>
6;; Lars Lindberg <lli@sypro.cap.se> 6;; Lars Lindberg <lli@sypro.cap.se>
7;; Created: 8 Feb 1994 7;; Created: 8 Feb 1994
8;; Version: 1.15 8;; Version: 1.17
9;; Keywords: tools 9;; Keywords: tools
10;; 10;;
11;; This program is free software; you can redistribute it and/or modify 11;; This program is free software; you can redistribute it and/or modify
@@ -37,10 +37,10 @@
37;; The package comes with a set of example functions for how to 37;; The package comes with a set of example functions for how to
38;; utilize this package. 38;; utilize this package.
39 39
40;; There are *examples* for index gathering functions for C/C++ and 40;; There are *examples* for index gathering functions/regular
41;; Lisp/Emacs Lisp but it is easy to customize for other modes. A 41;; expressions for C/C++ and Lisp/Emacs Lisp but it is easy to
42;; function for jumping to the chosen index position is also 42;; customize for other modes. A function for jumping to the chosen
43;; supplied. 43;; index position is also supplied.
44 44
45;;; Thanks goes to 45;;; Thanks goes to
46;; [simon] - Simon Leinen simon@lia.di.epfl.ch 46;; [simon] - Simon Leinen simon@lia.di.epfl.ch
@@ -50,6 +50,9 @@
50;; [wolfgang] - Wolfgang Bangerth zcg51122@rpool1.rus.uni-stuttgart.de 50;; [wolfgang] - Wolfgang Bangerth zcg51122@rpool1.rus.uni-stuttgart.de
51;; [kai] - Kai Grossjohann grossjoh@linus.informatik.uni-dortmund.de 51;; [kai] - Kai Grossjohann grossjoh@linus.informatik.uni-dortmund.de
52;; [david] - David M. Smith dsmith@stats.adelaide.edu.au 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
55
53;;; Code 56;;; Code
54(eval-when-compile (require 'cl)) 57(eval-when-compile (require 'cl))
55 58
@@ -58,6 +61,17 @@
58;;; Customizable variables 61;;; Customizable variables
59;;; 62;;;
60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
64(defvar imenu-use-keymap-menu nil
65 "* Set this to non-nil for using a keymap when making
66 the mouse menu.")
67
68(defvar imenu-auto-rescan nil
69 "* T if we always should rescan the buffers, nil to disable
70 automatic rescan.")
71
72(defvar imenu-auto-rescan-maxout 60000
73 "* auto-rescan is disabled in buffers larger than this.
74 This variable is buffer-local.")
61 75
62(defvar imenu-always-use-completion-buffer-p nil 76(defvar imenu-always-use-completion-buffer-p nil
63 "*Set this to non-nil for displaying the index in a completion buffer. 77 "*Set this to non-nil for displaying the index in a completion buffer.
@@ -105,12 +119,40 @@ with name concatenation.")
105(defvar imenu-submenu-name-format "%s..." 119(defvar imenu-submenu-name-format "%s..."
106 "*The format for making a submenu name.") 120 "*The format for making a submenu name.")
107 121
122;;;###autoload
108(defvar imenu-generic-expression nil 123(defvar imenu-generic-expression nil
109 "Generic regular expression for index gathering. 124 "The regex pattern to use for creating a buffer index.
125
126If non-nil this pattern is passed to `imenu-create-index-with-pattern'
127to create a buffer index.
128
129It is an alist with elements that look like this: (MENU-TITLE
130REGEXP INDEX).
131
132MENU-TITLE is a string used as the title for the submenu or nil if the
133entries are not nested.
134
135REGEXP is a regexp that should match a construct in the buffer that is
136to be displayed in the menu i.e. function or variable definitions,
137etc. It contains a substring which is the name to appear in the
138menu. See the info section on Regexps for more information.
139
140INDEX points to the substring in REGEXP that contains the name (of the
141function, variable or type) that is to appear in the menu.
142
143For emacs-lisp-mode for example PATTERN would look like:
144
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))
148
149The variable is buffer-local.")
150
151;;;###autoload
152(make-variable-buffer-local 'imenu-create-index-pattern)
110 153
111Can be either an regular expression or an alist in the form 154;; make sure the default is nil
112\(REGEXP PAREN).") 155(setq-default imenu-create-index-pattern nil)
113(make-variable-buffer-local 'imenu-generic-expression)
114 156
115;;;; Hooks 157;;;; Hooks
116 158
@@ -253,9 +295,134 @@ This function is called after the function pointed out by
253 index-alist)) 295 index-alist))
254 index-alist)) 296 index-alist))
255 297
298(defvar imenu-generic-lisp-expression
299 '(
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+]+\\)"
306 2))
307
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'.")
311
312;;;
313;;; C++
314;;;
315;; Example of an imenu-generic-expression
316;;
317(defvar imenu-generic-c++-expression
318 (`
319 ((nil
320 (,
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?
326
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()) {...}"
344
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?
364
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)
410 ))
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'.")
414
256;;; 415;;;
257;;; C 416;;; C
258;;; 417;;;
418;;;
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'.")
425
259;; Regular expression to find C functions 426;; Regular expression to find C functions
260(defvar imenu-example--function-name-regexp-c 427(defvar imenu-example--function-name-regexp-c
261 (concat 428 (concat
@@ -287,55 +454,19 @@ This function is called after the function pointed out by
287 (imenu-progress-message prev-pos 100) 454 (imenu-progress-message prev-pos 100)
288 (nreverse index-alist))) 455 (nreverse index-alist)))
289 456
290;;; 457
291;;; C++ 458;;
292;;; 459;; Ada
293;; Example of an imenu-generic-expression 460;;
461;; Written by Christian Egli <Christian.Egli@hcsd.hac.com>
294;; 462;;
295(defvar imenu-example--generic-c++-expression 463(defvar imenu-generic-ada-expression
296 (cons 464 '((nil "^\\s-*\\(procedure\\|function\\)\\s-+\\([A-Za-z0-9_]+\\)" 2)
297 ;; regular expression 465 ("Type Defs" "^\\s-*\\(sub\\)?type\\s-+\\([A-Za-z0-9_]+\\)" 2))
298 (concat 466
299 "^" ; beginning of line is required 467 "imenu generic expression for Ada mode in the form
300 "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>" 468(PATTERN), where PATTERN is a list containing entries of the form
301 "\\(" 469(MENU-TITLE REGEXP INDEX). See `imenu-generic-expression'.")
302
303 "\\(" ; >>looking for a function definition<<
304 "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; type specs; there can be no
305 "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; more than 3 tokens, right?
306
307 "\\(" ; last type spec including */&
308 "[a-zA-Z0-9_:]+"
309 "\\([ \t]*[*&]+[ \t]*\\|[ \t]+\\)" ; either pointer/ref sign or whitespace
310 "\\)?" ; if there is a last type spec
311
312 "\\(" ; name; take that into the imenu entry
313 "[a-zA-Z0-9_:~]+" ; member function, ctor or dtor...
314 ; (may not contain * because then
315 ; "a::operator char*" would become "char*"!)
316 "\\|"
317 "\\([a-zA-Z0-9_:~]*::\\)?operator"
318 "[^a-zA-Z1-9_][^(]*" ; ...or operator
319 " \\)"
320 "[ \t]*([^)]*)[ \t\n]*[^ ;]" ; require something other than a ; after
321 ; the (...) to avoid prototypes. Can't
322 ; catch cases with () inside the parentheses
323 ; surrounding the parameters
324 ; (like "int foo(int a=bar()) {...}"
325 "\\)" ; <<looking for a function definition>>
326
327 "\\|"
328
329 "\\(" ; >>class decl<<
330 "\\(class[ \t]+[a-zA-Z0-9_]+\\)" ; this is the string we want to get
331 "[ \t]*[:{]"
332 "\\)" ; <<class decl>>
333
334 "\\)")
335 ;; paren
336 (list 8 11))
337 "imenu generic expression for C++ mode in the form
338\(REGEXP PAR).")
339 470
340;;; 471;;;
341;;; TexInfo 472;;; TexInfo
@@ -343,14 +474,13 @@ This function is called after the function pointed out by
343;; Written by Wolfgang Bangerth <zcg51122@rpool1.rus.uni-stuttgart.de> 474;; Written by Wolfgang Bangerth <zcg51122@rpool1.rus.uni-stuttgart.de>
344;; 475;;
345;; 476;;
346(defvar imenu-example--generic-texinfo-expression 477(defvar imenu-generic-texinfo-expression
347 (cons 478 '((nil "^@node[ \t]+\\([^,\n]*\\)" 1)
348 (concat 479 ("Chapters" "^@chapter[ \t]+\\(.*\\)$" 1))
349 "^@node[ \t]+" 480
350 "\\([^,\n]*\\)")
351 (list 1))
352 "imenu generic expression for TexInfo mode in the form 481 "imenu generic expression for TexInfo mode in the form
353\(REGEXP PAR). 482(PATTERN), where PATTERN is a list containing entries of the form
483(MENU-TITLE REGEXP INDEX). See `imenu-generic-expression'.
354 484
355To overide this example, Either set 'imenu-generic-expression 485To overide this example, Either set 'imenu-generic-expression
356or 'imenu-create-index-function") 486or 'imenu-create-index-function")
@@ -361,22 +491,20 @@ or 'imenu-create-index-function")
361;; Written by Wolfgang Bangerth <zcg51122@rpool1.rus.uni-stuttgart.de> 491;; Written by Wolfgang Bangerth <zcg51122@rpool1.rus.uni-stuttgart.de>
362;; 492;;
363;; 493;;
364(defvar imenu-example--generic-latex-expression 494(defvar imenu-generic-latex-expression
365 (concat 495 '(
366 "\\(" 496 ("Part" "\\\\part{\\([^}]*\\)}" 1)
367 "%[ \t]*[0-9]+\\.[0-9]+[,;]?[ \t]?" ; i put numbers like 3.15 before my 497 ("Chapter" "\\\\chapter{\\([^}]*\\)}" 1)
368 ; \begin{equation}'s which tell me 498 ("Section" "\\\\[a-zA-Z]*section{\\([^}]*\\)}" 1)
369 ; the number the equation will get when 499 ;; i put numbers like 3.15 before my
370 ; being printed. 500 ;; \begin{equation}'s which tell me
371 "\\|" 501 ;; the number the equation will get when
372 "\\\\part{[^}]*}" 502 ;; being printed.
373 "\\|" 503 ("Equations" "%[ \t]*\\([0-9]+\\.[0-9]+\\)[,;]?[ \t]?" 1))
374 "\\\\chapter{[^}]*}" 504
375 "\\|"
376 "\\\\[a-zA-Z]*section{[^}]*}"
377 "\\)")
378 "imenu generic expression for LaTex mode in the form 505 "imenu generic expression for LaTex mode in the form
379\"REGEXP\".") 506(PATTERN), where PATTERN is a list containing entries of the form
507(MENU-TITLE REGEXP INDEX). See `imenu-generic-expression'.")
380 508
381;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 509;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
382;;; 510;;;
@@ -397,6 +525,23 @@ or 'imenu-create-index-function")
397(defvar imenu--history-list nil) 525(defvar imenu--history-list nil)
398(make-variable-buffer-local 'imenu--history-list) 526(make-variable-buffer-local 'imenu--history-list)
399 527
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))
536
537 "Alist of major mode and imenu scanning methods.
538
539Each item should be a list of the form: (MAJOR-MODE
540IMENU-SCANNING-METHOD) where both MAJOR-MODE and IMENU-SCANNING-METHOD
541are symbols. If IMENU-SCANNING-METHOD is a function then it is called
542to create an index. If it is a `pattern' (See `imenu-generic-expression')
543it is passed to imenu--generic-function to create an index.")
544
400;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 545;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
401;;; 546;;;
402;;; Internal support functions 547;;; Internal support functions
@@ -429,7 +574,7 @@ or 'imenu-create-index-function")
429;;; NAME is the base of the new submenu name. 574;;; NAME is the base of the new submenu name.
430;;; 575;;;
431(defun imenu-create-submenu-name (name) 576(defun imenu-create-submenu-name (name)
432 (format imenu-submenu-name-format name)) 577 (format imenu-submenu-name-format name))
433 578
434;; Split LIST into sublists of max length N. 579;; Split LIST into sublists of max length N.
435;; Example (imenu--split '(1 2 3 4 5 6 7 8) 3)-> '((1 2 3) (4 5 6) (7 8)) 580;; Example (imenu--split '(1 2 3 4 5 6 7 8) 3)-> '((1 2 3) (4 5 6) (7 8))
@@ -456,7 +601,7 @@ or 'imenu-create-index-function")
456;;; Split a menu in to several menus. 601;;; Split a menu in to several menus.
457;;; 602;;;
458(defun imenu--split-menu (menulist title) 603(defun imenu--split-menu (menulist title)
459 (cons "Function menus" 604 (cons "Index menu"
460 (mapcar 605 (mapcar
461 (function 606 (function
462 (lambda (menu) 607 (lambda (menu)
@@ -471,7 +616,10 @@ or 'imenu-create-index-function")
471 616
472(defun imenu--make-index-alist () 617(defun imenu--make-index-alist ()
473 ;; Create a list for this buffer only when needed. 618 ;; Create a list for this buffer only when needed.
474 (or imenu--index-alist 619 (or (and imenu--index-alist
620 (or (not imenu-auto-rescan)
621 (and imenu-auto-rescan
622 (> (buffer-size) imenu-auto-rescan-maxout))))
475 ;; Get the index 623 ;; Get the index
476 (setq imenu--index-alist 624 (setq imenu--index-alist
477 (save-excursion 625 (save-excursion
@@ -502,6 +650,42 @@ or 'imenu-create-index-function")
502 alist) 650 alist)
503 t)) 651 t))
504 652
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))))
662 (t
663 (let ((end (cons '(nil) t)))
664 (cons (car item)
665 (cons (car item) end))))
666 )))
667 alist)))
668
669(defun imenu--create-keymap-1 (title alist)
670 (append (list 'keymap title) (imenu--create-keymap-2 alist 0)))
671
672
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))
688
505(defun imenu-default-create-index-function () 689(defun imenu-default-create-index-function ()
506 "*Wrapper for index searching functions. 690 "*Wrapper for index searching functions.
507 691
@@ -528,19 +712,15 @@ Their results are gathered into an index alist."
528 ;; Use generic expression if possible. 712 ;; Use generic expression if possible.
529 ((and imenu-generic-expression) 713 ((and imenu-generic-expression)
530 (imenu--generic-function imenu-generic-expression)) 714 (imenu--generic-function imenu-generic-expression))
531 ;; Use supplied example functions 715 ;; Use supplied example functions or expressions
532 ((eq major-mode 'emacs-lisp-mode) 716 ((assq major-mode imenu--scanning-method-alist)
533 (imenu-example--create-lisp-index)) 717 (let ((method (cadr (assq major-mode imenu--scanning-method-alist))))
534 ((eq major-mode 'lisp-mode) 718 ;; is it a function?
535 (imenu-example--create-lisp-index)) 719 (if (fboundp method)
536 ((eq major-mode 'c++-mode) 720 ;; ... then call it
537 (imenu--generic-function imenu-example--generic-c++-expression)) 721 (funcall method)
538 ((eq major-mode 'c-mode) 722 ;; ...otherwise pass the pattern to imenu--generic-function
539 (imenu-example--create-c-index)) 723 (imenu--generic-function (eval method)))))
540 ((eq major-mode 'latex-mode)
541 (imenu--generic-function imenu-example--generic-latex-expression))
542 ((eq major-mode 'texinfo-mode)
543 (imenu--generic-function imenu-example--generic-texinfo-expression))
544 (t 724 (t
545 (error "The mode \"%s\" does not take full advantage of imenu.el yet." 725 (error "The mode \"%s\" does not take full advantage of imenu.el yet."
546 mode-name)))) 726 mode-name))))
@@ -581,61 +761,83 @@ Their results are gathered into an index alist."
581;;; 761;;;
582;;; Generic index gathering function. 762;;; Generic index gathering function.
583;;; 763;;;
584(defun imenu--generic-extract-name (paren) 764
585 (let ((numofpar (1- (length paren))) 765(defun imenu--generic-function (patterns)
586 (parencount 0) 766;; Built on some ideas that Erik Naggum <erik@naggum.no> once posted
587 (par) 767;; to comp.emacs
588 (index)) 768 "Return an index of the current buffer as an alist.
589 ;; Try until we get a match 769
590 (beginning-of-line) 770PATTERN is an alist with elements that look like this: (MENU-TITLE
591 (while (and (<= parencount numofpar) 771REGEXP INDEX).
592 (setq par (nth parencount paren)) 772
593 (equal (match-beginning par) nil) 773MENU-TITLE is a string used as the title for the submenu or nil if the
594 (equal (match-end par) nil)) 774entries are not nested.
595 (setq parencount (1+ parencount))) 775
596 (or (and 776REGEXP is a regexp that should match a construct in the buffer that is
597 (<= parencount numofpar) 777to be displayed in the menu i.e. function or variable definitions,
598 (setq index (buffer-substring (match-beginning par) 778etc. It contains a substring which is the name to appear in the
599 (match-end par)))) 779menu. See the info section on Regexps for more information.
600 ;; take the whole match just in case. 780
601 (setq index (buffer-substring (match-beginning 0) 781INDEX points to the substring in REGEXP that contains the name (of the
602 (match-end 0)))) 782function, variable or type) that is to appear in the menu.
603 index)) 783
604 784For emacs-lisp-mode for example PATTERN would look like:
605(defun imenu--generic-function (exp) 785
606 "Generic function for index gathering. 786'((nil \"^\\s-*(def\\(un\\|subst\\|macro\\|advice\\)\\s-+\\([-A-Za-z0-9]+\\)\" 2)
607 787 (\"*Vars*\" \"^\\s-*(def\\(var\\|const\\)\\s-+\\([-A-Za-z0-9]+\\)\" 2)
608EXP can be either an regular expression or an alist in the form 788 (\"*Types*\" \"^\\s-*(def\\(type\\|struct\\|class\\|ine-condition\\)\\s-+\\([-A-Za-z0-9]+\\)\" 2))'
609\(REGEXP PAREN). " 789
610 790Returns an index of the current buffer as an alist. The elements in
611 (let ((index-alist '()) 791the alist look like: (INDEX-NAME . INDEX-POSITION). They may also be
612 (regexp nil) 792nested index lists like (INDEX-NAME . INDEX-ALIST) depending on
613 (paren nil) 793pattern.
614 prev-pos name) 794
615 (cond ((stringp exp) 795\(imenu--generic-function PATTERN\)."
616 (setq regexp exp) 796
617 (setq paren nil)) 797 (let ((index-alist (list 'dummy))
618 ((listp exp) 798 (found nil)
619 (setq regexp (car exp)) 799 (global-regexp
620 (setq paren (cdr exp))) 800 (concat "\\("
621 (t 801 (mapconcat
622 (error "Wrong type of argument."))) 802 (function (lambda (pattern) (identity (cadr pattern))))
803 patterns "\\)\\|\\(")
804 "\\)"))
805 prev-pos)
806
623 (goto-char (point-max)) 807 (goto-char (point-max))
624 (imenu-progress-message prev-pos 0 t) 808 (imenu-progress-message prev-pos 0 t)
625 (while (re-search-backward regexp 1 t) 809 (save-match-data
626 (imenu-progress-message prev-pos nil t) 810 (while (re-search-backward global-regexp nil t)
627 (save-excursion 811 (imenu-progress-message prev-pos nil t)
628 ;; If paren get sub expression 812 (setq found nil)
629 (or (and paren 813 (save-excursion
630 (setq name (imenu--generic-extract-name paren))) 814 (goto-char (match-beginning 0))
631 ;; get the whole expression 815 (mapcar
632 (beginning-of-line) 816 (function
633 (setq name (buffer-substring (match-beginning 0) 817 (lambda (pat)
634 (match-end 0))))) 818 (let ((menu-title (car pat))
635 (and (stringp name) 819 (regexp (cadr pat))
636 (push (cons name (point)) index-alist))) 820 (index (caddr pat)))
637 (imenu-progress-message prev-pos 100 t) 821 (if (and (not found) ; Only allow one entry;
638 index-alist)) 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)))
639 841
640;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 842;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
641;;; 843;;;
@@ -703,7 +905,22 @@ Returns t for rescan and otherwise a position number."
703 index-alist) 905 index-alist)
704 (or title (buffer-name)))) 906 (or title (buffer-name))))
705 position) 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))))))
706 (setq position (x-popup-menu event 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))))))
707 (cond 924 (cond
708 ((eq position nil) 925 ((eq position nil)
709 position) 926 position)
@@ -713,7 +930,12 @@ Returns t for rescan and otherwise a position number."
713 (concat title imenu-level-separator 930 (concat title imenu-level-separator
714 (car (rassq position index-alist))) 931 (car (rassq position index-alist)))
715 (car (rassq position index-alist))))) 932 (car (rassq position index-alist)))))
716 ((= position (cdr imenu--rescan-item)) 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))))
717 t) 939 t)
718 (t 940 (t
719 (rassq position index-alist))))) 941 (rassq position index-alist)))))
@@ -757,6 +979,7 @@ The returned value is on the form (INDEX-NAME . INDEX-POSITION)."
757 (setq imenu--index-alist nil))) 979 (setq imenu--index-alist nil)))
758 result)) 980 result))
759 981
982;;;###autoload
760(defun imenu-add-to-menubar (name) 983(defun imenu-add-to-menubar (name)
761 "Adds an \"imenu\" entry to the menubar for the 984 "Adds an \"imenu\" entry to the menubar for the
762current local keymap. 985current local keymap.