Refactor out map.el usage
After some profiling, it turns out map-put and map-delete are 5-7x slower (more on Emacs 25) than delq, setf/alist-get and add-to-list for small lists (under 250 items), which is exactly how I've been using them. The only caveat is alist-get's signature is different on Emacs 25, thus a polyfill is necessary in core-lib.
This commit is contained in:
parent
f602a1f607
commit
f6dc6ac74e
29 changed files with 177 additions and 146 deletions
|
@ -12,7 +12,7 @@
|
|||
;; Like persistent-soft, caches assume a 2-tier structure, where all caches are
|
||||
;; namespaced by location.
|
||||
|
||||
(defvar doom-cache-alists ()
|
||||
(defvar doom-cache-alists '(t)
|
||||
"An alist of alists, containing lists of variables for the doom cache library
|
||||
to persist across Emacs sessions.")
|
||||
|
||||
|
@ -24,7 +24,7 @@ name under `pcache-directory' (by default a subdirectory under
|
|||
(defun doom|save-persistent-cache ()
|
||||
"Hook to run when an Emacs session is killed. Saves all persisted variables
|
||||
listed in `doom-cache-alists' to files."
|
||||
(dolist (alist doom-cache-alists)
|
||||
(dolist (alist (butlast doom-cache-alists 1))
|
||||
(cl-loop with key = (car alist)
|
||||
for var in (cdr alist)
|
||||
if (symbol-value var)
|
||||
|
@ -54,8 +54,8 @@ Warning: this is incompatible with buffer-local variables."
|
|||
(dolist (var variables)
|
||||
(when (doom-cache-exists var location)
|
||||
(set var (doom-cache-get var location))))
|
||||
(map-put doom-cache-alists location
|
||||
(append variables (cdr (assq location doom-cache-alists)))))
|
||||
(setf (alist-get location doom-cache-alists)
|
||||
(append variables (cdr (assq location doom-cache-alists)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-cache-desist (location &optional variables)
|
||||
|
@ -63,10 +63,11 @@ Warning: this is incompatible with buffer-local variables."
|
|||
`doom-cache-alists', thus preventing them from being saved between sessions.
|
||||
Does not affect the actual variables themselves or their values."
|
||||
(if variables
|
||||
(map-put doom-cache-alists location
|
||||
(cl-set-difference (cdr (assq location doom-cache-alists))
|
||||
variables))
|
||||
(map-delete doom-cache-alists location)))
|
||||
(setf (alist-get location doom-cache-alists)
|
||||
(cl-set-difference (cdr (assq location doom-cache-alists))
|
||||
variables))
|
||||
(delq (assq location doom-cache-alists)
|
||||
doom-cache-alists)))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-cache-get (key &optional location)
|
||||
|
|
|
@ -345,7 +345,7 @@ example; the package name can be omitted)."
|
|||
(package-install name))
|
||||
(if (not (package-installed-p name))
|
||||
(doom--delete-package-files name)
|
||||
(map-put doom-packages name plist)
|
||||
(setf (alist-get name alist) plist)
|
||||
name)))
|
||||
|
||||
;;;###autoload
|
||||
|
@ -388,9 +388,10 @@ package.el as appropriate."
|
|||
(unless (package-installed-p name)
|
||||
(user-error "%s isn't installed" name))
|
||||
(let ((inhibit-message (not doom-debug-mode))
|
||||
(spec (assq name quelpa-cache))
|
||||
quelpa-p)
|
||||
(when (assq name quelpa-cache)
|
||||
(setq quelpa-cache (map-delete quelpa-cache name))
|
||||
(when spec
|
||||
(setq quelpa-cache (delq spec quelpa-cache))
|
||||
(quelpa-save-cache)
|
||||
(setq quelpa-p t))
|
||||
(package-delete (cadr (assq name package-alist)) force-p)
|
||||
|
@ -439,11 +440,11 @@ calls."
|
|||
"Update `quelpa-cache' upon a successful `package-delete'."
|
||||
(doom-initialize-packages)
|
||||
(let ((name (package-desc-name desc)))
|
||||
(when (and (not (package-installed-p name))
|
||||
(assq name quelpa-cache))
|
||||
(setq quelpa-cache (map-delete quelpa-cache name))
|
||||
(quelpa-save-cache)
|
||||
(doom--delete-package-files name))))
|
||||
(unless (package-installed-p name)
|
||||
(when-let* ((spec (assq name quelpa-cache)))
|
||||
(setq quelpa-cache (delq spec quelpa-cache))
|
||||
(quelpa-save-cache)
|
||||
(doom--delete-package-files name)))))
|
||||
|
||||
|
||||
;;
|
||||
|
|
|
@ -78,10 +78,10 @@ BODY will be run when this dispatcher is called."
|
|||
(append
|
||||
(when aliases
|
||||
`((dolist (alias ',aliases)
|
||||
(map-put doom--dispatch-alias-alist alias ',cmd))))
|
||||
`((map-put doom--dispatch-command-alist ',cmd
|
||||
(list :desc ,docstring
|
||||
:body (lambda (args) ,form))))))))
|
||||
(setf (alist-get alias doom--dispatch-alias-alist) ',cmd))))
|
||||
`((setf (alist-get ',cmd doom--dispatch-command-alist)
|
||||
(list :desc ,docstring
|
||||
:body (lambda (args) ,form))))))))
|
||||
|
||||
|
||||
;;
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
;; Built in packages we use a lot of
|
||||
(require 'subr-x)
|
||||
(require 'cl-lib)
|
||||
(require 'map)
|
||||
|
||||
(eval-and-compile
|
||||
(unless EMACS26+
|
||||
|
@ -11,7 +10,23 @@
|
|||
;; if-let and when-let are deprecated in Emacs 26+ in favor of their
|
||||
;; if-let* variants, so we alias them for 25 users.
|
||||
(defalias 'if-let* #'if-let)
|
||||
(defalias 'when-let* #'when-let))))
|
||||
(defalias 'when-let* #'when-let)
|
||||
|
||||
;; `alist-get' doesn't have its 5th argument before Emacs 26
|
||||
(defun doom*alist-get (key alist &optional default remove testfn)
|
||||
"Return the value associated with KEY in ALIST.
|
||||
If KEY is not found in ALIST, return DEFAULT.
|
||||
Use TESTFN to lookup in the alist if non-nil. Otherwise, use `assq'.
|
||||
|
||||
This is a generalized variable suitable for use with `setf'.
|
||||
When using it to set a value, optional argument REMOVE non-nil
|
||||
means to remove KEY from ALIST if the new value is `eql' to DEFAULT."
|
||||
(ignore remove) ;;Silence byte-compiler.
|
||||
(let ((x (if (not testfn)
|
||||
(assq key alist)
|
||||
(assoc key alist testfn))))
|
||||
(if x (cdr x) default)))
|
||||
(advice-add #'alist-get :override #'doom*alist-get))))
|
||||
|
||||
|
||||
;;
|
||||
|
@ -402,7 +417,7 @@ The available conditions are:
|
|||
collect `(add-hook ',hook #',hook-name))
|
||||
`((add-hook 'after-change-major-mode-hook #',hook-name))))))
|
||||
(match
|
||||
`(map-put doom-auto-minor-mode-alist ,match ',mode))
|
||||
`(add-to-list 'doom-auto-minor-mode-alist '(,match . ,mode)))
|
||||
((user-error "Invalid `associate!' rules for mode [%s] (:modes %s :match %s :files %s :when %s)"
|
||||
mode modes match files when)))))
|
||||
|
||||
|
|
|
@ -35,8 +35,6 @@ A warning will be put out if these deprecated modules are used.")
|
|||
session of Dooming. Will noop if used more than once, unless FORCE-P is
|
||||
non-nil."
|
||||
(when (or force-p (not doom-init-modules-p))
|
||||
;; Set `doom-init-modules-p' early, so `doom-pre-init-hook' won't infinitely
|
||||
;; recurse by accident if any of them need `doom-initialize-modules'.
|
||||
(setq doom-init-modules-p t)
|
||||
(when doom-private-dir
|
||||
(condition-case e
|
||||
|
@ -184,7 +182,7 @@ non-nil, return paths of possible modules, activated or otherwise."
|
|||
;;
|
||||
;; This will load X on the first invokation of `find-file-hook' (then it will
|
||||
;; remove itself from the hook/function).
|
||||
(defvar doom--deferred-packages-alist ())
|
||||
(defvar doom--deferred-packages-alist '(t))
|
||||
(after! use-package-core
|
||||
(add-to-list 'use-package-deferring-keywords :after-call nil #'eq)
|
||||
(setq use-package-keywords
|
||||
|
@ -208,15 +206,19 @@ non-nil, return paths of possible modules, activated or otherwise."
|
|||
(if (functionp hook)
|
||||
(advice-remove hook #',fn)
|
||||
(remove-hook hook #',fn)))
|
||||
(map-delete doom--deferred-packages-alist ',name)
|
||||
(delq (assq ',name doom--deferred-packages-alist)
|
||||
doom--deferred-packages-alist)
|
||||
(fmakunbound ',fn))))
|
||||
(cl-loop for hook in hooks
|
||||
collect (if (functionp hook)
|
||||
`(advice-add #',hook :before #',fn)
|
||||
`(add-hook ',hook #',fn)))
|
||||
`((map-put doom--deferred-packages-alist
|
||||
',name
|
||||
'(,@hooks ,@(cdr (assq name doom--deferred-packages-alist)))))
|
||||
(let (forms)
|
||||
(dolist (hook hooks forms)
|
||||
(push (if (functionp hook)
|
||||
`(advice-add #',hook :before #',fn)
|
||||
`(add-hook ',hook #',fn))
|
||||
forms)))
|
||||
`((unless (assq ',name doom--deferred-packages-alist)
|
||||
(push '(,name) doom--deferred-packages-alist))
|
||||
(nconc (assq ',name doom--deferred-packages-alist)
|
||||
'(,@hooks)))
|
||||
(use-package-process-keywords name rest state))))))
|
||||
|
||||
|
||||
|
|
|
@ -222,8 +222,8 @@ elsewhere."
|
|||
doom-private-dir)
|
||||
(setq plist (plist-put plist :private t)))
|
||||
`(progn
|
||||
,(if pkg-pin `(map-put package-pinned-packages ',name ,pkg-pin))
|
||||
(map-put doom-packages ',name ',plist)
|
||||
,(if pkg-pin `(setf (alist-get ',name package-pinned-packages) ,pkg-pin))
|
||||
(setf (alist-get ',name doom-packages) ',plist)
|
||||
(not (memq ',name doom-disabled-packages)))))
|
||||
|
||||
(defmacro packages! (&rest packages)
|
||||
|
|
|
@ -67,7 +67,9 @@ Also see `doom-before-switch-buffer-hook'.")
|
|||
enable-recursive-minibuffers nil
|
||||
frame-inhibit-implied-resize t
|
||||
;; remove continuation arrow on right fringe
|
||||
fringe-indicator-alist (map-delete fringe-indicator-alist 'continuation)
|
||||
fringe-indicator-alist
|
||||
(delq (assq 'continuation fringe-indicator-alist)
|
||||
fringe-indicator-alist)
|
||||
highlight-nonselected-windows nil
|
||||
image-animate-loop t
|
||||
indicate-buffer-boundaries nil
|
||||
|
@ -126,13 +128,13 @@ Also see `doom-before-switch-buffer-hook'.")
|
|||
(format "%s modeline segment" name))))
|
||||
(cond ((and (symbolp (car body))
|
||||
(not (cdr body)))
|
||||
(map-put doom--modeline-var-alist name (car body))
|
||||
`(map-put doom--modeline-var-alist ',name ',(car body)))
|
||||
(add-to-list 'doom--modeline-var-alist (cons name (car body)))
|
||||
`(add-to-list 'doom--modeline-var-alist (cons ',name ',(car body))))
|
||||
(t
|
||||
(map-put doom--modeline-fn-alist name sym)
|
||||
(add-to-list 'doom--modeline-fn-alist (cons name sym))
|
||||
`(progn
|
||||
(fset ',sym (lambda () ,docstring ,@body))
|
||||
(map-put doom--modeline-fn-alist ',name ',sym)
|
||||
(add-to-list 'doom--modeline-fn-alist (cons ',name ',sym))
|
||||
,(unless (bound-and-true-p byte-compile-current-file)
|
||||
`(let (byte-compile-warnings)
|
||||
(byte-compile #',sym))))))))
|
||||
|
@ -549,7 +551,7 @@ frame's window-system, the theme will be reloaded.")
|
|||
(custom-set-faces
|
||||
(when (fontp doom-font)
|
||||
(let ((xlfd (font-xlfd-name doom-font)))
|
||||
(map-put default-frame-alist 'font xlfd)
|
||||
(add-to-list 'default-frame-alist (cons 'font xlfd))
|
||||
`(fixed-pitch ((t (:font ,xlfd))))))
|
||||
(when (fontp doom-variable-pitch-font)
|
||||
`(variable-pitch ((t (:font ,(font-xlfd-name doom-variable-pitch-font))))))
|
||||
|
@ -712,7 +714,7 @@ windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original
|
|||
(defun doom|init-ui ()
|
||||
"Initialize Doom's user interface by applying all its advice and hooks."
|
||||
;; Make `next-buffer', `other-buffer', etc. ignore unreal buffers.
|
||||
(map-put default-frame-alist 'buffer-predicate #'doom-buffer-frame-predicate)
|
||||
(add-to-list 'default-frame-alist (cons 'buffer-predicate #'doom-buffer-frame-predicate))
|
||||
;; Switch to `doom-fallback-buffer' if on last real buffer
|
||||
(advice-add #'kill-this-buffer :around #'doom*switch-to-fallback-buffer-maybe)
|
||||
;; Don't kill the fallback buffer
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue