From ea3d9e295779f29a354a6be8aeedfe8c901d0317 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 5 Apr 2019 01:24:16 -0400 Subject: [PATCH] Refactor & optimize define-leader-key! - Provides a 10-30% boost in startup time - which-key advice is no longer needed --- core/core-keybinds.el | 97 ++++++++++++++----------------------------- 1 file changed, 31 insertions(+), 66 deletions(-) diff --git a/core/core-keybinds.el b/core/core-keybinds.el index b8130b202..a676a1bac 100644 --- a/core/core-keybinds.el +++ b/core/core-keybinds.el @@ -80,14 +80,35 @@ If any hook returns non-nil, all hooks after it are ignored.") (defalias 'define-key! #'general-def) (defalias 'unmap! #'general-unbind) -;; We avoid `general-create-definer' to ensure that :states, :wk-full-keys and -;; :keymaps cannot be overwritten. -(defmacro define-leader-key! (&rest args) - `(general-define-key - :states nil - :wk-full-keys nil - :keymaps 'doom-leader-map - ,@args)) +;; A `define-leader-key' defined with `general-create-definer' consumes 20-30% +;; of Doom's startup time, we reimplement it ourselves. +(defmacro define-leader-key! (&rest keys) + "Define a leader key on `doom-leader-key'." + (let (prefix forms wkforms) + (while keys + (let ((key (pop keys)) + (def (pop keys))) + (if (keywordp key) + (when (memq key '(:prefix :infix)) + (setq prefix def)) + (let ((unquoted-def (cdr-safe (doom-unquote def)))) + (when prefix + (setq key `(general--concat t ,prefix ,key))) + (when-let* ((desc (plist-get unquoted-def :which-key))) + (push `(which-key-add-key-based-replacements + (general--concat t doom-leader-key ,key) + ,desc) + wkforms)) + (push `(define-key doom-leader-map (general--kbd ,key) + ,(if (general--extended-def-p unquoted-def) + (plist-get unquoted-def :def) + def)) + forms))))) + (macroexp-progn + (append (nreverse forms) + (when wkforms + `((eval-after-load 'which-key + (lambda () ,@(nreverse wkforms))))))))) (general-create-definer define-localleader-key! :major-modes t @@ -124,68 +145,12 @@ If any hook returns non-nil, all hooks after it are ignored.") (concat "\\(?:" (cl-loop for key in (append (list doom-leader-key doom-leader-alt-key) (where-is-internal 'doom/leader)) - if (stringp key) collect (regexp-quote key) into keys - else collect (regexp-quote (key-description key)) into keys + for keystr = (if (stringp key) key (key-description key)) + collect (regexp-quote keystr) into keys finally return (string-join keys "\\|")) "\\)")))) (add-hook 'doom-after-init-modules-hook #'doom|init-leader-keys) -;; However, the prefix command approach (along with :wk-full-keys in -;; `define-leader-key!') means that which-key is only informed of the key -;; sequence minus `doom-leader-key'/`doom-leader-alt-key'. e.g. binding to `SPC -;; f s' creates a wildcard label for any key that ends in 'f s'. -;; -;; So we forcibly inject `doom-leader-key' and `doom-leader-alt-key' into the -;; which-key key replacement regexp for keybinds created on `doom-leader-map'. -;; This is a dirty hack, but I'd rather this than general being responsible for -;; 50% of Doom's startup time. -(defun doom*general-extended-def-:which-key (_state keymap key edef kargs) - (with-eval-after-load 'which-key - (let* ((wk (general--getf2 edef :which-key :wk)) - (major-modes (general--getf edef kargs :major-modes)) - (keymaps (plist-get kargs :keymaps)) - ;; index of keymap in :keymaps - (keymap-index (cl-dotimes (ind (length keymaps)) - (when (eq (nth ind keymaps) keymap) - (cl-return ind)))) - (mode (let ((mode (if (and major-modes (listp major-modes)) - (nth keymap-index major-modes) - major-modes))) - (if (eq mode t) - (general--remove-map keymap) - mode))) - (key (key-description key)) - (key-regexp (concat (if (general--getf edef kargs :wk-full-keys) - "\\`" - ;; Modification begin - (if (memq 'doom-leader-map keymaps) - (concat "\\`" doom-which-key-leader-prefix-regexp " "))) - ;; Modification end - (regexp-quote key) - "\\'")) - (prefix (plist-get kargs :prefix)) - (binding (or (when (and (plist-get edef :def) - (not (plist-get edef :keymp))) - (plist-get edef :def)) - (when (and prefix (string= key prefix)) - (plist-get kargs :prefix-command)))) - (replacement (cond ((stringp wk) - (cons nil wk)) - (wk))) - (match/replacement - (cons - (cons (when (general--getf edef kargs :wk-match-keys) - key-regexp) - (when (and (general--getf edef kargs :wk-match-binding) - binding - (symbolp binding)) - (symbol-name binding))) - replacement))) - (general--add-which-key-replacement mode match/replacement) - (when (and (consp replacement) (not (functionp replacement))) - (general--add-which-key-title-prefix mode key (cdr replacement)))))) -(advice-add #'general-extended-def-:which-key :override #'doom*general-extended-def-:which-key) - ;; ;;; Packages