From e00dd88b666b686add1f9bc2d09c2b18b70d88cc Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Mon, 7 Feb 2022 21:27:50 +0300 Subject: feat(tazjin/emacs): implement MRU navigation for exwm workspaces 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 / 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 --- users/tazjin/emacs/config/desktop.el | 62 ++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) 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) -- cgit 1.4.1