about summary refs log tree commit diff
diff options
context:
space:
mode:
-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 c160ae131f8a..f9ed77f63b6b 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)