feat: add cycling for all buffers

This commit is contained in:
Pavel Korytov 2023-02-18 16:46:47 +03:00
parent 7d5f0922a3
commit 7b0a70b449

View file

@ -36,6 +36,8 @@
;; Other useful functions are:
;; - `perspective-exwm-cycle-exwm-buffers-backward' and
;; `perspective-exwm-cycle-exwm-buffers-backward'
;; - `perspective-exwm-cycle-all-buffers-backward' and
;; `perspective-exwm-cycle-all-buffers-forward'
;; - `perspective-exwm-switch-perspective'
;; - `perspective-exwm-copy-to-workspace' and
;; `perspective-exwm-move-to-workspace'
@ -62,8 +64,8 @@
"A function to return the current EXWM window title."
exwm-title)
(defcustom perspective-exwm-get-exwm-buffer-name #'perspective-exwm--get-class
"A function to get the EXWM buffer title.
(defcustom perspective-exwm-get-buffer-name #'perspective-exwm--get-class
"Retrieve buffer name for the cycle commands.
Meant to be ran in the context of the target buffer, e.g. with
`with-current-buffer'.
@ -75,6 +77,12 @@ The two default options are:
:type 'function
:options '(perspective-exwm--get-class perspective-exwm--get-title))
(defcustom perspective-exwm-cycle-max-message-length
(- (frame-width) 10)
"Maximum length of the message displayed by the cycle commands."
:group 'perspective-exwm
:type 'integer)
(defcustom perspective-exwm-override-initial-name nil
"Set initial perspective name for a particular EXWM workspace."
:group 'perspective-exwm
@ -105,13 +113,84 @@ Used in `perspective-exwm-switch-perspective'."
Used in `perspective-exwm-switch-perspective'."
:group 'perspective-exwm)
(defun perspective-exwm--cycle-exwm-buffers (dir)
"Cycle EXWM buffers in the current perspective.
(defun perspective-exwm--cycle-get-message (all-buffers cycle-buffers)
"Return the display message for the buffer cycling commands.
ALL-BUFFERS is the list of all buffers in the current perspective.
CYCLE-BUFFERS are the buffers to cycle through."
;; Iterate over all buffers
(cl-loop with seen-current = nil
for buf in all-buffers
for name = (with-current-buffer buf
(or (funcall perspective-exwm-get-buffer-name)
(buffer-name)))
for is-current = (eq (current-buffer) buf)
for is-skip = (not (member buf cycle-buffers))
if is-current do (setq seen-current t)
if is-current
collect (concat "[" (propertize name 'face 'perspective-exwm-cycle-current-face) "] ") into current-list
else if is-skip
collect (concat "[" (propertize name 'face 'perspective-exwm-cycle-skip-face) "] ") into skip-list
else if seen-current
collect (format " %s " name) into after-list
else
collect (format " %s " name) into before-list
;; 4 list:
;; - current-list - current buffers
;; - skip-list - buffers displayed in other windows
;; - before-list - buffers before current
;; - after-list - buffers after current
;; We want to display them in the following order:
;; skip-list before-list current-list after-list
;; And trim before-list and after-list to fit the message
;; length; that means trimming the end of before-list and
;; the beginning of after-list.
finally return
(let* ((skip-msg (mapconcat #'identity skip-list ""))
(current-msg (mapconcat #'identity current-list ""))
(len (+ (length skip-msg) (length current-msg) 8))
(before-stack (reverse before-list))
(after-stack after-list))
;; Length of nil is 0 :'(
(cl-loop for before-elem-len = (if before-stack (length (car before-stack)) 10000)
for after-elem-len = (if after-stack (length (car after-stack)) 10000)
while (and (or before-stack after-stack)
(< (+ len (min before-elem-len after-elem-len)) perspective-exwm-cycle-max-message-length))
for before = (when (and before-stack
(< (+ len before-elem-len) perspective-exwm-cycle-max-message-length))
(pop before-stack))
if before collect before into before-msg-list
if before do (setq len (+ len before-elem-len))
for after = (when (and after-stack
(< (+ len after-elem-len) perspective-exwm-cycle-max-message-length))
(pop after-stack))
if after concat after into after-msg
if after do (setq len (+ len after-elem-len))
finally return
(concat
skip-msg
(when before-stack
(format " (%s) "
(propertize (number-to-string (length before-stack))
'face 'perspective-exwm-cycle-skip-face)))
(mapconcat #'identity (reverse before-msg-list) "")
current-msg
after-msg
(when after-stack
(format " (%s) "
(propertize (number-to-string (length after-stack))
'face 'perspective-exwm-cycle-skip-face))))))))
(defun perspective-exwm--cycle-exwm-buffers (dir &optional all)
"Cycle buffers in the current perspective.
DIR is either 'forward or 'backward. A buffer is skipped if it is
already displayed in some other window of the current
perspective. The buffer name comes from
`perspective-exwm-get-exwm-buffer-name'.
`perspective-exwm-get-buffer-name'.
If ALL is nil, then cycle only EXWM buffers. Otherwise, cycle
all.
The function prints out the state to the messages. The current
buffer after the switch is highlighted with `warning', skipped
@ -122,7 +201,7 @@ buffer is highlighted with `persp-selected-face'"
(cl-loop for buf in (persp-current-buffers)
for is-another = (and (get-buffer-window buf) (not (eq current buf)))
if (and (buffer-live-p buf)
(eq 'exwm-mode (buffer-local-value 'major-mode buf))
(or all (eq 'exwm-mode (buffer-local-value 'major-mode buf)))
(not (string-match-p ignore-rx (buffer-name buf))))
collect buf into all-buffers
and if (not is-another) collect buf into cycle-buffers
@ -137,19 +216,8 @@ buffer is highlighted with `persp-selected-face'"
(length cycle-buffers)))
(next-buffer (nth next-pos cycle-buffers)))
(switch-to-buffer next-buffer)
(message
"%s"
(cl-loop for buf in all-buffers
for name = (with-current-buffer buf (funcall perspective-exwm-get-exwm-buffer-name))
for is-current = (eq (current-buffer) buf)
for is-skip = (not (member buf cycle-buffers))
if is-current
concat (concat "[" (propertize name 'face 'perspective-exwm-cycle-current-face) "] ") into res
else if is-skip
concat (concat "[" (propertize name 'face 'perspective-exwm-cycle-skip-face) "] ") into res
else
concat (format " %s " name) into res
finally return res))))))
(let ((msg (perspective-exwm--cycle-get-message all-buffers cycle-buffers)))
(message msg))))))
;;;###autoload
(defun perspective-exwm-cycle-exwm-buffers-forward ()
@ -169,6 +237,18 @@ detail."
(interactive)
(perspective-exwm--cycle-exwm-buffers 'backward))
;;;###autoload
(defun perspective-exwm-cycle-all-buffers-forward ()
"Cycle all buffers in the current perspective forward."
(interactive)
(perspective-exwm--cycle-exwm-buffers 'forward t))
;;;###autoload
(defun perspective-exwm-cycle-all-buffers-backward ()
"Cycle all buffers in the current perspective backward."
(interactive)
(perspective-exwm--cycle-exwm-buffers 'backward t))
;;;###autoload
(defun perspective-exwm-switch-perspective ()
"Switch to a perspective on any workspace."