Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit e1471ae
Showing
1 changed file
with
387 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,387 @@ | ||
;;; imenu+.el --- Extensions to `imenu.el'. | ||
;; | ||
;; Filename: imenu+.el | ||
;; Description: Extensions to `imenu.el'. | ||
;; Author: Drew Adams | ||
;; Maintainer: Drew Adams | ||
;; Copyright (C) 1999-2009, Drew Adams, all rights reserved. | ||
;; Created: Thu Aug 26 16:05:01 1999 | ||
;; Version: 21.0 | ||
;; Last-Updated: Sat Aug 1 15:34:06 2009 (-0700) | ||
;; By: dradams | ||
;; Update #: 566 | ||
;; URL: http://www.emacswiki.org/cgi-bin/wiki/imenu+.el | ||
;; Keywords: tools, menus | ||
;; Compatibility: GNU Emacs: 20.x, 21.x, 22.x, 23.x | ||
;; | ||
;; Features that might be required by this library: | ||
;; | ||
;; `imenu'. | ||
;; | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
;; | ||
;;; Commentary: | ||
;; | ||
;; Extensions to `imenu.el'. | ||
;; | ||
;; New functions defined here: | ||
;; | ||
;; `imenu-add-defs-to-menubar', `imenu--sort-submenu', | ||
;; `toggle-imenu-sort'. | ||
;; | ||
;; New user options (variables) defined here: | ||
;; | ||
;; `emacs-lisp-imenu-generic-expression', | ||
;; `imenu-emacs-face-defn-regexp', `imenu-emacs-key-defn-regexp-1', | ||
;; `imenu-emacs-key-defn-regexp-2', | ||
;; `imenu-emacs-option-defn-regexp', `imenu-lisp-fn-defn-regexp', | ||
;; `imenu-lisp-macro-defn-regexp', `imenu-lisp-other-defn-regexp', | ||
;; `imenu-lisp-var-defn-regexp', `imenu-sort-function'. | ||
;; | ||
;; Other variables defined here: | ||
;; | ||
;; `imenu-last-sort-function'. | ||
;; | ||
;; | ||
;; ***** NOTE: The following functions defined in `imenu.el' have | ||
;; been REDEFINED HERE: | ||
;; | ||
;; `imenu-update-menubar', `imenu--mouse-menu'. | ||
;; | ||
;; | ||
;; ***** NOTE: The following variable defined in `imenu.el' has | ||
;; been REDEFINED HERE: | ||
;; | ||
;; `imenu-sort-function'. | ||
;; | ||
;; ***** NOTE: The following variable defined in `lisp-mode.el' has | ||
;; been REDEFINED HERE: | ||
;; | ||
;; `lisp-imenu-generic-expression'. | ||
;; | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
;; | ||
;;; Change log: | ||
;; | ||
;; 2007/01/16 dadams | ||
;; imenu-lisp-fn-defn-regexp: Updated for icicle-define-add-to-alist-command. | ||
;; 2005/12/09 dadams | ||
;; imenu-lisp-fn-defn-regexp: Updated to include icicle-define*. | ||
;; Use regexp-opt for Emacs 20 version too. | ||
;; Moved Emacs 22 macro stuff to imenu-lisp-macro-defn-regexp. | ||
;; (emacs-)lisp-imenu-generic-expression: | ||
;; Updated Emacs 20 index to accomodate parens for icicle-define*. | ||
;; Added: imenu-emacs-(face|option)-defn-regexp, | ||
;; Removed: imenu-lisp-struct-defn-regexp. | ||
;; Renamed: imenu-lisp-type-defn-regexp to imenu-lisp-other-defn-regexp. | ||
;; 2005/05/17 dadams | ||
;; Updated to work with Emacs 22.x. | ||
;; 2004/11/21 dadams | ||
;; imenu-lisp-type-defn-regexp, imenu-lisp-fn-defn-regexp, | ||
;; imenu-lisp-var-defn-regexp: Got rid of purecopy & eval-when-compile. | ||
;; 2004/11/20 dadams | ||
;; Refined to deal with Emacs 21 < 21.3.50 (soon to be 22.x) | ||
;; 2004/10/12 dadams | ||
;; Updated for Emacs 21. | ||
;; 2001/01/05 dadams | ||
;; Unquoted mapcar lambda args. | ||
;; 2000/11/01 dadams | ||
;; Put imenu-add-defs-to-menubar inside condition-case, in (*-)lisp-mode-hooks | ||
;; 1999/08/30 dadams | ||
;; 1. imenu-emacs-key-defn-regexp-2: Added define-key-after. | ||
;; 2. Updated emacs-lisp-imenu-generic-expression (Keys in Maps). | ||
;; 1999/08/27 dadams | ||
;; 1. Corrected: imenu-lisp-fn-defn-regexp, imenu-lisp-macro-defn-regexp, | ||
;; imenu-lisp-var-defn-regexp, imenu--sort-submenu, | ||
;; imenu-emacs-key-defn-regexp-2. | ||
;; 2. Added: imenu--sort-submenu, imenu-update-menubar, imenu--mouse-menu. | ||
;; Redefinition of originals: imenu-update-menubar, imenu--mouse-menu. | ||
;; | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
;; | ||
;; This program is free software; you can redistribute it and/or modify | ||
;; it under the terms of the GNU General Public License as published by | ||
;; the Free Software Foundation; either version 2, or (at your option) | ||
;; any later version. | ||
|
||
;; This program is distributed in the hope that it will be useful, | ||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
;; GNU General Public License for more details. | ||
|
||
;; You should have received a copy of the GNU General Public License | ||
;; along with this program; see the file COPYING. If not, write to | ||
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth | ||
;; Floor, Boston, MA 02110-1301, USA. | ||
;; | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
;; | ||
;;; Code: | ||
|
||
(and (< emacs-major-version 20) (eval-when-compile (require 'cl))) ;; cadr, when, unless | ||
|
||
(require 'imenu) | ||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
|
||
;;; Customizable variables | ||
|
||
(defconst imenu-sort-function 'imenu--sort-by-name) | ||
|
||
;;;###autoload | ||
(defvar imenu-emacs-key-defn-regexp-1 "(\\s-*\\(\\(global\\|local\\)-\\(un\\)?\ | ||
set-key\\|undefine-keys-bound-to\\)\\s-*\\(\"[^\"]+\"\\|[[][^]]+[]]\\)" | ||
"*Regexp that recognizes Emacs key definitions. | ||
See also `imenu-emacs-key-defn-regexp-2'.") | ||
|
||
;;;###autoload | ||
(defvar imenu-emacs-key-defn-regexp-2 "(\\s-*\\(define-key\\(-after\\)?\\s-+\ | ||
\\|substitute-key-definition\\s-+'\\)\\(\\S-+\\)\\s-*'?\\(\"[^\"]+\"\\|[[][^]]+[]]\\)" | ||
"*Regexp that recognizes Emacs key definitions. | ||
See also `imenu-emacs-key-defn-regexp-1'.") | ||
|
||
;;;###autoload | ||
(defvar imenu-lisp-other-defn-regexp | ||
(if (>= emacs-major-version 22) | ||
(concat "^\\s-*(" | ||
(regexp-opt '("defgroup" "deftheme" "deftype" "defstruct" | ||
"defclass" "define-condition" "define-widget" | ||
"defpackage") t) | ||
"\\s-+'?\\(\\sw\\(\\sw\\|\\s_\\)+\\)") | ||
"(\\s-*def\\(type\\|class\\|ine-condition\\)\\s-+'?\\([^ \t()]+\\)") | ||
"*Regexp that recognizes other Lisp definitions.") | ||
|
||
;;;###autoload | ||
(defvar imenu-lisp-fn-defn-regexp | ||
(if (>= emacs-major-version 22) | ||
(concat "^\\s-*(" | ||
(regexp-opt '("defun" "defun*" "defsubst" "defadvice" "define-skeleton" | ||
"define-minor-mode" "define-global-minor-mode" | ||
"define-globalized-minor-mode" "define-derived-mode" | ||
"define-generic-mode" "defsetf" "define-setf-expander" | ||
"define-method-combination" "defgeneric" "defmethod" | ||
"icicle-define-command" "icicle-define-file-command") t) | ||
"\\s-+\\(\\sw\\(\\sw\\|\\s_\\)+\\)") | ||
(concat "^\\s-*(" | ||
(regexp-opt | ||
'("defun" "defun*" "defsubst" "defadvice" "define-skeleton" | ||
"define-derived-mode" "defsetf" "icicle-define-add-to-alist-command" | ||
"icicle-define-command" "icicle-define-file-command") t) | ||
"\\s-+\\(\\sw\\(\\sw\\|\\s_\\)+\\)")) | ||
"*Regexp that recognizes Lisp function definitions.") | ||
|
||
;;;###autoload | ||
(defvar imenu-lisp-macro-defn-regexp | ||
"(\\s-*\\(defmacro\\|define-compiler-macro\\|define-modify-macro\\)\\s-+\\([^ \t()]+\\)" | ||
"*Regexp that recognizes Lisp macro definitions.") | ||
|
||
;;;###autoload | ||
(defvar imenu-emacs-face-defn-regexp "(\\s-*\\(defface\\)\\s-+\\([^ \t()]+\\)" | ||
"*Regexp for Emacs face definitions (defface).") | ||
|
||
;;;###autoload | ||
(defvar imenu-emacs-option-defn-regexp "(\\s-*\\(defcustom\\)\\s-+\\([^ \t()]+\\)" | ||
"*Regexp for Emacs user option definitions (defcustom).") | ||
|
||
;;;###autoload | ||
(defvar imenu-lisp-var-defn-regexp | ||
(if (>= emacs-major-version 22) | ||
(concat "^\\s-*(" | ||
(regexp-opt '("defvar" "defconst" "defconstant" "defcustom" | ||
"defparameter" "define-symbol-macro") t) | ||
"\\s-+\\(\\sw\\(\\sw\\|\\s_\\)+\\)") | ||
"(\\s-*def\\(var\\|const\\)\\s-+\\([^ \t()]+\\)") | ||
"*Regexp that recognizes global Lisp variable definitions.") | ||
|
||
|
||
;; REPLACES ORIGINAL in `lisp-mode.el': | ||
;; Functions, Macros, Structures added. | ||
(defconst lisp-imenu-generic-expression | ||
(list | ||
(list "Other" imenu-lisp-other-defn-regexp 2) | ||
(list "Macros" imenu-lisp-macro-defn-regexp 2) | ||
(list "Functions" imenu-lisp-fn-defn-regexp (if (string-match "\\(?:\\)" "") 2 6)) | ||
(list "Variables" imenu-lisp-var-defn-regexp 2) | ||
) | ||
"*Imenu generic expression for Lisp mode. | ||
See `imenu-generic-expression'.") | ||
|
||
;;;###autoload | ||
(defvar emacs-lisp-imenu-generic-expression | ||
(list | ||
(list "Other" imenu-lisp-other-defn-regexp 2) | ||
(list "Keys in Maps" imenu-emacs-key-defn-regexp-2 4) | ||
(list "Keys" imenu-emacs-key-defn-regexp-1 4) | ||
(list "Macros" imenu-lisp-macro-defn-regexp 2) | ||
(list "Functions" imenu-lisp-fn-defn-regexp (if (string-match "\\(?:\\)" "") 2 6)) | ||
(list "Variables" imenu-lisp-var-defn-regexp 2) | ||
(list "User Options" imenu-emacs-option-defn-regexp 2) | ||
(list "Faces" imenu-emacs-face-defn-regexp 2) | ||
) | ||
"*Imenu generic expression for Emacs Lisp mode. | ||
See `imenu-generic-expression'.") | ||
|
||
(add-hook 'lisp-mode-hook | ||
'(lambda () | ||
(setq imenu-generic-expression lisp-imenu-generic-expression) | ||
(condition-case nil | ||
(imenu-add-defs-to-menubar) | ||
(error nil)))) | ||
|
||
(add-hook 'emacs-lisp-mode-hook | ||
'(lambda () | ||
(setq imenu-generic-expression emacs-lisp-imenu-generic-expression) | ||
(condition-case nil | ||
(imenu-add-defs-to-menubar) | ||
(error nil)))) | ||
|
||
|
||
;;; Internal variables | ||
|
||
(defvar imenu-last-sort-function nil | ||
"The last non-nil value for `imenu-sort-function' during this session.") | ||
|
||
;;;###autoload | ||
(defalias 'toggle-imenu-sort 'imenu-toggle-sort) | ||
(defun imenu-toggle-sort (force-p) | ||
"Toggle imenu between sorting menus and not. | ||
Non-nil prefix FORCE-P => Sort iff FORCE-P >= 0." | ||
(interactive "P") | ||
(cond (imenu-sort-function | ||
(setq imenu-last-sort-function imenu-sort-function) ; Save it. | ||
(when (or (null force-p) (<= (prefix-numeric-value force-p) 0)) | ||
(setq imenu-sort-function nil))) ; Don't sort. | ||
((or (null force-p) (> (prefix-numeric-value force-p) 0)) ; Ask to sort | ||
(if imenu-last-sort-function ; Sort using saved sort fn. | ||
(setq imenu-sort-function imenu-last-sort-function) | ||
(error "You first need to set `imenu-sort-function'")))) | ||
(imenu--menubar-select imenu--rescan-item) | ||
(if imenu-sort-function | ||
(message "Imenus are now being sorted via `%s'." imenu-sort-function) | ||
(message "Imenus are in buffer order (not sorted)."))) | ||
|
||
;;;###autoload | ||
(defun imenu-add-defs-to-menubar () | ||
"Add \"Defs\" imenu entry to menu bar for current local keymap. | ||
See `imenu' for more information." | ||
(interactive) | ||
(imenu-add-to-menubar "Defs")) | ||
|
||
(defun imenu--sort-submenu (submenu predicate) | ||
"Create an imenu SUBMENU, sorting with PREDICATE." | ||
(let ((menu-name (car submenu)) | ||
(menu-items (cdr submenu))) | ||
(cons menu-name (if (and (consp menu-items) | ||
(consp (cdr menu-items))) | ||
(sort menu-items predicate) | ||
menu-items)))) | ||
|
||
|
||
|
||
;;; REPLACES ORIGINAL in `imenu.el'. | ||
;;; Sorts each submenu before splitting submenus, instead of sorting among submenus after. | ||
;;;###autoload | ||
(defun imenu-update-menubar () | ||
"Update the imenu. Use as `menu-bar-update-hook'." | ||
(when (and (current-local-map) | ||
(keymapp (lookup-key (current-local-map) [menu-bar index])) | ||
(or (not (boundp 'imenu-menubar-modified-tick)) | ||
(not (eq (buffer-modified-tick) | ||
imenu-menubar-modified-tick)))) | ||
(when (boundp 'imenu-menubar-modified-tick) | ||
(setq imenu-menubar-modified-tick (buffer-modified-tick))) | ||
(let ((index-alist (imenu--make-index-alist t))) | ||
;; Don't bother updating if the index-alist has not changed | ||
;; since the last time we did it. | ||
(unless (equal index-alist imenu--last-menubar-index-alist) | ||
(let (menu menu1 old) | ||
(setq imenu--last-menubar-index-alist index-alist) | ||
(setq index-alist | ||
(imenu--split-submenus | ||
(if imenu-sort-function | ||
(mapcar (lambda (sm) (imenu--sort-submenu sm imenu-sort-function)) | ||
index-alist) | ||
index-alist))) | ||
(setq menu (imenu--split-menu index-alist (buffer-name))) | ||
(if (>= emacs-major-version 22) | ||
(setq menu1 (imenu--create-keymap (car menu) | ||
(cdr (if (< 1 (length (cdr menu))) | ||
menu | ||
(car (cdr menu)))) | ||
'imenu--menubar-select)) | ||
(setq menu1 (imenu--create-keymap-1 (car menu) | ||
(if (< 1 (length (cdr menu))) | ||
(cdr menu) | ||
(cdr (car (cdr menu)))) | ||
t))) | ||
(setq old (lookup-key (current-local-map) [menu-bar index])) | ||
(setcdr old (cdr menu1))))))) | ||
|
||
|
||
|
||
;;; REPLACES ORIGINAL in `imenu.el'. | ||
;;; Sorts each submenu before splitting submenus, instead of sorting among submenus after. | ||
;; | ||
;;;###autoload | ||
(defun imenu--mouse-menu (index-alist event &optional title) | ||
"Let the user select from a buffer index from a mouse menu. | ||
INDEX-ALIST is the buffer index. | ||
EVENT is a mouse event. | ||
TITLE is the menu title. | ||
Returns t for rescan, or else an element or subelement of INDEX-ALIST." | ||
(setq index-alist (imenu--split-submenus | ||
(if imenu-sort-function | ||
(mapcar (lambda (sm) | ||
(imenu--sort-submenu sm imenu-sort-function)) | ||
index-alist) | ||
index-alist))) | ||
(if (>= emacs-major-version 22) | ||
(let* ((menu (imenu--split-menu index-alist (or title (buffer-name)))) | ||
(map (imenu--create-keymap (car menu) | ||
(cdr (if (< 1 (length (cdr menu))) | ||
menu | ||
(car (cdr menu))))))) | ||
(popup-menu map event)) | ||
(let* ((menu (imenu--split-menu index-alist (or title (buffer-name)))) | ||
position) | ||
(setq menu (imenu--create-keymap-1 (car menu) | ||
(if (< 1 (length (cdr menu))) | ||
(cdr menu) | ||
(cdr (cadr menu))))) | ||
(setq position (x-popup-menu event menu)) | ||
(cond ((eq position nil) | ||
position) | ||
;; If one call to x-popup-menu handled the nested menus, | ||
;; find the result by looking down the menus here. | ||
((and (listp position) | ||
(numberp (car position)) | ||
(stringp (nth (1- (length position)) position))) | ||
(let ((final menu)) | ||
(while position | ||
(setq final (assq (car position) final)) | ||
(setq position (cdr position))) | ||
(or (string= (car final) (car imenu--rescan-item)) | ||
(nthcdr 3 final)))) | ||
;; If x-popup-menu went just one level and found a leaf item, | ||
;; return the INDEX-ALIST element for that. | ||
((and (consp position) | ||
(stringp (car position)) | ||
(null (cdr position))) | ||
(or (string= (car position) (car imenu--rescan-item)) | ||
(assq (car position) index-alist))) | ||
;; If x-popup-menu went just one level | ||
;; and found a non-leaf item (a submenu), | ||
;; recurse to handle the rest. | ||
((listp position) | ||
(imenu--mouse-menu position event | ||
(if title | ||
(concat title imenu-level-separator | ||
(car (rassq position index-alist))) | ||
(car (rassq position index-alist))))))))) | ||
|
||
;;;;;;;;;;;;;;;;;; | ||
|
||
(provide 'imenu+) | ||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
;;; imenu+.el ends here |