Imenu produces menus for accessing locations in documents, typically in the current buffer. You can access the locations using an ordinary menu (menu bar or other) or using minibuffer completion.
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 imenu.el
.
There are two ways to generate an Imenu menu (index):
‘imenu-generic-expression’
.‘imenu-create-index-function’
.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.
See Imenu in the Emacs manual.
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:
M-x imenu
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 ‘S-mouse-3’
:
(if (featurep 'xemacs) (global-set-key [(shift button3)] 'imenu) ; XEmacs (global-set-key [S-mouse-3] 'imenu)) ; GNU Emacs
You can avoid auto rescanning big buffers just making it easy to manually rescan:
(defun my-imenu-rescan () (interactive) (imenu--menubar-select imenu--rescan-item))
(global-set-key "\C-cI" 'my-imenu-rescan)
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 ‘imenu-max-items’
.
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.
The following patch lets the user (final user or major mode developer) control whether the submenus are sorted or kept on top. The guiding idea is that there is two major ways to offer an imenu, according to the mode:
1) Some modes show a hierarchy of language objects. For example: python-mode will show class/method, function/nested function, etc. relationships; org-mode will show section/subsection/subsubsection/… hierarchies. In these cases keeping the submenus on top is not adequate since it creates an artificial split of the list.
2) Some modes show top level submenus with fixed categories (Functions, Classes, Variables, etc). These modes will presumably want to keep the submenus on top and sorted in the order they were given.
3) Other modes would not fit either (1) or (2). Then, there is always the possibility of turning off sorting and provide the menu structure as is.
First, add a custom variable to enable submenu sorting:
> (defcustom imenu-sort-submenus nil > "Non-nil means Imenu should sort submenus also (using imenu-sort-function)." > :type 'boolean > :group 'imenu)
Then, modify imenu--split-menu:
< (when (imenu--subalist-p item) --- > (when (and imenu-sort-submenus > (imenu--subalist-p item))
Icicles command ‘icicle-imenu’
lets you browse the definitions in any set of Imenu-supported buffers, files, or bookmark destinations at the same time. Use it to navigate among Imenu entries anywhere.
This screenshot shows ‘icicle-imenu’
finding function definitions that match ‘kill’
:
There are more specific Icicles commands that browse only definitions of a specific type:
‘icicle-imenu-command’
– command definitions‘icicle-imenu-non-interactive-function’
– non-command Lisp fn defs‘icicle-imenu-macro’
– macro definitions‘icicle-imenu-user-option’
– user option definitions‘icicle-imenu-variable’
– variable definitions‘icicle-imenu-face’
– face definitions‘icicle-imenu-key-explicit-map’
, ‘icicle-imenu-key-implicit-map’
– key bindingsThere are also Icicles commands that let you match not only the name of the defined term (function etc.) but all parts of its definition. These have the same names as the commands above, but with the suffix ‘-full’
.
See Icicles - Search Commands, Overview.
Another way to use imenu indexes for multiple buffers or files is imenus package. Along with the usual ‘*Rescan*’
item it is possible to use a key binding (‘M-r’
by default) to rescan the current index. Also with other additional key bindings (‘M-s’
and ‘M-o’
by default) you can quickly “jump” from imenu prompt to ‘isearch’
or ‘occur’
.
Library imenu+.el (Imenu+) extends standard library imenu.el
.
‘imenu-update-menubar’
and ‘imenu--mouse-menu’
so that submenus are sorted before splitting.THING
s (strings, vectors, lists, sexps, symbols, words, colors (names/hex), numbers, decimal numbers, hex numbers, sentences, paragraphs,… whatever). More generally, you can go to buffer positions where a given predicate is true.‘defalias’
etc.) and more types of definitions.‘imenu-add-defs-to-menubar’
– Add Defs imenu to the menu bar for current local keymap.‘toggle-imenu-sort’
– Toggle sorting.‘imenup-toggle-case-sensitive-sorting’
– Toggle case-sensitivity when sorting by name.‘imenup-toggle-ignoring-comments’
– Toggle ignoring definitions that are inside comments. (Toggles option ‘imenup-ignore-comments-flag’
.)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 ‘imenu-generic-expression’
for ‘mail-mode’
:
(setq mail-imenu-generic-expression '(("Subject" "^Subject: *\\(.*\\)" 1) ("Cc" "^C[Cc]: *\\(.*\\)" 1) ("To" "^To: *\\(.*\\)" 1) ("From" "^From: *\\(.*\\)" 1)))
You can hook this to ‘mail-mode’
:
(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)))
Lisp:idomenu.el by GeorgBrandl lets you use Ido with imenu.
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
– shjk (updated by MattKeller to handle overlays as “positions”; updated by VegardOye to set the mark before jumping).
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.
– mina86
Maybe this (I don’t use folding):
(defadvice imenu (around unfold-it compile activate) (save-restriction (widen) ad-do-it))
Do this:
(setq minibuffer-prompt-properties '(point-entered minibuffer-avoid-prompt) imenu-always-use-completion-buffer-p)
(or customize m-p-p and set Inviolable)
M-x imenu
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
CategoryCode CategoryMenus CategoryModes CategoryProgrammerUtils CategoryNavigation