]> code.delx.au - gnu-emacs/blobdiff - lisp/imenu.el
(describe_category_1): Pass new args to describe_vector.
[gnu-emacs] / lisp / imenu.el
index c35f963e9906f02f55d57c2f92b8cdd8eac58f26..dc5241420b9e6bcac8369ce2a1c1f182264bfc65 100644 (file)
@@ -1,6 +1,6 @@
 ;;; imenu.el --- Framework for mode-specific buffer indexes.
 
-;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
 
 ;; Author: Ake Stenhoff <etxaksf@aom.ericsson.se>
 ;;         Lars Lindberg <lli@sypro.cap.se>
 ;;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(defvar imenu-auto-rescan nil
-  "*Non-nil means Imenu should always rescan the buffers.")
+(defgroup imenu nil
+  "Mode-specific buffer indexes."
+  :group 'matching
+  :group 'frames)
 
-(defvar imenu-auto-rescan-maxout 60000 
-  "* auto-rescan is disabled in buffers larger than this.
-This variable is buffer-local.")
+(defcustom imenu-use-markers t
+  "*Non-nil means use markers instead of integers for Imenu buffer positions.
+Setting this to nil makes Imenu work faster.
 
-(defvar imenu-always-use-completion-buffer-p nil
+This might not yet be honored by all index-building functions."
+  :type 'boolean
+  :group 'imenu)
+
+
+(defcustom imenu-max-item-length 60
+  "*If a number, truncate Imenu entries to that length."
+  :type 'integer
+  :group 'imenu)
+
+(defcustom imenu-auto-rescan nil
+  "*Non-nil means Imenu should always rescan the buffers."
+  :type 'boolean
+  :group 'imenu)
+
+(defcustom imenu-auto-rescan-maxout 60000 
+  "*Imenu auto-rescan is disabled in buffers larger than this size.
+This variable is buffer-local."
+  :type 'integer
+  :group 'imenu)
+
+(defcustom imenu-always-use-completion-buffer-p nil
   "*Set this to non-nil for displaying the index in a completion buffer.
 
-Non-nil means always display the index in a completion buffer.
-Nil means display the index as a mouse menu when the mouse was
-used to invoke `imenu'.
-`never' means never automatically display a listing of any kind.")
+`never' means never automatically display a listing of any kind.
+A value of nil (the default) means display the index as a mouse menu
+if the mouse was used to invoke `imenu'.
+Another non-nil value means always display the index in a completion buffer."
+  :type '(choice (const :tag "On Mouse" nil)
+                (const :tag "Never" never)
+                (sexp :tag "Always" :format "%t\n" t))
+  :group 'imenu)
 
-(defvar imenu-sort-function nil
+(defcustom imenu-sort-function nil
   "*The function to use for sorting the index mouse-menu.
 
 Affects only the mouse index menu.
@@ -93,33 +120,43 @@ Set it to `imenu--sort-by-name' if you want alphabetic sorting.
 
 The function should take two arguments and return T if the first
 element should come before the second.  The arguments are cons cells;
-\(NAME . POSITION).  Look at `imenu--sort-by-name' for an example.")
+\(NAME . POSITION).  Look at `imenu--sort-by-name' for an example."
+  :type 'function
+  :group 'imenu)
 
-(defvar imenu-max-items 25
-  "*Maximum number of elements in an mouse menu for Imenu.")
+(defcustom imenu-max-items 25
+  "*Maximum number of elements in a mouse menu for Imenu."
+  :type 'integer
+  :group 'imenu)
 
-(defvar imenu-scanning-message "Scanning buffer for index (%3d%%)"
+(defcustom imenu-scanning-message "Scanning buffer for index (%3d%%)"
   "*Progress message during the index scanning of the buffer.
-If non-nil, user gets a message during the scanning of the buffer
+If non-nil, user gets a message during the scanning of the buffer.
 
 Relevant only if the mode-specific function that creates the buffer
-index use `imenu-progress-message'.")
+index use `imenu-progress-message'."
+  :type 'string
+  :group 'imenu)
 
-(defvar imenu-space-replacement "^"
+(defcustom imenu-space-replacement "^"
   "*The replacement string for spaces in index names.
 Used when presenting the index in a completion-buffer to make the
-names work as tokens.")
+names work as tokens."
+  :type 'string
+  :group 'imenu)
 
-(defvar imenu-level-separator ":"
+(defcustom imenu-level-separator ":"
   "*The separator between index names of different levels.
 Used for making mouse-menu titles and for flattening nested indexes
-with name concatenation.")
+with name concatenation."
+  :type 'string
+  :group 'imenu)
 
 ;;;###autoload
 (defvar imenu-generic-expression nil
   "The regex pattern to use for creating a buffer index.
 
-If non-nil this pattern is passed to `imenu-create-index-with-pattern'
+If non-nil this pattern is passed to `imenu--generic-function'
 to create a buffer index.
 
 The value should be an alist with elements that look like this:
@@ -191,6 +228,12 @@ This function is called after the function pointed out by
 `imenu-prev-index-position-function'.")
 (make-variable-buffer-local 'imenu-extract-index-name-function)
 
+(defvar imenu-default-goto-function 'imenu-default-goto-function
+  "The default function called when selecting an Imenu item.
+The function in this variable is called when selecting a normal index-item.")
+(make-variable-buffer-local 'imenu-default-goto-function)
+
+
 (defun imenu--subalist-p (item)
   (and (consp (cdr item)) (listp (cadr item))
        (not (eq (caadr item) 'lambda))))
@@ -226,12 +269,11 @@ This function is called after the function pointed out by
 (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)
+    ;; [ydi] modified for imenu-use-markers
+    (let ((beg (if imenu-use-markers (point-marker) (point)))
+         (end (progn (forward-sexp) (point))))
       (cons (buffer-substring beg end)
-           marker))))
+           beg))))
 
 ;;;
 ;;; Lisp
@@ -447,6 +489,21 @@ This function is called after the function pointed out by
                        elt)))
          alist))
 
+;;; Truncate all strings in MENULIST to imenu-max-item-length
+(defun imenu--truncate-items (menulist)
+  (mapcar (function
+          (lambda (item)
+            (cond
+             ((consp (cdr item))
+              (imenu--truncate-items (cdr item)))
+             (t
+              ;; truncate if necessary
+              (if (and (numberp imenu-max-item-length)
+                       (> (length (car item)) imenu-max-item-length))
+                  (setcar item (substring (car item) 0 imenu-max-item-length)))))))
+         menulist))
+
+
 (defun imenu--make-index-alist (&optional noerror)
   "Create an index-alist for the definitions in the current buffer.
 
@@ -462,10 +519,14 @@ as a way for the user to ask to recalculate the buffer's index alist."
           (or (not imenu-auto-rescan)
               (and imenu-auto-rescan
                    (> (buffer-size)  imenu-auto-rescan-maxout))))
-      ;; Get the index
-      (setq imenu--index-alist
-           (save-excursion
-             (funcall imenu-create-index-function))))
+      ;; Get the index; truncate if necessary
+      (progn
+       (setq imenu--index-alist
+             (save-excursion
+               (save-restriction
+                 (widen)
+                 (funcall imenu-create-index-function))))
+       (imenu--truncate-items imenu--index-alist)))
   (or imenu--index-alist noerror
       (error "No items suitable for an index found in this buffer"))
   (or imenu--index-alist
@@ -569,14 +630,16 @@ Their results are gathered into an index alist."
             (save-excursion
               (setq name (funcall imenu-extract-index-name-function)))
             (and (stringp name)
-                 (push (cons name (point)) index-alist)))
+                 ;; [ydi] updated for imenu-use-markers
+                 (push (cons name (if imenu-use-markers (point-marker) (point)))
+                       index-alist)))
           (imenu-progress-message prev-pos 100 t)
           index-alist))
        ;; Use generic expression if possible.
        ((and imenu-generic-expression)
         (imenu--generic-function imenu-generic-expression)) 
        (t
-        (error "The mode `%s' does not support Imenu" mode-name))))
+        (error "This buffer cannot use `imenu-default-create-index-function'"))))
 
 (defun imenu--replace-spaces (name replacement)
   ;; Replace all spaces in NAME with REPLACEMENT.
@@ -675,15 +738,17 @@ pattern.
                    (rest (cddddr pat)))
                (if (and (not found) ; Only allow one entry;
                         (looking-at regexp))
-                   (let ((beg (make-marker))
+                   (let ((beg (match-beginning index))
                          (end (match-end index)))
-                     (set-marker beg (match-beginning index))
                      (setq found t)
                      (push 
                       (let ((name
                              (buffer-substring-no-properties beg end)))
+                        ;; [ydi] updated for imenu-use-markers
+                        (if imenu-use-markers
+                            (setq beg (set-marker (make-marker) beg)))
                         (if function
-                            (nconc (list name function name beg)
+                            (nconc (list name beg function)
                                    rest)
                           (cons name beg)))
                       (cdr 
@@ -836,15 +901,19 @@ The returned value is of the form (INDEX-NAME . INDEX-POSITION)."
 NAME is a string used to name the menu bar item.
 See the command `imenu' for more information."
   (interactive "sImenu menu item name: ")
-  (let ((newmap (make-sparse-keymap))
-       (menu-bar (lookup-key (current-local-map) [menu-bar])))
-    (define-key newmap [menu-bar]
-      (append (make-sparse-keymap) menu-bar))
-    (define-key newmap [menu-bar index]
-      (cons name (nconc (make-sparse-keymap "Imenu")
-                       (make-sparse-keymap))))
-    (use-local-map (append newmap (current-local-map))))
-  (add-hook 'menu-bar-update-hook 'imenu-update-menubar))
+  (if (or (and (fboundp imenu-prev-index-position-function)
+                  (fboundp imenu-extract-index-name-function))
+             (and imenu-generic-expression))
+        (let ((newmap (make-sparse-keymap))
+              (menu-bar (lookup-key (current-local-map) [menu-bar])))
+          (define-key newmap [menu-bar]
+            (append (make-sparse-keymap) menu-bar))
+          (define-key newmap [menu-bar index]
+            (cons name (nconc (make-sparse-keymap "Imenu")
+                              (make-sparse-keymap))))
+          (use-local-map (append newmap (current-local-map)))
+          (add-hook 'menu-bar-update-hook 'imenu-update-menubar))
+    (error "The mode `%s' does not support Imenu" mode-name)))
 
 (defvar imenu-buffer-menubar nil)
 
@@ -870,45 +939,43 @@ See the command `imenu' for more information."
 
 (defun imenu--menubar-select (item)
   "Use Imenu to select the function or variable named in this menu item."
-  (if (equal item '("*Rescan*" . -99))
+  (if (equal item imenu--rescan-item)
       (progn
        (imenu--cleanup)
        (setq imenu--index-alist nil)
        (imenu-update-menubar))
     (imenu item)))
 
+(defun imenu-default-goto-function (name position &optional rest)
+  "This function is used for moving the point to POSITION. 
+The NAME and REST parameters are not used, they are here just to make
+this function have the same interface as a function placed in a special 
+index-item."
+  (if (or (< position (point-min))
+         (> position (point-max)))
+      ;; widen if outside narrowing
+      (widen))
+  (goto-char position))
+
 ;;;###autoload
 (defun imenu (index-item)
   "Jump to a place in the buffer chosen using a buffer menu or mouse menu.
 See `imenu-choose-buffer-index' for more information."
-  (interactive
-   (list (save-restriction 
-          (widen)
-          (imenu-choose-buffer-index))))
+  (interactive (list (imenu-choose-buffer-index)))
   ;; Convert a string to an alist element.
   (if (stringp index-item)
       (setq index-item (assoc index-item (imenu--make-index-alist))))
   (and index-item
        (progn
         (push-mark)
-        (cond
-         ((markerp (cdr index-item))
-          (if (or (< (marker-position (cdr index-item)) (point-min))
-                  (> (marker-position (cdr index-item)) (point-max)))
-              ;; widen if outside narrowing
-              (widen))
-          (goto-char (marker-position (cdr index-item))))
-         ((imenu--subalist-p index-item)
-          (if (or (< (cdr index-item) (point-min))
-                  (> (cdr index-item) (point-max)))
-              ;; widen if outside narrowing
-              (widen))
-          (goto-char (cdr index-item)))
-         (t
-          ;; A special item with a function.
-          (let ((function (cadr index-item))
-                (rest (cddr index-item)))
-            (apply function (car index-item) rest)))))))
+        (let* ((is-special-item (listp (cdr index-item)))
+               (function 
+                (if is-special-item
+                    (caddr index-item) imenu-default-goto-function))
+              (position (if is-special-item
+                            (cadr index-item) (cdr index-item)))
+              (rest (if is-special-item (cddr index-item))))
+          (apply function (car index-item) position rest)))))
 
 (provide 'imenu)