Commit 78dd6ab1 authored by Martin Rudalics's avatar Martin Rudalics
Browse files

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.
parent 7e510e28
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
......
......@@ -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,18 +3378,35 @@ all window-local buffer lists."
;; Unrecord BUFFER in WINDOW.
(unrecord-window-buffer window buffer)))))
(defun quit-window (&optional kill window)
"Quit WINDOW and bury its 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.
With prefix argument KILL non-nil, kill the buffer instead of
burying it.
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."
(interactive "P")
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))
......@@ -3374,13 +3418,13 @@ one. If non-nil, reset `quit-restore' parameter to nil."
(not (eq (setq prev-buffer (cadr prev-buffers))
buffer))))
prev-buffer)))
quad resize)
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 kill))
(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))))
......@@ -3388,21 +3432,32 @@ one. If non-nil, reset `quit-restore' parameter to nil."
(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
(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))
;; Unrecord WINDOW's buffer here (Bug#9937) to make sure it's not
;; re-recorded by `set-window-buffer'.
(unrecord-window-buffer window buffer)
;; 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.
......@@ -3414,12 +3469,29 @@ one. If non-nil, reset `quit-restore' parameter to nil."
(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)))
(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)))))
;; Kill WINDOW's old-buffer if requested
(if kill
(kill-buffer buffer)
(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.
With prefix argument KILL non-nil, kill the buffer instead of
burying it.
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."
(interactive "P")
(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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment