Optionally have 'display-buffer' reuse windows of indirect buffers
* lisp/window.el (window-indirect-buffer-p): New function. (get-buffer-window-list): New argument INDIRECT. (display-buffer-reuse-window): New alist entry 'reuse-indirect' to reuse a window indirectly related to the BUFFER argument. * doc/lispref/windows.texi (Buffers and Windows): Describe new function 'window-indirect-buffer-p' and new argument INDIRECT of 'get-buffer-window-list'. (Buffer Display Action Functions): Describe new action alist entry 'reuse-indirect'. * etc/NEWS: Announce new argument for 'get-buffer-window-list' and new 'display-buffer' action alist entry 'reuse-indirect'.
This commit is contained in:
parent
be60601ae8
commit
a205d55452
3 changed files with 144 additions and 24 deletions
|
@ -2697,7 +2697,37 @@ Ordering}). This function may be changed in a future version of Emacs
|
|||
to eliminate this discrepancy.
|
||||
@end defun
|
||||
|
||||
@defun get-buffer-window-list &optional buffer-or-name minibuf all-frames
|
||||
The following function can tell for a specific window whether its buffer
|
||||
shares the text of some other buffer (@pxref{Indirect Buffers}).
|
||||
|
||||
@defun window-indirect-buffer-p &optional window buffer-or-name
|
||||
This function returns non-@code{nil} if @var{window} is indirectly
|
||||
related to @var{buffer-or-name}. @var{window} must be a live window and
|
||||
defaults to the selected window. @var{buffer-or-name} may be a buffer
|
||||
or the name of an existing buffer and defaults to the current buffer.
|
||||
|
||||
@var{window} is indirectly related to @var{buffer-or-name} if one of the
|
||||
following conditions hold:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
@var{buffer-or-name} specifies an indirect buffer and @var{window}'s
|
||||
buffer is its base buffer.
|
||||
|
||||
@item
|
||||
@var{window}'s buffer is an indirect buffer whose base buffer is the
|
||||
buffer specified by @var{buffer-or-name}.
|
||||
|
||||
@item
|
||||
Both, @var{window}'s buffer and the buffer specified by
|
||||
@var{buffer-or-name}, are indirect buffer's sharing the same base
|
||||
buffer.
|
||||
@end itemize
|
||||
|
||||
It returns @code{nil} if none of the above holds.
|
||||
@end defun
|
||||
|
||||
@defun get-buffer-window-list &optional buffer-or-name minibuf all-frames indirect
|
||||
This function returns a list of all windows currently displaying
|
||||
@var{buffer-or-name}. @var{buffer-or-name} should be a buffer or the
|
||||
name of an existing buffer. If omitted or @code{nil}, it defaults to
|
||||
|
@ -2709,6 +2739,13 @@ The arguments @var{minibuf} and @var{all-frames} have the same
|
|||
meanings as in the function @code{next-window} (@pxref{Cyclic Window
|
||||
Ordering}). Note that the @var{all-frames} argument does @emph{not}
|
||||
behave exactly like in @code{get-buffer-window}.
|
||||
|
||||
The optional argument @var{indirect} non-@code{nil} means to append to
|
||||
the list of windows showing @var{buffer-or-name} a list of all windows
|
||||
that are indirectly related to @var{buffer-or-name}, that is, windows
|
||||
for which @code{window-indirect-buffer-p} (see above) with the window
|
||||
and the buffer specified by @var{buffer-or-name} as arguments returns
|
||||
non-@code{nil}.
|
||||
@end defun
|
||||
|
||||
@deffn Command replace-buffer-in-windows &optional buffer-or-name
|
||||
|
@ -3165,6 +3202,17 @@ searches just the selected frame.
|
|||
If this function chooses a window on another frame, it makes that
|
||||
frame visible and, unless @var{alist} contains an
|
||||
@code{inhibit-switch-frame} entry, raises that frame if necessary.
|
||||
|
||||
If @var{alist} has a non-@code{nil} @code{reuse-indirect} entry and no
|
||||
window showing @var{buffer} has been found, this function tries to find
|
||||
a window that is indirectly related to @var{buffer}---a window for which
|
||||
@code{window-indirect-buffer-p} (@pxref{Buffers and Windows}) with the
|
||||
window and @var{buffer} as arguments returns non-@code{nil}. If such a
|
||||
window has been found and the @sc{cdr} of the @code{reuse-indirect}
|
||||
entry equals the symbol @code{buffer}, it does not replace the buffer of
|
||||
that window with @var{buffer} but returns the window with its old buffer
|
||||
in place. Otherwise, it puts @var{buffer} into that window and returns
|
||||
that window.
|
||||
@end defun
|
||||
|
||||
@defun display-buffer-reuse-mode-window buffer alist
|
||||
|
|
11
etc/NEWS
11
etc/NEWS
|
@ -247,6 +247,17 @@ landscape shape for instance, Emacs could split horizontally before
|
|||
splitting vertically. The default setting preserves Emacs historical
|
||||
behavior to try to split vertically first.
|
||||
|
||||
+++
|
||||
*** New argument INDIRECT for 'get-buffer-window-list'.
|
||||
With this argument non-nil, 'get-buffer-window-list' will include in the
|
||||
return value windows whose buffers share their text with BUFFER-OR-NAME.
|
||||
|
||||
+++
|
||||
*** New 'display-buffer' action alist entry 'reuse-indirect'.
|
||||
With such an entry, 'display-buffer-reuse-window' may also choose a
|
||||
window whose buffer shares text with the buffer to display.
|
||||
|
||||
|
||||
** Frames
|
||||
|
||||
+++
|
||||
|
|
107
lisp/window.el
107
lisp/window.el
|
@ -2616,7 +2616,36 @@ selected frame and no others."
|
|||
(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
|
||||
|
@ -2645,12 +2674,23 @@ non-nil values of ALL-FRAMES have special meanings:
|
|||
- 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)
|
||||
|
@ -8348,35 +8388,56 @@ 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 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 that
|
||||
window with BUFFER but return the window with its old buffer in place.
|
||||
Otherwise, put BUFFER into that 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)))))))
|
||||
|
|
Loading…
Add table
Reference in a new issue