diff options
| author | Richard M. Stallman | 1995-06-27 06:23:43 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1995-06-27 06:23:43 +0000 |
| commit | 2d24227e430bf2d911cbde60b52ab285b572a823 (patch) | |
| tree | fd9889f2b6d31fac583e0daab5aac78bbfa528ba | |
| parent | 7e8696590861bee6fb2f04b31e4dbd3f5e5ab61f (diff) | |
| download | emacs-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.el | 521 |
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 | |||
| 126 | If non-nil this pattern is passed to `imenu-create-index-with-pattern' | ||
| 127 | to create a buffer index. | ||
| 128 | |||
| 129 | It is an alist with elements that look like this: (MENU-TITLE | ||
| 130 | REGEXP INDEX). | ||
| 131 | |||
| 132 | MENU-TITLE is a string used as the title for the submenu or nil if the | ||
| 133 | entries are not nested. | ||
| 134 | |||
| 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. | ||
| 139 | |||
| 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. | ||
| 142 | |||
| 143 | For 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 | |||
| 149 | The variable is buffer-local.") | ||
| 150 | |||
| 151 | ;;;###autoload | ||
| 152 | (make-variable-buffer-local 'imenu-create-index-pattern) | ||
| 110 | 153 | ||
| 111 | Can 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 | ||
| 355 | To overide this example, Either set 'imenu-generic-expression | 485 | To overide this example, Either set 'imenu-generic-expression |
| 356 | or 'imenu-create-index-function") | 486 | or '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 | |||
| 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.") | ||
| 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) | 770 | PATTERN is an alist with elements that look like this: (MENU-TITLE |
| 591 | (while (and (<= parencount numofpar) | 771 | REGEXP INDEX). |
| 592 | (setq par (nth parencount paren)) | 772 | |
| 593 | (equal (match-beginning par) nil) | 773 | MENU-TITLE is a string used as the title for the submenu or nil if the |
| 594 | (equal (match-end par) nil)) | 774 | entries are not nested. |
| 595 | (setq parencount (1+ parencount))) | 775 | |
| 596 | (or (and | 776 | REGEXP is a regexp that should match a construct in the buffer that is |
| 597 | (<= parencount numofpar) | 777 | to be displayed in the menu i.e. function or variable definitions, |
| 598 | (setq index (buffer-substring (match-beginning par) | 778 | etc. It contains a substring which is the name to appear in the |
| 599 | (match-end par)))) | 779 | menu. 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) | 781 | INDEX points to the substring in REGEXP that contains the name (of the |
| 602 | (match-end 0)))) | 782 | function, variable or type) that is to appear in the menu. |
| 603 | index)) | 783 | |
| 604 | 784 | For 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) | |
| 608 | EXP 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 | 790 | Returns an index of the current buffer as an alist. The elements in | |
| 611 | (let ((index-alist '()) | 791 | the alist look like: (INDEX-NAME . INDEX-POSITION). They may also be |
| 612 | (regexp nil) | 792 | nested index lists like (INDEX-NAME . INDEX-ALIST) depending on |
| 613 | (paren nil) | 793 | pattern. |
| 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 |
| 762 | current local keymap. | 985 | current local keymap. |