From 93680af5c77811f6e58adda92ba7f0143c278be5 Mon Sep 17 00:00:00 2001 From: StrawberryTea Date: Sun, 6 Aug 2023 16:12:05 -0400 Subject: [PATCH 1/6] fix: make leader key descriptions in the keymap This commit moves leader key descriptions from `which-key-replacement-alist` to the keymap itself. This helps with performance because that way, which-key does not have to calculate every single leader key description for each keypress. Furthermore, this fixes issues like #1413 where relocating leader keymaps resulted in which-key not showing the correct leader key descriptions. I also made the leader prefix maps have their own prefix commands by populating the function slot of the keymap variables. This is an Emacs convention. I made `doom-leader-map` follow this convention as well. --- lisp/doom-keybinds.el | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/lisp/doom-keybinds.el b/lisp/doom-keybinds.el index 29788e9a9..0125a18b7 100644 --- a/lisp/doom-keybinds.el +++ b/lisp/doom-keybinds.el @@ -145,11 +145,8 @@ all hooks after it are ignored.") forms)) (when-let (desc (cadr (memq :which-key udef))) (prependq! - wkforms `((which-key-add-key-based-replacements - (general--concat t doom-leader-alt-key ,key) - ,desc) - (which-key-add-key-based-replacements - (general--concat t doom-leader-key ,key) + wkforms `((which-key-add-keymap-based-replacements doom-leader-map + ,key ,desc)))))))) (macroexp-progn (append (and wkforms `((after! which-key ,@(nreverse wkforms)))) @@ -195,7 +192,7 @@ localleader prefix." ;; :prefix/:non-normal-prefix properties because general is incredibly slow ;; binding keys en mass with them in conjunction with :states -- an effective ;; doubling of Doom's startup time! -(define-prefix-command 'doom/leader 'doom-leader-map) +(define-prefix-command 'doom-leader-map) (define-key doom-leader-map [override-state] 'all) ;; Bind `doom-leader-key' and `doom-leader-alt-key' as late as possible to give @@ -210,9 +207,9 @@ localleader prefix." (set-keymap-parent doom-leader-map mode-specific-map)) ((equal doom-leader-alt-key "C-x") (set-keymap-parent doom-leader-map ctl-x-map))) - (define-key map (kbd doom-leader-alt-key) 'doom/leader)) - (evil-define-key* '(normal visual motion) map (kbd doom-leader-key) 'doom/leader) - (evil-define-key* '(emacs insert) map (kbd doom-leader-alt-key) 'doom/leader)) + (define-key map (kbd doom-leader-alt-key) #'doom-leader-map)) + (evil-define-key* '(normal visual motion) map (kbd doom-leader-key) #'doom-leader-map) + (evil-define-key* '(emacs insert) map (kbd doom-leader-alt-key) #'doom-leader-map)) (general-override-mode +1)))) @@ -317,6 +314,8 @@ For example, :nvi will map to (list 'normal 'visual 'insert). See :prefix prefix) rest)) (push `(defvar ,keymap (make-sparse-keymap)) + doom--map-forms) + (push `(define-prefix-command ',keymap) doom--map-forms)))) (:prefix (cl-destructuring-bind (prefix . desc) From afaf2936e1a1500c49f5e7e5c6451b7e494e7638 Mon Sep 17 00:00:00 2001 From: StrawberryTea Date: Sun, 13 Aug 2023 00:14:58 -0400 Subject: [PATCH 2/6] fix: make localleader map relocatable With this commit, now you can define any key to `doom-locallleader-map` symbol and it will work as expected. The `which-key` descriptions will work as expected too. The only caveat is that the localleader map is now updated using hooks so there the potential for bugs where the incorrect map is selected. --- lisp/doom-keybinds.el | 72 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/lisp/doom-keybinds.el b/lisp/doom-keybinds.el index 0125a18b7..4443556b3 100644 --- a/lisp/doom-keybinds.el +++ b/lisp/doom-keybinds.el @@ -25,6 +25,14 @@ and Emacs states, and for non-evil users.") (defvar doom-leader-map (make-sparse-keymap) "An overriding keymap for keys.") +(defvar doom-localleader-map-alist nil + "An alist mapping major modes to their localleader keymaps.") + +(defvar doom-localleader-map (make-sparse-keymap) + "The current major mode's localleader keymap.") + +(defvar doom-localleader-current-major-mode nil + "The major mode of the current localleader keymap.") ;; ;;; Global keybind settings @@ -165,6 +173,43 @@ See `doom-leader-key' and `doom-leader-alt-key' to change the leader prefix." :keymaps 'doom-leader-map ,@args)) +(defmacro doom--define-localleader-leader-key (&rest keys) + (let ((modes (cl-mapcar #'general--remove-map + (doom-unquote (progn (pop keys) (pop keys))))) + prefix forms wkforms result) + (macroexp-progn (dolist (mode modes result) + (unless (keymapp (alist-get mode doom-localleader-map-alist)) + (setf (alist-get mode doom-localleader-map-alist) + (make-sparse-keymap))) + (let ((keys keys)) + (while keys + (let ((key (pop keys)) + (def (pop keys))) + (if (keywordp key) + (when (memq key '(:prefix :infix)) + (setq prefix def)) + (when prefix + (setq key `(general--concat t ,prefix ,key))) + (let* ((udef (cdr-safe (doom-unquote def))) + (bdef (if (general--extended-def-p udef) + (general--extract-def (general--normalize-extended-def udef)) + def))) + (unless (eq bdef :ignore) + (push `(define-key + (alist-get ',mode doom-localleader-map-alist) + (general--kbd ,key) + ,bdef) + forms)) + (when-let (desc (cadr (memq :which-key udef))) + (prependq! + wkforms `((which-key-add-keymap-based-replacements + (alist-get ',mode doom-localleader-map-alist) + ,key + ,desc)))))))) + (prependq! result + (append (and wkforms `((after! which-key ,@(nreverse wkforms)))) + (nreverse forms)))))))) + (defmacro define-localleader-key! (&rest args) "Define key. @@ -192,8 +237,23 @@ localleader prefix." ;; :prefix/:non-normal-prefix properties because general is incredibly slow ;; binding keys en mass with them in conjunction with :states -- an effective ;; doubling of Doom's startup time! -(define-prefix-command 'doom-leader-map) (define-key doom-leader-map [override-state] 'all) +(define-prefix-command 'doom-leader-map) +(define-prefix-command 'doom-localleader-map) + +(add-hook! '(after-change-major-mode-hook + doom-switch-buffer-hook + doom-switch-window-hook + doom-switch-frame-hook) + (defun doom-init-localleader-key-h () + "Set the localleader keys for the current major-mode." + (unless (or (derived-mode-p 'special-mode) + (derived-mode-p 'minibuffer-inactive-mode) + (derived-mode-p 'minibuffer-mode) + (derived-mode-p 'compilation-mode)) + (setq doom-localleader-current-major-mode major-mode) + (set-keymap-parent doom-localleader-map + (cdr (assq major-mode doom-localleader-map-alist)))))) ;; Bind `doom-leader-key' and `doom-leader-alt-key' as late as possible to give ;; the user a chance to modify them. @@ -207,9 +267,12 @@ localleader prefix." (set-keymap-parent doom-leader-map mode-specific-map)) ((equal doom-leader-alt-key "C-x") (set-keymap-parent doom-leader-map ctl-x-map))) - (define-key map (kbd doom-leader-alt-key) #'doom-leader-map)) + (define-key map (kbd doom-leader-alt-key) #'doom-leader-map) + (define-key map (kbd doom-localleader-alt-key) #'doom-localleader-map)) (evil-define-key* '(normal visual motion) map (kbd doom-leader-key) #'doom-leader-map) - (evil-define-key* '(emacs insert) map (kbd doom-leader-alt-key) #'doom-leader-map)) + (evil-define-key* '(emacs insert) map (kbd doom-leader-alt-key) #'doom-leader-map) + (evil-define-key* '(normal visual motion) map (kbd doom-localleader-key) #'doom-localleader-map) + (evil-define-key* '(emacs insert) map (kbd doom-localleader-alt-key) #'doom-localleader-map)) (general-override-mode +1)))) @@ -280,7 +343,6 @@ For example, :nvi will map to (list 'normal 'visual 'insert). See (let ((key (pop rest))) (cond ((listp key) (doom--map-nested nil key)) - ((keywordp key) (pcase key (:leader @@ -288,7 +350,7 @@ For example, :nvi will map to (list 'normal 'visual 'insert). See (setq doom--map-fn 'doom--define-leader-key)) (:localleader (doom--map-commit) - (setq doom--map-fn 'define-localleader-key!)) + (setq doom--map-fn 'doom--define-localleader-leader-key)) (:after (doom--map-nested (list 'after! (pop rest)) rest) (setq rest nil)) From f0bf0d670b7574aa9ba77aec60935e81b58c82e4 Mon Sep 17 00:00:00 2001 From: LemonBreezes Date: Wed, 30 Aug 2023 21:06:22 -0500 Subject: [PATCH 3/6] fix: exclude fundamental-mode from localleader maps --- lisp/doom-keybinds.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lisp/doom-keybinds.el b/lisp/doom-keybinds.el index 4443556b3..ed2ff0430 100644 --- a/lisp/doom-keybinds.el +++ b/lisp/doom-keybinds.el @@ -250,7 +250,8 @@ localleader prefix." (unless (or (derived-mode-p 'special-mode) (derived-mode-p 'minibuffer-inactive-mode) (derived-mode-p 'minibuffer-mode) - (derived-mode-p 'compilation-mode)) + (derived-mode-p 'compilation-mode) + (eq major-mode 'fundamental-mode)) (setq doom-localleader-current-major-mode major-mode) (set-keymap-parent doom-localleader-map (cdr (assq major-mode doom-localleader-map-alist)))))) From 8429b60d992c97d571edc890496447e3347df750 Mon Sep 17 00:00:00 2001 From: LemonBreezes Date: Wed, 30 Aug 2023 21:42:40 -0500 Subject: [PATCH 4/6] fix: use doom-unreal-buffer-p for doom-init-localleader-key-h --- lisp/doom-keybinds.el | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lisp/doom-keybinds.el b/lisp/doom-keybinds.el index ed2ff0430..82f32e9cb 100644 --- a/lisp/doom-keybinds.el +++ b/lisp/doom-keybinds.el @@ -247,11 +247,8 @@ localleader prefix." doom-switch-frame-hook) (defun doom-init-localleader-key-h () "Set the localleader keys for the current major-mode." - (unless (or (derived-mode-p 'special-mode) - (derived-mode-p 'minibuffer-inactive-mode) - (derived-mode-p 'minibuffer-mode) - (derived-mode-p 'compilation-mode) - (eq major-mode 'fundamental-mode)) + (unless (and (doom-unreal-buffer-p (current-buffer)) + (not (derived-mode-p 'text-mode 'prog-mode 'conf-mode))) (setq doom-localleader-current-major-mode major-mode) (set-keymap-parent doom-localleader-map (cdr (assq major-mode doom-localleader-map-alist)))))) From 6624c396820c34164ba7388ba954f521757f5fc5 Mon Sep 17 00:00:00 2001 From: StrawberryTea Date: Wed, 18 Oct 2023 15:31:53 -0500 Subject: [PATCH 5/6] fix: set doom/leader for backwards compatibility --- lisp/doom-keybinds.el | 1 + 1 file changed, 1 insertion(+) diff --git a/lisp/doom-keybinds.el b/lisp/doom-keybinds.el index 82f32e9cb..0ab7b5c5e 100644 --- a/lisp/doom-keybinds.el +++ b/lisp/doom-keybinds.el @@ -240,6 +240,7 @@ localleader prefix." (define-key doom-leader-map [override-state] 'all) (define-prefix-command 'doom-leader-map) (define-prefix-command 'doom-localleader-map) +(fset 'doom/leader doom-leader-map) ; For backwards compatibility. (add-hook! '(after-change-major-mode-hook doom-switch-buffer-hook From 167911ba7b88eb271d44c11037156bd6a928c144 Mon Sep 17 00:00:00 2001 From: StrawberryTea Date: Wed, 18 Oct 2023 15:32:10 -0500 Subject: [PATCH 6/6] fix: use a post-command-hook for updating localleader --- lisp/doom-keybinds.el | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/lisp/doom-keybinds.el b/lisp/doom-keybinds.el index 0ab7b5c5e..3f4532515 100644 --- a/lisp/doom-keybinds.el +++ b/lisp/doom-keybinds.el @@ -31,9 +31,6 @@ and Emacs states, and for non-evil users.") (defvar doom-localleader-map (make-sparse-keymap) "The current major mode's localleader keymap.") -(defvar doom-localleader-current-major-mode nil - "The major mode of the current localleader keymap.") - ;; ;;; Global keybind settings @@ -242,17 +239,12 @@ localleader prefix." (define-prefix-command 'doom-localleader-map) (fset 'doom/leader doom-leader-map) ; For backwards compatibility. -(add-hook! '(after-change-major-mode-hook - doom-switch-buffer-hook - doom-switch-window-hook - doom-switch-frame-hook) - (defun doom-init-localleader-key-h () - "Set the localleader keys for the current major-mode." - (unless (and (doom-unreal-buffer-p (current-buffer)) - (not (derived-mode-p 'text-mode 'prog-mode 'conf-mode))) - (setq doom-localleader-current-major-mode major-mode) - (set-keymap-parent doom-localleader-map - (cdr (assq major-mode doom-localleader-map-alist)))))) +(defun doom-update-localleader-key-h () + "Set the localleader keys for the current major-mode." + (set-keymap-parent doom-localleader-map + (cdr (assq major-mode doom-localleader-map-alist)))) + +(add-hook 'post-command-hook #'doom-update-localleader-key-h) ;; Bind `doom-leader-key' and `doom-leader-alt-key' as late as possible to give ;; the user a chance to modify them.