This is part of the Emacs Starter Kit.
(defun make-imenu-marker-list ()
(unless imenu--index-alist
(imenu--make-index-alist t))
(let (imenu-marker-list)
(mapc
(lambda (list1)
(if (listp (cdr list1))
(progn
(mapc
(lambda (alist1)
(setq imenu-marker-list (cons (cdr alist1) imenu-marker-list)))
(cdr list1)))
(setq imenu-marker-list (cons (cdr list1) imenu-marker-list))))
imenu--index-alist)
(sort imenu-marker-list '<)))
(defun search-marker-in-marker-list (marker marker-list search-right)
(let ((member-list (member marker marker-list))
(pos (if search-right 0 -1)))
(if member-list
(setq pos (- (length marker-list) (length member-list)))
(catch 'found-marker
(mapc
(lambda (am)
(when (> am marker)
(throw 'found-marker am))
(setq pos (1+ pos)))
marker-list)))
pos))
(defun imenu-prev-defun ()
(require 'imenu)
(interactive)
(let ((marker (make-marker))
(marker-list (make-imenu-marker-list))
pos)
(when marker-list
(move-marker marker (point))
(push-mark marker t nil)
(setq pos (search-marker-in-marker-list marker marker-list t))
(goto-char (nth (1- pos) marker-list)))))
(defun imenu-next-defun ()
(require 'imenu)
(interactive)
(let ((marker (make-marker))
(marker-list (make-imenu-marker-list))
pos)
(when marker-list
(move-marker marker (point))
(push-mark marker t nil)
(setq pos (search-marker-in-marker-list marker marker-list nil))
(goto-char (nth (1+ pos) marker-list)))))
(set-keybindings-for-modes-after-load
'(((kbd "C-c C-p") . imenu-prev-defun)
((kbd "C-c C-n") . imenu-next-defun))
'(c-mode c++-mode fortran-mode f90-mode
LaTeX-mode emacs-lisp-mode))
(set-keybindings-for-modes-after-load
'(((kbd "C-c C-p") . beginning-of-defun)
((kbd "C-c C-n") . end-of-defun))
'(python-mode))
(setq imenu-sort-function #'imenu--sort-by-position)
(setq imenu-auto-rescan nil)
(defun starter-kit-imenu-rescan ()
(interactive)
(require 'imenu)
(when (derived-mode-p
'org-mode 'prog-mode 'markdown-mode 'rst-mode 'latex-mode)
(if (null imenu--index-alist)
(imenu--make-index-alist t)
(imenu--menubar-select imenu--rescan-item))))
(add-hook 'after-save-hook 'starter-kit-imenu-rescan)
(defun my-imenu (&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)
(my-imenu (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))
(my-imenu 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))))))))
Define my own imenu for LaTeX.
(defun my-latex-imenu-create-index-function ()
(imenu--generic-function imenu-generic-expression))
(defun my-latex-imenu-setup ()
(setq-local imenu-create-index-function 'my-latex-imenu-create-index-function)
(setq-local imenu-generic-expression
'(("Frame" "^ *\\\\begin{frame}{\\(.+\\)}" 1)
("Frame" "^ *\\\\frametitle{\\(.+\\)}" 1)
("Section" "^ *\\\\section\\*?{\\(.+\\)}" 1)
("Subsection" "^ *\\\\subsection\\*?{\\(.+\\)}" 1))))
(add-hook 'LaTeX-mode-hook 'my-latex-imenu-setup)
(setq rnc-enable-imenu t)
I don’t whether it’s a bug or not python.el integrated with Emacs can’t create imenu index automatically. I have to set imenu-create-index-function myself.
(defun my-python-imenu-setup ()
(setq imenu-create-index-function 'python-imenu-create-index))
(add-hook 'python-mode-hook 'my-python-imenu-setup)