summaryrefslogtreecommitdiff
path: root/.emacs.d/site-lisp
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2022-01-28 23:14:14 -0700
committerSean Whitton <spwhitton@spwhitton.name>2022-01-29 16:58:47 -0700
commita863a322b8b5eb1dd18948fde8be5f7e2ca4f13b (patch)
tree6d2ced5df86c97a1a06f537a9018abdeed8372a4 /.emacs.d/site-lisp
parent851fa42498456f46ffd0efbf88ec6d236802458f (diff)
downloaddotfiles-a863a322b8b5eb1dd18948fde8be5f7e2ca4f13b.tar.gz
attempt to extract transient-cycles-window-buffers-mode
Diffstat (limited to '.emacs.d/site-lisp')
-rw-r--r--.emacs.d/site-lisp/transient-cycles.el70
1 files changed, 69 insertions, 1 deletions
diff --git a/.emacs.d/site-lisp/transient-cycles.el b/.emacs.d/site-lisp/transient-cycles.el
index 08789259..f03df062 100644
--- a/.emacs.d/site-lisp/transient-cycles.el
+++ b/.emacs.d/site-lisp/transient-cycles.el
@@ -404,7 +404,75 @@ keys are \\`<left>' and \\`<right>'. Otherwise the fallbacks
`transient-cycles-default-cycle-backwards-key' and
`transient-cycles-default-cycle-forwards-key' are used."
:lighter nil :keymap transient-cycles-window-buffers-mode-map :global t
- :group 'transient-cycles)
+ :group 'transient-cycles
+ (if transient-cycles-window-buffers-mode
+ ;; Clear window parameter just when the list of next buffers is cleared.
+ (advice-add 'set-window-buffer :after
+ #'transient-cycles--reset-window-recent-buffer)
+ (advice-remove 'set-window-buffer
+ #'transient-cycles--reset-window-recent-buffer)))
+
+(cl-symbol-macrolet
+ ((param (window-parameter nil 'transient-cycles--window-recent-bufer)))
+ (transient-cycles-define-commands (recent-buffer last-recent-buffer)
+ (([remap previous-buffer] (count)
+ (interactive "p")
+ (setq recent-buffer (and (window-next-buffers) count)
+ last-recent-buffer param)
+ (previous-buffer count))
+
+ ([remap next-buffer] (count)
+ (interactive "p")
+ ;; We consider only the window's next buffers, not the frame's next
+ ;; buffers as `next-buffer' does. This is because otherwise our
+ ;; `recent-buffer' and window parameter become invalid.
+ ;;
+ ;; `previous-buffer' and `next-buffer' use `switch-to-prev-buffer' and
+ ;; `switch-to-next-buffer' as subroutines, so buffers previously shown
+ ;; in the selected window come up first
+ (if (window-next-buffers)
+ (progn (setq recent-buffer (* -1 count)
+ last-recent-buffer param)
+ (next-buffer count))
+ (user-error "No next buffer"))))
+
+ (lambda (_ignore)
+ (lambda (count)
+ (if (cl-plusp count)
+ (if (window-next-buffers)
+ (progn (when recent-buffer (cl-decf recent-buffer count))
+ (next-buffer count))
+ (message "No next buffer"))
+ (setq count (* -1 count))
+ (when recent-buffer (cl-incf recent-buffer count))
+ (previous-buffer count))))
+ ;; If `recent-buffer' is zero then we are back where we started.
+ ;; in. In that case, restore the old parameter value so that
+ ;; `transient-cycles-window-buffers-back-and-forth' does something useful.
+ :on-exit (setq param (if (and recent-buffer (zerop recent-buffer))
+ last-recent-buffer
+ recent-buffer))
+ :keymap transient-cycles-window-buffers-mode-map)
+
+ (defun transient-cycles--reset-window-recent-buffer (&rest _ignore)
+ (setq param nil))
+
+ (defun transient-cycles-window-buffers-back-and-forth ()
+ "Switch to the buffer most recently accessed using the bindings
+established by `transient-cycles-window-buffers-mode', on the
+condition that no other commands have set this window's buffer
+since then. Otherwise, call `previous-buffer'."
+ (interactive)
+ (cond (param
+ (let ((new (and (window-next-buffers) (* -1 param))))
+ (cond ((cl-plusp param) (next-buffer param))
+ ((cl-minusp param) (previous-buffer (* -1 param))))
+ (setq param new)))
+ ((window-next-buffers)
+ (let ((count (length (window-next-buffers))))
+ (next-buffer count)
+ (setq param (* -1 count))))
+ (t (previous-buffer)))))
(provide 'transient-cycles)