Rewrite switch-to-prev-/next-buffer and quit-window; add display-buffer-below-selected.
* window.el (switch-to-prev-buffer): Handle additional values of BURY-OR-KILL argument. Don't switch in minibuffer window. (switch-to-next-buffer): Don't switch in minibuffer window. (quit-restore-window): New function based on quit-window. Handle additional values of former KILL argument. (quit-window): Call quit-restore-window with appropriate interpretation of KILL argument. (display-buffer-below-selected): New buffer display action function.
This commit is contained in:
parent
7e510e2844
commit
78dd6ab198
2 changed files with 183 additions and 85 deletions
|
@ -1,3 +1,15 @@
|
|||
2012-09-01 Martin Rudalics <rudalics@gmx.at>
|
||||
|
||||
* window.el (switch-to-prev-buffer): Handle additional values of
|
||||
BURY-OR-KILL argument. Don't switch in minibuffer window.
|
||||
(switch-to-next-buffer): Don't switch in minibuffer window.
|
||||
(quit-restore-window): New function based on quit-window.
|
||||
Handle additional values of former KILL argument.
|
||||
(quit-window): Call quit-restore-window with appropriate
|
||||
interpretation of KILL argument.
|
||||
(display-buffer-below-selected): New buffer display action
|
||||
function.
|
||||
|
||||
2012-09-01 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* minibuffer.el (completion-at-point-functions): Complete docstring
|
||||
|
|
256
lisp/window.el
256
lisp/window.el
|
@ -2972,7 +2972,12 @@ found.
|
|||
|
||||
Optional argument BURY-OR-KILL non-nil means the buffer currently
|
||||
shown in WINDOW is about to be buried or killed and consequently
|
||||
shall not be switched to in future invocations of this command."
|
||||
shall not be switched to in future invocations of this command.
|
||||
|
||||
As a special case, if BURY-OR-KILL equals `append', this means to
|
||||
move the buffer to the end of WINDOW's previous buffers list so a
|
||||
future invocation of `switch-to-prev-buffer' less likely switches
|
||||
to it."
|
||||
(interactive)
|
||||
(let* ((window (window-normalize-window window t))
|
||||
(frame (window-frame window))
|
||||
|
@ -2980,26 +2985,34 @@ shall not be switched to in future invocations of this command."
|
|||
;; Save this since it's destroyed by `set-window-buffer'.
|
||||
(next-buffers (window-next-buffers window))
|
||||
(pred (frame-parameter frame 'buffer-predicate))
|
||||
entry buffer new-buffer killed-buffers visible)
|
||||
entry new-buffer killed-buffers visible)
|
||||
(when (window-minibuffer-p window)
|
||||
;; Don't switch in minibuffer window.
|
||||
(unless (setq window (minibuffer-selected-window))
|
||||
(error "Window %s is a minibuffer window" window)))
|
||||
|
||||
(when (window-dedicated-p window)
|
||||
;; Don't switch in dedicated window.
|
||||
(error "Window %s is dedicated to buffer %s" window old-buffer))
|
||||
|
||||
(catch 'found
|
||||
;; Scan WINDOW's previous buffers first, skipping entries of next
|
||||
;; buffers.
|
||||
(dolist (entry (window-prev-buffers window))
|
||||
(when (and (setq buffer (car entry))
|
||||
(or (buffer-live-p buffer)
|
||||
(when (and (setq new-buffer (car entry))
|
||||
(or (buffer-live-p new-buffer)
|
||||
(not (setq killed-buffers
|
||||
(cons buffer killed-buffers))))
|
||||
(or (null pred) (funcall pred buffer))
|
||||
(not (eq buffer old-buffer))
|
||||
(or bury-or-kill (not (memq buffer next-buffers))))
|
||||
(cons new-buffer killed-buffers))))
|
||||
(not (eq new-buffer old-buffer))
|
||||
(or (null pred) (funcall pred new-buffer))
|
||||
;; When BURY-OR-KILL is nil, avoid switching to a
|
||||
;; buffer in WINDOW's next buffers list.
|
||||
(or bury-or-kill (not (memq new-buffer next-buffers))))
|
||||
(if (and (not switch-to-visible-buffer)
|
||||
(get-buffer-window buffer frame))
|
||||
;; Try to avoid showing a buffer visible in some other window.
|
||||
(setq visible buffer)
|
||||
(setq new-buffer buffer)
|
||||
(get-buffer-window new-buffer frame))
|
||||
;; Try to avoid showing a buffer visible in some other
|
||||
;; window.
|
||||
(setq visible new-buffer)
|
||||
(set-window-buffer-start-and-point
|
||||
window new-buffer (nth 1 entry) (nth 2 entry))
|
||||
(throw 'found t))))
|
||||
|
@ -3014,8 +3027,8 @@ shall not be switched to in future invocations of this command."
|
|||
(nreverse (buffer-list frame))))
|
||||
(when (and (buffer-live-p buffer)
|
||||
(not (eq buffer old-buffer))
|
||||
(not (eq (aref (buffer-name buffer) 0) ?\s))
|
||||
(or (null pred) (funcall pred buffer))
|
||||
(not (eq (aref (buffer-name buffer) 0) ?\s))
|
||||
(or bury-or-kill (not (memq buffer next-buffers))))
|
||||
(if (get-buffer-window buffer frame)
|
||||
;; Try to avoid showing a buffer visible in some other window.
|
||||
|
@ -3047,12 +3060,20 @@ shall not be switched to in future invocations of this command."
|
|||
(set-window-buffer-start-and-point window new-buffer)))
|
||||
|
||||
(if bury-or-kill
|
||||
;; Remove `old-buffer' from WINDOW's previous and (restored list
|
||||
;; of) next buffers.
|
||||
(progn
|
||||
(let ((entry (and (eq bury-or-kill 'append)
|
||||
(assq old-buffer (window-prev-buffers window)))))
|
||||
;; Remove `old-buffer' from WINDOW's previous and (restored list
|
||||
;; of) next buffers.
|
||||
(set-window-prev-buffers
|
||||
window (assq-delete-all old-buffer (window-prev-buffers window)))
|
||||
(set-window-next-buffers window (delq old-buffer next-buffers)))
|
||||
(set-window-next-buffers window (delq old-buffer next-buffers))
|
||||
(when entry
|
||||
;; Append old-buffer's entry to list of WINDOW's previous
|
||||
;; buffers so it's less likely to get switched to soon but
|
||||
;; `display-buffer-in-previous-window' can nevertheless find
|
||||
;; it.
|
||||
(set-window-prev-buffers
|
||||
window (append (window-prev-buffers window) (list entry)))))
|
||||
;; Move `old-buffer' to head of WINDOW's restored list of next
|
||||
;; buffers.
|
||||
(set-window-next-buffers
|
||||
|
@ -3080,8 +3101,14 @@ found."
|
|||
(old-buffer (window-buffer window))
|
||||
(next-buffers (window-next-buffers window))
|
||||
(pred (frame-parameter frame 'buffer-predicate))
|
||||
buffer new-buffer entry killed-buffers visible)
|
||||
new-buffer entry killed-buffers visible)
|
||||
(when (window-minibuffer-p window)
|
||||
;; Don't switch in minibuffer window.
|
||||
(unless (setq window (minibuffer-selected-window))
|
||||
(error "Window %s is a minibuffer window" window)))
|
||||
|
||||
(when (window-dedicated-p window)
|
||||
;; Don't switch in dedicated window.
|
||||
(error "Window %s is dedicated to buffer %s" window old-buffer))
|
||||
|
||||
(catch 'found
|
||||
|
@ -3100,9 +3127,10 @@ found."
|
|||
;; Scan the buffer list of WINDOW's frame next, skipping previous
|
||||
;; buffers entries.
|
||||
(dolist (buffer (buffer-list frame))
|
||||
(when (and (buffer-live-p buffer) (not (eq buffer old-buffer))
|
||||
(not (eq (aref (buffer-name buffer) 0) ?\s))
|
||||
(when (and (buffer-live-p buffer)
|
||||
(not (eq buffer old-buffer))
|
||||
(or (null pred) (funcall pred buffer))
|
||||
(not (eq (aref (buffer-name buffer) 0) ?\s))
|
||||
(not (assq buffer (window-prev-buffers window))))
|
||||
(if (get-buffer-window buffer frame)
|
||||
;; Try to avoid showing a buffer visible in some other window.
|
||||
|
@ -3113,18 +3141,17 @@ found."
|
|||
;; Scan WINDOW's reverted previous buffers last (must not use
|
||||
;; nreverse here!)
|
||||
(dolist (entry (reverse (window-prev-buffers window)))
|
||||
(when (and (setq buffer (car entry))
|
||||
(or (buffer-live-p buffer)
|
||||
(when (and (setq new-buffer (car entry))
|
||||
(or (buffer-live-p new-buffer)
|
||||
(not (setq killed-buffers
|
||||
(cons buffer killed-buffers))))
|
||||
(or (null pred) (funcall pred buffer))
|
||||
(not (eq buffer old-buffer)))
|
||||
(cons new-buffer killed-buffers))))
|
||||
(not (eq new-buffer old-buffer))
|
||||
(or (null pred) (funcall pred new-buffer)))
|
||||
(if (and (not switch-to-visible-buffer)
|
||||
(get-buffer-window buffer frame))
|
||||
(get-buffer-window new-buffer frame))
|
||||
;; Try to avoid showing a buffer visible in some other window.
|
||||
(unless visible
|
||||
(setq visible buffer))
|
||||
(setq new-buffer buffer)
|
||||
(setq visible new-buffer))
|
||||
(set-window-buffer-start-and-point
|
||||
window new-buffer (nth 1 entry) (nth 2 entry))
|
||||
(throw 'found t))))
|
||||
|
@ -3351,6 +3378,107 @@ all window-local buffer lists."
|
|||
;; Unrecord BUFFER in WINDOW.
|
||||
(unrecord-window-buffer window buffer)))))
|
||||
|
||||
(defun quit-restore-window (&optional window bury-or-kill)
|
||||
"Quit WINDOW and deal with its buffer.
|
||||
WINDOW must be a live window and defaults to the selected one.
|
||||
|
||||
According to information stored in WINDOW's `quit-restore' window
|
||||
parameter either (1) delete WINDOW and its frame, (2) delete
|
||||
WINDOW, (3) restore the buffer previously displayed in WINDOW,
|
||||
or (4) make WINDOW display some other buffer than the present
|
||||
one. If non-nil, reset `quit-restore' parameter to nil.
|
||||
|
||||
Optional second argument BURY-OR-KILL tells how to proceed with
|
||||
the buffer of WINDOW. The following values are handled:
|
||||
|
||||
`nil' means to not handle the buffer in a particular way. This
|
||||
means that if WINDOW is not deleted by this function, invoking
|
||||
`switch-to-prev-buffer' will usually show the buffer again.
|
||||
|
||||
`append' means that if WINDOW is not deleted, move its buffer to
|
||||
the end of WINDOW's previous buffers so it's less likely that a
|
||||
future invocation of `switch-to-prev-buffer' will switch to it.
|
||||
Also, move the buffer to the end of the frame's buffer list.
|
||||
|
||||
`bury' means that if WINDOW is not deleted, remove its buffer
|
||||
from WINDOW'S list of previous buffers. Also, move the buffer
|
||||
to the end of the frame's buffer list. This value provides the
|
||||
most reliable remedy to not have `switch-to-prev-buffer' switch
|
||||
to this buffer again without killing the buffer.
|
||||
|
||||
`kill' means to kill WINDOW's buffer."
|
||||
(setq window (window-normalize-window window t))
|
||||
(let* ((buffer (window-buffer window))
|
||||
(quit-restore (window-parameter window 'quit-restore))
|
||||
(prev-buffer
|
||||
(let* ((prev-buffers (window-prev-buffers window))
|
||||
(prev-buffer (caar prev-buffers)))
|
||||
(and (or (not (eq prev-buffer buffer))
|
||||
(and (cdr prev-buffers)
|
||||
(not (eq (setq prev-buffer (cadr prev-buffers))
|
||||
buffer))))
|
||||
prev-buffer)))
|
||||
quad entry)
|
||||
(cond
|
||||
((and (not prev-buffer)
|
||||
(memq (nth 1 quit-restore) '(window frame))
|
||||
(eq (nth 3 quit-restore) buffer)
|
||||
;; Delete WINDOW if possible.
|
||||
(window--delete window nil (eq bury-or-kill 'kill)))
|
||||
;; If the previously selected window is still alive, select it.
|
||||
(when (window-live-p (nth 2 quit-restore))
|
||||
(select-window (nth 2 quit-restore))))
|
||||
((and (listp (setq quad (nth 1 quit-restore)))
|
||||
(buffer-live-p (car quad))
|
||||
(eq (nth 3 quit-restore) buffer))
|
||||
;; Show another buffer stored in quit-restore parameter.
|
||||
(when (and (integerp (nth 3 quad))
|
||||
(/= (nth 3 quad) (window-total-size window)))
|
||||
;; Try to resize WINDOW to its old height but don't signal an
|
||||
;; error.
|
||||
(condition-case nil
|
||||
(window-resize window (- (nth 3 quad) (window-total-size window)))
|
||||
(error nil)))
|
||||
(set-window-dedicated-p window nil)
|
||||
;; Restore WINDOW's previous buffer, start and point position.
|
||||
(set-window-buffer-start-and-point
|
||||
window (nth 0 quad) (nth 1 quad) (nth 2 quad))
|
||||
;; Deal with the buffer we just removed from WINDOW.
|
||||
(setq entry (and (eq bury-or-kill 'append)
|
||||
(assq buffer (window-prev-buffers window))))
|
||||
(when bury-or-kill
|
||||
;; Remove buffer from WINDOW's previous and next buffers.
|
||||
(set-window-prev-buffers
|
||||
window (assq-delete-all buffer (window-prev-buffers window)))
|
||||
(set-window-next-buffers
|
||||
window (delq buffer (window-next-buffers window))))
|
||||
(when entry
|
||||
;; Append old buffer's entry to list of WINDOW's previous
|
||||
;; buffers so it's less likely to get switched to soon but
|
||||
;; `display-buffer-in-previous-window' can nevertheless find it.
|
||||
(set-window-prev-buffers
|
||||
window (append (window-prev-buffers window) (list entry))))
|
||||
;; Reset the quit-restore parameter.
|
||||
(set-window-parameter window 'quit-restore nil)
|
||||
;; Select old window.
|
||||
(when (window-live-p (nth 2 quit-restore))
|
||||
(select-window (nth 2 quit-restore))))
|
||||
(t
|
||||
;; Show some other buffer in WINDOW and reset the quit-restore
|
||||
;; parameter.
|
||||
(set-window-parameter window 'quit-restore nil)
|
||||
;; Make sure that WINDOW is no more dedicated.
|
||||
(set-window-dedicated-p window nil)
|
||||
(switch-to-prev-buffer window bury-or-kill)))
|
||||
|
||||
;; Deal with the buffer.
|
||||
(cond
|
||||
((not (buffer-live-p buffer)))
|
||||
((eq bury-or-kill 'kill)
|
||||
(kill-buffer buffer))
|
||||
(bury-or-kill
|
||||
(bury-buffer-internal buffer)))))
|
||||
|
||||
(defun quit-window (&optional kill window)
|
||||
"Quit WINDOW and bury its buffer.
|
||||
WINDOW must be a live window and defaults to the selected one.
|
||||
|
@ -3363,63 +3491,7 @@ WINDOW, (3) restore the buffer previously displayed in WINDOW,
|
|||
or (4) make WINDOW display some other buffer than the present
|
||||
one. If non-nil, reset `quit-restore' parameter to nil."
|
||||
(interactive "P")
|
||||
(setq window (window-normalize-window window t))
|
||||
(let* ((buffer (window-buffer window))
|
||||
(quit-restore (window-parameter window 'quit-restore))
|
||||
(prev-buffer
|
||||
(let* ((prev-buffers (window-prev-buffers window))
|
||||
(prev-buffer (caar prev-buffers)))
|
||||
(and (or (not (eq prev-buffer buffer))
|
||||
(and (cdr prev-buffers)
|
||||
(not (eq (setq prev-buffer (cadr prev-buffers))
|
||||
buffer))))
|
||||
prev-buffer)))
|
||||
quad resize)
|
||||
(cond
|
||||
((and (not prev-buffer)
|
||||
(memq (nth 1 quit-restore) '(window frame))
|
||||
(eq (nth 3 quit-restore) buffer)
|
||||
;; Delete WINDOW if possible.
|
||||
(window--delete window nil kill))
|
||||
;; If the previously selected window is still alive, select it.
|
||||
(when (window-live-p (nth 2 quit-restore))
|
||||
(select-window (nth 2 quit-restore))))
|
||||
((and (listp (setq quad (nth 1 quit-restore)))
|
||||
(buffer-live-p (car quad))
|
||||
(eq (nth 3 quit-restore) buffer))
|
||||
;; Show another buffer stored in quit-restore parameter.
|
||||
(setq resize (and (integerp (nth 3 quad))
|
||||
(/= (nth 3 quad) (window-total-size window))))
|
||||
(set-window-dedicated-p window nil)
|
||||
(when resize
|
||||
;; Try to resize WINDOW to its old height but don't signal an
|
||||
;; error.
|
||||
(condition-case nil
|
||||
(window-resize window (- (nth 3 quad) (window-total-size window)))
|
||||
(error nil)))
|
||||
;; Restore WINDOW's previous buffer, start and point position.
|
||||
(set-window-buffer-start-and-point
|
||||
window (nth 0 quad) (nth 1 quad) (nth 2 quad))
|
||||
;; Unrecord WINDOW's buffer here (Bug#9937) to make sure it's not
|
||||
;; re-recorded by `set-window-buffer'.
|
||||
(unrecord-window-buffer window buffer)
|
||||
;; Reset the quit-restore parameter.
|
||||
(set-window-parameter window 'quit-restore nil)
|
||||
;; Select old window.
|
||||
(when (window-live-p (nth 2 quit-restore))
|
||||
(select-window (nth 2 quit-restore))))
|
||||
(t
|
||||
;; Show some other buffer in WINDOW and reset the quit-restore
|
||||
;; parameter.
|
||||
(set-window-parameter window 'quit-restore nil)
|
||||
;; Make sure that WINDOW is no more dedicated.
|
||||
(set-window-dedicated-p window nil)
|
||||
(switch-to-prev-buffer window 'bury-or-kill)))
|
||||
|
||||
;; Kill WINDOW's old-buffer if requested
|
||||
(if kill
|
||||
(kill-buffer buffer)
|
||||
(bury-buffer-internal buffer))))
|
||||
(quit-restore-window window (if kill 'kill 'bury)))
|
||||
|
||||
(defun quit-windows-on (&optional buffer-or-name kill frame)
|
||||
"Quit all windows showing BUFFER-OR-NAME.
|
||||
|
@ -5330,6 +5402,20 @@ again with `display-buffer-pop-up-window'."
|
|||
(and pop-up-windows
|
||||
(display-buffer-pop-up-window buffer alist))))
|
||||
|
||||
(defun display-buffer-below-selected (buffer _alist)
|
||||
"Try displaying BUFFER in a window below the selected window.
|
||||
This either splits the selected window or reuses the window below
|
||||
the selected one."
|
||||
(let (window)
|
||||
(or (and (not (frame-parameter nil 'unsplittable))
|
||||
(setq window (window--try-to-split-window (selected-window)))
|
||||
(window--display-buffer
|
||||
buffer window 'window display-buffer-mark-dedicated))
|
||||
(and (setq window (window-in-direction 'below))
|
||||
(not (window-dedicated-p window))
|
||||
(window--display-buffer
|
||||
buffer window 'reuse display-buffer-mark-dedicated)))))
|
||||
|
||||
(defun display-buffer-use-some-window (buffer alist)
|
||||
"Display BUFFER in an existing window.
|
||||
Search for a usable window, set that window to the buffer, and
|
||||
|
|
Loading…
Add table
Reference in a new issue