aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/imenu.el78
1 files changed, 63 insertions, 15 deletions
diff --git a/lisp/imenu.el b/lisp/imenu.el
index 885a0d20ae7..1b858799634 100644
--- a/lisp/imenu.el
+++ b/lisp/imenu.el
@@ -334,6 +334,10 @@ This function is called after the function pointed out by
334(defvar imenu--index-alist nil) 334(defvar imenu--index-alist nil)
335(make-variable-buffer-local 'imenu--index-alist) 335(make-variable-buffer-local 'imenu--index-alist)
336 336
337;; The latest buffer index used to update the menu bar menu.
338(defvar imenu--last-menubar-index-alist nil)
339(make-variable-buffer-local 'imenu--last-menubar-index-alist)
340
337;; History list for 'jump-to-function-in-buffer'. 341;; History list for 'jump-to-function-in-buffer'.
338;; Making this buffer local caused it not to work! 342;; Making this buffer local caused it not to work!
339(defvar imenu--history-list nil) 343(defvar imenu--history-list nil)
@@ -410,7 +414,7 @@ This function is called after the function pointed out by
410;;; ((NAME . POSITION) (NAME . POSITION) ...) 414;;; ((NAME . POSITION) (NAME . POSITION) ...)
411;;; 415;;;
412 416
413(defun imenu--make-index-alist () 417(defun imenu--make-index-alist (&optional noerror)
414 ;; Create a list for this buffer only when needed. 418 ;; Create a list for this buffer only when needed.
415 (or (and imenu--index-alist 419 (or (and imenu--index-alist
416 (or (not imenu-auto-rescan) 420 (or (not imenu-auto-rescan)
@@ -420,8 +424,10 @@ This function is called after the function pointed out by
420 (setq imenu--index-alist 424 (setq imenu--index-alist
421 (save-excursion 425 (save-excursion
422 (funcall imenu-create-index-function)))) 426 (funcall imenu-create-index-function))))
423 (or imenu--index-alist 427 (or imenu--index-alist noerror
424 (error "No items suitable for an index found in this buffer")) 428 (error "No items suitable for an index found in this buffer"))
429 (or imenu--index-alist
430 (setq imenu--index-alist (list nil)))
425 ;; Add a rescan option to the index. 431 ;; Add a rescan option to the index.
426 (cons imenu--rescan-item imenu--index-alist)) 432 (cons imenu--rescan-item imenu--index-alist))
427;;; 433;;;
@@ -446,7 +452,7 @@ This function is called after the function pointed out by
446 alist) 452 alist)
447 t)) 453 t))
448 454
449(defun imenu--create-keymap-2 (alist counter) 455(defun imenu--create-keymap-2 (alist counter &optional commands)
450 (let ((map nil)) 456 (let ((map nil))
451 (mapcar 457 (mapcar
452 (function 458 (function
@@ -454,16 +460,21 @@ This function is called after the function pointed out by
454 (cond 460 (cond
455 ((listp (cdr item)) 461 ((listp (cdr item))
456 (append (list (incf counter) (car item) 'keymap (car item)) 462 (append (list (incf counter) (car item) 'keymap (car item))
457 (imenu--create-keymap-2 (cdr item) (+ counter 10)))) 463 (imenu--create-keymap-2 (cdr item) (+ counter 10) commands)))
458 (t 464 (t
459 (let ((end (cons '(nil) t))) 465 (let ((end (if commands (list 'lambda 'nil '(interactive)
466 (list 'imenu--menubar-select item))
467 (cons '(nil) t))))
460 (cons (car item) 468 (cons (car item)
461 (cons (car item) end)))) 469 (cons (car item) end))))
462 ))) 470 )))
463 alist))) 471 alist)))
464 472
465(defun imenu--create-keymap-1 (title alist) 473;; If COMMANDS is non-nil, make a real keymap
466 (append (list 'keymap title) (imenu--create-keymap-2 alist 0))) 474;; with a real command used as the definition.
475;; If it is nil, make something suitable for x-popup-menu.
476(defun imenu--create-keymap-1 (title alist &optional commands)
477 (append (list 'keymap title) (imenu--create-keymap-2 alist 0 commands)))
467 478
468 479
469(defun imenu--in-alist (str alist) 480(defun imenu--in-alist (str alist)
@@ -769,13 +780,47 @@ The returned value is on the form (INDEX-NAME . INDEX-POSITION)."
769 780
770;;;###autoload 781;;;###autoload
771(defun imenu-add-to-menubar (name) 782(defun imenu-add-to-menubar (name)
772 "Adds an \"imenu\" entry to the menubar for the current local keymap. 783 "Adds an \"imenu\" entry to the menu bar for the current major mode.
773NAME is the string naming the menu to be added. 784NAME is a string used to name the menu bar item.
774See 'imenu' for more information." 785See `imenu' for more information."
775 (interactive "sMenu name: ") 786 (interactive "sImenu menu item name: ")
776 (and window-system 787 (define-key (current-local-map) [menu-bar index]
777 (define-key (current-local-map) [menu-bar index] 788 (cons name (nconc (make-sparse-keymap "Imenu") (make-sparse-keymap))))
778 (cons name 'imenu)))) 789 (add-hook 'menu-bar-update-hook 'imenu-update-menubar))
790
791(defun imenu-update-menubar ()
792 (and (current-local-map)
793 (keymapp (lookup-key (current-local-map) [menu-bar index]))
794 (let ((index-alist (imenu--make-index-alist t)))
795 ;; Don't bother updating if the index-alist has not changed
796 ;; since the last time we did it.
797 (or (equal index-alist imenu--last-menubar-index-alist)
798 (let (menu menu1 old)
799 (setq imenu--last-menubar-index-alist index-alist)
800 (setq menu (imenu--split-menu
801 (if imenu-sort-function
802 (sort
803 (let ((res nil)
804 (oldlist index-alist))
805 ;; Copy list method from the cl package `copy-list'
806 (while (consp oldlist) (push (pop oldlist) res))
807 (prog1 (nreverse res) (setcdr res oldlist)))
808 imenu-sort-function)
809 index-alist)
810 (buffer-name)))
811 (setq menu1 (imenu--create-keymap-1 (car menu)
812 (if (< 1 (length (cdr menu)))
813 (cdr menu)
814 (cdr (car (cdr menu))))
815 t))
816 (setq old (lookup-key (current-local-map) [menu-bar index]))
817 (if (keymapp old)
818 (setcdr (nthcdr 2 old) menu1)))))))
819
820(defun imenu--menubar-select (item)
821 "Use Imenu to select the function or variable named in this menu item."
822 (interactive)
823 (imenu item))
779 824
780;;;###autoload 825;;;###autoload
781(defun imenu (index-item) 826(defun imenu (index-item)
@@ -784,7 +829,10 @@ See `imenu-choose-buffer-index' for more information."
784 (interactive 829 (interactive
785 (list (save-restriction 830 (list (save-restriction
786 (widen) 831 (widen)
787 (imenu-choose-buffer-index)))) 832 (car (imenu-choose-buffer-index)))))
833 ;; Convert a string to an alist element.
834 (if (stringp index-item)
835 (setq index-item (assoc index-item (imenu--make-index-alist))))
788 (and index-item 836 (and index-item
789 (progn 837 (progn
790 (push-mark) 838 (push-mark)