diff options
| author | Karl Heuer | 1994-11-30 20:50:33 +0000 |
|---|---|---|
| committer | Karl Heuer | 1994-11-30 20:50:33 +0000 |
| commit | 615b306cf5a98587d070caecd3f45a686e6950f5 (patch) | |
| tree | 8078efe0e8bb2c8ccafa475c4c3795c57b19ca6a | |
| parent | 4ad26d84e1379aefb1c4982da7c62432eca8948b (diff) | |
| download | emacs-615b306cf5a98587d070caecd3f45a686e6950f5.tar.gz emacs-615b306cf5a98587d070caecd3f45a686e6950f5.zip | |
(imenu-generic-expression): New variable.
(imenu-example--generic-c++-expression): New variable.
(imenu-example--generic-texinfo-expression): New variable.
(imenu-example--generic-latex-expression): New variable.
(imenu-example--create-c++-index): Deleted.
(imenu-example--function-name-regexp-c++): Deleted.
(imenu--generic-function): New function.
(imenu--generic-extract-name): New function.
(imenu-default-create-index-function): Added the generic function calls for
the provided examples.
| -rw-r--r-- | lisp/imenu.el | 514 |
1 files changed, 333 insertions, 181 deletions
diff --git a/lisp/imenu.el b/lisp/imenu.el index 9721677c7fb..bd7c1adbe02 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.12 | 8 | ;; Version: 1.14 |
| 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 |
| @@ -47,6 +47,7 @@ | |||
| 47 | ;; [dean] - Dean Andrews ada@unison.com | 47 | ;; [dean] - Dean Andrews ada@unison.com |
| 48 | ;; [alon] - Alon Albert al@mercury.co.il | 48 | ;; [alon] - Alon Albert al@mercury.co.il |
| 49 | ;; [greg] - Greg Thompson gregt@porsche.visix.COM | 49 | ;; [greg] - Greg Thompson gregt@porsche.visix.COM |
| 50 | ;; [wolfgang] - Wolfgang Bangerth zcg51122@rpool1.rus.uni-stuttgart.de | ||
| 50 | ;; [kai] - Kai Grossjohann grossjoh@linus.informatik.uni-dortmund.de | 51 | ;; [kai] - Kai Grossjohann grossjoh@linus.informatik.uni-dortmund.de |
| 51 | 52 | ||
| 52 | ;;; Code | 53 | ;;; Code |
| @@ -103,6 +104,13 @@ with name concatenation.") | |||
| 103 | (defvar imenu-submenu-name-format "%s..." | 104 | (defvar imenu-submenu-name-format "%s..." |
| 104 | "*The format for making a submenu name.") | 105 | "*The format for making a submenu name.") |
| 105 | 106 | ||
| 107 | (defvar imenu-generic-expression nil | ||
| 108 | "Generic regular expression for index gathering. | ||
| 109 | |||
| 110 | Can be either an regular expression or an alist in the form | ||
| 111 | \(REGEXP PAREN).") | ||
| 112 | (make-variable-buffer-local 'imenu-generic-expression) | ||
| 113 | |||
| 106 | ;;;; Hooks | 114 | ;;;; Hooks |
| 107 | 115 | ||
| 108 | (defvar imenu-create-index-function 'imenu-default-create-index-function | 116 | (defvar imenu-create-index-function 'imenu-default-create-index-function |
| @@ -137,6 +145,238 @@ This function is called after the function pointed out by | |||
| 137 | `imenu-prev-index-position-function'.") | 145 | `imenu-prev-index-position-function'.") |
| 138 | (make-variable-buffer-local 'imenu-extract-index-name-function) | 146 | (make-variable-buffer-local 'imenu-extract-index-name-function) |
| 139 | 147 | ||
| 148 | ;;; | ||
| 149 | ;;; Macro to display a progress message. | ||
| 150 | ;;; RELPOS is the relative position to display. | ||
| 151 | ;;; If RELPOS is nil, then the relative position in the buffer | ||
| 152 | ;;; is calculated. | ||
| 153 | ;;; PREVPOS is the variable in which we store the last position displayed. | ||
| 154 | (defmacro imenu-progress-message (prevpos &optional relpos reverse) | ||
| 155 | (` (and | ||
| 156 | imenu-scanning-message | ||
| 157 | (let ((pos (, (if relpos | ||
| 158 | relpos | ||
| 159 | (` (imenu--relative-position (, reverse))))))) | ||
| 160 | (if (, (if relpos t | ||
| 161 | (` (> pos (+ 5 (, prevpos)))))) | ||
| 162 | (progn | ||
| 163 | (message imenu-scanning-message pos) | ||
| 164 | (setq (, prevpos) pos))))))) | ||
| 165 | |||
| 166 | |||
| 167 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 168 | ;;;; | ||
| 169 | ;;;; Some examples of functions utilizing the framework of this | ||
| 170 | ;;;; package. | ||
| 171 | ;;;; | ||
| 172 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 173 | |||
| 174 | ;; Return the current/previous sexp and the location of the sexp (it's | ||
| 175 | ;; beginning) without moving the point. | ||
| 176 | (defun imenu-example--name-and-position () | ||
| 177 | (save-excursion | ||
| 178 | (forward-sexp -1) | ||
| 179 | (let ((beg (point)) | ||
| 180 | (end (progn (forward-sexp) (point))) | ||
| 181 | (marker (make-marker))) | ||
| 182 | (set-marker marker beg) | ||
| 183 | (cons (buffer-substring beg end) | ||
| 184 | marker)))) | ||
| 185 | |||
| 186 | ;;; | ||
| 187 | ;;; Lisp | ||
| 188 | ;;; | ||
| 189 | |||
| 190 | (defun imenu-example--lisp-extract-index-name () | ||
| 191 | ;; Example of a candidate for `imenu-extract-index-name-function'. | ||
| 192 | ;; This will generate a flat index of definitions in a lisp file. | ||
| 193 | (save-match-data | ||
| 194 | (and (looking-at "(def") | ||
| 195 | (condition-case nil | ||
| 196 | (progn | ||
| 197 | (down-list 1) | ||
| 198 | (forward-sexp 2) | ||
| 199 | (let ((beg (point)) | ||
| 200 | (end (progn (forward-sexp -1) (point)))) | ||
| 201 | (buffer-substring beg end))) | ||
| 202 | (error nil))))) | ||
| 203 | |||
| 204 | (defun imenu-example--create-lisp-index () | ||
| 205 | ;; Example of a candidate for `imenu-create-index-function'. | ||
| 206 | ;; It will generate a nested index of definitions. | ||
| 207 | (let ((index-alist '()) | ||
| 208 | (index-var-alist '()) | ||
| 209 | (index-type-alist '()) | ||
| 210 | (index-unknown-alist '()) | ||
| 211 | prev-pos) | ||
| 212 | (goto-char (point-max)) | ||
| 213 | (imenu-progress-message prev-pos 0) | ||
| 214 | ;; Search for the function | ||
| 215 | (while (beginning-of-defun) | ||
| 216 | (imenu-progress-message prev-pos nil t) | ||
| 217 | (save-match-data | ||
| 218 | (and (looking-at "(def") | ||
| 219 | (save-excursion | ||
| 220 | (down-list 1) | ||
| 221 | (cond | ||
| 222 | ((looking-at "def\\(var\\|const\\)") | ||
| 223 | (forward-sexp 2) | ||
| 224 | (push (imenu-example--name-and-position) | ||
| 225 | index-var-alist)) | ||
| 226 | ((looking-at "def\\(un\\|subst\\|macro\\|advice\\)") | ||
| 227 | (forward-sexp 2) | ||
| 228 | (push (imenu-example--name-and-position) | ||
| 229 | index-alist)) | ||
| 230 | ((looking-at "def\\(type\\|struct\\|class\\|ine-condition\\)") | ||
| 231 | (forward-sexp 2) | ||
| 232 | (if (= (char-after (1- (point))) ?\)) | ||
| 233 | (progn | ||
| 234 | (forward-sexp -1) | ||
| 235 | (down-list 1) | ||
| 236 | (forward-sexp 1))) | ||
| 237 | (push (imenu-example--name-and-position) | ||
| 238 | index-type-alist)) | ||
| 239 | (t | ||
| 240 | (forward-sexp 2) | ||
| 241 | (push (imenu-example--name-and-position) | ||
| 242 | index-unknown-alist))))))) | ||
| 243 | (imenu-progress-message prev-pos 100) | ||
| 244 | (and index-var-alist | ||
| 245 | (push (cons (imenu-create-submenu-name "Variables") index-var-alist) | ||
| 246 | index-alist)) | ||
| 247 | (and index-type-alist | ||
| 248 | (push (cons (imenu-create-submenu-name "Types") index-type-alist) | ||
| 249 | index-alist)) | ||
| 250 | (and index-unknown-alist | ||
| 251 | (push (cons (imenu-create-submenu-name "Syntax-unknown") index-unknown-alist) | ||
| 252 | index-alist)) | ||
| 253 | index-alist)) | ||
| 254 | |||
| 255 | ;;; | ||
| 256 | ;;; C | ||
| 257 | ;;; | ||
| 258 | ;; Regular expression to find C functions | ||
| 259 | (defvar imenu-example--function-name-regexp-c | ||
| 260 | (concat | ||
| 261 | "^[a-zA-Z0-9]+[ \t]?" ; type specs; there can be no | ||
| 262 | "\\([a-zA-Z0-9_*]+[ \t]+\\)?" ; more than 3 tokens, right? | ||
| 263 | "\\([a-zA-Z0-9_*]+[ \t]+\\)?" | ||
| 264 | "\\([*&]+[ \t]*\\)?" ; pointer | ||
| 265 | "\\([a-zA-Z0-9_*]+\\)[ \t]*(" ; name | ||
| 266 | )) | ||
| 267 | |||
| 268 | (defun imenu-example--create-c-index (&optional regexp) | ||
| 269 | (let ((index-alist '()) | ||
| 270 | prev-pos char) | ||
| 271 | (goto-char (point-min)) | ||
| 272 | (imenu-progress-message prev-pos 0) | ||
| 273 | ;; Search for the function | ||
| 274 | (save-match-data | ||
| 275 | (while (re-search-forward | ||
| 276 | (or regexp imenu-example--function-name-regexp-c) | ||
| 277 | nil t) | ||
| 278 | (imenu-progress-message prev-pos) | ||
| 279 | (backward-up-list 1) | ||
| 280 | (save-excursion | ||
| 281 | (goto-char (scan-sexps (point) 1)) | ||
| 282 | (setq char (following-char))) | ||
| 283 | ;; Skip this function name if it is a prototype declaration. | ||
| 284 | (if (not (eq char ?\;)) | ||
| 285 | (push (imenu-example--name-and-position) index-alist)))) | ||
| 286 | (imenu-progress-message prev-pos 100) | ||
| 287 | (nreverse index-alist))) | ||
| 288 | |||
| 289 | ;;; | ||
| 290 | ;;; C++ | ||
| 291 | ;;; | ||
| 292 | ;; Example of an imenu-generic-expression | ||
| 293 | ;; | ||
| 294 | (defvar imenu-example--generic-c++-expression | ||
| 295 | (cons | ||
| 296 | ;; regular expression | ||
| 297 | (concat | ||
| 298 | "^" ; beginning of line is required | ||
| 299 | "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>" | ||
| 300 | "\\(" | ||
| 301 | |||
| 302 | "\\(" ; >>looking for a function definition<< | ||
| 303 | "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; type specs; there can be no | ||
| 304 | "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; more than 3 tokens, right? | ||
| 305 | |||
| 306 | "\\(" ; last type spec including */& | ||
| 307 | "[a-zA-Z0-9_:]+" | ||
| 308 | "\\([ \t]*[*&]+[ \t]*\\|[ \t]+\\)" ; either pointer/ref sign or whitespace | ||
| 309 | "\\)?" ; if there is a last type spec | ||
| 310 | |||
| 311 | "\\(" ; name; take that into the imenu entry | ||
| 312 | "[a-zA-Z0-9_:~]+" ; member function, ctor or dtor... | ||
| 313 | ; (may not contain * because then | ||
| 314 | ; "a::operator char*" would become "char*"!) | ||
| 315 | "\\|" | ||
| 316 | "\\([a-zA-Z0-9_:~]*::\\)?operator" | ||
| 317 | "[^a-zA-Z1-9_][^(]*" ; ...or operator | ||
| 318 | " \\)" | ||
| 319 | "[ \t]*([^)]*)[ \t\n]*[^ ;]" ; require something other than a ; after | ||
| 320 | ; the (...) to avoid prototypes. Can't | ||
| 321 | ; catch cases with () inside the parentheses | ||
| 322 | ; surrounding the parameters | ||
| 323 | ; (like "int foo(int a=bar()) {...}" | ||
| 324 | "\\)" ; <<looking for a function definition>> | ||
| 325 | |||
| 326 | "\\|" | ||
| 327 | |||
| 328 | "\\(" ; >>class decl<< | ||
| 329 | "\\(class[ \t]+[a-zA-Z0-9_]+\\)" ; this is the string we want to get | ||
| 330 | "[ \t]*[:{]" | ||
| 331 | "\\)" ; <<class decl>> | ||
| 332 | |||
| 333 | "\\)") | ||
| 334 | ;; paren | ||
| 335 | (list 8 11)) | ||
| 336 | "imenu generic expression for C++ mode in the form | ||
| 337 | \(REGEXP PAR).") | ||
| 338 | |||
| 339 | ;;; | ||
| 340 | ;;; TexInfo | ||
| 341 | ;;; | ||
| 342 | ;; Written by Wolfgang Bangerth <zcg51122@rpool1.rus.uni-stuttgart.de> | ||
| 343 | ;; | ||
| 344 | ;; | ||
| 345 | (defvar imenu-example--generic-texinfo-expression | ||
| 346 | (cons | ||
| 347 | (concat | ||
| 348 | "^@node[ \t]+" | ||
| 349 | "\\([^,\n]*\\)") | ||
| 350 | (list 1)) | ||
| 351 | "imenu generic expression for TexInfo mode in the form | ||
| 352 | \(REGEXP PAR). | ||
| 353 | |||
| 354 | To overide this example, Either set 'imenu-generic-expression | ||
| 355 | or 'imenu-create-index-function") | ||
| 356 | |||
| 357 | ;;; | ||
| 358 | ;;; LaTex | ||
| 359 | ;;; | ||
| 360 | ;; Written by Wolfgang Bangerth <zcg51122@rpool1.rus.uni-stuttgart.de> | ||
| 361 | ;; | ||
| 362 | ;; | ||
| 363 | (defvar imenu-example--generic-latex-expression | ||
| 364 | (concat | ||
| 365 | "\\(" | ||
| 366 | "%[ \t]*[0-9]+\\.[0-9]+[,;]?[ \t]?" ; i put numbers like 3.15 before my | ||
| 367 | ; \begin{equation}'s which tell me | ||
| 368 | ; the number the equation will get when | ||
| 369 | ; being printed. | ||
| 370 | "\\|" | ||
| 371 | "\\\\part{[^}]*}" | ||
| 372 | "\\|" | ||
| 373 | "\\\\chapter{[^}]*}" | ||
| 374 | "\\|" | ||
| 375 | "\\\\[a-zA-Z]*section{[^}]*}" | ||
| 376 | "\\)") | ||
| 377 | "imenu generic expression for LaTex mode in the form | ||
| 378 | \"REGEXP\".") | ||
| 379 | |||
| 140 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 380 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 141 | ;;; | 381 | ;;; |
| 142 | ;;; Internal variables | 382 | ;;; Internal variables |
| @@ -183,24 +423,6 @@ This function is called after the function pointed out by | |||
| 183 | (/ (* 100 (1- pos)) (max total 1))))) | 423 | (/ (* 100 (1- pos)) (max total 1))))) |
| 184 | 424 | ||
| 185 | ;;; | 425 | ;;; |
| 186 | ;;; Macro to display a progress message. | ||
| 187 | ;;; RELPOS is the relative position to display. | ||
| 188 | ;;; If RELPOS is nil, then the relative position in the buffer | ||
| 189 | ;;; is calculated. | ||
| 190 | ;;; PREVPOS is the variable in which we store the last position displayed. | ||
| 191 | (defmacro imenu-progress-message (prevpos &optional relpos reverse) | ||
| 192 | (` (and | ||
| 193 | imenu-scanning-message | ||
| 194 | (let ((pos (, (if relpos | ||
| 195 | relpos | ||
| 196 | (` (imenu--relative-position (, reverse))))))) | ||
| 197 | (if (, (if relpos t | ||
| 198 | (` (> pos (+ 5 (, prevpos)))))) | ||
| 199 | (progn | ||
| 200 | (message imenu-scanning-message pos) | ||
| 201 | (setq (, prevpos) pos))))))) | ||
| 202 | |||
| 203 | ;;; | ||
| 204 | ;;; Function for suporting general looking submenu names. | 426 | ;;; Function for suporting general looking submenu names. |
| 205 | ;;; Uses `imenu-submenu-name-format' for creating the name. | 427 | ;;; Uses `imenu-submenu-name-format' for creating the name. |
| 206 | ;;; NAME is the base of the new submenu name. | 428 | ;;; NAME is the base of the new submenu name. |
| @@ -274,8 +496,9 @@ This function is called after the function pointed out by | |||
| 274 | (set-marker (cdr item) nil)) | 496 | (set-marker (cdr item) nil)) |
| 275 | ((listp (cdr item)) | 497 | ((listp (cdr item)) |
| 276 | (imenu--cleanup (cdr item)))))) | 498 | (imenu--cleanup (cdr item)))))) |
| 277 | (if alist alist imenu--index-alist)) | 499 | (if alist alist imenu--index-alist)) |
| 278 | t)) | 500 | t)) |
| 501 | |||
| 279 | (defun imenu-default-create-index-function () | 502 | (defun imenu-default-create-index-function () |
| 280 | "*Wrapper for index searching functions. | 503 | "*Wrapper for index searching functions. |
| 281 | 504 | ||
| @@ -284,21 +507,10 @@ Moves point to end of buffer and then repeatedly calls | |||
| 284 | Their results are gathered into an index alist." | 507 | Their results are gathered into an index alist." |
| 285 | ;; These should really be done by setting imenu-create-index-function | 508 | ;; These should really be done by setting imenu-create-index-function |
| 286 | ;; in these major modes. But save that change for later. | 509 | ;; in these major modes. But save that change for later. |
| 287 | (cond ((eq major-mode 'emacs-lisp-mode) | 510 | (cond ((and (fboundp imenu-prev-index-position-function) |
| 288 | (imenu-example--create-lisp-index)) | 511 | (fboundp imenu-extract-index-name-function)) |
| 289 | ((eq major-mode 'lisp-mode) | ||
| 290 | (imenu-example--create-lisp-index)) | ||
| 291 | ((eq major-mode 'c++-mode) | ||
| 292 | (imenu-example--create-c++-index)) | ||
| 293 | ((eq major-mode 'c-mode) | ||
| 294 | (imenu-example--create-c-index)) | ||
| 295 | (t | ||
| 296 | (or (and (fboundp imenu-prev-index-position-function) | ||
| 297 | (fboundp imenu-extract-index-name-function)) | ||
| 298 | (error "The mode \"%s\" does not take full advantage of imenu.el yet." | ||
| 299 | mode-name)) | ||
| 300 | (let ((index-alist '()) | 512 | (let ((index-alist '()) |
| 301 | name prev-pos) | 513 | prev-pos name) |
| 302 | (goto-char (point-max)) | 514 | (goto-char (point-max)) |
| 303 | (imenu-progress-message prev-pos 0 t) | 515 | (imenu-progress-message prev-pos 0 t) |
| 304 | ;; Search for the function | 516 | ;; Search for the function |
| @@ -309,7 +521,26 @@ Their results are gathered into an index alist." | |||
| 309 | (and (stringp name) | 521 | (and (stringp name) |
| 310 | (push (cons name (point)) index-alist))) | 522 | (push (cons name (point)) index-alist))) |
| 311 | (imenu-progress-message prev-pos 100 t) | 523 | (imenu-progress-message prev-pos 100 t) |
| 312 | index-alist)))) | 524 | index-alist)) |
| 525 | ;; Use generic expression if possible. | ||
| 526 | ((and imenu-generic-expression) | ||
| 527 | (imenu--generic-function imenu-generic-expression)) | ||
| 528 | ;; Use supplied example functions | ||
| 529 | ((eq major-mode 'emacs-lisp-mode) | ||
| 530 | (imenu-example--create-lisp-index)) | ||
| 531 | ((eq major-mode 'lisp-mode) | ||
| 532 | (imenu-example--create-lisp-index)) | ||
| 533 | ((eq major-mode 'c++-mode) | ||
| 534 | (imenu--generic-function imenu-example--generic-c++-expression)) | ||
| 535 | ((eq major-mode 'c-mode) | ||
| 536 | (imenu-example--create-c-index)) | ||
| 537 | ((eq major-mode 'latex-mode) | ||
| 538 | (imenu--generic-function imenu-example--generic-latex-expression)) | ||
| 539 | ((eq major-mode 'texinfo-mode) | ||
| 540 | (imenu--generic-function imenu-example--generic-texinfo-expression)) | ||
| 541 | (t | ||
| 542 | (error "The mode \"%s\" does not take full advantage of imenu.el yet." | ||
| 543 | mode-name)))) | ||
| 313 | 544 | ||
| 314 | (defun imenu--replace-spaces (name replacement) | 545 | (defun imenu--replace-spaces (name replacement) |
| 315 | ;; Replace all spaces in NAME with REPLACEMENT. | 546 | ;; Replace all spaces in NAME with REPLACEMENT. |
| @@ -344,6 +575,65 @@ Their results are gathered into an index alist." | |||
| 344 | (imenu--flatten-index-alist pos new-prefix)))))) | 575 | (imenu--flatten-index-alist pos new-prefix)))))) |
| 345 | index-alist)) | 576 | index-alist)) |
| 346 | 577 | ||
| 578 | ;;; | ||
| 579 | ;;; Generic index gathering function. | ||
| 580 | ;;; | ||
| 581 | (defun imenu--generic-extract-name (paren) | ||
| 582 | (let ((numofpar (1- (length paren))) | ||
| 583 | (parencount 0) | ||
| 584 | (par) | ||
| 585 | (index)) | ||
| 586 | ;; Try until we get a match | ||
| 587 | (beginning-of-line) | ||
| 588 | (while (and (<= parencount numofpar) | ||
| 589 | (setq par (nth parencount paren)) | ||
| 590 | (equal (match-beginning par) nil) | ||
| 591 | (equal (match-end par) nil)) | ||
| 592 | (setq parencount (1+ parencount))) | ||
| 593 | (or (and | ||
| 594 | (<= parencount numofpar) | ||
| 595 | (setq index (buffer-substring (match-beginning par) | ||
| 596 | (match-end par)))) | ||
| 597 | ;; take the whole match just in case. | ||
| 598 | (setq index (buffer-substring (match-beginning 0) | ||
| 599 | (match-end 0)))) | ||
| 600 | index)) | ||
| 601 | |||
| 602 | (defun imenu--generic-function (exp) | ||
| 603 | "Generic function for index gathering. | ||
| 604 | |||
| 605 | EXP can be either an regular expression or an alist in the form | ||
| 606 | \(REGEXP PAREN). " | ||
| 607 | |||
| 608 | (let ((index-alist '()) | ||
| 609 | (regexp nil) | ||
| 610 | (paren nil) | ||
| 611 | prev-pos name) | ||
| 612 | (cond ((stringp exp) | ||
| 613 | (setq regexp exp) | ||
| 614 | (setq paren nil)) | ||
| 615 | ((listp exp) | ||
| 616 | (setq regexp (car exp)) | ||
| 617 | (setq paren (cdr exp))) | ||
| 618 | (t | ||
| 619 | (error "Wrong type of argument."))) | ||
| 620 | (goto-char (point-max)) | ||
| 621 | (imenu-progress-message prev-pos 0 t) | ||
| 622 | (while (re-search-backward regexp 1 t) | ||
| 623 | (imenu-progress-message prev-pos nil t) | ||
| 624 | (save-excursion | ||
| 625 | ;; If paren get sub expression | ||
| 626 | (or (and paren | ||
| 627 | (setq name (imenu--generic-extract-name paren))) | ||
| 628 | ;; get the whole expression | ||
| 629 | (beginning-of-line) | ||
| 630 | (setq name (buffer-substring (match-beginning 0) | ||
| 631 | (match-end 0))))) | ||
| 632 | (and (stringp name) | ||
| 633 | (push (cons name (point)) index-alist))) | ||
| 634 | (imenu-progress-message prev-pos 100 t) | ||
| 635 | index-alist)) | ||
| 636 | |||
| 347 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 637 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 348 | ;;; | 638 | ;;; |
| 349 | ;;; The main functions for this package! | 639 | ;;; The main functions for this package! |
| @@ -356,13 +646,13 @@ Their results are gathered into an index alist." | |||
| 356 | Returns t for rescan and otherwise a position number." | 646 | Returns t for rescan and otherwise a position number." |
| 357 | ;; Create a list for this buffer only when needed. | 647 | ;; Create a list for this buffer only when needed. |
| 358 | (let (name choice | 648 | (let (name choice |
| 359 | (prepared-index-alist | 649 | (prepared-index-alist |
| 360 | (mapcar | 650 | (mapcar |
| 361 | (function | 651 | (function |
| 362 | (lambda (item) | 652 | (lambda (item) |
| 363 | (cons (imenu--replace-spaces (car item) imenu-space-replacement) | 653 | (cons (imenu--replace-spaces (car item) imenu-space-replacement) |
| 364 | (cdr item)))) | 654 | (cdr item)))) |
| 365 | index-alist))) | 655 | index-alist))) |
| 366 | (save-window-excursion | 656 | (save-window-excursion |
| 367 | ;; Display the completion buffer | 657 | ;; Display the completion buffer |
| 368 | (with-output-to-temp-buffer "*Completions*" | 658 | (with-output-to-temp-buffer "*Completions*" |
| @@ -495,144 +785,6 @@ See `imenu-choose-buffer-index' for more information." | |||
| 495 | (widen)) | 785 | (widen)) |
| 496 | (goto-char (cdr index-item)))))))) | 786 | (goto-char (cdr index-item)))))))) |
| 497 | 787 | ||
| 498 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 499 | ;;;; | ||
| 500 | ;;;; Some examples of functions utilizing the framework of this | ||
| 501 | ;;;; package. | ||
| 502 | ;;;; | ||
| 503 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 504 | |||
| 505 | ;; Return the current/previous sexp and the location of the sexp (its | ||
| 506 | ;; beginning) without moving the point. | ||
| 507 | (defun imenu-example--name-and-position () | ||
| 508 | (save-excursion | ||
| 509 | (forward-sexp -1) | ||
| 510 | (let ((beg (point)) | ||
| 511 | (end (progn (forward-sexp) (point))) | ||
| 512 | (marker (make-marker))) | ||
| 513 | (set-marker marker beg) | ||
| 514 | (cons (buffer-substring beg end) | ||
| 515 | marker)))) | ||
| 516 | |||
| 517 | ;;; | ||
| 518 | ;;; Lisp | ||
| 519 | ;;; | ||
| 520 | |||
| 521 | (defun imenu-example--lisp-extract-index-name () | ||
| 522 | ;; Example of a candidate for `imenu-extract-index-name-function'. | ||
| 523 | ;; This will generate a flat index of definitions in a lisp file. | ||
| 524 | (save-match-data | ||
| 525 | (and (looking-at "(def") | ||
| 526 | (condition-case nil | ||
| 527 | (progn | ||
| 528 | (down-list 1) | ||
| 529 | (forward-sexp 2) | ||
| 530 | (let ((beg (point)) | ||
| 531 | (end (progn (forward-sexp -1) (point)))) | ||
| 532 | (buffer-substring beg end))) | ||
| 533 | (error nil))))) | ||
| 534 | |||
| 535 | (defun imenu-example--create-lisp-index () | ||
| 536 | ;; Example of a candidate for `imenu-create-index-function'. | ||
| 537 | ;; It will generate a nested index of definitions. | ||
| 538 | (let ((index-alist '()) | ||
| 539 | (index-var-alist '()) | ||
| 540 | (index-type-alist '()) | ||
| 541 | (index-unknown-alist '()) | ||
| 542 | prev-pos) | ||
| 543 | (goto-char (point-max)) | ||
| 544 | (imenu-progress-message prev-pos 0) | ||
| 545 | ;; Search for the function | ||
| 546 | (while (beginning-of-defun) | ||
| 547 | (imenu-progress-message prev-pos nil t) | ||
| 548 | (save-match-data | ||
| 549 | (and (looking-at "(def") | ||
| 550 | (save-excursion | ||
| 551 | (down-list 1) | ||
| 552 | (cond | ||
| 553 | ((looking-at "def\\(var\\|const\\)") | ||
| 554 | (forward-sexp 2) | ||
| 555 | (push (imenu-example--name-and-position) | ||
| 556 | index-var-alist)) | ||
| 557 | ((looking-at "def\\(un\\|subst\\|macro\\|advice\\)") | ||
| 558 | (forward-sexp 2) | ||
| 559 | (push (imenu-example--name-and-position) | ||
| 560 | index-alist)) | ||
| 561 | ((looking-at "def\\(type\\|struct\\|class\\|ine-condition\\)") | ||
| 562 | (forward-sexp 2) | ||
| 563 | (if (= (char-after (1- (point))) ?\)) | ||
| 564 | (progn | ||
| 565 | (forward-sexp -1) | ||
| 566 | (down-list 1) | ||
| 567 | (forward-sexp 1))) | ||
| 568 | (push (imenu-example--name-and-position) | ||
| 569 | index-type-alist)) | ||
| 570 | (t | ||
| 571 | (forward-sexp 2) | ||
| 572 | (push (imenu-example--name-and-position) | ||
| 573 | index-unknown-alist))))))) | ||
| 574 | (imenu-progress-message prev-pos 100) | ||
| 575 | (and index-var-alist | ||
| 576 | (push (cons (imenu-create-submenu-name "Variables") index-var-alist) | ||
| 577 | index-alist)) | ||
| 578 | (and index-type-alist | ||
| 579 | (push (cons (imenu-create-submenu-name "Types") index-type-alist) | ||
| 580 | index-alist)) | ||
| 581 | (and index-unknown-alist | ||
| 582 | (push (cons (imenu-create-submenu-name "Syntax-unknown") index-unknown-alist) | ||
| 583 | index-alist)) | ||
| 584 | index-alist)) | ||
| 585 | |||
| 586 | |||
| 587 | ;;; | ||
| 588 | ;;; C | ||
| 589 | ;;; | ||
| 590 | ;; Regular expression to find C functions | ||
| 591 | (defvar imenu-example--function-name-regexp-c | ||
| 592 | (concat | ||
| 593 | "^[a-zA-Z0-9]+[ \t]?" ; type specs; there can be no | ||
| 594 | "\\([a-zA-Z0-9_*]+[ \t]+\\)?" ; more than 3 tokens, right? | ||
| 595 | "\\([a-zA-Z0-9_*]+[ \t]+\\)?" | ||
| 596 | "\\([*&]+[ \t]*\\)?" ; pointer | ||
| 597 | "\\([a-zA-Z0-9_*]+\\)[ \t]*(" ; name | ||
| 598 | )) | ||
| 599 | |||
| 600 | (defun imenu-example--create-c-index (&optional regexp) | ||
| 601 | (let ((index-alist '()) | ||
| 602 | prev-pos char) | ||
| 603 | (goto-char (point-min)) | ||
| 604 | (imenu-progress-message prev-pos 0) | ||
| 605 | ;; Search for the function | ||
| 606 | (save-match-data | ||
| 607 | (while (re-search-forward | ||
| 608 | (or regexp imenu-example--function-name-regexp-c) | ||
| 609 | nil t) | ||
| 610 | (imenu-progress-message prev-pos) | ||
| 611 | (backward-up-list 1) | ||
| 612 | (save-excursion | ||
| 613 | (goto-char (scan-sexps (point) 1)) | ||
| 614 | (setq char (following-char))) | ||
| 615 | ;; Skip this function name if it is a prototype declaration. | ||
| 616 | (if (not (eq char ?\;)) | ||
| 617 | (push (imenu-example--name-and-position) index-alist)))) | ||
| 618 | (imenu-progress-message prev-pos 100) | ||
| 619 | (nreverse index-alist))) | ||
| 620 | |||
| 621 | ;;; | ||
| 622 | ;;; C++ | ||
| 623 | ;;; | ||
| 624 | ;; Regular expression to find C++ functions | ||
| 625 | (defvar imenu-example--function-name-regexp-c++ | ||
| 626 | (concat | ||
| 627 | "^[a-zA-Z0-9:]+[ \t]?" ; type specs; there can be no | ||
| 628 | "\\([a-zA-Z0-9_:~*]+[ \t]+\\)?" ; more than 3 tokens, right? | ||
| 629 | "\\([a-zA-Z0-9_:~*]+[ \t]+\\)?" | ||
| 630 | "\\([*&]+[ \t]*\\)?" ; pointer | ||
| 631 | "\\([a-zA-Z0-9_:*]+\\)[ \t]*(" ; name | ||
| 632 | )) | ||
| 633 | (defun imenu-example--create-c++-index () | ||
| 634 | (imenu-example--create-c-index imenu-example--function-name-regexp-c++)) | ||
| 635 | |||
| 636 | (provide 'imenu) | 788 | (provide 'imenu) |
| 637 | 789 | ||
| 638 | ;;; imenu.el ends here | 790 | ;;; imenu.el ends here |