[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#32825: 27.0.50; Deterministic window management
From: |
martin rudalics |
Subject: |
bug#32825: 27.0.50; Deterministic window management |
Date: |
Tue, 13 Nov 2018 10:12:23 +0100 |
>> Maybe better to represent a list of prev/next buffers as a tree?
>> Then inserting a new buffer inside it will create a leaf that
>> can be ignored for navigation. An analogy of this is undo-tree.
>
> More precisely, navigating in the tree trunk and ignoring branches.
Note that 'display-buffer-in-previous-window' doesn't care about the
order in which a buffer appears in a window's previous buffers list.
It only wants to know whether it's there and traversing a tree for
that purpose looks like overkill.
OTOH we would still have to decide what to do with a window's buffer
when displaying another buffer in that window via 'display-buffer':
Make it the first buffer we would want to switch to in the next
'switch-to-prev-buffer' call or make it insignificant (a leaf in your
parlance).
I currently tend to favor a solution like the below (we could also use
the 'buffer-predicate' frame parameter for that purpose but that would
affect 'other-buffer' as well, something I'd like to avoid).
The solution below should behave as follows: Assume TAGS is shown in
the selected window. Then doing 'switch-to-prev-buffer' followed by
'switch-to-next-buffer' there should get me back to TAGS. Doing
‘display-buffer’ there followed by 'switch-to-prev-buffer' should get
me to the buffer shown there before TAGS.
Then I could set the default of 'debugger-bury-or-kill' to 'append'
and *Backtrace* would not show up accidentally via
'switch-to-prev-buffer' but still remain on the list of previous
buffers so 'display-buffer-in-previous-window' will find it. WDYT?
martin
(defcustom switch-to-prev-buffer-skip-regexp
"\\*Backtrace\\*\\|TAGS"
"Regexp matching names of buffer `switch-to-prev-buffer' should skip.
The default matches the *Backtrace* and the TAGS buffers."
:type '(repeat (regexp :format "%v"))
:group 'windows)
(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."
(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))
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)))
(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 (setq new-buffer (car entry))
(or (buffer-live-p new-buffer)
(not (setq killed-buffers
(cons new-buffer killed-buffers))))
(not (eq new-buffer old-buffer))
(not (string-match-p
switch-to-prev-buffer-skip-regexp
(buffer-name new-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 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))))
;; 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))
(not (string-match-p
switch-to-prev-buffer-skip-regexp
(buffer-name new-buffer)))
(or (null pred) (funcall pred buffer))
(not (eq (aref (buffer-name buffer) 0) ?\s))
;; Don't show a buffer shown in a side window before.
(not (buffer-local-value 'window--sides-shown buffer))
(or bury-or-kill (not (memq 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.
(unless visible
(setq visible 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))
(not (string-match-p
switch-to-prev-buffer-skip-regexp
(buffer-name new-buffer)))
(or (null pred) (funcall pred buffer))
(setq entry (assq buffer (window-prev-buffers window))))
(setq new-buffer buffer)
(set-window-buffer-start-and-point
window new-buffer (nth 1 entry) (nth 2 entry))
(throw 'found t))))
;; Show a buffer visible in another window.
(when visible
(setq new-buffer visible)
(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))
- bug#32825: 27.0.50; Deterministic window management, (continued)
- bug#32825: 27.0.50; Deterministic window management, Juri Linkov, 2018/11/08
- bug#32825: 27.0.50; Deterministic window management, martin rudalics, 2018/11/09
- bug#32825: 27.0.50; Deterministic window management, Michael Heerdegen, 2018/11/09
- bug#32825: 27.0.50; Deterministic window management, martin rudalics, 2018/11/09
- bug#32825: 27.0.50; Deterministic window management, Juri Linkov, 2018/11/10
- bug#32825: 27.0.50; Deterministic window management, martin rudalics, 2018/11/11
- bug#32825: 27.0.50; Deterministic window management, Juri Linkov, 2018/11/11
- bug#32825: 27.0.50; Deterministic window management, martin rudalics, 2018/11/12
- bug#32825: 27.0.50; Deterministic window management, Juri Linkov, 2018/11/12
- bug#32825: 27.0.50; Deterministic window management, Juri Linkov, 2018/11/12
- bug#32825: 27.0.50; Deterministic window management,
martin rudalics <=
- bug#32825: 27.0.50; Deterministic window management, Juri Linkov, 2018/11/13
- bug#32825: 27.0.50; Deterministic window management, martin rudalics, 2018/11/14
- bug#32825: 27.0.50; Deterministic window management, Juri Linkov, 2018/11/14
- bug#32825: 27.0.50; Deterministic window management, martin rudalics, 2018/11/15
- bug#32825: 27.0.50; Deterministic window management, Juri Linkov, 2018/11/15
- bug#32825: 27.0.50; Deterministic window management, martin rudalics, 2018/11/16
- bug#32825: 27.0.50; Deterministic window management, martin rudalics, 2018/11/16
- bug#32825: 27.0.50; Deterministic window management, Juri Linkov, 2018/11/17
- bug#32825: 27.0.50; Deterministic window management, martin rudalics, 2018/11/18
- bug#32825: 27.0.50; Deterministic window management, Juri Linkov, 2018/11/18