Add new alist entry 'some-window' for 'display-buffer-use-some-window'

* doc/lispref/windows.texi (Buffer Display Action Functions):
Add details of using the alist entry 'some-window' in
'display-buffer-use-some-window'.
(Buffer Display Action Alists): Add 'some-window'.

* lisp/window.el (display-buffer-use-some-window):
Handle the alist entry 'some-window' (bug#70949).
Extend docstring with its description.
This commit is contained in:
Juri Linkov 2024-06-07 19:45:06 +03:00
parent 24082fc3c3
commit 979365eef2
3 changed files with 63 additions and 5 deletions

View file

@ -2805,6 +2805,21 @@ If no less recently used window is found, this function will try to use
some other window, preferably a large window on some visible frame. It
can fail if all windows are dedicated to other buffers (@pxref{Dedicated
Windows}).
The above describes the behavior when @code{some-window} @var{alist}
entry is @code{lru} or @code{nil} which is the default. But when,
for example, @code{display-buffer-base-action} is customized to
@w{@code{(nil . ((some-window . mru)))}}, then the value @code{mru}
means that this function will prefer the most recently used window
that is useful to display several buffers from the consecutive calls
of @code{display-buffer} in the same window. Consider a configuration
of three or more windows where a user wants to consult, in
a non-selected window, one after the other, the results of a query
spread among several buffers. With the @code{lru} strategy, Emacs might
continuously choose another window because the least recently used
window changes with every call of @code{display-buffer-use-some-window}.
With the @code{mru} strategy, the window chosen would always remain the
same, resulting in a predictable user experience.
@end defun
@defun display-buffer-use-least-recent-window buffer alist
@ -3358,6 +3373,16 @@ since there is no guarantee that an arbitrary caller of
will display the buffer. @code{display-buffer-no-window} is the only
action function that cares about this entry.
@vindex some-window@r{, a buffer display action alist entry}
@item some-window
If the value is @code{nil} or @code{lru}, @code{display-buffer-use-some-window}
prefers the least recently used window while avoiding selecting windows
that are not full-width and windows on another frame. If the value is
@code{mru}, it prefers the most recently used window not considering the
selected window and windows on any frame but the selected one. If the
value is a function, it is called with two arguments: a buffer and an
alist, and should return the window where to display the buffer.
@vindex body-function@r{, a buffer display action alist entry}
@item body-function
The value must be a function taking one argument (a displayed window).

View file

@ -323,6 +323,14 @@ right-aligned to is controlled by the new user option
** Windows
+++
*** New action alist entry 'some-window' for 'display-buffer'.
It defines which window 'display-buffer-use-some-window' should prefer.
For example, when 'display-buffer-base-action' is customized to
'(nil . ((some-window . mru)))' then a buffer will be displayed
in the same most recently used window from the consecutive calls
display-buffer' (on a configuration with more than two windows).
+++
*** New action alist entry 'category' for 'display-buffer'.
If the caller of 'display-buffer' passes '(category . symbol)'

View file

@ -7849,6 +7849,18 @@ Action alist entries are:
parameters to give the chosen window.
`allow-no-window' -- A non-nil value means that `display-buffer'
may not display the buffer and return nil immediately.
`some-window' -- This entry defines which window
`display-buffer-use-some-window' should choose. The possible choices
are `lru' or nil (the default) to select the least recently used window,
and `mru' to select the most recently used window. It can also be
a function that takes two arguments: a buffer and an alist, and should
return the window where to display the buffer. If the value is `lru',
it avoids selecting windows that are not full-width and windows on
another frame. If the value is `mru', it does not consider the
selected window and windows on any frame but the selected one.
It's useful to customize `display-buffer-base-action' to
`(nil . ((some-window . mru))) when you want to display buffers in the
same non-selected window in a configuration with more than two windows.
`body-function' -- A function called with one argument - the
displayed window. It is called after the buffer is
displayed, and before `window-height', `window-width'
@ -8738,20 +8750,33 @@ If ALIST has a non-nil `inhibit-switch-frame' entry, then in the
event that a window on another frame is chosen, avoid raising
that frame.
If ALIST contains a non-nil `some-window' entry, then prefer the least
recently used window if the entry's value is `lru' or nil, or the most
recently used window if it's `mru'. If the value is a function, it is
called with two arguments: a buffer and an alist, and should return
the window where to display the buffer.
This is an action function for buffer display, see Info
node `(elisp) Buffer Display Action Functions'. It should be
called only by `display-buffer' or a function directly or
indirectly called by the latter."
(let* ((not-this-window (cdr (assq 'inhibit-same-window alist)))
(some-window-method (cdr (assq 'some-window alist)))
(frame (or (window--frame-usable-p (selected-frame))
(window--frame-usable-p (last-nonminibuffer-frame))))
(window
;; Reuse an existing window.
(or (display-buffer--lru-window
(or (cond
((memq some-window-method '(nil lru))
(display-buffer--lru-window
;; If ALIST specifies 'lru-frames' or 'window-min-width'
;; let them prevail.
(append alist `((lru-frames . ,frame)
(window-min-width . full-width))))
(window-min-width . full-width)))))
((eq some-window-method 'mru)
(get-mru-window nil nil t))
((functionp some-window-method)
(funcall some-window-method buffer alist)))
(let ((window (get-buffer-window buffer 'visible)))
(unless (and not-this-window
(eq window (selected-window)))