bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#70949: display-buffer-choose-some-window


From: Juri Linkov
Subject: bug#70949: display-buffer-choose-some-window
Date: Mon, 20 May 2024 19:54:54 +0300
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/30.0.50 (x86_64-pc-linux-gnu)

>> +    `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 .  When a function, it
>
> I'd say "It can also be a function that takes two arguments ..."
>
>> +    takes two arguments: a buffer and an alist, and should return the window
>> +    where to display the buffer.  When the value is `lru', it avoids
>> +    selecting windows that are not full-width and windows on another frame.
>> +    When the value is `mru', it avoids selecting an already selected window
>> +    and windows on another frame.
>
> I'd say "..., it does not consider the selected window and windows on
> any frame but the selected one."
>
> But the more important thing is to tell users how this can help to fix
> problems like the one that triggered this thread.  A short description
> in the doc-string and a more elaborated one with an example in the Elisp
> manual in the description of 'display-buffer-use-some-window' and in the
> "Action Alists for Buffer Display" section.

Thanks for suggestions, here is a complete patch:

diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi
index 61e72eae680..efffb0d3f3f 100644
--- a/doc/lispref/windows.texi
+++ b/doc/lispref/windows.texi
@@ -2805,6 +2805,14 @@ Buffer Display Action Functions
 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 in the same window
+in a layout with more than two windows.
 @end defun
 
 @defun display-buffer-use-least-recent-window buffer alist
@@ -3358,6 +3366,16 @@ Buffer Display Action Alists
 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 4e52d4dccb2..cc2405ca09a 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -306,6 +306,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 any buffer will be displayed
+in the same most recently used window on a layout 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 e709e978cc9..1549fba6f2e 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -7845,6 +7850,18 @@ display-buffer
     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 layout 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'
@@ -8734,20 +8751,33 @@ display-buffer-use-some-window
 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)))

reply via email to

[Prev in Thread] Current Thread [Next in Thread]