From: Stephen Berman <stephen.berman@gmx.net>
To: Heime <heimeborgia@protonmail.com>
Cc: Heime via Users list for the GNU Emacs text editor
<help-gnu-emacs@gnu.org>
Subject: Re: Listing headings in dedicated buffer with imenu.
Date: Wed, 31 Jul 2024 10:35:17 +0200 [thread overview]
Message-ID: <87wml2rmbe.fsf@gmx.net> (raw)
In-Reply-To: <nYcOoFCP2OPiG350WoR43x5S0euLKx1gHxYYqt20MuUPl3Zc_G3SkV6wJsNwuN-vhC8MbrnTn-LJuiwCvBd2J19Yzi-8f1Bwf2LleemDbuo=@protonmail.com> (Heime's message of "Tue, 30 Jul 2024 21:30:28 +0000")
On Tue, 30 Jul 2024 21:30:28 +0000 Heime <heimeborgia@protonmail.com> wrote:
> Sent with Proton Mail secure email.
>
> On Wednesday, July 31st, 2024 at 3:59 AM, Heime <heimeborgia@protonmail.com> wrote:
>
>> On Tuesday, July 30th, 2024 at 1:02 AM, Stephen Berman
>> stephen.berman@gmx.net wrote:
>>
>> > [I sent this yesterday but it hasn't shown up in the list, so
>> > resending.]
>> >
>> > On Mon, 29 Jul 2024 11:53:07 +0000 Heime heimeborgia@protonmail.com wrote:
>> >
>> > > On Monday, July 29th, 2024 at 11:45 PM, Stephen Berman
>> > > stephen.berman@gmx.net wrote:
>> > >
>> > > > On Mon, 29 Jul 2024 11:29:07 +0000 Heime heimeborgia@protonmail.com wrote:
>> > > >
>> > > > > Sent with Proton Mail secure email.
>> > > > >
>> > > > > On Monday, July 29th, 2024 at 10:51 PM, Stephen Berman
>> > > > > stephen.berman@gmx.net wrote:
>> > > > >
>> > > > > > On Mon, 29 Jul 2024 10:41:08 +0000 Heime
>> > > > > > heimeborgia@protonmail.com wrote:
>> > > > > >
>> > > > > > > Sent with Proton Mail secure email.
>> > > > > > >
>> > > > > > > On Monday, July 29th, 2024 at 10:32 PM, Stephen Berman
>> > > > > > > stephen.berman@gmx.net wrote:
>> > > > > > >
>> > > > > > > > On Mon, 29 Jul 2024 10:26:22 +0000 Heime
>> > > > > > > > heimeborgia@protonmail.com wrote:
>> > > > > > > >
>> > > > > > > > > Sent with Proton Mail secure email.
>> > > > > > > > >
>> > > > > > > > > On Monday, July 29th, 2024 at 9:33 PM, Stephen Berman
>> > > > > > > > > stephen.berman@gmx.net wrote:
>> > > > > > > > >
>> > > > > > > > > > On Mon, 29 Jul 2024 08:48:38 +0000 Heime
>> > > > > > > > > > heimeborgia@protonmail.com wrote:
>> > > > > > > > > >
>> > > > > > > > > > > I wish to list headings in a dedicated buffer with imenu.
>> > > > > > > > > > > The listing should be in the order in which headings occur
>> > > > > > > > > > > in the buffer.
>> > > > > > > > > > >
>> > > > > > > > > > > Have done the following, but the buffer ends up empty.
>> > > > > > > > > > >
>> > > > > > > > > > > (defun vodil-imenu-bfh ()
>> > > > > > > > > > > "Insert imenu headings in order in a dedicated buffer."
>> > > > > > > > > > > (interactive)
>> > > > > > > > > > >
>> > > > > > > > > > > (let ((imenu-items (imenu--make-index-alist t))
>> > > > > > > > > > > (buffer-name "Imenu Headings"))
>> > > > > > > > > > > (with-current-buffer (get-buffer-create buffer-name)
>> > > > > > > > > > > (erase-buffer)
>> > > > > > > > > > > (dolist (item imenu-items)
>> > > > > > > > > > > (let ((name (car item))
>> > > > > > > > > > > (position (cdr item)))
>> > > > > > > > > > > (when (and (stringp name) (number-or-marker-p position))
>> > > > > > > > > > > (insert (format "%s\n" name)))))
>> > > > > > > > > > > (goto-char (point-min)))
>> > > > > > > > > > > (pop-to-buffer buffer-name)))
>> > > > > > > > > >
>> > > > > > > > > > It works for me, as long as imenu.el is loaded.
>> > > > > > > > > >
>> > > > > > > > > > Steve Berman
>> > > > > > > > >
>> > > > > > > > > What would I need to load it ?
>> > > > > > > >
>> > > > > > > > One way is this:
>> > > > > > > >
>> > > > > > > > (defun vodil-imenu-bfh ()
>> > > > > > > > "Insert imenu headings in order in a dedicated buffer."
>> > > > > > > > (interactive)
>> > > > > > > > (eval-when-compile
>> > > > > > > > (require 'imenu))
>> > > > > > > > (let ((imenu-items (imenu--make-index-alist t))
>> > > > > > > > (buffer-name "Imenu Headings"))
>> > > > > > > > (with-current-buffer (get-buffer-create buffer-name)
>> > > > > > > > (erase-buffer)
>> > > > > > > > (dolist (item imenu-items)
>> > > > > > > > (let ((name (car item))
>> > > > > > > > (position (cdr item)))
>> > > > > > > > (when (and (stringp name) (number-or-marker-p position))
>> > > > > > > > (insert (format "%s\n" name)))))
>> > > > > > > > (goto-char (point-min)))
>> > > > > > > > (pop-to-buffer buffer-name)))
>> > > > > > > >
>> > > > > > > > Steve Berman
>> > > > > > >
>> > > > > > > Right. I have this function that I run. Running vodil-imenu-bfh
>> > > > > > > after executing vodil-imenu-expr gives me rescan in the buffer.
>> > > > > > >
>> > > > > > > (defun vodil-imenu-expr ()
>> > > > > > > "Set up `imenu` to show a list of functions in the current buffer."
>> > > > > > >
>> > > > > > > (interactive)
>> > > > > > >
>> > > > > > > (setq imenu-generic-expression
>> > > > > > > '( ("headings" "^;;;\\s-+\\([HM][[:digit:]]\\)\\s-+\\(.*\\)" 2)))
>> > > > > > >
>> > > > > > > (imenu-add-to-menubar "Iml")
>> > > > > > > (imenu--make-index-alist t)
>> > > > > > > (call-interactively 'imenu))
>> > > > > >
>> > > > > > What were the contents of the current buffer when you executed
>> > > > > > vodil-imenu-expr?
>> > > > > >
>> > > > > > Steve Berman
>> > > > >
>> > > > > I had an elisp file. I ran "M-x vodil-imenu-expr" when in the file to get
>> > > > > the correct imenu entries. But executing "M-x vodil-imenu-bfh" after that
>> > > > > I end up with the buffer "Imenu Headings" having only rescan in it.
>> > > >
>> > > > When I test your code on one of the built-in Emacs Lisp libraries,
>> > > > e.g. avoid.el, then, on invoking vodil-imenu-expr, I get prompted for an
>> > > > Index item, and typing TAB, the Completions buffer pops up containing
>> > > > Rescan and nil. I then type C-g and then M-x vodil-imenu-bfh, and the
>> > > > Imenu Headings buffer pops up containing just Rescan. However, when
>> > > > I start Emacs -Q, evaluate just my emendation of your vodil-imenu-bfh
>> > > > command, then visit avoid.el and invoking vodil-imenu-bfh, the
>> > > > Imenu Headings buffer pops up containing this:
>> > > >
>> > > > Rescan
>> > > > mouse-avoidance-set-pointer-shape
>> > > > mouse-avoidance-point-position
>> > > > mouse-avoidance-set-mouse-position
>> > > > mouse-avoidance-too-close-p
>> > > > mouse-avoidance-banish-destination
>> > > > mouse-avoidance-banish-mouse
>> > > > mouse-avoidance-delta
>> > > > mouse-avoidance-nudge-mouse
>> > > > mouse-avoidance-random-shape
>> > > > mouse-avoidance-ignore-p
>> > > > mouse-avoidance-banish
>> > > > mouse-avoidance-exile
>> > > > mouse-avoidance-fancy
>> > > > mouse-avoidance-mode
>> > > >
>> > > > So at least the contents of avoid.el does not contain a match for your
>> > > > setting of imenu-generic-expression, and presumably the same goes for
>> > > > the file you tested your code on.
>> > > >
>> > > > Steve Berman
>> > >
>> > > Try with this to pick up (defun
>> > >
>> > > ("defun" "^\\s-*(defun\\s-+\\([[:word:]-]+\\)") 1)
>> > >
>> > > imenu-generic-expression works on my elisp file. Only the new buffer has rescan
>> >
>> > Ok, now I see the problem: the list produced by imenu--make-index-alist
>> > contains two elements: ("Rescan" . -99) is the first, and the second
>> > is a list whose car is "defun" (or for your file presumably "headings")
>> > and whose cdr is the list of strings from the matching elements
>> > (defuns/headings) in the file with their positions. What you want to
>> > loop over is just the latter list. So it should work if you use this in
>> > vodil-imenu-bfh:
>> >
>> > (let ((imenu-items (cdadr (imenu--make-index-alist t)))
>> > ...)
>> > ...)
>> >
>> > Steve Berman
>>
>>
>> Now things are working as I hoped.
>>
>
> Would you be so kind to explain why I need cdadr ? It returns the
> `cdr' of the `car' of the `cdr'. A quite complicated thing for me.
As I noted, imenu--make-index-alist returns a two-element list, which
looks like this (using "defun" and avoid.el for a specific example, and
formatting for legibility):
(("*Rescan*" . -99)
("defun"
("mouse-avoidance-point-position" . #<marker at 5353 in avoid.el>)
("mouse-avoidance-set-mouse-position" . #<marker at 5959 in avoid.el>)
("mouse-avoidance-too-close-p" . #<marker at 6191 in avoid.el>)
("mouse-avoidance-banish-destination" . #<marker at 6974 in avoid.el>)
("mouse-avoidance-banish-mouse" . #<marker at 9012 in avoid.el>)
("mouse-avoidance-nudge-mouse" . #<marker at 10063 in avoid.el>)
("mouse-avoidance-random-shape" . #<marker at 11753 in avoid.el>)
("mouse-avoidance-ignore-p" . #<marker at 12482 in avoid.el>)
("mouse-avoidance-banish" . #<marker at 13768 in avoid.el>)
("mouse-avoidance-exile" . #<marker at 13880 in avoid.el>)
("mouse-avoidance-fancy" . #<marker at 14740 in avoid.el>)
("mouse-avoidance-mode" . #<marker at 15183 in avoid.el>)))
You want to loop over the list of cons cells containing the function
names and their positions in the file. To get this list, first take the
cdr of the above list, giving
(("defun" ("mouse-avoidance-mode" . "<marker at 5353 in avoid") ...))
, then take the car of this, giving
("defun" ("mouse-avoidance-mode" . "<marker at 5353 in avoid") ...)
, then finally take the cdr of this, giving
(("mouse-avoidance-mode" . "<marker at 5353 in avoid") ...)
, which is the list you want. In Lisp:
(cdr (car (cdr (("*Rescan*" . 99) ("defun" ("mouse-avoidance-mode"
. "<marker at 5353 in avoid") ...)))))
Since this sequence of invocations is common, the function `cdadr' was
introduced to facilitate applying it. (Likewise, there are a number of
other functions for various combinations of `car' and `cdr'; in Emacs
these are all in the subr.el library.)
Steve Berman
next prev parent reply other threads:[~2024-07-31 8:35 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-29 8:48 Listing headings in dedicated buffer with imenu Heime
2024-07-29 9:33 ` Stephen Berman
2024-07-29 10:26 ` Heime
2024-07-29 10:32 ` Heime
2024-07-29 10:32 ` Stephen Berman
2024-07-29 10:41 ` Heime
2024-07-29 10:51 ` Stephen Berman
2024-07-29 11:29 ` Heime
2024-07-29 11:45 ` Stephen Berman
2024-07-29 11:53 ` Heime
2024-07-29 13:02 ` Stephen Berman
2024-07-30 15:59 ` Heime
2024-07-30 21:30 ` Heime
2024-07-31 8:35 ` Stephen Berman [this message]
2024-07-29 11:43 ` Sharon Kimble
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87wml2rmbe.fsf@gmx.net \
--to=stephen.berman@gmx.net \
--cc=heimeborgia@protonmail.com \
--cc=help-gnu-emacs@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).