diff lisp/imenu.el @ 10093:caafb376e619

(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.
author Karl Heuer <kwzh@gnu.org>
date Wed, 30 Nov 1994 20:50:33 +0000
parents a7b70665c937
children 34b66bff7aec
line wrap: on
line diff
--- a/lisp/imenu.el	Wed Nov 30 19:37:48 1994 +0000
+++ b/lisp/imenu.el	Wed Nov 30 20:50:33 1994 +0000
@@ -5,7 +5,7 @@
 ;; Author: Ake Stenhoff <etxaksf@aom.ericsson.se>
 ;;         Lars Lindberg <lli@sypro.cap.se>
 ;; Created: 8 Feb 1994
-;; Version: 1.12
+;; Version: 1.14
 ;; Keywords: tools
 ;;
 ;; This program is free software; you can redistribute it and/or modify
@@ -47,6 +47,7 @@
 ;;  [dean] - Dean Andrews ada@unison.com
 ;;  [alon] - Alon Albert al@mercury.co.il 
 ;;  [greg] - Greg Thompson gregt@porsche.visix.COM
+;;  [wolfgang] - Wolfgang Bangerth zcg51122@rpool1.rus.uni-stuttgart.de
 ;;  [kai] - Kai Grossjohann grossjoh@linus.informatik.uni-dortmund.de
 
 ;;; Code
@@ -103,6 +104,13 @@
 (defvar imenu-submenu-name-format "%s..."
   "*The format for making a submenu name.")
 
+(defvar imenu-generic-expression nil
+  "Generic regular expression for index gathering.
+
+Can be either an regular expression or an alist in the form
+\(REGEXP PAREN).")
+(make-variable-buffer-local 'imenu-generic-expression)
+
 ;;;; Hooks
 
 (defvar imenu-create-index-function 'imenu-default-create-index-function
@@ -137,6 +145,238 @@
 `imenu-prev-index-position-function'.")
 (make-variable-buffer-local 'imenu-extract-index-name-function)
 
+;;;
+;;; Macro to display a progress message.
+;;; RELPOS is the relative position to display.
+;;; If RELPOS is nil, then the relative position in the buffer
+;;; is calculated.
+;;; PREVPOS is the variable in which we store the last position displayed.
+(defmacro imenu-progress-message (prevpos &optional relpos reverse)
+  (` (and
+      imenu-scanning-message
+      (let ((pos (, (if relpos
+			relpos
+		      (` (imenu--relative-position (, reverse)))))))
+	(if (, (if relpos t
+		 (` (> pos (+ 5 (, prevpos))))))
+	    (progn
+	      (message imenu-scanning-message pos)
+	      (setq (, prevpos) pos)))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;
+;;;; Some examples of functions utilizing the framework of this
+;;;; package.
+;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Return the current/previous sexp and the location of the sexp (it's
+;; beginning) without moving the point.
+(defun imenu-example--name-and-position ()
+  (save-excursion
+    (forward-sexp -1)
+    (let ((beg (point))
+	  (end (progn (forward-sexp) (point)))
+	  (marker (make-marker)))
+      (set-marker marker beg)
+      (cons (buffer-substring beg end)
+	    marker))))
+
+;;;
+;;; Lisp
+;;; 
+
+(defun imenu-example--lisp-extract-index-name ()
+  ;; Example of a candidate for `imenu-extract-index-name-function'.
+  ;; This will generate a flat index of definitions in a lisp file.
+  (save-match-data
+    (and (looking-at "(def")
+	 (condition-case nil
+	     (progn
+	       (down-list 1)
+	       (forward-sexp 2)
+	       (let ((beg (point))
+		     (end (progn (forward-sexp -1) (point))))
+		 (buffer-substring beg end)))
+	   (error nil)))))
+
+(defun imenu-example--create-lisp-index ()
+  ;; Example of a candidate for `imenu-create-index-function'.
+  ;; It will generate a nested index of definitions.
+  (let ((index-alist '())
+	(index-var-alist '())
+	(index-type-alist '())
+	(index-unknown-alist '())
+	prev-pos)
+    (goto-char (point-max))
+    (imenu-progress-message prev-pos 0)
+    ;; Search for the function
+    (while (beginning-of-defun)
+      (imenu-progress-message prev-pos nil t)
+      (save-match-data
+	(and (looking-at "(def")
+	     (save-excursion
+	       (down-list 1)
+	       (cond
+		((looking-at "def\\(var\\|const\\)")
+		 (forward-sexp 2)
+		 (push (imenu-example--name-and-position)
+		       index-var-alist))
+		((looking-at "def\\(un\\|subst\\|macro\\|advice\\)")
+		 (forward-sexp 2)
+		 (push (imenu-example--name-and-position)
+		       index-alist))
+		((looking-at "def\\(type\\|struct\\|class\\|ine-condition\\)")
+ 		 (forward-sexp 2)
+ 		 (if (= (char-after (1- (point))) ?\))
+ 		     (progn
+ 		       (forward-sexp -1)
+ 		       (down-list 1)
+ 		       (forward-sexp 1)))
+ 		 (push (imenu-example--name-and-position)
+ 		       index-type-alist))
+		(t
+		 (forward-sexp 2)
+		 (push (imenu-example--name-and-position)
+		       index-unknown-alist)))))))
+    (imenu-progress-message prev-pos 100)
+    (and index-var-alist
+	 (push (cons (imenu-create-submenu-name "Variables") index-var-alist)
+	       index-alist))
+    (and index-type-alist
+ 	 (push (cons (imenu-create-submenu-name "Types") index-type-alist)
+  	       index-alist))
+    (and index-unknown-alist
+	 (push (cons (imenu-create-submenu-name "Syntax-unknown") index-unknown-alist)
+	       index-alist))
+    index-alist))
+
+;;;
+;;; C
+;;;
+;; Regular expression to find C functions
+(defvar imenu-example--function-name-regexp-c
+  (concat 
+   "^[a-zA-Z0-9]+[ \t]?"		; type specs; there can be no
+   "\\([a-zA-Z0-9_*]+[ \t]+\\)?"	; more than 3 tokens, right?
+   "\\([a-zA-Z0-9_*]+[ \t]+\\)?"
+   "\\([*&]+[ \t]*\\)?"			; pointer
+   "\\([a-zA-Z0-9_*]+\\)[ \t]*("	; name
+   ))
+
+(defun imenu-example--create-c-index (&optional regexp)
+  (let ((index-alist '())
+	prev-pos char)
+    (goto-char (point-min))
+    (imenu-progress-message prev-pos 0)
+    ;; Search for the function
+    (save-match-data
+      (while (re-search-forward
+	      (or regexp imenu-example--function-name-regexp-c)
+	      nil t)
+	(imenu-progress-message prev-pos)
+	(backward-up-list 1)
+	(save-excursion
+	  (goto-char (scan-sexps (point) 1))
+	  (setq char (following-char)))
+	;; Skip this function name if it is a prototype declaration.
+	(if (not (eq char ?\;))
+	    (push (imenu-example--name-and-position) index-alist))))
+    (imenu-progress-message prev-pos 100)
+    (nreverse index-alist)))
+
+;;;
+;;; C++
+;;;
+;; Example of an imenu-generic-expression
+;;
+(defvar imenu-example--generic-c++-expression
+  (cons
+   ;; regular expression
+   (concat 
+    "^"					; beginning of line is required
+    "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>"
+    "\\("
+    
+    "\\("				; >>looking for a function definition<<
+    "\\([a-zA-Z0-9_:]+[ \t]+\\)?"	; type specs; there can be no
+    "\\([a-zA-Z0-9_:]+[ \t]+\\)?"	; more than 3 tokens, right?
+    
+    "\\("				; last type spec including */&
+    "[a-zA-Z0-9_:]+"
+    "\\([ \t]*[*&]+[ \t]*\\|[ \t]+\\)"	; either pointer/ref sign or whitespace
+    "\\)?"				; if there is a last type spec
+    
+    "\\("				; name; take that into the imenu entry
+    "[a-zA-Z0-9_:~]+"			; member function, ctor or dtor...
+                                        ; (may not contain * because then 
+                                        ; "a::operator char*" would become "char*"!)
+    "\\|"
+    "\\([a-zA-Z0-9_:~]*::\\)?operator"
+    "[^a-zA-Z1-9_][^(]*"		; ...or operator
+    " \\)"
+    "[ \t]*([^)]*)[ \t\n]*[^		;]"          ; require something other than a ; after
+                                        ; the (...) to avoid prototypes. Can't
+                                        ; catch cases with () inside the parentheses
+                                        ; surrounding the parameters
+                                        ; (like "int foo(int a=bar()) {...}"
+    "\\)"				; <<looking for a function definition>>
+    
+    "\\|"
+    
+    "\\("				; >>class decl<<
+    "\\(class[ \t]+[a-zA-Z0-9_]+\\)"	; this is the string we want to get
+    "[ \t]*[:{]"
+    "\\)"				; <<class decl>>
+    
+    "\\)")
+   ;; paren
+   (list 8 11))
+  "imenu generic expression for C++ mode in the form
+\(REGEXP PAR).")
+
+;;; 
+;;; TexInfo
+;;; 
+;; Written by Wolfgang Bangerth <zcg51122@rpool1.rus.uni-stuttgart.de>
+;;
+;;
+(defvar imenu-example--generic-texinfo-expression
+  (cons
+   (concat 
+    "^@node[ \t]+"
+    "\\([^,\n]*\\)")
+   (list 1))
+  "imenu generic expression for TexInfo mode in the form
+\(REGEXP PAR).
+
+To overide this example, Either set 'imenu-generic-expression
+or 'imenu-create-index-function")
+
+;;; 
+;;; LaTex
+;;; 
+;; Written by Wolfgang Bangerth <zcg51122@rpool1.rus.uni-stuttgart.de>
+;;
+;;
+(defvar imenu-example--generic-latex-expression
+  (concat
+   "\\("
+   "%[ \t]*[0-9]+\\.[0-9]+[,;]?[ \t]?"  ; i put numbers like 3.15 before my
+                                        ; \begin{equation}'s which tell me
+                                        ; the number the equation will get when
+                                        ; being printed.
+   "\\|"
+   "\\\\part{[^}]*}"
+   "\\|"
+   "\\\\chapter{[^}]*}"
+   "\\|"
+   "\\\\[a-zA-Z]*section{[^}]*}"
+   "\\)")
+  "imenu generic expression for LaTex mode in the form
+\"REGEXP\".")
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;
 ;;; Internal variables
@@ -183,24 +423,6 @@
       (/ (* 100 (1- pos)) (max total 1)))))
 
 ;;;
-;;; Macro to display a progress message.
-;;; RELPOS is the relative position to display.
-;;; If RELPOS is nil, then the relative position in the buffer
-;;; is calculated.
-;;; PREVPOS is the variable in which we store the last position displayed.
-(defmacro imenu-progress-message (prevpos &optional relpos reverse)
-  (` (and
-      imenu-scanning-message
-      (let ((pos (, (if relpos
-		      relpos
-		    (` (imenu--relative-position (, reverse)))))))
-	(if (, (if relpos t
-		 (` (> pos (+ 5 (, prevpos))))))
-	    (progn
-	      (message imenu-scanning-message pos)
-	      (setq (, prevpos) pos)))))))
-
-;;;
 ;;; Function for suporting general looking submenu names.
 ;;; Uses `imenu-submenu-name-format' for creating the name.
 ;;; NAME is the base of the new submenu name.
@@ -274,8 +496,9 @@
 	     (set-marker (cdr item) nil))
 	    ((listp (cdr item))
 	     (imenu--cleanup (cdr item))))))
-	 (if alist alist imenu--index-alist))
-	t))
+	(if alist alist imenu--index-alist))
+       t))
+
 (defun imenu-default-create-index-function ()
   "*Wrapper for index searching functions.
 
@@ -284,21 +507,10 @@
 Their results are gathered into an index alist."
   ;; These should really be done by setting imenu-create-index-function
   ;; in these major modes.  But save that change for later.
-  (cond ((eq major-mode 'emacs-lisp-mode)
-	 (imenu-example--create-lisp-index))
-	((eq major-mode 'lisp-mode)
-	 (imenu-example--create-lisp-index))
-	((eq major-mode 'c++-mode)
-	 (imenu-example--create-c++-index))
-	((eq major-mode 'c-mode)
-	 (imenu-example--create-c-index))
-	(t
-	 (or (and (fboundp imenu-prev-index-position-function)
-		  (fboundp imenu-extract-index-name-function))
-	     (error "The mode \"%s\" does not take full advantage of imenu.el yet."
-		    mode-name))      
+  (cond ((and (fboundp imenu-prev-index-position-function)
+	      (fboundp imenu-extract-index-name-function))
 	 (let ((index-alist '())
-	       name prev-pos)
+	       prev-pos name)
 	   (goto-char (point-max))
 	   (imenu-progress-message prev-pos 0 t)
 	   ;; Search for the function
@@ -309,7 +521,26 @@
 	     (and (stringp name)
 		  (push (cons name (point)) index-alist)))
 	   (imenu-progress-message prev-pos 100 t)
-	   index-alist))))
+	   index-alist))
+	;; Use generic expression if possible.
+	((and imenu-generic-expression)
+	 (imenu--generic-function imenu-generic-expression))
+	;; Use supplied example functions
+	((eq major-mode 'emacs-lisp-mode)
+	 (imenu-example--create-lisp-index))
+	((eq major-mode 'lisp-mode)
+	 (imenu-example--create-lisp-index))
+	((eq major-mode 'c++-mode)
+	 (imenu--generic-function imenu-example--generic-c++-expression))
+	((eq major-mode 'c-mode)
+	 (imenu-example--create-c-index))
+	((eq major-mode 'latex-mode)
+	 (imenu--generic-function imenu-example--generic-latex-expression))
+	((eq major-mode 'texinfo-mode)
+	 (imenu--generic-function imenu-example--generic-texinfo-expression))
+	(t
+	 (error "The mode \"%s\" does not take full advantage of imenu.el yet."
+		mode-name))))      
 
 (defun imenu--replace-spaces (name replacement)
   ;; Replace all spaces in NAME with REPLACEMENT.
@@ -344,6 +575,65 @@
 	  (imenu--flatten-index-alist pos new-prefix))))))
    index-alist))
 
+;;;
+;;; Generic index gathering function.
+;;;
+(defun imenu--generic-extract-name (paren)
+  (let ((numofpar (1- (length paren)))
+	(parencount 0)
+	(par)
+	(index))
+    ;; Try until we get a match
+    (beginning-of-line)
+    (while (and (<= parencount numofpar)
+		(setq par (nth parencount paren))
+		(equal (match-beginning par) nil)
+		(equal (match-end par) nil))
+      (setq parencount (1+ parencount)))
+    (or (and 
+	 (<= parencount numofpar)
+	 (setq index (buffer-substring (match-beginning par)
+				       (match-end par))))
+	;; take the whole match just in case.
+	(setq index (buffer-substring (match-beginning 0)
+				      (match-end 0))))
+    index))
+
+(defun imenu--generic-function (exp)
+  "Generic function for index gathering.
+
+EXP can be either an regular expression or an alist in the form
+\(REGEXP PAREN). "
+  
+  (let ((index-alist '())
+	(regexp nil)
+	(paren nil)
+	prev-pos name)
+    (cond ((stringp exp)
+	   (setq regexp exp)
+	   (setq paren nil))
+          ((listp exp)
+	   (setq regexp (car exp))
+	   (setq paren (cdr exp)))
+          (t
+           (error "Wrong type of argument.")))
+    (goto-char (point-max))
+    (imenu-progress-message prev-pos 0 t)
+    (while (re-search-backward regexp 1 t)
+      (imenu-progress-message prev-pos nil t)
+      (save-excursion
+	;; If paren get sub expression
+	(or  (and paren
+		  (setq name (imenu--generic-extract-name paren)))
+	     ;; get the whole expression
+	     (beginning-of-line)
+	     (setq name (buffer-substring (match-beginning 0) 
+					  (match-end 0)))))
+      (and (stringp name)
+	   (push (cons name (point)) index-alist)))
+    (imenu-progress-message prev-pos 100 t)
+    index-alist))
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;
 ;;; The main functions for this package!
@@ -356,13 +646,13 @@
 Returns t for rescan and otherwise a position number."
   ;; Create a list for this buffer only when needed.
   (let (name choice
-	(prepared-index-alist
-	 (mapcar
-	  (function
-	   (lambda (item)
-	     (cons (imenu--replace-spaces (car item) imenu-space-replacement)
-		   (cdr item))))
-	  index-alist)))
+	     (prepared-index-alist
+	      (mapcar
+	       (function
+		(lambda (item)
+		  (cons (imenu--replace-spaces (car item) imenu-space-replacement)
+			(cdr item))))
+	       index-alist)))
     (save-window-excursion
       ;; Display the completion buffer
       (with-output-to-temp-buffer "*Completions*"
@@ -495,144 +785,6 @@
 		 (widen))
 	     (goto-char (cdr index-item))))))))
 
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;;
-;;;; Some examples of functions utilizing the framework of this
-;;;; package.
-;;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; Return the current/previous sexp and the location of the sexp (its
-;; beginning) without moving the point.
-(defun imenu-example--name-and-position ()
-  (save-excursion
-    (forward-sexp -1)
-    (let ((beg (point))
-	  (end (progn (forward-sexp) (point)))
-	  (marker (make-marker)))
-      (set-marker marker beg)
-      (cons (buffer-substring beg end)
-	    marker))))
-  
-;;;
-;;; Lisp
-;;; 
-
-(defun imenu-example--lisp-extract-index-name ()
-  ;; Example of a candidate for `imenu-extract-index-name-function'.
-  ;; This will generate a flat index of definitions in a lisp file.
-  (save-match-data
-    (and (looking-at "(def")
-	 (condition-case nil
-	     (progn
-	       (down-list 1)
-	       (forward-sexp 2)
-	       (let ((beg (point))
-		     (end (progn (forward-sexp -1) (point))))
-		 (buffer-substring beg end)))
-	   (error nil)))))
-
-(defun imenu-example--create-lisp-index ()
-  ;; Example of a candidate for `imenu-create-index-function'.
-  ;; It will generate a nested index of definitions.
-  (let ((index-alist '())
-	(index-var-alist '())
-	(index-type-alist '())
-	(index-unknown-alist '())
-	prev-pos)
-    (goto-char (point-max))
-    (imenu-progress-message prev-pos 0)
-    ;; Search for the function
-    (while (beginning-of-defun)
-      (imenu-progress-message prev-pos nil t)
-      (save-match-data
-	(and (looking-at "(def")
-	     (save-excursion
-	       (down-list 1)
-	       (cond
-		((looking-at "def\\(var\\|const\\)")
-		 (forward-sexp 2)
-		 (push (imenu-example--name-and-position)
-		       index-var-alist))
-		((looking-at "def\\(un\\|subst\\|macro\\|advice\\)")
-		 (forward-sexp 2)
-		 (push (imenu-example--name-and-position)
-		       index-alist))
-		((looking-at "def\\(type\\|struct\\|class\\|ine-condition\\)")
- 		 (forward-sexp 2)
- 		 (if (= (char-after (1- (point))) ?\))
- 		     (progn
- 		       (forward-sexp -1)
- 		       (down-list 1)
- 		       (forward-sexp 1)))
- 		 (push (imenu-example--name-and-position)
- 		       index-type-alist))
-		(t
-		 (forward-sexp 2)
-		 (push (imenu-example--name-and-position)
-		       index-unknown-alist)))))))
-    (imenu-progress-message prev-pos 100)
-    (and index-var-alist
-	 (push (cons (imenu-create-submenu-name "Variables") index-var-alist)
-	       index-alist))
-    (and index-type-alist
- 	 (push (cons (imenu-create-submenu-name "Types") index-type-alist)
-  	       index-alist))
-    (and index-unknown-alist
-	 (push (cons (imenu-create-submenu-name "Syntax-unknown") index-unknown-alist)
-	       index-alist))
-    index-alist))
-    
-
-;;;
-;;; C
-;;;
-;; Regular expression to find C functions
-(defvar imenu-example--function-name-regexp-c
-  (concat 
-   "^[a-zA-Z0-9]+[ \t]?"		; type specs; there can be no
-   "\\([a-zA-Z0-9_*]+[ \t]+\\)?"	; more than 3 tokens, right?
-   "\\([a-zA-Z0-9_*]+[ \t]+\\)?"
-   "\\([*&]+[ \t]*\\)?"			; pointer
-   "\\([a-zA-Z0-9_*]+\\)[ \t]*("	; name
-   ))
-
-(defun imenu-example--create-c-index (&optional regexp)
-  (let ((index-alist '())
-	prev-pos char)
-    (goto-char (point-min))
-    (imenu-progress-message prev-pos 0)
-    ;; Search for the function
-    (save-match-data
-      (while (re-search-forward
-	      (or regexp imenu-example--function-name-regexp-c)
-	      nil t)
-	(imenu-progress-message prev-pos)
-	(backward-up-list 1)
-	(save-excursion
-	  (goto-char (scan-sexps (point) 1))
-	  (setq char (following-char)))
-	;; Skip this function name if it is a prototype declaration.
-	(if (not (eq char ?\;))
-	    (push (imenu-example--name-and-position) index-alist))))
-    (imenu-progress-message prev-pos 100)
-    (nreverse index-alist)))
-
-;;; 
-;;; C++
-;;; 
-;; Regular expression to find C++ functions
-(defvar imenu-example--function-name-regexp-c++
-  (concat 
-   "^[a-zA-Z0-9:]+[ \t]?"		; type specs; there can be no
-   "\\([a-zA-Z0-9_:~*]+[ \t]+\\)?"	; more than 3 tokens, right?
-   "\\([a-zA-Z0-9_:~*]+[ \t]+\\)?"
-   "\\([*&]+[ \t]*\\)?"			; pointer
-   "\\([a-zA-Z0-9_:*]+\\)[ \t]*("	; name
-   ))
-(defun imenu-example--create-c++-index ()
-  (imenu-example--create-c-index imenu-example--function-name-regexp-c++))
-
 (provide 'imenu)
 
 ;;; imenu.el ends here