(ispell-local-dictionary-alist): Add
[bpt/emacs.git] / lisp / imenu.el
index 30f9383..42f50fb 100644 (file)
@@ -1,6 +1,6 @@
 ;;; imenu.el --- framework for mode-specific buffer indexes
 
-;; Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 2003 Free Software Foundation, Inc.
 
 ;; Author: Ake Stenhoff <etxaksf@aom.ericsson.se>
 ;;         Lars Lindberg <lli@sypro.cap.se>
@@ -104,17 +104,26 @@ 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.
-
-`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)
-                (other :tag "Always" t))
-  :group 'imenu)
+(defvar imenu-always-use-completion-buffer-p nil)
+(make-obsolete-variable 'imenu-always-use-completion-buffer-p
+                       'imenu-use-popup-menu "21.4")
+
+(defcustom imenu-use-popup-menu
+  (if imenu-always-use-completion-buffer-p
+      (not (eq imenu-always-use-completion-buffer-p 'never))
+    'on-mouse)
+  "Use a popup menu rather than a minibuffer prompt.
+If nil, always use a minibuffer prompt.
+If t, always use a popup menu,
+If `on-mouse' use a popup menu when `imenu' was invoked with the mouse."
+  :type '(choice (const :tag "On Mouse" on-mouse)
+                (const :tag "Never" nil)
+                (other :tag "Always" t)))
+
+(defcustom imenu-eager-completion-buffer
+  (not (eq imenu-always-use-completion-buffer-p 'never))
+  "If non-nil, eagerly popup the completion buffer."
+  :type 'boolean)
 
 (defcustom imenu-after-jump-hook nil
   "*Hooks called after jumping to a place in the buffer.
@@ -164,7 +173,7 @@ which case you might as well set this to nil."
   "*The replacement string for spaces in index names.
 Used when presenting the index in a completion buffer to make the
 names work as tokens."
-  :type 'string
+  :type '(choice string (const nil))
   :group 'imenu)
 
 (defcustom imenu-level-separator ":"
@@ -518,22 +527,17 @@ This variable is local in all buffers, once set.")
              menulist (delq imenu--rescan-item menulist)))
     (setq tail menulist)
     (dolist (item tail)
-      (if (imenu--subalist-p item)
-         (setq keep-at-top (cons item keep-at-top)
-               menulist (delq item menulist))))
+      (when (imenu--subalist-p item)
+       (push item keep-at-top)
+       (setq menulist (delq item menulist))))
     (if imenu-sort-function
-       (setq menulist
-             (sort
-              (copy-sequence menulist)
-              imenu-sort-function)))
+       (setq menulist (sort menulist imenu-sort-function)))
     (if (> (length menulist) imenu-max-items)
-       (let ((count 0))
-         (setq menulist
-               (mapcar
-                (function
-                 (lambda (menu)
-                   (cons (format "From: %s" (caar menu)) menu)))
-                (imenu--split menulist imenu-max-items)))))
+       (setq menulist
+             (mapcar
+              (lambda (menu)
+                (cons (format "From: %s" (caar menu)) menu))
+              (imenu--split menulist imenu-max-items))))
     (cons title
          (nconc (nreverse keep-at-top) menulist))))
 
@@ -625,19 +629,18 @@ as a way for the user to ask to recalculate the buffer's index alist."
        alist)
        t))
 
-(defun imenu--create-keymap-1 (title alist)
-  (let ((counter 0))
-    (list* 'keymap title
-          (mapcar
-           (lambda (item)
-             (list* (car item) (car item)
-                    (cond
-                     ((imenu--subalist-p item)
-                      (imenu--create-keymap-1 (car item) (cdr item)))
-                     (t
-                      `(lambda () (interactive)
-                         (imenu--menubar-select ',item))))))
-           alist))))
+(defun imenu--create-keymap (title alist &optional cmd)
+  (list* 'keymap title
+        (mapcar
+         (lambda (item)
+           (list* (car item) (car item)
+                  (cond
+                   ((imenu--subalist-p item)
+                    (imenu--create-keymap (car item) (cdr item) cmd))
+                   (t
+                    `(lambda () (interactive)
+                       ,(if cmd `(,cmd ',item) (list 'quote item)))))))
+         alist)))
 
 (defun imenu--in-alist (str alist)
   "Check whether the string STR is contained in multi-level ALIST."
@@ -667,7 +670,7 @@ as a way for the user to ask to recalculate the buffer's index alist."
   "Alist of syntax table modifiers to use while in `imenu--generic-function'.
 
 The car of the assocs may be either a character or a string and the
-cdr is a syntax description appropriate fo `modify-syntax-entry'.  For
+cdr is a syntax description appropriate for `modify-syntax-entry'.  For
 a string, all the characters in the string get the specified syntax.
 
 This is typically used to give word syntax to characters which
@@ -708,25 +711,25 @@ Their results are gathered into an index alist."
         (error "This buffer cannot use `imenu-default-create-index-function'"))))
 
 ;; Not used and would require cl at run time
-;;; (defun imenu--flatten-index-alist (index-alist &optional concat-names prefix)
-;;;   ;; Takes a nested INDEX-ALIST and returns a flat index alist.
-;;;   ;; If optional CONCAT-NAMES is non-nil, then a nested index has its
-;;;   ;; name and a space concatenated to the names of the children.
-;;;   ;; Third argument PREFIX is for internal use only.
-;;;   (mapcan
-;;;    (lambda (item)
-;;;      (let* ((name (car item))
-;;;        (pos (cdr item))
-;;;        (new-prefix (and concat-names
-;;;                         (if prefix
-;;;                             (concat prefix imenu-level-separator name)
-;;;                           name))))
-;;;        (cond
-;;;    ((or (markerp pos) (numberp pos))
-;;;     (list (cons new-prefix pos)))
-;;;    (t
-;;;     (imenu--flatten-index-alist pos new-prefix)))))
-;;;    index-alist))
+;; (defun imenu--flatten-index-alist (index-alist &optional concat-names prefix)
+;;   ;; Takes a nested INDEX-ALIST and returns a flat index alist.
+;;   ;; If optional CONCAT-NAMES is non-nil, then a nested index has its
+;;   ;; name and a space concatenated to the names of the children.
+;;   ;; Third argument PREFIX is for internal use only.
+;;   (mapcan
+;;    (lambda (item)
+;;      (let* ((name (car item))
+;;         (pos (cdr item))
+;;         (new-prefix (and concat-names
+;;                          (if prefix
+;;                              (concat prefix imenu-level-separator name)
+;;                            name))))
+;;        (cond
+;;     ((or (markerp pos) (numberp pos))
+;;      (list (cons new-prefix pos)))
+;;     (t
+;;      (imenu--flatten-index-alist pos new-prefix)))))
+;;    index-alist))
 
 ;;;
 ;;; Generic index gathering function.
@@ -736,9 +739,8 @@ Their results are gathered into an index alist."
   "Defines whether `imenu--generic-function' should fold case when matching.
 
 This variable should be set (only) by initialization code
-for modes which use `imenu--generic-function'.  If it is not set, that
-function will use the current value of `case-fold-search' to match
-patterns.")
+for modes which use `imenu--generic-function'.  If it is not set, but
+`font-lock-defaults' is set, then font-lock's setting is used.")
 ;;;###autoload
 (make-variable-buffer-local 'imenu-case-fold-search)
 
@@ -749,6 +751,9 @@ patterns.")
 
 PATTERNS is an alist with elements that look like this:
  (MENU-TITLE REGEXP INDEX).
+or like this:
+ (MENU-TITLE REGEXP INDEX FUNCTION ARGUMENTS...)
+with zero or more ARGUMENTS.
 
 MENU-TITLE is a string used as the title for the submenu or nil if the
 entries are not nested.
@@ -764,13 +769,20 @@ function, variable or type) that is to appear in the menu.
 See `lisp-imenu-generic-expression' for an example of PATTERNS.
 
 Returns an index of the current buffer as an alist.  The elements in
-the alist look like: (INDEX-NAME . INDEX-POSITION).  They may also be
-nested index lists like (INDEX-NAME . INDEX-ALIST) depending on
-PATTERNS."
+the alist look like:
+ (INDEX-NAME . INDEX-POSITION)
+or like:
+ (INDEX-NAME INDEX-POSITION FUNCTION ARGUMENTS...)
+They may also be nested index alists like: 
+ (INDEX-NAME . INDEX-ALIST)
+depending on PATTERNS."
 
   (let ((index-alist (list 'dummy))
        prev-pos beg
-        (case-fold-search imenu-case-fold-search)
+        (case-fold-search (if (or (local-variable-p 'imenu-case-fold-search)
+                                 (not (local-variable-p 'font-lock-defaults)))
+                             imenu-case-fold-search
+                           (nth 2 font-lock-defaults)))
         (old-table (syntax-table))
         (table (copy-syntax-table (syntax-table)))
         (slist imenu-syntax-alist))
@@ -779,8 +791,9 @@ PATTERNS."
       ;; The character(s) to modify may be a single char or a string.
       (if (numberp (car syn))
          (modify-syntax-entry (car syn) (cdr syn) table)
-       (dolist (c (car syn))
-         (modify-syntax-entry c (cdr syn) table))))
+        (mapc (lambda (c)
+                (modify-syntax-entry c (cdr syn) table))
+              (car syn))))
     (goto-char (point-max))
     (imenu-progress-message prev-pos 0 t)
     (unwind-protect                    ; for syntax table
@@ -857,37 +870,26 @@ Returns t for rescan and otherwise a position number."
   (let ((name (thing-at-point 'symbol))
        choice
        (prepared-index-alist
-        (mapcar
-         (lambda (item)
-           (cons (subst-char-in-string ?\ (aref imenu-space-replacement 0)
-                                       (car item))
-                 (cdr item)))
-         index-alist)))
+        (if (not imenu-space-replacement) index-alist
+          (mapcar
+           (lambda (item)
+             (cons (subst-char-in-string ?\ (aref imenu-space-replacement 0)
+                                         (car item))
+                   (cdr item)))
+           index-alist))))
     (when (stringp name)
       (setq name (or (imenu-find-default name prepared-index-alist) name)))
     (cond (prompt)
          ((and name (imenu--in-alist name prepared-index-alist))
           (setq prompt (format "Index item (default %s): " name)))
          (t (setq prompt "Index item: ")))
-    (if (eq imenu-always-use-completion-buffer-p 'never)
-       (setq name (completing-read prompt
-                                   prepared-index-alist
-                                   nil t nil 'imenu--history-list name))
-      (save-window-excursion
-       ;; Display the completion buffer
-       (with-output-to-temp-buffer "*Completions*"
-         (display-completion-list
-          (all-completions "" prepared-index-alist )))
-       (let ((minibuffer-setup-hook
-              (function
-               (lambda ()
-                 (let ((buffer (current-buffer)))
-                   (with-current-buffer "*Completions*"
-                     (setq completion-reference-buffer buffer)))))))
-         ;; Make a completion question
-         (setq name (completing-read prompt
-                                     prepared-index-alist
-                                     nil t nil 'imenu--history-list name)))))
+    (let ((minibuffer-setup-hook minibuffer-setup-hook))
+      ;; Display the completion buffer.
+      (if (not imenu-eager-completion-buffer)
+         (add-hook 'minibuffer-setup-hook 'minibuffer-completion-help))
+      (setq name (completing-read prompt
+                                 prepared-index-alist
+                                 nil t nil 'imenu--history-list name)))
     (cond ((not (stringp name)) nil)
          ((string= name (car imenu--rescan-item)) t)
          (t
@@ -904,10 +906,10 @@ INDEX-ALIST is the buffer index and EVENT is a mouse event.
 Returns t for rescan and otherwise an element or subelement of INDEX-ALIST."
   (setq index-alist (imenu--split-submenus index-alist))
   (let* ((menu (imenu--split-menu index-alist (or title (buffer-name))))
-        (map (imenu--create-keymap-1 (car menu)
-                                     (if (< 1 (length (cdr menu)))
-                                         (cdr menu)
-                                       (cdr (car (cdr menu)))))))
+        (map (imenu--create-keymap (car menu)
+                                   (cdr (if (< 1 (length (cdr menu)))
+                                            menu
+                                          (car (cdr menu)))))))
     (popup-menu map event)))
 
 (defun imenu-choose-buffer-index (&optional prompt alist)
@@ -923,7 +925,7 @@ select from ALIST.
 With no index alist ALIST, it calls `imenu--make-index-alist' to
 create the index alist.
 
-If `imenu-always-use-completion-buffer-p' is non-nil, then the
+If `imenu-use-popup-menu' is non-nil, then the
 completion buffer is always used, no matter if the mouse was used or
 not.
 
@@ -941,8 +943,8 @@ The returned value is of the form (INDEX-NAME . INDEX-POSITION)."
     (while (eq result t)
       (setq index-alist (if alist alist (imenu--make-index-alist)))
       (setq result
-           (if (and mouse-triggered
-                    (not imenu-always-use-completion-buffer-p))
+           (if (and imenu-use-popup-menu
+                    (or (eq imenu-use-popup-menu t) mouse-triggered))
                (imenu--mouse-menu index-alist last-nonmenu-event)
              (imenu--completion-buffer index-alist prompt)))
       (and (eq result t)
@@ -1000,10 +1002,11 @@ This value becomes local in every buffer when it is set.")
          (setq index-alist (imenu--split-submenus index-alist))
          (setq menu (imenu--split-menu index-alist
                                        (buffer-name)))
-         (setq menu1 (imenu--create-keymap-1 (car menu)
-                                             (if (< 1 (length (cdr menu)))
-                                                 (cdr menu)
-                                               (cdr (car (cdr menu))))))
+         (setq menu1 (imenu--create-keymap (car menu)
+                                           (cdr (if (< 1 (length (cdr menu)))
+                                                    menu
+                                                  (car (cdr menu))))
+                                           'imenu--menubar-select))
          (setq old (lookup-key (current-local-map) [menu-bar index]))
          (setcdr old (cdr menu1)))))))
 
@@ -1059,4 +1062,5 @@ for more information."
 
 (provide 'imenu)
 
+;;; arch-tag: 98a2f5f5-4b91-4704-b18c-3aacf77d77a7
 ;;; imenu.el ends here