From 4fde0bd5431af74aa03492e7bb2485ac1f4731a7 Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Fri, 7 Jun 2024 19:45:06 +0300 Subject: [PATCH] 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. (cherry picked from commit 979365eef2f09e2c9d21cbf5ff0d350b210d4127) --- doc/lispref/windows.texi | 25 +++++++++++++++++++++++++ etc/NEWS | 8 ++++++++ lisp/window.el | 35 ++++++++++++++++++++++++++++++----- 3 files changed, 63 insertions(+), 5 deletions(-) diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 61e72eae680..ef61e2780c1 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -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). diff --git a/etc/NEWS b/etc/NEWS index e91270701d3..e464168908f 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -297,6 +297,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)' diff --git a/lisp/window.el b/lisp/window.el index 6a97cdec118..54568a9389a 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -7855,6 +7855,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' @@ -8748,20 +8760,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 - ;; If ALIST specifies 'lru-frames' or 'window-min-width' - ;; let them prevail. - (append alist `((lru-frames . ,frame) - (window-min-width . full-width)))) + (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))))) + ((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))) -- 2.39.2