When I create an imenu
with the help of the lisp snippet
(defun my-index-function ()
(message "Running `my-index-function'.")
'(("1" . 1) ("1.1" ("1.1.1" . 2) ("1.1.2" . 3) ("1.1.3" . 4)) ("1.2" . 5)))
(setq imenu-create-index-function #'my-index-function)
(imenu-add-to-menubar "index menu")
I get an index menu with the items
- 1.1
- 1.1.1
- 1.1.2
- 1.1.3
- 1
- 1.2
But this does not correspond to the wanted order of elements in the list returned by my-index-function
– which is
- 1
- 1.1
- 1.1.1
- 1.1.2
- 1.1.3
- 1.2
What am I missing? Is this some special feature of imenu
or is it just a bug?
How can I get the wanted order in the index menu?
emacs-version
: GNU Emacs 25.1.1
The real application is adding imenu
-support to reftex
.
Below you find the first rough test version which works for a single-LaTeX-source buffer.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; imenu-support for reftex
(require 'imenu)
(unless (fboundp #'substring-no-indent)
(defun substring-no-indent (str)
"Return STR without its leading whitespace."
(substring str (string-match "[^[:space:]]" str))))
(defun reftex-outline-tree-recursive (docstruct &optional level)
"Returns a cons of a tree generated from DOCSTRUCT and the rest of DOCSTRUCT to be processed.
The initial DOCSTRUCT should be the value of the symbol stored at `reftex-docstruct-symbol'."
(unless (equal (caar docstruct) 'toc)
(setq docstruct (cl-remove-if-not (lambda (entry)
(equal (car entry) 'toc))
docstruct)))
(unless level
(setq level (nth 5 (car docstruct))))
(let (tree)
(cl-block nil
(while docstruct
(let* ((entry (car docstruct))
(entry-level (nth 5 entry))
(next-entry (car-safe (cdr docstruct)))
(next-entry-level (nth 5 next-entry))
leaf)
(cond
((or (null (numberp entry-level))
(< entry-level level))
(cl-return))
((and (numberp next-entry-level) (> next-entry-level entry-level))
(cl-multiple-value-setq (leaf docstruct) (reftex-outline-tree-recursive (cdr docstruct)))
(setq leaf (cons (cons "-\"-" (car (last entry))) leaf)) ; prepend the section itself
(setq tree (cons (cons (substring-no-indent (nth 2 entry)) leaf) tree)))
(t ; entry-level == level
(setq tree (cons (cons (substring-no-indent (nth 2 entry)) (car (last entry))) tree)
docstruct (cdr docstruct)))))))
(list (nreverse tree) docstruct)))
(defun reftex-outline-tree (docstruct)
"Returns the toc tree generated from DOCSTRUCT as stored as value of the symbol stored at `reftex-docstruct-symbol'."
(let (subtree tree)
(while docstruct
(cl-multiple-value-setq (subtree docstruct) (reftex-outline-tree-recursive docstruct))
(setq tree (append tree subtree)))
tree))
(defcustom reftex-outline-flat-default nil
"The index menu \"TeX Outline\" has a flat structure if this option is true."
:group 'reftex-table-of-contents-browser
:type 'boolean)
(defvar reftex-outline-flat reftex-outline-flat-default
"The index menu \"TeX Outline\" has a flat structure if this option is true.
The default is read from `reftex-outline-flat-default'.")
(defun reftex-outline ()
"Add the index of the TeX document."
(interactive)
(reftex-access-scan-info t)
(let ((docstruct (cl-remove-if-not (lambda (entry)
(equal (car entry) 'toc))
(symbol-value reftex-docstruct-symbol))))
(if reftex-outline-flat
(mapcar (lambda (item)
(cons (format "%s" (nth 2 item))
(car (last item))))
docstruct)
(reftex-outline-tree docstruct))))
(defun reftex-toggle-outline-flat (&optional force)
"Toggle `reftex-outline-flat'.
With prefix arg > 0 switch flat outline on. With prefix arg <= 0 switch it off."
(interactive "p")
(if (numberp force)
(setq reftex-outline-flat (> force 0))
(setq reftex-outline-flat (null reftex-outline-flat))))
(defun reftex-imenu-update-advice (&rest args)
"Add \"Flat Outline\" to \"TeX Outline\" menu."
(ignore args)
(when (and imenu--index-alist reftex-docstruct-symbol)
(easy-menu-add-item imenu--menubar-keymap nil ["Flat Outline" (progn (reftex-toggle-outline-flat) (imenu--menubar-select '("*Rescan*" . -99))) :style toggle :selected reftex-outline-flat] "*Rescan*")))
(defun reftex-outline-imenu-enable ()
"Enable imenu in the current TeX buffer."
(interactive)
(setq-local imenu-create-index-function
#'reftex-outline)
(imenu-add-to-menubar "TeX Outline")
(advice-add #'imenu-update-menubar :after #'reftex-imenu-update-advice))
(defun reftex-outline-imenu-disable ()
"Disable imenu in the current PDF buffer."
(interactive)
(setq-local imenu-create-index-function nil)
(local-set-key [menu-bar index] nil))
This gives the index entry -"-
for the start of the first sub-section after the first sub-sub-section for the following example:
\documentclass{article}
\begin{document}
\section{1}
\subsection{11}
\subsubsection{111}
\subsubsection{112}
\subsection{12}
\end{document}
%%% Local Variables:
%%% mode: latex
%%% TeX-master: t
%%% End:
I know about imenu-add-menubar-index
but I don't like the splitting of the table of contents into groups. I like better if imenu
creates sub-menus for subsections.
[email protected]
to make the sorting inimenu
optional?