unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* May we have a variant of display-buffer-reuse-window that considers indirect buffers? (was: Indirect follow mode in agenda: Display, edition and how to hide drawers)
       [not found] <878qtycdmi.fsf@k-7.ch>
@ 2024-12-15 15:28 ` Ihor Radchenko
  2024-12-16  7:49   ` May we have a variant of display-buffer-reuse-window that considers indirect buffers? Juri Linkov
  0 siblings, 1 reply; 12+ messages in thread
From: Ihor Radchenko @ 2024-12-15 15:28 UTC (permalink / raw)
  To: Sébastien Gendre; +Cc: Org Mode List, emacs-devel

Hi,

We got a use case when we want to display an Org buffer in other window,
but want to reuse an indirect buffer if it is already present.

May it be possible?
It feels like a natural thing to be available for `display-buffer', but
I cannot find anything.

Sébastien Gendre <seb@k-7.ch> writes:

> When I want to edit a task and press "TAB", the point is moved to
> a window that show all the task. Not into the window opened by the
> indirect follow mode. Is it possible to modify this ?

-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>



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

* Re: May we have a variant of display-buffer-reuse-window that considers indirect buffers?
  2024-12-15 15:28 ` May we have a variant of display-buffer-reuse-window that considers indirect buffers? (was: Indirect follow mode in agenda: Display, edition and how to hide drawers) Ihor Radchenko
@ 2024-12-16  7:49   ` Juri Linkov
  2024-12-16  9:23     ` martin rudalics
  2024-12-16 18:07     ` Ihor Radchenko
  0 siblings, 2 replies; 12+ messages in thread
From: Juri Linkov @ 2024-12-16  7:49 UTC (permalink / raw)
  To: Ihor Radchenko
  Cc: Sébastien Gendre, Org Mode List, emacs-devel,
	martin rudalics

>> When I want to edit a task and press "TAB", the point is moved to
>> a window that show all the task. Not into the window opened by the
>> indirect follow mode. Is it possible to modify this ?
>
> We got a use case when we want to display an Org buffer in other window,
> but want to reuse an indirect buffer if it is already present.
>
> May it be possible?
> It feels like a natural thing to be available for `display-buffer', but
> I cannot find anything.

It's possible to select the necessary window by using 'pop-to-buffer'
while displaying the non-selected window with a simple 'display-window'.



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

* Re: May we have a variant of display-buffer-reuse-window that considers indirect buffers?
  2024-12-16  7:49   ` May we have a variant of display-buffer-reuse-window that considers indirect buffers? Juri Linkov
@ 2024-12-16  9:23     ` martin rudalics
  2024-12-16 18:07     ` Ihor Radchenko
  1 sibling, 0 replies; 12+ messages in thread
From: martin rudalics @ 2024-12-16  9:23 UTC (permalink / raw)
  To: Juri Linkov, Ihor Radchenko
  Cc: Sébastien Gendre, Org Mode List, emacs-devel

 > It's possible to select the necessary window by using 'pop-to-buffer'
 > while displaying the non-selected window with a simple 'display-window'.

                                                          'display-buffer'

I suppose.

martin



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

* Re: May we have a variant of display-buffer-reuse-window that considers indirect buffers?
  2024-12-16  7:49   ` May we have a variant of display-buffer-reuse-window that considers indirect buffers? Juri Linkov
  2024-12-16  9:23     ` martin rudalics
@ 2024-12-16 18:07     ` Ihor Radchenko
  2024-12-17  9:01       ` martin rudalics
  1 sibling, 1 reply; 12+ messages in thread
From: Ihor Radchenko @ 2024-12-16 18:07 UTC (permalink / raw)
  To: Juri Linkov
  Cc: Sébastien Gendre, Org Mode List, emacs-devel,
	martin rudalics

Juri Linkov <juri@linkov.net> writes:

>> We got a use case when we want to display an Org buffer in other window,
>> but want to reuse an indirect buffer if it is already present.
>>
>> May it be possible?
>> It feels like a natural thing to be available for `display-buffer', but
>> I cannot find anything.
>
> It's possible to select the necessary window by using 'pop-to-buffer'
> while displaying the non-selected window with a simple 'display-window'.

May you please provide more information? AFAIK, `pop-to-buffer' will
search for exact buffer without considering its indirect buffers and
base buffer.

-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>



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

* Re: May we have a variant of display-buffer-reuse-window that considers indirect buffers?
  2024-12-16 18:07     ` Ihor Radchenko
@ 2024-12-17  9:01       ` martin rudalics
  2024-12-17 18:11         ` Ihor Radchenko
  0 siblings, 1 reply; 12+ messages in thread
From: martin rudalics @ 2024-12-17  9:01 UTC (permalink / raw)
  To: Ihor Radchenko, Juri Linkov
  Cc: Sébastien Gendre, Org Mode List, emacs-devel

 > May you please provide more information? AFAIK, `pop-to-buffer' will
 > search for exact buffer without considering its indirect buffers and
 > base buffer.

Could you please tell us what you would like 'display-buffer' to do
without referring to org-mode.  IIUC you want it to automatically detect
that if a base buffer has been displayed in a window earlier and BUFFER
is an indirect buffer sharing that base buffer, then it should try to
use that window for the indirect buffer.  Is that assumption correct?

martin




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

* Re: May we have a variant of display-buffer-reuse-window that considers indirect buffers?
  2024-12-17  9:01       ` martin rudalics
@ 2024-12-17 18:11         ` Ihor Radchenko
  2024-12-18  9:08           ` martin rudalics
  0 siblings, 1 reply; 12+ messages in thread
From: Ihor Radchenko @ 2024-12-17 18:11 UTC (permalink / raw)
  To: martin rudalics
  Cc: Juri Linkov, Sébastien Gendre, Org Mode List, emacs-devel

martin rudalics <rudalics@gmx.at> writes:

> Could you please tell us what you would like 'display-buffer' to do
> without referring to org-mode.  IIUC you want it to automatically detect
> that if a base buffer has been displayed in a window earlier and BUFFER
> is an indirect buffer sharing that base buffer, then it should try to
> use that window for the indirect buffer.  Is that assumption correct?

Yup.

To be 100% clear, let me try to restate exactly what I have in mind.

I want to call something like

 (pop-to-buffer BUFFER
   '((display-buffer-reuse-window display-buffer-pop-up-window)
     (reuse-indirect . t)))

1. If there is a window displaying BUFFER, switch to that window
2. If there is a window that is an indirect buffer of BUFFER or that
   shares the same base buffer with BUFFER, switch to that window
3. Otherwise, pop up a new window displaying BUFFER

(2) is the feature I am failing to find.

-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>



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

* Re: May we have a variant of display-buffer-reuse-window that considers indirect buffers?
  2024-12-17 18:11         ` Ihor Radchenko
@ 2024-12-18  9:08           ` martin rudalics
  2024-12-18 18:18             ` Ihor Radchenko
  0 siblings, 1 reply; 12+ messages in thread
From: martin rudalics @ 2024-12-18  9:08 UTC (permalink / raw)
  To: Ihor Radchenko
  Cc: Juri Linkov, Sébastien Gendre, Org Mode List, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 629 bytes --]

 > To be 100% clear, let me try to restate exactly what I have in mind.
 >
 > I want to call something like
 >
 >   (pop-to-buffer BUFFER
 >     '((display-buffer-reuse-window display-buffer-pop-up-window)
 >       (reuse-indirect . t)))
 >
 > 1. If there is a window displaying BUFFER, switch to that window
 > 2. If there is a window that is an indirect buffer of BUFFER or that
 >     shares the same base buffer with BUFFER, switch to that window

I included the facility that if there is a window whose buffer is the
base buffer of BUFFER use that window.  See the attached diff which I
did not test very thoroughly.

martin

[-- Attachment #2: display-indirect-buffer.diff --]
[-- Type: text/x-patch, Size: 4165 bytes --]

diff --git a/lisp/window.el b/lisp/window.el
index e9d57652ec6..31c2ae50792 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -2615,7 +2615,36 @@ get-largest-window
 	  (setq best-window window))))
     best-window))
 
-(defun get-buffer-window-list (&optional buffer-or-name minibuf all-frames)
+(defun window-indirect-buffer-p (&optional window buffer-or-name)
+  "Return non-nil if specified WINDOW is indirectly related to BUFFER-OR-NAME.
+WINDOW must be a live window and defaults to the selected window.
+BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
+defaults to the current buffer.
+
+WINODW is indirectly related to BUFFER-OR-NAME if one of the following
+conditions hold:
+
+- BUFFER-OR-NAME specifies an indirect buffer and WINDOW's buffer is its
+  base buffer.
+
+- WINDOW's buffer is an indirect buffer whose base buffer is the buffer
+  specified by BUFFER-OR-NAME.
+
+- Both, WINDOW's buffer and the buffer specified by BUFFER-OR-NAME, are
+  indirect buffer's sharing the same base buffer.
+
+Return nil if none of the above holds."
+  (let* ((window (window-normalize-window window t))
+	 (window-buffer (window-buffer window))
+	 (window-base-buffer (buffer-base-buffer window-buffer))
+	 (buffer (window-normalize-buffer buffer-or-name))
+	 (buffer-base-buffer (buffer-base-buffer buffer)))
+    (or (eq buffer-base-buffer window-buffer)
+	(eq window-base-buffer buffer)
+	(and buffer-base-buffer
+	     (eq buffer-base-buffer window-base-buffer)))))
+
+(defun get-buffer-window-list (&optional buffer-or-name minibuf all-frames indirect)
   "Return list of all windows displaying BUFFER-OR-NAME, or nil if none.
 BUFFER-OR-NAME may be a buffer or the name of an existing buffer
 and defaults to the current buffer.  If the selected window displays
@@ -2644,11 +2673,17 @@ get-buffer-window-list
 - A frame means consider all windows on that frame only.
 
 Anything else means consider all windows on the selected frame
-and no others."
+and no others.
+
+INDIRECT non-nil means to include in the list returned all windows that
+are indirectly related to BUFFER-OR-NAME, that is, all windows for which
+`window-indirect-buffer-p' with the window and the buffer specified by
+BUFFER-OR-NAME as arguments returns non-nil."
   (let ((buffer (window-normalize-buffer buffer-or-name))
 	windows)
     (dolist (window (window-list-1 (selected-window) minibuf all-frames))
-      (when (eq (window-buffer window) buffer)
+      (when (or (eq (window-buffer window) buffer)
+		(and indirect (window-indirect-buffer-p window buffer)))
 	(setq windows (cons window windows))))
     (nreverse windows)))
 
@@ -8239,20 +8274,24 @@ display-buffer-reuse-window
 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* ((alist-entry (assq 'reusable-frames alist))
-	 (frames (cond (alist-entry (cdr alist-entry))
+  (let* ((reusable-frames (assq 'reusable-frames alist))
+	 (reuse-indirect (assq 'reuse-indirect alist))
+	 (frames (cond (reusable-frames (cdr reusable-frames))
 		       ((window--pop-up-frames alist)
 			0)
 		       (display-buffer-reuse-frames 0)
 		       (t (last-nonminibuffer-frame))))
-	 (window (if (and (eq buffer (window-buffer))
+	 (window (if (and (or (eq buffer (window-buffer))
+			      (and reuse-indirect
+				   (window-indirect-buffer-p nil buffer)))
 			  (not (cdr (assq 'inhibit-same-window alist))))
 		     (selected-window)
                    ;; Preferably use a window on the selected frame,
                    ;; if such a window exists (Bug#36680).
-                   (let* ((windows (delq (selected-window)
-                                         (get-buffer-window-list
-                                          buffer 'nomini frames)))
+                   (let* ((windows
+			   (delq (selected-window)
+                                 (get-buffer-window-list
+                                  buffer 'nomini frames reuse-indirect)))
                           (first (car windows))
                           (this-frame (selected-frame)))
                      (cond

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

* Re: May we have a variant of display-buffer-reuse-window that considers indirect buffers?
  2024-12-18  9:08           ` martin rudalics
@ 2024-12-18 18:18             ` Ihor Radchenko
  2024-12-18 19:13               ` martin rudalics
  0 siblings, 1 reply; 12+ messages in thread
From: Ihor Radchenko @ 2024-12-18 18:18 UTC (permalink / raw)
  To: martin rudalics
  Cc: Juri Linkov, Sébastien Gendre, Org Mode List, emacs-devel

martin rudalics <rudalics@gmx.at> writes:

>  >   (pop-to-buffer BUFFER
>  >     '((display-buffer-reuse-window display-buffer-pop-up-window)
>  >       (reuse-indirect . t)))
>  >
>  > 1. If there is a window displaying BUFFER, switch to that window
>  > 2. If there is a window that is an indirect buffer of BUFFER or that
>  >     shares the same base buffer with BUFFER, switch to that window
>
> I included the facility that if there is a window whose buffer is the
> base buffer of BUFFER use that window.  See the attached diff which I
> did not test very thoroughly.

Thanks!
It seems to work, although somewhat different than I described.

With your diff, in case (2), if BUFFER is what is passed to
`pop-to-buffer' and BUFFER2 is indirectly related buffer displayed in a
visible window, then BUFFER2 is replaced with BUFFER. I expected that
BUFFER2's window will be selected; nothing more.

-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>



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

* Re: May we have a variant of display-buffer-reuse-window that considers indirect buffers?
  2024-12-18 18:18             ` Ihor Radchenko
@ 2024-12-18 19:13               ` martin rudalics
  2024-12-19 17:47                 ` Ihor Radchenko
  0 siblings, 1 reply; 12+ messages in thread
From: martin rudalics @ 2024-12-18 19:13 UTC (permalink / raw)
  To: Ihor Radchenko
  Cc: Juri Linkov, Sébastien Gendre, Org Mode List, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 931 bytes --]

attached.
 >>   > 1. If there is a window displaying BUFFER, switch to that window
 >>   > 2. If there is a window that is an indirect buffer of BUFFER or that
 >>   >     shares the same base buffer with BUFFER, switch to that window
 >>
 >> I included the facility that if there is a window whose buffer is the
 >> base buffer of BUFFER use that window.  See the attached diff which I
 >> did not test very thoroughly.
 >
 > Thanks!
 > It seems to work, although somewhat different than I described.
 >
 > With your diff, in case (2), if BUFFER is what is passed to
 > `pop-to-buffer' and BUFFER2 is indirectly related buffer displayed in a
 > visible window, then BUFFER2 is replaced with BUFFER. I expected that
 > BUFFER2's window will be selected; nothing more.

Hmmm...  This is not really what 'display-buffer' is supposed to do.  I
have to disguise the fact that we wanted to display BUFFER.  I attach a
new patch.

martin

[-- Attachment #2: display-indirect-buffer.diff --]
[-- Type: text/x-patch, Size: 6261 bytes --]

diff --git a/lisp/window.el b/lisp/window.el
index e9d57652ec6..dd030547350 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -2615,7 +2615,36 @@ get-largest-window
 	  (setq best-window window))))
     best-window))
 
-(defun get-buffer-window-list (&optional buffer-or-name minibuf all-frames)
+(defun window-indirect-buffer-p (&optional window buffer-or-name)
+  "Return non-nil if specified WINDOW is indirectly related to BUFFER-OR-NAME.
+WINDOW must be a live window and defaults to the selected window.
+BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
+defaults to the current buffer.
+
+WINODW is indirectly related to BUFFER-OR-NAME if one of the following
+conditions hold:
+
+- BUFFER-OR-NAME specifies an indirect buffer and WINDOW's buffer is its
+  base buffer.
+
+- WINDOW's buffer is an indirect buffer whose base buffer is the buffer
+  specified by BUFFER-OR-NAME.
+
+- Both, WINDOW's buffer and the buffer specified by BUFFER-OR-NAME, are
+  indirect buffer's sharing the same base buffer.
+
+Return nil if none of the above holds."
+  (let* ((window (window-normalize-window window t))
+	 (window-buffer (window-buffer window))
+	 (window-base-buffer (buffer-base-buffer window-buffer))
+	 (buffer (window-normalize-buffer buffer-or-name))
+	 (buffer-base-buffer (buffer-base-buffer buffer)))
+    (or (eq buffer-base-buffer window-buffer)
+	(eq window-base-buffer buffer)
+	(and buffer-base-buffer
+	     (eq buffer-base-buffer window-base-buffer)))))
+
+(defun get-buffer-window-list (&optional buffer-or-name minibuf all-frames indirect)
   "Return list of all windows displaying BUFFER-OR-NAME, or nil if none.
 BUFFER-OR-NAME may be a buffer or the name of an existing buffer
 and defaults to the current buffer.  If the selected window displays
@@ -2644,12 +2673,23 @@ get-buffer-window-list
 - A frame means consider all windows on that frame only.
 
 Anything else means consider all windows on the selected frame
-and no others."
+and no others.
+
+INDIRECT non-nil means to append to the list of windows showing
+BUFFER-OR-NAME a list of all windows that are indirectly related to
+BUFFER-OR-NAME, that is, windows for which `window-indirect-buffer-p'
+with the window and the buffer specified by BUFFER-OR-NAME as arguments
+returns non-nil."
   (let ((buffer (window-normalize-buffer buffer-or-name))
+	(window-list (window-list-1 (selected-window) minibuf all-frames))
 	windows)
-    (dolist (window (window-list-1 (selected-window) minibuf all-frames))
+    (dolist (window window-list)
       (when (eq (window-buffer window) buffer)
 	(setq windows (cons window windows))))
+    (when indirect
+      (dolist (window window-list)
+	(when (window-indirect-buffer-p window buffer)
+	  (setq windows (cons window windows)))))
     (nreverse windows)))
 
 (defun minibuffer-window-active-p (window)
@@ -8235,35 +8275,53 @@ display-buffer-reuse-window
 event that a window on another frame is chosen, avoid raising
 that frame.
 
+If ALIST has a non-nil `reuse-indirect' entry and no window showing
+BUFFER has been found, try to find a window that is indirectly related
+to BUFFER and return that window.  This would be a window for which
+`window-indirect-buffer-p' with the window and BUFFER as arguments
+returns non-nil.
+
 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* ((alist-entry (assq 'reusable-frames alist))
-	 (frames (cond (alist-entry (cdr alist-entry))
+  (let* ((reusable-frames (assq 'reusable-frames alist))
+	 (reuse-indirect (assq 'reuse-indirect alist))
+	 (frames (cond (reusable-frames (cdr reusable-frames))
 		       ((window--pop-up-frames alist)
 			0)
 		       (display-buffer-reuse-frames 0)
 		       (t (last-nonminibuffer-frame))))
-	 (window (if (and (eq buffer (window-buffer))
-			  (not (cdr (assq 'inhibit-same-window alist))))
-		     (selected-window)
-                   ;; Preferably use a window on the selected frame,
-                   ;; if such a window exists (Bug#36680).
-                   (let* ((windows (delq (selected-window)
-                                         (get-buffer-window-list
-                                          buffer 'nomini frames)))
-                          (first (car windows))
-                          (this-frame (selected-frame)))
-                     (cond
-                      ((eq (window-frame first) this-frame)
-                       first)
-                      ((catch 'found
-                         (dolist (next (cdr windows))
-                           (when (eq (window-frame next) this-frame)
-                             (throw 'found next)))))
-                      (t first))))))
+	 (inhibit-same (cdr (assq 'inhibit-same-window alist)))
+	 (window
+	  ;; Avoid calling 'get-buffer-window-list' if the selected
+	  ;; window already shows BUFFER and can be used.
+	  (if (and (eq buffer (window-buffer)) (not inhibit-same))
+	      (selected-window)
+            ;; Preferably use a window on the selected frame,
+            ;; if such a window exists (Bug#36680).
+            (let* ((windows-raw
+		    (get-buffer-window-list
+                     buffer 'nomini frames reuse-indirect))
+		   (windows (if inhibit-same
+				(delq (selected-window) windows-raw)
+			      windows-raw))
+                   (first (car windows))
+                   (this-frame (selected-frame)))
+              (cond
+               ((eq (window-frame first) this-frame)
+                first)
+               ((catch 'found
+                  (dolist (next (cdr windows))
+                    (when (eq (window-frame next) this-frame)
+                      (throw 'found next)))))
+               (t first))))))
     (when (window-live-p window)
+      (when (and reuse-indirect
+		 (not (eq (window-buffer window) buffer)))
+	;; Pretend we were asking for a window showing the buffer of
+	;; that window.
+	(setq buffer (window-buffer window)))
       (prog1 (window--display-buffer buffer window 'reuse alist)
 	(unless (cdr (assq 'inhibit-switch-frame alist))
 	  (window--maybe-raise-frame (window-frame window)))))))

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

* Re: May we have a variant of display-buffer-reuse-window that considers indirect buffers?
  2024-12-18 19:13               ` martin rudalics
@ 2024-12-19 17:47                 ` Ihor Radchenko
  2024-12-20  9:02                   ` martin rudalics
  0 siblings, 1 reply; 12+ messages in thread
From: Ihor Radchenko @ 2024-12-19 17:47 UTC (permalink / raw)
  To: martin rudalics
  Cc: Juri Linkov, Sébastien Gendre, Org Mode List, emacs-devel

martin rudalics <rudalics@gmx.at> writes:

>  > It seems to work, although somewhat different than I described.
>  >
>  > With your diff, in case (2), if BUFFER is what is passed to
>  > `pop-to-buffer' and BUFFER2 is indirectly related buffer displayed in a
>  > visible window, then BUFFER2 is replaced with BUFFER. I expected that
>  > BUFFER2's window will be selected; nothing more.
>
> Hmmm...  This is not really what 'display-buffer' is supposed to do.  I
> have to disguise the fact that we wanted to display BUFFER.  I attach a
> new patch.

Now, when you said that, it does feel not right indeed.

What I was concerned about is the situation my request originated from:

1. Org displays a *narrowed* indirect buffer
2. User requests to jump to a heading in base buffer of that indirect
   buffer
3. Changing the buffer (even in the same window - with your patch) will
   suddenly change the narrowing state.

That said, it is not a problem `display-buffer' is supposed to solve
anyway. The modified `get-buffer-window-list' from your patch may also
be used in the above scenario before deciding which buffer we want to
change to.

So, I'd myself vote for the first version of the patch if looking from
more general Emacs perspective.

-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>



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

* Re: May we have a variant of display-buffer-reuse-window that considers indirect buffers?
  2024-12-19 17:47                 ` Ihor Radchenko
@ 2024-12-20  9:02                   ` martin rudalics
  2024-12-21 12:34                     ` Ihor Radchenko
  0 siblings, 1 reply; 12+ messages in thread
From: martin rudalics @ 2024-12-20  9:02 UTC (permalink / raw)
  To: Ihor Radchenko
  Cc: Juri Linkov, Sébastien Gendre, Org Mode List, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1147 bytes --]

 >> Hmmm...  This is not really what 'display-buffer' is supposed to do.  I
 >> have to disguise the fact that we wanted to display BUFFER.  I attach a
 >> new patch.
 >
 > Now, when you said that, it does feel not right indeed.
 >
 > What I was concerned about is the situation my request originated from:
 >
 > 1. Org displays a *narrowed* indirect buffer
 > 2. User requests to jump to a heading in base buffer of that indirect
 >     buffer
 > 3. Changing the buffer (even in the same window - with your patch) will
 >     suddenly change the narrowing state.
 >
 > That said, it is not a problem `display-buffer' is supposed to solve
 > anyway. The modified `get-buffer-window-list' from your patch may also
 > be used in the above scenario before deciding which buffer we want to
 > change to.
 >
 > So, I'd myself vote for the first version of the patch if looking from
 > more general Emacs perspective.

I attach a version which does both.  With (reuse-indirect . buffer) it
leaves the window's buffer alone.  With any other value it puts BUFFER
into the window.  Run it for a while and when you think it's useful I'll
install it.

martin

[-- Attachment #2: display-indirect-buffer.diff --]
[-- Type: text/x-patch, Size: 6554 bytes --]

diff --git a/lisp/window.el b/lisp/window.el
index e9d57652ec6..5178e302238 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -2615,7 +2615,36 @@ get-largest-window
 	  (setq best-window window))))
     best-window))
 
-(defun get-buffer-window-list (&optional buffer-or-name minibuf all-frames)
+(defun window-indirect-buffer-p (&optional window buffer-or-name)
+  "Return non-nil if specified WINDOW is indirectly related to BUFFER-OR-NAME.
+WINDOW must be a live window and defaults to the selected window.
+BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
+defaults to the current buffer.
+
+WINODW is indirectly related to BUFFER-OR-NAME if one of the following
+conditions hold:
+
+- BUFFER-OR-NAME specifies an indirect buffer and WINDOW's buffer is its
+  base buffer.
+
+- WINDOW's buffer is an indirect buffer whose base buffer is the buffer
+  specified by BUFFER-OR-NAME.
+
+- Both, WINDOW's buffer and the buffer specified by BUFFER-OR-NAME, are
+  indirect buffer's sharing the same base buffer.
+
+Return nil if none of the above holds."
+  (let* ((window (window-normalize-window window t))
+	 (window-buffer (window-buffer window))
+	 (window-base-buffer (buffer-base-buffer window-buffer))
+	 (buffer (window-normalize-buffer buffer-or-name))
+	 (buffer-base-buffer (buffer-base-buffer buffer)))
+    (or (eq buffer-base-buffer window-buffer)
+	(eq window-base-buffer buffer)
+	(and buffer-base-buffer
+	     (eq buffer-base-buffer window-base-buffer)))))
+
+(defun get-buffer-window-list (&optional buffer-or-name minibuf all-frames indirect)
   "Return list of all windows displaying BUFFER-OR-NAME, or nil if none.
 BUFFER-OR-NAME may be a buffer or the name of an existing buffer
 and defaults to the current buffer.  If the selected window displays
@@ -2644,12 +2673,23 @@ get-buffer-window-list
 - A frame means consider all windows on that frame only.
 
 Anything else means consider all windows on the selected frame
-and no others."
+and no others.
+
+INDIRECT non-nil means to append to the list of windows showing
+BUFFER-OR-NAME a list of all windows that are indirectly related to
+BUFFER-OR-NAME, that is, windows for which `window-indirect-buffer-p'
+with the window and the buffer specified by BUFFER-OR-NAME as arguments
+returns non-nil."
   (let ((buffer (window-normalize-buffer buffer-or-name))
+	(window-list (window-list-1 (selected-window) minibuf all-frames))
 	windows)
-    (dolist (window (window-list-1 (selected-window) minibuf all-frames))
+    (dolist (window window-list)
       (when (eq (window-buffer window) buffer)
 	(setq windows (cons window windows))))
+    (when indirect
+      (dolist (window window-list)
+	(when (window-indirect-buffer-p window buffer)
+	  (setq windows (cons window windows)))))
     (nreverse windows)))
 
 (defun minibuffer-window-active-p (window)
@@ -8235,35 +8275,57 @@ display-buffer-reuse-window
 event that a window on another frame is chosen, avoid raising
 that frame.
 
+If ALIST has a non-nil `reuse-indirect' entry and no window showing
+BUFFER has been found, try to find a window that is indirectly related
+to BUFFER and return that window.  This would be a window for which
+`window-indirect-buffer-p' with the window and BUFFER as arguments
+returns non-nil.  If a suitable window has been found and the cdr of the
+entry equals the symbol `buffer', do not replace the buffer of the
+chosen window with BUFFER but return the window with its old buffer in
+place.  Otherwise, put BUFFER into the chosen window and return the
+window.
+
 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* ((alist-entry (assq 'reusable-frames alist))
-	 (frames (cond (alist-entry (cdr alist-entry))
+  (let* ((reusable-frames (assq 'reusable-frames alist))
+	 (reuse-indirect (assq 'reuse-indirect alist))
+	 (frames (cond (reusable-frames (cdr reusable-frames))
 		       ((window--pop-up-frames alist)
 			0)
 		       (display-buffer-reuse-frames 0)
 		       (t (last-nonminibuffer-frame))))
-	 (window (if (and (eq buffer (window-buffer))
-			  (not (cdr (assq 'inhibit-same-window alist))))
-		     (selected-window)
-                   ;; Preferably use a window on the selected frame,
-                   ;; if such a window exists (Bug#36680).
-                   (let* ((windows (delq (selected-window)
-                                         (get-buffer-window-list
-                                          buffer 'nomini frames)))
-                          (first (car windows))
-                          (this-frame (selected-frame)))
-                     (cond
-                      ((eq (window-frame first) this-frame)
-                       first)
-                      ((catch 'found
-                         (dolist (next (cdr windows))
-                           (when (eq (window-frame next) this-frame)
-                             (throw 'found next)))))
-                      (t first))))))
+	 (inhibit-same (cdr (assq 'inhibit-same-window alist)))
+	 (window
+	  ;; Avoid calling 'get-buffer-window-list' if the selected
+	  ;; window already shows BUFFER and can be used.
+	  (if (and (eq buffer (window-buffer)) (not inhibit-same))
+	      (selected-window)
+            ;; Preferably use a window on the selected frame,
+            ;; if such a window exists (Bug#36680).
+            (let* ((windows-raw
+		    (get-buffer-window-list
+                     buffer 'nomini frames reuse-indirect))
+		   (windows (if inhibit-same
+				(delq (selected-window) windows-raw)
+			      windows-raw))
+                   (first (car windows))
+                   (this-frame (selected-frame)))
+              (cond
+               ((eq (window-frame first) this-frame)
+                first)
+               ((catch 'found
+                  (dolist (next (cdr windows))
+                    (when (eq (window-frame next) this-frame)
+                      (throw 'found next)))))
+               (t first))))))
     (when (window-live-p window)
+      (when (and (eq (cdr reuse-indirect) 'buffer)
+		 (not (eq (window-buffer window) buffer)))
+	;; Pretend we were asking for a window showing the buffer of
+	;; that window.
+	(setq buffer (window-buffer window)))
       (prog1 (window--display-buffer buffer window 'reuse alist)
 	(unless (cdr (assq 'inhibit-switch-frame alist))
 	  (window--maybe-raise-frame (window-frame window)))))))

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

* Re: May we have a variant of display-buffer-reuse-window that considers indirect buffers?
  2024-12-20  9:02                   ` martin rudalics
@ 2024-12-21 12:34                     ` Ihor Radchenko
  0 siblings, 0 replies; 12+ messages in thread
From: Ihor Radchenko @ 2024-12-21 12:34 UTC (permalink / raw)
  To: martin rudalics
  Cc: Juri Linkov, Sébastien Gendre, Org Mode List, emacs-devel

martin rudalics <rudalics@gmx.at> writes:

> I attach a version which does both.  With (reuse-indirect . buffer) it
> leaves the window's buffer alone.  With any other value it puts BUFFER
> into the window.  Run it for a while and when you think it's useful I'll
> install it.

Sebastien, would you be interested to test this? I can add a
complementary patch for Org that will work in tandem with this patch for
Emacs.

-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>



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

end of thread, other threads:[~2024-12-21 12:34 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <878qtycdmi.fsf@k-7.ch>
2024-12-15 15:28 ` May we have a variant of display-buffer-reuse-window that considers indirect buffers? (was: Indirect follow mode in agenda: Display, edition and how to hide drawers) Ihor Radchenko
2024-12-16  7:49   ` May we have a variant of display-buffer-reuse-window that considers indirect buffers? Juri Linkov
2024-12-16  9:23     ` martin rudalics
2024-12-16 18:07     ` Ihor Radchenko
2024-12-17  9:01       ` martin rudalics
2024-12-17 18:11         ` Ihor Radchenko
2024-12-18  9:08           ` martin rudalics
2024-12-18 18:18             ` Ihor Radchenko
2024-12-18 19:13               ` martin rudalics
2024-12-19 17:47                 ` Ihor Radchenko
2024-12-20  9:02                   ` martin rudalics
2024-12-21 12:34                     ` Ihor Radchenko

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