emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: martin rudalics <rudalics@gmx.at>
To: Ihor Radchenko <yantar92@posteo.net>
Cc: "Juri Linkov" <juri@linkov.net>, "Sébastien Gendre" <seb@k-7.ch>,
	"Org Mode List" <emacs-orgmode@gnu.org>,
	emacs-devel@gnu.org
Subject: Re: May we have a variant of display-buffer-reuse-window that considers indirect buffers?
Date: Fri, 20 Dec 2024 10:02:28 +0100	[thread overview]
Message-ID: <eb7f9c58-583c-41aa-9940-4d3d7ed67ad0@gmx.at> (raw)
In-Reply-To: <87cyhn7efy.fsf@localhost>

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

  reply	other threads:[~2024-12-20  9:03 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-05  8:02 Indirect follow mode in agenda: Display, edition and how to hide drawers Sébastien Gendre
2024-11-05  9:22 ` Kristoffer Balintona
2024-11-05 21:15   ` Karthik Chikmagalur
2024-11-08 15:05     ` Sébastien Gendre
2024-11-08 14:59   ` Sébastien Gendre
2024-11-10 23:34 ` Sébastien Gendre
2024-11-11  0:09   ` Sébastien Gendre
2024-11-11 17:59     ` Ihor Radchenko
2024-11-12  0:30       ` Sébastien Gendre
2024-11-12 19:17         ` Ihor Radchenko
2024-11-18 23:22           ` Sébastien Gendre
2024-12-15 15:09             ` Ihor Radchenko
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 [this message]
2024-12-21 12:34                     ` Ihor Radchenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=eb7f9c58-583c-41aa-9940-4d3d7ed67ad0@gmx.at \
    --to=rudalics@gmx.at \
    --cc=emacs-devel@gnu.org \
    --cc=emacs-orgmode@gnu.org \
    --cc=juri@linkov.net \
    --cc=seb@k-7.ch \
    --cc=yantar92@posteo.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.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).