about summary refs log tree commit diff
path: root/users/tazjin/emacs/config/desktop.el
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-02-07T18·27+0300
committertazjin <tazjin@tvl.su>2022-02-07T19·08+0000
commite00dd88b666b686add1f9bc2d09c2b18b70d88cc (patch)
treea341518a68adb2526c8059b7038861e3458c1512 /users/tazjin/emacs/config/desktop.el
parent50d959175da3d7e6ae0b3e8a0ba1ff2cdd976ca1 (diff)
feat(tazjin/emacs): implement MRU navigation for exwm workspaces r/3779
this makes it possible to move forwards/backwards in workspace history
in the order in which I used them, while tracking the offset (e.g. it
is possible to go 3 steps back, do something, then move 2 steps
forward again).

this should make it possible to learn ad-hoc relative layouts for
whatever task i'm working on and reduce the number of times where i
frantically flip through all workspaces and try to figure out where
anything is.

note that this key binding is not very ergonomic, but i've remapped it
on my kinesis to the prior/next buttons. i never use those. using
<prior>/<next> directly doesn't work because too many modes override
them.

Change-Id: I257723b9e14a68b53be68539dd752db3445546e7
Reviewed-on: https://cl.tvl.fyi/c/depot/+/5243
Tested-by: BuildkiteCI
Reviewed-by: tazjin <tazjin@tvl.su>
Diffstat (limited to 'users/tazjin/emacs/config/desktop.el')
-rw-r--r--users/tazjin/emacs/config/desktop.el62
1 files changed, 62 insertions, 0 deletions
diff --git a/users/tazjin/emacs/config/desktop.el b/users/tazjin/emacs/config/desktop.el
index c160ae131f..f9ed77f63b 100644
--- a/users/tazjin/emacs/config/desktop.el
+++ b/users/tazjin/emacs/config/desktop.el
@@ -140,6 +140,68 @@
                          (interactive)
                          (exwm-workspace-switch-create ,i))))
 
+;; Implement MRU functionality for EXWM workspaces, making it possible
+;; to jump to the previous/next workspace very easily.
+(defvar *recent-workspaces* nil
+  "List of the most recently used EXWM workspaces.")
+
+(defvar *workspace-jumping-to* nil
+  "What offset in the workspace history are we jumping to?")
+
+(defvar *workspace-history-position* 0
+  "Where in the workspace history are we right now?")
+
+(defun update-recent-workspaces ()
+  "Hook to run on every workspace switch which will prepend the new
+workspace to the MRU list, unless we are already on that
+workspace. Does not affect the MRU list if a jump is
+in-progress."
+
+  (if *workspace-jumping-to*
+      (setq *workspace-history-position* *workspace-jumping-to*
+            *workspace-jumping-to* nil)
+
+    ;; reset the history position to the front on a normal jump
+    (setq *workspace-history-position* 0)
+
+    (unless (eq exwm-workspace-current-index (car *recent-workspaces*))
+      (setq *recent-workspaces* (cons exwm-workspace-current-index
+                                      (-take 9 *recent-workspaces*))))))
+
+(add-to-list 'exwm-workspace-switch-hook #'update-recent-workspaces)
+
+(defun switch-to-previous-workspace ()
+  "Switch to the previous workspace in the MRU workspace list."
+  (interactive)
+
+  (let* (;; the previous workspace is one position further down in the
+         ;; workspace history
+         (position (+ *workspace-history-position* 1))
+         (target-idx (elt *recent-workspaces* position)))
+    (if (not target-idx)
+        (message "No previous workspace in history!")
+
+      (setq *workspace-jumping-to* position)
+      (exwm-workspace-switch target-idx))))
+
+(exwm-input-set-key (kbd "s-b") #'switch-to-previous-workspace)
+
+(defun switch-to-next-workspace ()
+  "Switch to the next workspace in the MRU workspace list."
+  (interactive)
+
+  (if (<= *workspace-history-position* 1)
+      (message "No next workspace in history!")
+    (let* (;; The next workspace is one position further up in the
+           ;; history. This always exists unless someone messed with
+           ;; it.
+           (position (- *workspace-history-position* 1))
+           (target-idx (elt *recent-workspaces* position)))
+      (setq *workspace-jumping-to* position)
+      (exwm-workspace-switch target-idx))))
+
+(exwm-input-set-key (kbd "s-f") #'switch-to-next-workspace)
+
 ;; Launch applications / any command with completion (dmenu style!)
 (exwm-input-set-key (kbd "s-d") #'counsel-linux-app)
 (exwm-input-set-key (kbd "s-x") #'run-external-command)