I would like to have a single shortcut to jump to the next item on the imenu of current buffer. E.g., if the current buffer is in org mode, next-imenu-item = org-next-visible-heading.

Anyone did that before?

  • I grepped the Emacs 25.1 source code for next-imenu-item, and came up with nothing -- i.e., it does not exist. In my setup, imenu creates a menu with all main first level headings, and the subheadings (e.g., second level) are alphabetized (if there are lots, then they are grouped into alphabetized groups). The main ingredient that creates this is (org-set-local 'imenu-create-index-function 'org-imenu-get-tree) within my org-mode setup. Please consider editing your question to provide some additional details regarding your setup and what it is specifically you wish to accomplish.
    – lawlist
    Feb 13, 2017 at 22:58
  • And, also have this: (eval-after-load "imenu" '(progn (add-hook 'imenu-after-jump-hook (lambda () (when (derived-mode-p 'org-mode) (org-show-context 'org-goto))))))
    – lawlist
    Feb 13, 2017 at 23:01
  • 1
    I implemented what I wanted and posted as an answer below. Feel free to comment. Thanks.
    – AhLeung
    Jun 24, 2017 at 7:13

1 Answer 1

(defun my-imenu-goto--closest-dir (direction)
  "Jump to the closest imenu item on the current buffer.
If direction is 1, jump to next imenu item.
If direction is -1, jump to previous imenu item.
See https://emacs.stackexchange.com/questions/30673
Adapted from `which-function' in::
  ;; Ensure `imenu--index-alist' is populated.

  (let ((alist imenu--index-alist)
        (minoffset (point-max))
        offset pair mark imstack destination)
    ;; Elements of alist are either ("name" . marker), or
    ;; ("submenu" ("name" . marker) ... ). The list can be
    ;; Arbitrarily nested.
    (while (or alist imstack)
      (if alist
            (setq pair (car-safe alist)
                  alist (cdr-safe alist))
             ((atom pair)) ;; Skip anything not a cons.

             ((imenu--subalist-p pair)
              (setq imstack   (cons alist imstack)
                    alist     (cdr pair)))

             ((number-or-marker-p (setq mark (cdr pair)))
              (when (> (setq offset (* (- mark (point)) direction)) 0)
                (when (< offset minoffset) ;; Find the closest item.
                  (setq minoffset offset
                        destination mark))))))

        (setq alist   (car imstack)
              imstack (cdr imstack))))
    (when destination
      (imenu-default-goto-function "" destination ""))))

(defun my-imenu-goto-next ()
  (unless (my-imenu-goto--closest-dir 1)
    (goto-char (point-max))))

(defun my-imenu-goto-prev ()
  (unless (my-imenu-goto--closest-dir -1)
    (goto-char (point-min))))
  • You should think about commenting and explaining your answer.
    – theldoria
    Jun 24, 2017 at 12:13
  • And you should think about submitting it for inclusion in imenu.el.
    – Stefan
    Jun 24, 2017 at 13:46
  • @theldoria Added some comments to the function.
    – AhLeung
    Jul 1, 2017 at 6:14
  • 1
    @Stefan I haven't submitted anything to open source project before. Do you have some related pointers / tutorials (on contributing to GNU emac?) for me to follow? Thanks.
    – AhLeung
    Jul 1, 2017 at 6:16
  • 1
    You can check the file CONTRIBUTE at the top-level of Emacs's source code. Basically, in your case, change imenu.el by adding yur feature to it, then generate a patch for the change and send it via M-x report-emacs-bug (which is used not just for bug-reports but for patch submission and feature requests as well).
    – Stefan
    Jul 2, 2017 at 2:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.