unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Switch buffers without modifying the buffer list ordering?
@ 2022-01-30 21:26 Augusto Stoffel
  2022-01-31  8:42 ` martin rudalics
  2022-02-01 14:48 ` Kevin Vigouroux via Emacs development discussions.
  0 siblings, 2 replies; 5+ messages in thread
From: Augusto Stoffel @ 2022-01-30 21:26 UTC (permalink / raw)
  To: emacs-devel; +Cc: Daniel Mendler, Omar Antolín Camarena

With the following code, I can verify that the NORECORD argument of
`switch-to-buffer' does what it promises:

```
(progn
  (switch-to-buffer "A")
  (switch-to-buffer "B" 'norecord)
  (car (buffer-list)))
```

Namely, this makes buffer B current, but returns #<buffer A>.

Now, here's a catch: if next I type `M-x (car (buffer-list))', I get
#<buffer B> instead of #<buffer A>.  Why does that happen, and is there
a way to switch to buffer B and *really* not modify the buffer list
ordering?

I'm asking this because of an issue with the live preview feature of the
Consult package.  Very succinctly, the idea here is to temporarily
change the current buffer during a `completing-read' call, in order to
display more information about the candidates.  When the
`completing-read' ends, we would like to restore the original order of
the buffer list.  There seems to be no simple way to achieve that, and
some kludge like the following seems necessary.  Any better suggestions?

```
(let ((buffers (buffer-list)))
    (unwind-protect
        <do the completing-read with live preview>
      (save-window-excursion
        ;; Restore the original buffer list ordering
        (dolist (buffer buffers)
          (when (buffer-live-p buffer)
            (bury-buffer-internal buffer))))))
```



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Switch buffers without modifying the buffer list ordering?
  2022-01-30 21:26 Switch buffers without modifying the buffer list ordering? Augusto Stoffel
@ 2022-01-31  8:42 ` martin rudalics
  2022-02-01 18:46   ` Augusto Stoffel
  2022-02-02 11:24   ` Kevin Vigouroux via Emacs development discussions.
  2022-02-01 14:48 ` Kevin Vigouroux via Emacs development discussions.
  1 sibling, 2 replies; 5+ messages in thread
From: martin rudalics @ 2022-01-31  8:42 UTC (permalink / raw)
  To: Augusto Stoffel, emacs-devel; +Cc: Daniel Mendler, Omar Antolín Camarena

 > With the following code, I can verify that the NORECORD argument of
 > `switch-to-buffer' does what it promises:
 >
 > ```
 > (progn
 >    (switch-to-buffer "A")
 >    (switch-to-buffer "B" 'norecord)
 >    (car (buffer-list)))
 > ```
 >
 > Namely, this makes buffer B current, but returns #<buffer A>.
 >
 > Now, here's a catch: if next I type `M-x (car (buffer-list))',

... M-: (car (buffer-list)) I suppose ...

 > I get
 > #<buffer B> instead of #<buffer A>.  Why does that happen, and is there
 > a way to switch to buffer B and *really* not modify the buffer list
 > ordering?

It's restoring the window configuration after reading from the
minibuffer but before evaluating the expression you typed that gets in
the way.  Try with emacs -Q and evaluate the forms below step by step

(display-buffer "*Messages*")

(defun foo ()
   (message
    "%s - %s" (selected-window) (car (buffer-list))))

(add-hook 'buffer-list-update-hook 'foo)

(progn
   (switch-to-buffer "A")
   (switch-to-buffer "B" 'norecord)
   (car (buffer-list)))

and now type M-: (car (buffer-list)).  This gets me in the *Messages*
buffer

#<window 3 on A> - A [3 times]
#<buffer A>
#<window 3 on B> - A
#<window 4 on  *Minibuf-1*> -  *Minibuf-1* [4 times]
#<window 3 on B> - B [2 times]
#<buffer B>

Now try again the same scenario but first evaluate

(setq read-minibuffer-restore-windows nil)

which gets me here the

#<window 3 on A> - A [3 times]
#<buffer A>

you probably expected.

 > I'm asking this because of an issue with the live preview feature of the
 > Consult package.  Very succinctly, the idea here is to temporarily
 > change the current buffer during a `completing-read' call, in order to
 > display more information about the candidates.  When the
 > `completing-read' ends, we would like to restore the original order of
 > the buffer list.  There seems to be no simple way to achieve that, and
 > some kludge like the following seems necessary.  Any better suggestions?
 >
 > ```
 > (let ((buffers (buffer-list)))
 >      (unwind-protect
 >          <do the completing-read with live preview>
 >        (save-window-excursion
 >          ;; Restore the original buffer list ordering
 >          (dolist (buffer buffers)
 >            (when (buffer-live-p buffer)
 >              (bury-buffer-internal buffer))))))

That's a different issue.  'buffer-list' is a function that returns a
list from the internal C variable Vbuffer_alist - a variable, Lisp code
is not allowed to modify directly.  In order to modify Vbuffer_alist, a
Lisp programmer has to bury buffers in precisely the same way as you do.

You could try coming up with a macro, say 'with-buffer-list-unmodified'
(where you probably should suspend calling 'buffer-list-update-hook'
while running it).

martin



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Switch buffers without modifying the buffer list ordering?
  2022-01-30 21:26 Switch buffers without modifying the buffer list ordering? Augusto Stoffel
  2022-01-31  8:42 ` martin rudalics
@ 2022-02-01 14:48 ` Kevin Vigouroux via Emacs development discussions.
  1 sibling, 0 replies; 5+ messages in thread
From: Kevin Vigouroux via Emacs development discussions. @ 2022-02-01 14:48 UTC (permalink / raw)
  To: emacs-devel; +Cc: Augusto Stoffel

`buffer-list' displays the buffers in a specific order: the buffer in
the selected window is displayed first.

I don’t really understand how it works, but we can see that the buffer
appears at the end of the list when we select another window before
evaluating the expression `(buffer-list)'.
-- 
Best regards,
Kevin Vigouroux



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Switch buffers without modifying the buffer list ordering?
  2022-01-31  8:42 ` martin rudalics
@ 2022-02-01 18:46   ` Augusto Stoffel
  2022-02-02 11:24   ` Kevin Vigouroux via Emacs development discussions.
  1 sibling, 0 replies; 5+ messages in thread
From: Augusto Stoffel @ 2022-02-01 18:46 UTC (permalink / raw)
  To: martin rudalics; +Cc: Daniel Mendler, Omar Antolín Camarena, emacs-devel

Thanks, this essentially clarifies everything.

On Mon, 31 Jan 2022 at 09:42, martin rudalics <rudalics@gmx.at> wrote:

>> With the following code, I can verify that the NORECORD argument of
>> `switch-to-buffer' does what it promises:
>>
>> ```
>> (progn
>>    (switch-to-buffer "A")
>>    (switch-to-buffer "B" 'norecord)
>>    (car (buffer-list)))
>> ```
>>
>> Namely, this makes buffer B current, but returns #<buffer A>.
>>
>> Now, here's a catch: if next I type `M-x (car (buffer-list))',
>
> ... M-: (car (buffer-list)) I suppose ...
>
>> I get
>> #<buffer B> instead of #<buffer A>.  Why does that happen, and is there
>> a way to switch to buffer B and *really* not modify the buffer list
>> ordering?
>
> It's restoring the window configuration after reading from the
> minibuffer but before evaluating the expression you typed that gets in
> the way.  Try with emacs -Q and evaluate the forms below step by step
>
> (display-buffer "*Messages*")
>
> (defun foo ()
>   (message
>    "%s - %s" (selected-window) (car (buffer-list))))
>
> (add-hook 'buffer-list-update-hook 'foo)
>
> (progn
>   (switch-to-buffer "A")
>   (switch-to-buffer "B" 'norecord)
>   (car (buffer-list)))
>
> and now type M-: (car (buffer-list)).  This gets me in the *Messages*
> buffer
>
> #<window 3 on A> - A [3 times]
> #<buffer A>
> #<window 3 on B> - A
> #<window 4 on  *Minibuf-1*> -  *Minibuf-1* [4 times]
> #<window 3 on B> - B [2 times]
> #<buffer B>
>
> Now try again the same scenario but first evaluate
>
> (setq read-minibuffer-restore-windows nil)
>
> which gets me here the
>
> #<window 3 on A> - A [3 times]
> #<buffer A>
>
> you probably expected.
>
>> I'm asking this because of an issue with the live preview feature of the
>> Consult package.  Very succinctly, the idea here is to temporarily
>> change the current buffer during a `completing-read' call, in order to
>> display more information about the candidates.  When the
>> `completing-read' ends, we would like to restore the original order of
>> the buffer list.  There seems to be no simple way to achieve that, and
>> some kludge like the following seems necessary.  Any better suggestions?
>>
>> ```
>> (let ((buffers (buffer-list)))
>>      (unwind-protect
>>          <do the completing-read with live preview>
>>        (save-window-excursion
>>          ;; Restore the original buffer list ordering
>>          (dolist (buffer buffers)
>>            (when (buffer-live-p buffer)
>>              (bury-buffer-internal buffer))))))
>
> That's a different issue.  'buffer-list' is a function that returns a
> list from the internal C variable Vbuffer_alist - a variable, Lisp code
> is not allowed to modify directly.  In order to modify Vbuffer_alist, a
> Lisp programmer has to bury buffers in precisely the same way as you do.
>
> You could try coming up with a macro, say 'with-buffer-list-unmodified'
> (where you probably should suspend calling 'buffer-list-update-hook'
> while running it).
>
> martin



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Switch buffers without modifying the buffer list ordering?
  2022-01-31  8:42 ` martin rudalics
  2022-02-01 18:46   ` Augusto Stoffel
@ 2022-02-02 11:24   ` Kevin Vigouroux via Emacs development discussions.
  1 sibling, 0 replies; 5+ messages in thread
From: Kevin Vigouroux via Emacs development discussions. @ 2022-02-02 11:24 UTC (permalink / raw)
  To: emacs-devel; +Cc: martin rudalics

The NORECORD argument of `switch-to-buffer' is actually passed to
`select-window' (see its docstring).

#+begin_quote
Optional second arg NORECORD non-nil means do not put this buffer at the
front of the buffer list and do not make this window the most recently
selected one.  Also, do not mark WINDOW for redisplay unless NORECORD
equals the special symbol ‘mark-for-redisplay’.
#+end_quote

Anyway, `switch-to-buffer' displays the buffer in some window and
finally selects that window.

#+begin_quote
Also note that the main editor command loop sets the current buffer to
the buffer of the selected window before each command.
#+end_quote

The displayed buffer is in the selected window, so the command loops
sets the current buffer to this buffer.

⏵ Emacs Lisp Ref. Manual — 27.8 “The Buffer List”.

#+begin_quote
A buffer moves to the front of this list whenever it is chosen for
display in a window (*note Switching Buffers) or a window displaying
it is selected (see Selecting Windows).
#+end_quote

If we select another window, we see that everything works as you expected.
-- 
Kevin Vigouroux
Best regards



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-02-02 11:24 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-30 21:26 Switch buffers without modifying the buffer list ordering? Augusto Stoffel
2022-01-31  8:42 ` martin rudalics
2022-02-01 18:46   ` Augusto Stoffel
2022-02-02 11:24   ` Kevin Vigouroux via Emacs development discussions.
2022-02-01 14:48 ` Kevin Vigouroux via Emacs development discussions.

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

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).