Refactor Doom core init process (again)
- Eager-load all core autoloaded libraries if autoloads file isn't present. - Renames functions to be more descriptive of their true purpose: - doom-initialize-autoloads -> doom-load-autoloads-file - doom-load-env-vars -> doom-load-envvars-file - Use doom-module-p instead of featurep! for backend use (the latter is mainly syntax sugar for module use, and evaluates at compile/expansion time, which may cause hash-table-p errors early in the startup process). - Reorder plist library to prevent load order race condition with the functions using the macros that haven't been defined yet.
This commit is contained in:
parent
23d111132a
commit
93f7520c79
11 changed files with 109 additions and 107 deletions
|
@ -61,8 +61,8 @@ It is useful to only pull in changes performed by 'doom refresh' on the command
|
|||
line."
|
||||
(interactive "P")
|
||||
;; TODO regenerate autoloads
|
||||
(doom-initialize-autoloads doom-autoload-file)
|
||||
(doom-initialize-autoloads doom-package-autoload-file))
|
||||
(doom-load-autoloads-file doom-autoload-file)
|
||||
(doom-load-autoloads-file doom-package-autoload-file))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom/reload-env ()
|
||||
|
@ -75,7 +75,7 @@ Uses the same mechanism as 'bin/doom env reload'."
|
|||
(sit-for 1))
|
||||
(unless (file-readable-p doom-env-file)
|
||||
(error "Failed to generate env file"))
|
||||
(doom-load-env-vars doom-env-file))
|
||||
(doom-load-envvars-file doom-env-file))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom/reload-theme ()
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
;;; core/autoload/packages.el -*- lexical-binding: t; -*-
|
||||
|
||||
(require 'straight)
|
||||
|
||||
|
||||
;;
|
||||
;;; Package metadata
|
||||
|
||||
|
|
|
@ -1,39 +1,5 @@
|
|||
;;; ../work/conf/doom-emacs/core/autoload/plist.el -*- lexical-binding: t; -*-
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-plist-get (plist prop &optional nil-value)
|
||||
"Return PROP in PLIST, if it exists. Otherwise NIL-VALUE."
|
||||
(if-let (val (plist-member plist prop))
|
||||
(cadr val)
|
||||
nil-value))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-plist-merge (from-plist to-plist)
|
||||
"Destructively merge FROM-PLIST onto TO-PLIST"
|
||||
(while plist
|
||||
(plist-put! old-plist (pop plist) (pop plist))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-plist-delete-nil (plist)
|
||||
"Delete `nil' properties from a copy of PLIST."
|
||||
(let (p)
|
||||
(while plist
|
||||
(if (car plist)
|
||||
(setq p (plist-put p (car plist) (nth 1 plist))))
|
||||
(setq plist (cddr plist)))
|
||||
p))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-plist-delete (plist prop)
|
||||
"Delete PROP from a copy of PLIST."
|
||||
(let (p)
|
||||
(while plist
|
||||
(if (not (eq prop (car plist)))
|
||||
(setq p (plist-put p (car plist) (nth 1 plist))))
|
||||
(setq plist (cddr plist)))
|
||||
p))
|
||||
|
||||
|
||||
;;
|
||||
;;; Macros
|
||||
|
||||
|
@ -82,3 +48,40 @@ BODY."
|
|||
,plist-sym
|
||||
,(doom-keyword-intern (symbol-name prop))))))
|
||||
,@body)))
|
||||
|
||||
|
||||
;;
|
||||
;;; Library
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-plist-get (plist prop &optional nil-value)
|
||||
"Return PROP in PLIST, if it exists. Otherwise NIL-VALUE."
|
||||
(if-let (val (plist-member plist prop))
|
||||
(cadr val)
|
||||
nil-value))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-plist-merge (from-plist to-plist)
|
||||
"Destructively merge FROM-PLIST onto TO-PLIST"
|
||||
(while plist
|
||||
(plist-put! old-plist (pop plist) (pop plist))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-plist-delete-nil (plist)
|
||||
"Delete `nil' properties from a copy of PLIST."
|
||||
(let (p)
|
||||
(while plist
|
||||
(if (car plist)
|
||||
(plist-put! p (car plist) (nth 1 plist)))
|
||||
(setq plist (cddr plist)))
|
||||
p))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-plist-delete (plist prop)
|
||||
"Delete PROP from a copy of PLIST."
|
||||
(let (p)
|
||||
(while plist
|
||||
(if (not (eq prop (car plist)))
|
||||
(plist-put! p (car plist) (nth 1 plist)))
|
||||
(setq plist (cddr plist)))
|
||||
p))
|
||||
|
|
|
@ -111,7 +111,7 @@ If DIR is not a project, it will be indexed (but not cached)."
|
|||
(call-interactively
|
||||
;; Intentionally avoid `helm-projectile-find-file', because it runs
|
||||
;; asynchronously, and thus doesn't see the lexical `default-directory'
|
||||
(if (featurep! :completion ivy)
|
||||
(if (doom-module-p :completion 'ivy)
|
||||
#'counsel-projectile-find-file
|
||||
#'projectile-find-file)))
|
||||
((fboundp 'project-find-file-in) ; emacs 26.1+ only
|
||||
|
@ -127,8 +127,8 @@ If DIR is not a project, it will be indexed (but not cached)."
|
|||
"Traverse a file structure starting linearly from DIR."
|
||||
(let ((default-directory (file-truename (expand-file-name dir))))
|
||||
(call-interactively
|
||||
(cond ((featurep! :completion ivy)
|
||||
(cond ((doom-module-p :completion 'ivy)
|
||||
#'counsel-find-file)
|
||||
((featurep! :completion helm)
|
||||
((doom-module-p :completion 'helm)
|
||||
#'helm-find-files)
|
||||
(#'find-file)))))
|
||||
|
|
|
@ -270,7 +270,7 @@ Run this whenever your `doom!' block, or a module autoload file, is modified."
|
|||
return t)))
|
||||
(ignore
|
||||
(print! (success "Skipping core autoloads, they are up-to-date"))
|
||||
(doom-initialize-autoloads doom-autoload-file))
|
||||
(doom-load-autoloads-file doom-autoload-file))
|
||||
(print! (start "Regenerating core autoloads file"))
|
||||
|
||||
(if (doom-delete-autoloads-file doom-autoload-file)
|
||||
|
@ -393,7 +393,7 @@ This should be run whenever your `doom!' block or update your packages."
|
|||
return t)))
|
||||
(ignore
|
||||
(print! (success "Skipping package autoloads, they are up-to-date"))
|
||||
(doom-initialize-autoloads doom-package-autoload-file))
|
||||
(doom-load-autoloads-file doom-package-autoload-file))
|
||||
(let (;; The following bindings are in `package-generate-autoloads'.
|
||||
;; Presumably for a good reason, so I just copied them
|
||||
(noninteractive t)
|
||||
|
|
|
@ -91,8 +91,8 @@ If RECOMPILE-P is non-nil, only recompile out-of-date files."
|
|||
|
||||
;; But first we must be sure that Doom and your private config have been
|
||||
;; fully loaded. Which usually aren't so in an noninteractive session.
|
||||
(doom-initialize-autoloads doom-autoload-file)
|
||||
(doom-initialize-autoloads doom-package-autoload-file)
|
||||
(doom-load-autoloads-file doom-autoload-file)
|
||||
(doom-load-autoloads-file doom-package-autoload-file)
|
||||
|
||||
;;
|
||||
(unless target-dirs
|
||||
|
|
|
@ -98,7 +98,7 @@ default, on Linux, this is '$SHELL -ic /usr/bin/env'. Variables in
|
|||
"#\n"
|
||||
"# It is NOT safe to edit this file. Changes will be overwritten next time that\n"
|
||||
"# `doom env refresh` is executed. Alternatively, create your own env file and\n"
|
||||
"# load it with `(doom-load-env-vars FILE)`.\n"
|
||||
"# load it with `(doom-load-envvars-file FILE)`.\n"
|
||||
"#\n"
|
||||
"# To auto-regenerate this file when `doom reload` is run, use `doom env auto' or\n"
|
||||
"# set DOOMENV=1 in your shell environment/config.\n"
|
||||
|
|
|
@ -16,8 +16,8 @@ current directory."
|
|||
(patterns nil)
|
||||
(args command-line-args-left)
|
||||
(doom-modules (doom-modules)))
|
||||
(doom-initialize-autoloads doom-autoload-file)
|
||||
(doom-initialize-autoloads doom-package-autoload-file)
|
||||
(doom-load-autoloads-file doom-autoload-file)
|
||||
(doom-load-autoloads-file doom-package-autoload-file)
|
||||
(while args
|
||||
(cond
|
||||
;; ((member (car args) '("--traceback"))
|
||||
|
|
|
@ -144,13 +144,6 @@ BODY will be run when this dispatcher is called."
|
|||
;;
|
||||
;;; Dispatch commands
|
||||
|
||||
;; Eagerly load these libraries because this module may be loaded in a session
|
||||
;; that hasn't been fully initialized (where autoloads files haven't been
|
||||
;; generated or `load-path' populated).
|
||||
(load! "autoload/format")
|
||||
(load! "autoload/packages")
|
||||
|
||||
|
||||
;; Load all of our subcommands
|
||||
(def-command! (refresh re) (&optional force-p)
|
||||
"Ensure Doom is properly set up.
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
;;; core/core-packages.el -*- lexical-binding: t; -*-
|
||||
|
||||
(require 'core-modules)
|
||||
|
||||
;; Emacs package management is opinionated, and so is Doom. Doom uses `straight'
|
||||
;; to create a declarative, lazy-loaded and optionally rolling-release package
|
||||
;; management system. We use `straight' over `package' because the latter is
|
||||
|
@ -131,6 +129,7 @@ This ensure `doom-packages' is populated, if isn't aren't already. Use this
|
|||
before any of straight's or Doom's package management's API to ensure all the
|
||||
necessary package metadata is initialized and available for them."
|
||||
(when (or force-p (not doom-init-packages-p))
|
||||
(doom-log "Initializing straight")
|
||||
(setq doom-init-packages-p t)
|
||||
(straight--reset-caches)
|
||||
(mapc #'straight-use-recipes doom-core-package-sources)
|
||||
|
@ -145,16 +144,14 @@ necessary package metadata is initialized and available for them."
|
|||
(dolist (package (straight--directory-files (straight--build-dir)))
|
||||
(add-to-list 'load-path (directory-file-name (straight--build-dir package)))))
|
||||
(when (or force-p (not doom-packages))
|
||||
;; On first install, the packages API will be unavailable
|
||||
(unless (fboundp 'doom-package-list)
|
||||
(load! "autoload/packages.el"))
|
||||
(doom-log "Initializing doom-packages")
|
||||
(setq doom-disabled-packages nil
|
||||
doom-packages (doom-package-list))
|
||||
(cl-loop for (pkg . plist) in doom-packages
|
||||
for ignored = (eval (plist-get plist :ignore) t)
|
||||
for disabled = (eval (plist-get plist :disable) t)
|
||||
if disabled
|
||||
do (add-to-list 'doom-disabled-packages pkg)
|
||||
do (cl-pushnew pkg doom-disabled-packages)
|
||||
else if (not ignored)
|
||||
do (with-demoted-errors "Package error: %s"
|
||||
(straight-register-package
|
||||
|
@ -176,7 +173,9 @@ necessary package metadata is initialized and available for them."
|
|||
;; version of Emacs that doesn't match the one it was compiled with.
|
||||
;; Getting this error isn't very good UX...
|
||||
(catch 'emacs-version-changed
|
||||
(unless (require 'straight nil t)
|
||||
(if (or (featurep 'staight)
|
||||
(load (file-name-sans-extension bootstrap-file) t t))
|
||||
(cl-return-from 'straight t)
|
||||
(unless (file-exists-p bootstrap-file)
|
||||
(with-current-buffer
|
||||
(url-retrieve-synchronously
|
||||
|
@ -188,7 +187,7 @@ necessary package metadata is initialized and available for them."
|
|||
(cl-return-from 'straight t))
|
||||
;; ...so we transform it into a more graceful error message:
|
||||
(with-temp-buffer
|
||||
(insert-file-contents-literally (expand-file-name "build-cache.el" straight-dir))
|
||||
(insert-file-contents-literally (doom-path straight-dir "build-cache.el"))
|
||||
(let ((_ (read (current-buffer)))
|
||||
(last-emacs-version (read (current-buffer))))
|
||||
(user-error "Your version of Emacs has changed (from %S to %S). You must rebuild your packages with 'doom rebuild'."
|
||||
|
|
94
core/core.el
94
core/core.el
|
@ -430,7 +430,7 @@ If RETURN-P, return the message as a string instead of displaying it."
|
|||
'window-setup-hook))
|
||||
(run-hook-wrapped hook #'doom-try-run-hook)))
|
||||
|
||||
(defun doom-initialize-autoloads (file)
|
||||
(defun doom-load-autoloads-file (file)
|
||||
"Tries to load FILE (an autoloads file). Return t on success, throws an error
|
||||
in interactive sessions, nil otherwise (but logs a warning)."
|
||||
(condition-case e
|
||||
|
@ -442,10 +442,11 @@ in interactive sessions, nil otherwise (but logs a warning)."
|
|||
(message "Autoload file warning: %s -> %s" (car e) (error-message-string e))
|
||||
(signal 'doom-autoload-error (list (file-name-nondirectory file) e))))))
|
||||
|
||||
(defun doom-load-env-vars (file)
|
||||
(defun doom-load-envvars-file (file &optional noerror)
|
||||
"Read and set envvars in FILE."
|
||||
(if (not (file-readable-p file))
|
||||
(signal 'file-error (list "Couldn't read envvar file" file))
|
||||
(unless noerror
|
||||
(signal 'file-error (list "Couldn't read envvar file" file)))
|
||||
(with-temp-buffer
|
||||
(insert-file-contents file)
|
||||
(search-forward "\n\n" nil t)
|
||||
|
@ -497,68 +498,77 @@ to least)."
|
|||
(when (or force-p (not doom-init-p))
|
||||
(setq doom-init-p t)
|
||||
|
||||
;; Reset as much state as possible
|
||||
;; Reset as much state as possible, so `doom-initialize' can be treated like
|
||||
;; a reset function. Particularly useful for reloading the config.
|
||||
(setq exec-path doom--initial-exec-path
|
||||
load-path doom--initial-load-path
|
||||
process-environment doom--initial-process-environment)
|
||||
|
||||
(require 'core-lib)
|
||||
(require 'core-modules)
|
||||
(let (;; `doom-autoload-file' tells Emacs where to load all its functions
|
||||
;; from. This includes everything in core/autoload/*.el and autoload
|
||||
;; files in enabled modules.
|
||||
(core-autoloads-p (doom-load-autoloads-file doom-autoload-file))
|
||||
;; Loads `doom-package-autoload-file', which loads a concatenated
|
||||
;; package autoloads file which caches `load-path', `auto-mode-alist',
|
||||
;; `Info-directory-list', and `doom-disabled-packages'. A big
|
||||
;; reduction in startup time.
|
||||
(pkg-autoloads-p (doom-load-autoloads-file doom-package-autoload-file)))
|
||||
|
||||
;; `doom-autoload-file' tells Emacs where to load all its functions from.
|
||||
;; This includes everything in core/autoload/*.el and autoload files in
|
||||
;; enabled modules.
|
||||
(when (or (not (doom-initialize-autoloads doom-autoload-file))
|
||||
force-p)
|
||||
(dolist (dir (list doom-local-dir doom-etc-dir doom-cache-dir doom-elpa-dir))
|
||||
(unless (file-directory-p dir)
|
||||
(make-directory dir 'parents-too)))
|
||||
(if (and core-autoloads-p (not force-p))
|
||||
;; In case we want to use package.el or straight via M-x
|
||||
(progn
|
||||
(after! (:or package straight)
|
||||
(require 'core-packages))
|
||||
(after! straight
|
||||
(doom-initialize-packages)))
|
||||
|
||||
;; Ensure the package management system (and straight) are ready for
|
||||
;; action (and all core packages/repos are installed)
|
||||
(require 'core-packages)
|
||||
(doom-ensure-straight)
|
||||
(doom-initialize-packages force-p)
|
||||
;; Eagerly load these libraries because this module may be loaded in a session
|
||||
;; that hasn't been fully initialized (where autoloads files haven't been
|
||||
;; generated or `load-path' populated).
|
||||
(let ((default-directory doom-core-dir))
|
||||
(dolist (file (file-expand-wildcards "autoload/*.el"))
|
||||
(load file t t)))
|
||||
|
||||
(unless (or force-p noninteractive)
|
||||
(user-error "Your doom autoloads are missing! Run `bin/doom refresh' to regenerate them")))
|
||||
;; Create all our core directories to quell file errors
|
||||
(dolist (dir (list doom-local-dir doom-etc-dir doom-cache-dir doom-elpa-dir))
|
||||
(unless (file-directory-p dir)
|
||||
(make-directory dir 'parents)))
|
||||
|
||||
;; Loads `doom-package-autoload-file', which loads a concatenated package
|
||||
;; autoloads file which caches `load-path', `auto-mode-alist',
|
||||
;; `Info-directory-list', and `doom-disabled-packages'. A big reduction in
|
||||
;; startup time.
|
||||
(unless (or force-p
|
||||
(doom-initialize-autoloads doom-package-autoload-file)
|
||||
noninteractive)
|
||||
(user-error "Your package autoloads are missing! Run `bin/doom refresh' to regenerate them"))
|
||||
;; Ensure the package management system (and straight) are ready for
|
||||
;; action (and all core packages/repos are installed)
|
||||
(require 'core-packages)
|
||||
(doom-ensure-straight)
|
||||
(doom-initialize-packages force-p))
|
||||
|
||||
;; Load shell environment
|
||||
(when (and (not noninteractive)
|
||||
(file-exists-p doom-env-file))
|
||||
(doom-load-env-vars doom-env-file))))
|
||||
(unless (or (and core-autoloads-p pkg-autoloads-p)
|
||||
force-p
|
||||
noninteractive)
|
||||
(unless core-autoloads-p
|
||||
(message "Your Doom core autoloads file is missing"))
|
||||
(unless pkg-autoloads-p
|
||||
(message "Your package autoloads file is missing"))
|
||||
(user-error "Run `bin/doom refresh' to generate them")))
|
||||
|
||||
;; Load shell environment, optionally generated from 'doom env'
|
||||
(unless noninteractive
|
||||
(doom-load-envvars-file doom-env-file 'noerror))))
|
||||
|
||||
|
||||
;;
|
||||
;;; Bootstrap Doom
|
||||
|
||||
(doom-initialize noninteractive)
|
||||
|
||||
;; In case we want to use package.el's API
|
||||
(with-eval-after-load 'package
|
||||
(require 'core-packages))
|
||||
;; Or straight interactively
|
||||
(with-eval-after-load 'straight
|
||||
(require 'core-packages)
|
||||
(doom-initialize-packages))
|
||||
|
||||
(if noninteractive
|
||||
(require 'core-cli)
|
||||
(add-hook 'window-setup-hook #'doom-display-benchmark-h)
|
||||
(require 'core-keybinds)
|
||||
(require 'core-ui)
|
||||
(require 'core-projects)
|
||||
(require 'core-editor)
|
||||
(doom-initialize-modules))
|
||||
(require 'core-editor))
|
||||
|
||||
(doom-initialize-modules)
|
||||
|
||||
(provide 'core)
|
||||
;;; core.el ends here
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue