TL;DR: How can I force evaluation of a setq statement at start-up so that imenu updates appropriately? (You can skip down to the second code-block below, if you want.)

I love the concept of imenu (esp. when integrated with helm) and I think it has great potential to improve my workflow...assuming I learn how to correctly set definitions for imenu categories.

As a simplified example, let's say that I'd like to add a few definitions to my init file's imenu which would be useful when making updates - namely, the list of imported packages.

Let's consider the following three lines as the code we want to parse (purely illustrative; my init file doesn't actually have an explicit line for importing dired and electric):

(defconst dc/default-directory "/path/to/directory")
(use-package dired)
(use-package electric)

In order to extract the constants and package names in imenu, I've included the code below in my init.el file. This code works BUT only after I manually eval the second line, (i.e., the second setq statement below).

(setq dc-additions '(("Imported packages" ".*(use-package \\(.*\\))*" 1)
                     ("Defined constants" ".*(defconst \\(.*\\))*"    1)))
(setq imenu-generic-expression (copy-sequence `(,@dc-additions ,@imenu-generic-expression)))
(add-hook 'emacs-lisp-mode 'imenu-generic-expression)

If I don't manually evaluate the second step, the imenu list shows only the default definitions. However, after I eval the second statement above, the imenu list correctly include includes items based on my definition.

How can I force evaluation of the second statement? In other words, what can I do to to ensure that imenu will automatically consider items based on my definition?

Exhibit 1: imenu after start-up but before I manually eval the second setq statement:

enter image description here

Exhibit 2: imenu after I manually eval the statement:

enter image description here

  • Could you try helm-imenu alone? helm-semantic-or-imenu, as its name suggests, use either semantic or imenu. If the command has candidates from helm-semantic, it won't display imenu's candidates, unless the candidates from helm-semantic is nil. There's also a stand alone helm-semantic. The advantage of helm-semantic is that it provides more information, so you can look thing like function interface and preselect the candidate when run helm-semantic. But Imenu is easier to extend without touching Semantic parser. – Tu Do Oct 30 '14 at 17:32
  • unfortunately, helm-imenu is also blank. in fact, both helm-imenu and helm-semantic are blank. – iceman Oct 30 '14 at 17:46
  • You use setq which overrides the default imenu-generic-expression, and I think your regex is potentially wrong, so it shows nothing. Try removing your change and test helm-imenu again. – Tu Do Oct 30 '14 at 17:52
  • @Tu Do: I've updated the methodology so that my new list of definitions is appended to the existing list (using the ,@ operator). As described in my (heavily) edited post above, the new code works but only after I manually evaluated part of the code (details above). – iceman Oct 30 '14 at 20:58
  • You're saying it doesn't take effect during initialization? – Malabarba Oct 30 '14 at 21:00

imenu-generic-expression is a buffer local variable. When opening a new buffer, imenu will set imenu-generic-expression local value to something interesting for the current buffer. So setting imenu-generic-expression in init won't be useful, as its default-value is never used.

What you want to set is the variable that it used by imenu for setting imenu-generic-expression in emacs-lisp-mode. It seem that it is the value from lisp-imenu-generic-expression, that is define in lisp-mode. So you just have to:

(with-eval-after-load 'lisp-mode
    (setq lisp-imenu-generic-expression (append dc-additions lisp-imenu-generic-expression)))

Note that you must eval the setq lisp-imenu-generic-expression in a with-eval-after-load because you depend on the default value of lisp-imenu-generic-expression that won't be known to Emacs before lisp-mode is loaded.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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