A typical use of Imenu shows a menu-bar menu that is an index or table of contents for the current buffer. For a source-code buffer it is typical to index definitions of functions, variables, and so on.
You can use Imenu with any major mode and any programming language or document type. If there is no Imenu support for your context, you can add it using EmacsLisp and the constructs provided in library
There are two ways to generate an Imenu menu (index):
For a source-code buffer the locations to index are typically definitions of functions, variables, and so on. For a text or markup buffer (e.g. LaTeX) the locations might be section headings. You can use an EmacsLisp marker as a target destination, so that targets need not be limited to the current buffer.
To automatically add an Imenu menu to the menu bar for a given mode, do something like this:
(add-hook 'my-mode-hook 'imenu-add-menubar-index)
‘font-lock-mode-hook’ is run after entering a major mode. You can make use of this to add an Imenu index to the menu bar in any mode that supports Imenu:
(defun try-to-add-imenu () (condition-case nil (imenu-add-to-menubar "yourFancyName") (error nil))) (add-hook 'font-lock-mode-hook 'try-to-add-imenu)
It can often be quicker to access an Imenu menu from the keyboard, using completion:
Why? Because you don’t have to read down a long list of menu items, many of which look similar. Just type a prefix of the defined name, and let completion do the work for you.
Icicles can make this even handier, by letting you complete any part of a defined name (or its definition), not just a prefix – see ImenuBrowser, below. Just type enough of a name to identify it uniquely, and voila!
You can bind Imenu to any key sequence. Here is how to bind it to
(if (featurep 'xemacs) (global-set-key [(shift button3)] 'imenu) ; XEmacs (global-set-key [S-mouse-3] 'imenu)) ; GNU Emacs
If there are too many Imenu menu items then Imenu splits them into submenus. By default, these submenus are labeled `
From: ...’ – see ImenuScreenshot, below. You can change how many menu items can be listed in each submenu by customizing option
Long menu items are truncated to
‘imenu-max-item-length’ characters. Depending on the size of your display, you might want to customize this option also.
You can control the order of Imenu menu items by customizing option
‘imenu-sort-function’. For alphabetical order, use
‘imenu--sort-by-name’ as the value.
‘icicle-imenu’ turns any Imenu-supported buffer into an Imenu browser. Use it to navigate among the various Imenu entries. No need for a separate window such as SpeedBar. See Icicles - Search Commands, Overview.
Here’s a screenshot of using
‘icicle-imenu’ to find function definitions (Imenu submenu Functions) that match the regexp
So much for navigating by cycling among defined terms. Most of the time, however, you just want to go directly to a definition; you aren’t interested in browsing among multiple definitions. Since
‘icicle-imenu’ is an Icicles command, you can also use completion against any parts of a definition (just type a regexp, such as a substring).
This is quite handy. You can also use simple completion with the vanilla Emacs command
‘imenu’, but with
‘icicle-imenu’ you can type any part of a defined term – in fact, any part of the line that defines it, and go to the definition in the buffer immediately.
‘icicle-imenu’ you can also combine semantic search with the purely syntactic search of Imenu. In EmacsLispMode, if you supply a prefix argument to
‘icicle-imenu’, you can selectively find only commands or only non-interactive functions.
Library imenu+.el (Imenu+) extends standard library
‘imenu--mouse-menu’so that submenus are sorted before splitting.
‘imenu-add-defs-to-menubar’– Add Defs imenu to the menu bar for current local keymap.
‘toggle-imenu-sort’– Toggle sorting.
imenu-anywhere package provides `imenu-anywhere` command that pops an IDO interface with all the imenu tags across all buffers with the same mode as the current one. This makes it similar to etag selection, but only for the open buffers. This is often more convenient as you don’t have to explicitly build the etags table.
The package is also available from melpa repository. To activate, just bind `imenu-anywhere` to a convenient key:
(global-set-key (kbd "C-.") 'imenu-anywhere)
There is also `helm-imenu-anywhere` which is like `menu-anywhere` but uses helm interface instead of IDO.
Here is an example of an
(setq mail-imenu-generic-expression '(("Subject" "^Subject: *\\(.*\\)" 1) ("Cc" "^C[Cc]: *\\(.*\\)" 1) ("To" "^To: *\\(.*\\)" 1) ("From" "^From: *\\(.*\\)" 1)))
You can hook this to
(add-hook 'mail-mode-hook (lambda () (setq imenu-generic-expression mail-imenu-generic-expression)))
Here’s a more complex example, for PL/SQL (for SqlMode):
(setq sql-imenu-generic-expression '(("Comments" "^-- \\(.+\\)" 1) ("Function Definitions" "^\\s-*\\(function\\|procedure\\)[ \n\t]+\\([a-z0-9_]+\\)\ [ \n\t]*([a-z0-9 _,\n\t]*)[ \n\t]*\\(return[ \n\t]+[a-z0-9_]+[ \n\t]+\\)?[ai]s\\b" 2) ("Function Prototypes" "^\\s-*\\(function\\|procedure\\)[ \n\t]+\\([a-z0-9_]+\\)\ [ \n\t]*([a-z0-9 _,\n\t]*)[ \n\t]*\\(return[ \n\t]+[a-z0-9_]+[ \n\t]*\\)?;" 2) ("Indexes" "^\\s-*create\\s-+index\\s-+\\(\\w+\\)" 1) ("Tables" "^\\s-*create\\s-+table\\s-+\\(\\w+\\)" 1)))
(defcustom tal-imenu-expression-alist '(("Sections" "^\\?SECTION +\\(\\w+\\b\\)" 1) ("Pages" "^\\?PAGE +\"\\(.+?\\)\"" 1) ("SubProcs" "^\\w*\\s-*subproc\\s-+\\(\\w+\\)\\b" 1) ("procs" "^\\(?:\\w+\\(?:\\s-*(\\w+)\\)?\\s-+\\)?proc\\s-+\\(\\w+\\)\\b" 1) ) "Alist of regular expressions for the imode index. Each element has the form (submenu-name regexp index). Where submenu-name is the name of the submenu under which items matching regexp are placed. When submenu-name is nil the matching entries appear in the root imenu list. Regexp index indicates which regext text group defines the text entry. When the index is 0 the entire text that matches regexp appears." :type '(repeat (list (choice :tag "Submenu Name" string (const nil)) regexp (integer :tag "Regexp index"))) :group 'tal )
In these examples, the major mode supports a buffer local copy of the “real” variable,
‘imenu-generic-expression’. If your mode doesn’t do it, you will have to rely on a hook. Here is an example for a fictive foo-mode. Note that we still require a foo-mode-hook. Without a hook, things would be really messy (but not impossible).
(add-hook 'foo-mode-hook (lambda () (set (make-local-variable imenu-generic-expression) '(("Comments" "^\\s-*#" 1) ...))))
That way, setting
‘imenu-generic-expression’ will only change for the buffer the hook runs in – the foo-mode buffer.
I do not like completion I/F. I prefer using selection buffer. – Anonymous
(define-derived-mode imenu-selection-mode fundamental-mode "imenu" "Major mode for imenu selection." (suppress-keymap imenu-selection-mode-map) (define-key imenu-selection-mode-map "j" 'next-line) (define-key imenu-selection-mode-map "k" 'previous-line) (define-key imenu-selection-mode-map "l" 'imenu-selection-select) (define-key imenu-selection-mode-map "\C-m" 'imenu-selection-select) (define-key imenu-selection-mode-map "h" 'kill-this-buffer) ) (defvar imenu--selection-buffer " *imenu-select*") (defvar imenu--target-buffer nil) (defun imenu-make-selection-buffer (&optional index-alist) (interactive) (require 'which-func) (setq index-alist (if index-alist index-alist (imenu--make-index-alist))) (let ((cur (which-function))) (when (listp cur) (setq cur (car cur))) (setq imenu--target-buffer (current-buffer)) (switch-to-buffer imenu--selection-buffer) (buffer-disable-undo) (erase-buffer) (dolist (x index-alist) (insert (car x) "\n")) (if cur (search-backward (concat cur "\n") nil t)) (imenu-selection-mode))) (defun imenu-selection-select () (interactive) (let ((sel (substring (thing-at-point 'line) 0 -1))) (bury-buffer) (switch-to-buffer imenu--target-buffer) (imenu sel)))
Alternatively, add the following command to your init file:
(defun ido-goto-symbol (&optional symbol-list) "Refresh imenu and jump to a place in the buffer using Ido." (interactive) (unless (featurep 'imenu) (require 'imenu nil t)) (cond ((not symbol-list) (let ((ido-mode ido-mode) (ido-enable-flex-matching (if (boundp 'ido-enable-flex-matching) ido-enable-flex-matching t)) name-and-pos symbol-names position) (unless ido-mode (ido-mode 1) (setq ido-enable-flex-matching t)) (while (progn (imenu--cleanup) (setq imenu--index-alist nil) (ido-goto-symbol (imenu--make-index-alist)) (setq selected-symbol (ido-completing-read "Symbol? " symbol-names)) (string= (car imenu--rescan-item) selected-symbol))) (unless (and (boundp 'mark-active) mark-active) (push-mark nil t nil)) (setq position (cdr (assoc selected-symbol name-and-pos))) (cond ((overlayp position) (goto-char (overlay-start position))) (t (goto-char position))))) ((listp symbol-list) (dolist (symbol symbol-list) (let (name position) (cond ((and (listp symbol) (imenu--subalist-p symbol)) (ido-goto-symbol symbol)) ((listp symbol) (setq name (car symbol)) (setq position (cdr symbol))) ((stringp symbol) (setq name symbol) (setq position (get-text-property 1 'org-imenu-marker symbol)))) (unless (or (null position) (null name) (string= (car imenu--rescan-item) name)) (add-to-list 'symbol-names name) (add-to-list 'name-and-pos (cons name position))))))))
(global-set-key "\C-ci" 'ido-goto-symbol) ; or any key you see fit
Anything is a candidate selection framework. Start with
‘M-x anything-imenu’, narrow the list by typing some patterns(multiple patterns are space-delimited string), select with up/down/pgup/pgdown/C-p/C-n/C-v/M-v, choose with enter, With
‘C-z’ contents of selected candidate are displayed without quitting anything session.
Maybe this (I don’t use folding):
(defadvice imenu (around unfold-it compile activate) (save-restriction (widen) ad-do-it))
(setq minibuffer-prompt-properties '(point-entered minibuffer-avoid-prompt) imenu-always-use-completion-buffer-p)
(or customize m-p-p and set Inviolable)
In Gnu Emacs 21.4.1, I get an “Args out of range” error. It’s fixed in GNU Emacs in CVS.
Now can anybody tell me why I set my minibuffer prompt to be inviolable? :-)
– DenisHowe 2007-03-08