Function: switch-to-prev-buffer
switch-to-prev-buffer is an interactive and byte-compiled function
defined in window.el.gz.
Signature
(switch-to-prev-buffer &optional WINDOW BURY-OR-KILL)
Documentation
In WINDOW switch to previous buffer.
WINDOW must be a live window and defaults to the selected one. Return the buffer switched to, nil if no suitable buffer could be 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.
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.
The option switch-to-prev-buffer-skip can be used to not switch
to certain buffers, for example, to those already shown in
another window. Also, if WINDOW's frame has a buffer-predicate
parameter, that predicate may inhibit switching to certain
buffers.
This function is called by previous-buffer.
Probably introduced at or before Emacs version 24.1.
Key Bindings
Source Code
;; Defined in /usr/src/emacs/lisp/window.el.gz
(defun switch-to-prev-buffer (&optional window bury-or-kill)
"In WINDOW switch to previous buffer.
WINDOW must be a live window and defaults to the selected one.
Return the buffer switched to, nil if no suitable buffer could be
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.
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.
The option `switch-to-prev-buffer-skip' can be used to not switch
to certain buffers, for example, to those already shown in
another window. Also, if WINDOW's frame has a `buffer-predicate'
parameter, that predicate may inhibit switching to certain
buffers.
This function is called by `previous-buffer'."
(interactive)
(let* ((window (window-normalize-window window t))
(frame (window-frame window))
(window-side (window-parameter window 'window-side))
(old-buffer (window-buffer window))
;; Save this since it's destroyed by `set-window-buffer'.
(next-buffers (window-next-buffers window))
(pred (frame-parameter frame 'buffer-predicate))
(skip
(cond
((or (functionp switch-to-prev-buffer-skip)
(memq switch-to-prev-buffer-skip '(t visible 0)))
switch-to-prev-buffer-skip)
((or switch-to-prev-buffer-skip
(not switch-to-visible-buffer))
frame)))
entry new-buffer killed-buffers skipped)
(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)))
(unless (memq (window-dedicated-p window) '(nil side))
;; 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 (not (eq (car entry) old-buffer))
(setq new-buffer (car entry))
(or (buffer-live-p new-buffer)
(not (setq killed-buffers
(cons new-buffer killed-buffers))))
(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 (switch-to-prev-buffer-skip-p skip window new-buffer bury-or-kill)
(setq skipped new-buffer)
(set-window-buffer-start-and-point
window new-buffer (nth 1 entry) (nth 2 entry))
(throw 'found t))))
;; Scan reverted buffer list of WINDOW's frame next, skipping
;; entries of next buffers. Note that when we bury or kill a
;; buffer we don't reverse the global buffer list to avoid showing
;; a buried buffer instead. Otherwise, we must reverse the global
;; buffer list in order to make sure that switching to the
;; previous/next buffer traverse it in opposite directions. Skip
;; this step for side windows.
(unless window-side
(dolist (buffer (if bury-or-kill
(buffer-list frame)
(nreverse (buffer-list frame))))
(when (and (buffer-live-p buffer)
(not (eq buffer old-buffer))
(or (null pred) (funcall pred buffer))
;; Skip buffers whose names start with a space.
(not (eq (aref (buffer-name buffer) 0) ?\s))
;; Skip buffers shown in a side window before.
(not (buffer-local-value 'window--sides-shown buffer))
(or bury-or-kill (not (memq buffer next-buffers))))
(if (switch-to-prev-buffer-skip-p skip window buffer bury-or-kill)
(setq skipped (or skipped buffer))
(setq new-buffer buffer)
(set-window-buffer-start-and-point window new-buffer)
(throw 'found t)))))
(unless bury-or-kill
;; Scan reverted next buffers last (must not use nreverse
;; here!).
(dolist (buffer (reverse next-buffers))
;; Actually, buffer _must_ be live here since otherwise it
;; would have been caught in the scan of previous buffers.
(when (and (or (buffer-live-p buffer)
(not (setq killed-buffers
(cons buffer killed-buffers))))
(not (eq buffer old-buffer))
(or (null pred) (funcall pred buffer))
(setq entry (assq buffer (window-prev-buffers window))))
(if (switch-to-prev-buffer-skip-p skip window buffer bury-or-kill)
(setq skipped (or skipped buffer))
(setq new-buffer buffer)
(set-window-buffer-start-and-point
window new-buffer (nth 1 entry) (nth 2 entry))
(throw 'found t)))))
(when (and skipped (not (functionp switch-to-prev-buffer-skip)))
;; Show first skipped buffer, unless skip was a function.
(setq new-buffer skipped)
(set-window-buffer-start-and-point window new-buffer)))
(if bury-or-kill
(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))
(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
window (cons old-buffer (delq old-buffer next-buffers))))
;; Remove killed buffers from WINDOW's previous and next buffers.
(when killed-buffers
(dolist (buffer killed-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)))))
;; Return new-buffer.
new-buffer))