refactor: move startup optimizations to doom.el
I move our hackiest and least offensive startup optimizations to core, so they're easy for me to keep track of (they'll likely change often, between major Emacs releases), to keep them from affecting non-Doom profiles, and make it easy for readers to use as a reference.
This commit is contained in:
parent
9ac167fb84
commit
42d88421ba
3 changed files with 248 additions and 242 deletions
143
early-init.el
143
early-init.el
|
@ -31,78 +31,32 @@
|
||||||
;; cause stuttering/freezes.
|
;; cause stuttering/freezes.
|
||||||
(setq gc-cons-threshold most-positive-fixnum)
|
(setq gc-cons-threshold most-positive-fixnum)
|
||||||
|
|
||||||
(eval-and-compile
|
|
||||||
;; PERF: Don't use precious startup time checking mtime on elisp bytecode.
|
;; PERF: Don't use precious startup time checking mtime on elisp bytecode.
|
||||||
;; Ensuring correctness is 'doom sync's job, not the interactive session's.
|
;; Ensuring correctness is 'doom sync's job, not the interactive session's.
|
||||||
;; Still, stale byte-code will cause *heavy* losses in startup efficiency.
|
;; Still, stale byte-code will cause *heavy* losses in startup efficiency.
|
||||||
(setq load-prefer-newer noninteractive))
|
(setq load-prefer-newer noninteractive)
|
||||||
|
|
||||||
;; UX: If debug mode is on, be more verbose about loaded files.
|
|
||||||
(setq force-load-messages init-file-debug)
|
|
||||||
|
|
||||||
;; PERF: Employ various startup optimizations. This benefits all sessions,
|
|
||||||
;; including noninteractive ones...
|
|
||||||
(unless (or (daemonp) ; ...but be more liberal in daemon sessions
|
|
||||||
init-file-debug ; ...and don't interfere with the debugger
|
|
||||||
(boundp 'doom-version)) ; ...or if doom is already loaded
|
|
||||||
|
|
||||||
;; PERF: `file-name-handler-alist' is consulted on each `require', `load' and
|
|
||||||
;; various path/io functions (like `expand-file-name' or `file-remote-p').
|
|
||||||
;; You get a noteable, boost to startup times by unsetting this.
|
|
||||||
(let ((old-file-name-handler-alist file-name-handler-alist))
|
|
||||||
(setq file-name-handler-alist
|
|
||||||
;; HACK: If the bundled elisp for this Emacs install isn't
|
|
||||||
;; byte-compiled (but is compressed), then leave the gzip file
|
|
||||||
;; handler there so Emacs won't forget how to read read them.
|
|
||||||
;;
|
|
||||||
;; calc-loaddefs.el is our heuristic for this because it is built-in
|
|
||||||
;; to all supported versions of Emacs, and calc.el explicitly loads
|
|
||||||
;; it uncompiled. This ensures that the only other, possible
|
|
||||||
;; fallback would be calc-loaddefs.el.gz.
|
|
||||||
(if (eval-when-compile
|
|
||||||
(locate-file-internal "calc-loaddefs.el" load-path nil))
|
|
||||||
nil
|
|
||||||
(list (rassq 'jka-compr-handler file-name-handler-alist))))
|
|
||||||
;; ...but restore `file-name-handler-alist' later, because it is needed for
|
|
||||||
;; handling encrypted or compressed files, among other things.
|
|
||||||
(defun doom-reset-file-handler-alist-h ()
|
|
||||||
(setq file-name-handler-alist
|
|
||||||
;; Merge instead of overwrite because there may have been changes to
|
|
||||||
;; `file-name-handler-alist' since startup we want to preserve.
|
|
||||||
(delete-dups (append file-name-handler-alist
|
|
||||||
old-file-name-handler-alist))))
|
|
||||||
(add-hook 'emacs-startup-hook #'doom-reset-file-handler-alist-h 101))
|
|
||||||
|
|
||||||
;; PERF: Site files tend to use `load-file', which emits "Loading X..."
|
|
||||||
;; messages in the echo area. Writing to the echo-area triggers a redisplay,
|
|
||||||
;; which can be expensive during startup. This can also cause an ugly flash
|
|
||||||
;; of white when first creating the frame. This attempts try to avoid both.
|
|
||||||
(define-advice load-file (:override (file) silence)
|
|
||||||
(load file nil :nomessage))
|
|
||||||
|
|
||||||
;; FIX: ...Then undo our `load-file' advice later, as to limit the scope of
|
|
||||||
;; any edge cases it may possibly introduce.
|
|
||||||
(define-advice startup--load-user-init-file (:before (&rest _) init-doom)
|
|
||||||
(advice-remove #'load-file #'load-file@silence)))
|
|
||||||
|
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;;; Detect `user-emacs-directory'
|
;;; Bootstrap
|
||||||
|
|
||||||
;; Prevent recursive profile processing, in case you're loading a Doom profile.
|
(or
|
||||||
(unless (boundp 'doom-version)
|
;; PERF: `file-name-handler-alist' is consulted often. Unsetting it offers a
|
||||||
;; Not using `command-switch-alist' to process --profile and --init-directory
|
;; notable saving in startup time.
|
||||||
;; was intentional. `command-switch-alist' is processed too late at startup to
|
(let (file-name-handler-alist)
|
||||||
;; change `user-emacs-directory' in time.
|
;; FEAT: First, we process --init-directory and --profile to detect what
|
||||||
|
;; `user-emacs-directory' to load from. I avoid using
|
||||||
|
;; `command-switch-alist' to process --profile and --init-directory because
|
||||||
|
;; it is processed too late to change `user-emacs-directory' in time.
|
||||||
|
|
||||||
;; DEPRECATED: Backported from Emacs 29.
|
;; REVIEW: Backported from Emacs 29. Remove when 28 support is dropped.
|
||||||
(let ((initdir (or (cadr (member "--init-directory" command-line-args))
|
(let ((initdir (or (cadr (member "--init-directory" command-line-args))
|
||||||
(getenv-internal "EMACSDIR"))))
|
(getenv-internal "EMACSDIR"))))
|
||||||
(when initdir
|
(when initdir
|
||||||
;; FIX: Discard the switch to prevent "invalid option" errors later.
|
;; FIX: Discard the switch to prevent "invalid option" errors later.
|
||||||
(push (cons "--init-directory" (lambda (_) (pop argv))) command-switch-alist)
|
(push (cons "--init-directory" (lambda (_) (pop argv))) command-switch-alist)
|
||||||
(setq user-emacs-directory (expand-file-name initdir))))
|
(setq user-emacs-directory (expand-file-name initdir))))
|
||||||
|
;; Initialize a known profile, if requested.
|
||||||
(let ((profile (or (cadr (member "--profile" command-line-args))
|
(let ((profile (or (cadr (member "--profile" command-line-args))
|
||||||
(getenv-internal "DOOMPROFILE"))))
|
(getenv-internal "DOOMPROFILE"))))
|
||||||
(when profile
|
(when profile
|
||||||
|
@ -136,53 +90,54 @@
|
||||||
(when (file-directory-p profile-dir)
|
(when (file-directory-p profile-dir)
|
||||||
(setq user-emacs-directory profile-dir)
|
(setq user-emacs-directory profile-dir)
|
||||||
(throw 'found t)))
|
(throw 'found t)))
|
||||||
|
|
||||||
(user-error "No %S profile found" profile)))
|
(user-error "No %S profile found" profile)))
|
||||||
|
|
||||||
(when init-file-debug
|
(when init-file-debug
|
||||||
(message "Selected profile: %s" profile))
|
(message "Selected profile: %s" profile))
|
||||||
;; Ensure the selected profile persists through the session
|
;; Ensure the selected profile persists through the session
|
||||||
(setenv "DOOMPROFILE" profile))))
|
(setenv "DOOMPROFILE" profile)))
|
||||||
|
|
||||||
|
|
||||||
|
;; PERF: When `load'ing or `require'ing files, each permutation of
|
||||||
|
;; `load-suffixes' and `load-file-rep-suffixes' (then `load-suffixes' +
|
||||||
|
;; `load-file-rep-suffixes') is used to locate the file. Each permutation
|
||||||
|
;; is a file op, which is normally very fast, but they can add up over the
|
||||||
|
;; hundreds/thousands of files Emacs needs to load.
|
||||||
;;
|
;;
|
||||||
;;; Bootstrap
|
;; To reduce that burden -- and since Doom doesn't load any dynamic modules
|
||||||
|
;; -- I remove `.so' from `load-suffixes' and pass the `must-suffix' arg to
|
||||||
(let (init-file)
|
;; `load'. See the docs of `load' for details.
|
||||||
;; Load the heart of Doom Emacs
|
(or (let ((load-suffixes '(".elc" ".el")))
|
||||||
(if (load (expand-file-name "lisp/doom" user-emacs-directory) 'noerror 'nomessage)
|
;; Load the heart of Doom Emacs.
|
||||||
;; ...and prepare for an interactive session.
|
(if (load (expand-file-name "lisp/doom" user-emacs-directory)
|
||||||
|
'noerror 'nomessage nil 'must-suffix)
|
||||||
|
;; ...and prepare for the rest of the session.
|
||||||
(if noninteractive
|
(if noninteractive
|
||||||
(require 'doom-cli)
|
(doom-require 'doom-cli)
|
||||||
(setq init-file (expand-file-name "doom-start" doom-core-dir)))
|
;; HACK: This advice hijacks Emacs' initfile resolver to replace
|
||||||
;; ...but if that fails, then this is likely not a Doom config.
|
;; $EMACSDIR/init.el (and ~/.emacs or ~/_emacs) with a
|
||||||
(setq early-init-file (expand-file-name "early-init" user-emacs-directory))
|
;; a Doom-provided init file. Later, this file will be
|
||||||
(load early-init-file 'noerror 'nomessage))
|
;; generated by 'doom sync' for the active Doom profile;
|
||||||
|
;; `doom-start' is its stand-in until that's implemented.
|
||||||
;; We hijack Emacs' initfile resolver to inject our own entry point. Why do
|
|
||||||
;; this? Because:
|
|
||||||
;;
|
;;
|
||||||
;; - It spares Emacs the effort of looking for/loading useless initfiles, like
|
;; This effort spares Emacs the overhead of searching for
|
||||||
;; ~/.emacs and ~/_emacs. And skips ~/.emacs.d/init.el, which won't exist if
|
;; initfiles we don't care about, enables savvier hackers to
|
||||||
;; you're using Doom (fyi: doom hackers or chemacs users could then use
|
;; use $EMACSDIR as their $DOOMDIR, and gives us an opportunity
|
||||||
;; $EMACSDIR as their $DOOMDIR, if they wanted).
|
;; to fall back to a "safe mode", so we can present a more
|
||||||
;; - Later, 'doom sync' will dynamically generate its bootstrap file, which
|
;; user-friendly failure state.
|
||||||
;; will be important for Doom's profile system later. Until then, we'll use
|
|
||||||
;; lisp/doom-start.el.
|
|
||||||
;; - A "fallback" initfile can be trivially specified, in case the
|
|
||||||
;; bootstrapper is missing (if the user hasn't run 'doom sync' or is a
|
|
||||||
;; first-timer). This is an opportunity to display a "safe mode" environment
|
|
||||||
;; that's less intimidating and more helpful than the broken state errors
|
|
||||||
;; would've left Emacs in, otherwise.
|
|
||||||
;; - A generated config allows for a file IO optimized startup.
|
|
||||||
(define-advice startup--load-user-init-file (:filter-args (args) init-doom)
|
(define-advice startup--load-user-init-file (:filter-args (args) init-doom)
|
||||||
"Initialize Doom Emacs in an interactive session."
|
"Initialize Doom Emacs in an interactive session."
|
||||||
(list (lambda ()
|
(list (lambda ()
|
||||||
(or init-file
|
(file-name-concat doom-core-dir "doom-start"))
|
||||||
(expand-file-name "init.el" user-emacs-directory)))
|
|
||||||
(when (boundp 'doom-profiles-dir)
|
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(expand-file-name "safe-mode@static/init.el" doom-profiles-dir)))
|
(file-name-concat doom-profiles-dir "safe-mode" "init.el"))
|
||||||
(caddr args))))
|
(caddr args))))))
|
||||||
|
;; Failing that, assume we're loading a non-Doom config and prepare.
|
||||||
|
(ignore
|
||||||
|
(setq early-init-file (expand-file-name "early-init" user-emacs-directory)
|
||||||
|
;; I make no assumptions about the config we're about to load, so
|
||||||
|
;; to limit side-effects, undo any leftover optimizations:
|
||||||
|
load-prefer-newer t))))
|
||||||
|
|
||||||
|
;; Then continue on to the config/profile we want to load.
|
||||||
|
(load early-init-file 'noerror 'nomessage nil 'must-suffix))
|
||||||
|
|
||||||
;;; early-init.el ends here
|
;;; early-init.el ends here
|
||||||
|
|
|
@ -95,47 +95,6 @@
|
||||||
(add-hook 'doom-first-buffer-hook #'gcmh-mode)
|
(add-hook 'doom-first-buffer-hook #'gcmh-mode)
|
||||||
|
|
||||||
|
|
||||||
;;; Startup optimizations
|
|
||||||
;; Resizing the Emacs frame can be a terribly expensive part of changing the
|
|
||||||
;; font. By inhibiting this, we halve startup times, particularly when we use
|
|
||||||
;; fonts that are larger than the system default (which would resize the frame).
|
|
||||||
(setq frame-inhibit-implied-resize t)
|
|
||||||
|
|
||||||
;; Remove command line options that aren't relevant to our current OS; means
|
|
||||||
;; slightly less to process at startup.
|
|
||||||
(eval-when! (not IS-MAC) (setq command-line-ns-option-alist nil))
|
|
||||||
(eval-when! (not IS-LINUX) (setq command-line-x-option-alist nil))
|
|
||||||
|
|
||||||
;; HACK: `tty-run-terminal-initialization' is *tremendously* slow for some
|
|
||||||
;; reason; inexplicably doubling startup time for terminal Emacs. Keeping it
|
|
||||||
;; disabled will have nasty side-effects, so we simply delay it instead, and
|
|
||||||
;; invoke it later, at which point it runs quickly; how mysterious!
|
|
||||||
(unless (or (daemonp) init-file-debug)
|
|
||||||
(advice-add #'tty-run-terminal-initialization :override #'ignore)
|
|
||||||
(defun doom-init-tty-h ()
|
|
||||||
(advice-remove #'tty-run-terminal-initialization #'ignore)
|
|
||||||
(tty-run-terminal-initialization (selected-frame) nil t))
|
|
||||||
(add-hook 'window-setup-hook #'doom-init-tty-h))
|
|
||||||
|
|
||||||
;; Reduce *Message* noise at startup. An empty scratch buffer (or the dashboard)
|
|
||||||
;; is more than enough, and faster to display.
|
|
||||||
(setq inhibit-startup-screen t
|
|
||||||
inhibit-startup-echo-area-message user-login-name
|
|
||||||
inhibit-default-init t)
|
|
||||||
;; Get rid of "For information about GNU Emacs..." message at startup. It's
|
|
||||||
;; redundant with our dashboard and incurs a redraw. In daemon sessions it says
|
|
||||||
;; "Starting Emacs daemon" instead, which is fine.
|
|
||||||
(unless (daemonp)
|
|
||||||
(advice-add #'display-startup-echo-area-message :override #'ignore))
|
|
||||||
|
|
||||||
;; Shave seconds off startup time by starting the scratch buffer in
|
|
||||||
;; `fundamental-mode', rather than, say, `org-mode' or `text-mode', which pull
|
|
||||||
;; in a ton of packages. `doom/open-scratch-buffer' provides a better scratch
|
|
||||||
;; buffer anyway.
|
|
||||||
(setq initial-major-mode 'fundamental-mode
|
|
||||||
initial-scratch-message nil)
|
|
||||||
|
|
||||||
|
|
||||||
;;; Language
|
;;; Language
|
||||||
;; Contrary to what many Emacs users have in their configs, you don't need more
|
;; Contrary to what many Emacs users have in their configs, you don't need more
|
||||||
;; than this to make UTF-8 the default coding system:
|
;; than this to make UTF-8 the default coding system:
|
||||||
|
|
200
lisp/doom.el
200
lisp/doom.el
|
@ -88,37 +88,147 @@
|
||||||
|
|
||||||
;; Remember these variables' initial values, so we can safely reset them at a
|
;; Remember these variables' initial values, so we can safely reset them at a
|
||||||
;; later time, or consult them without fear of contamination.
|
;; later time, or consult them without fear of contamination.
|
||||||
(dolist (var '(exec-path load-path process-environment))
|
(dolist (var '(exec-path load-path process-environment
|
||||||
|
file-name-handler-alist))
|
||||||
(unless (get var 'initial-value)
|
(unless (get var 'initial-value)
|
||||||
(put var 'initial-value (default-value var))))
|
(put var 'initial-value (default-toplevel-value var))))
|
||||||
|
|
||||||
;; Ensure Doom's core libraries are visible for loading
|
|
||||||
(add-to-list 'load-path (file-name-directory load-file-name))
|
|
||||||
|
|
||||||
;; Since Emacs 27, package initialization occurs before `user-init-file' is
|
;; Since Emacs 27, package initialization occurs before `user-init-file' is
|
||||||
;; loaded, but after `early-init-file'. Doom handles package initialization, so
|
;; loaded, but after `early-init-file'. Doom handles package initialization, so
|
||||||
;; we must prevent Emacs from doing it again.
|
;; we must prevent Emacs from doing it again.
|
||||||
(setq package-enable-at-startup nil)
|
(setq package-enable-at-startup nil)
|
||||||
|
|
||||||
;; Custom error types
|
|
||||||
(define-error 'doom-error "An unexpected Doom error")
|
|
||||||
(define-error 'doom-core-error "Unexpected error in Doom's core" 'doom-error)
|
|
||||||
(define-error 'doom-hook-error "Error in a Doom startup hook" 'doom-error)
|
|
||||||
(define-error 'doom-autoload-error "Error in Doom's autoloads file" 'doom-error)
|
|
||||||
(define-error 'doom-user-error "Error caused by user's config or system" 'doom-error)
|
|
||||||
(define-error 'doom-module-error "Error in a Doom module" 'doom-error)
|
|
||||||
(define-error 'doom-package-error "Error with packages" 'doom-error)
|
|
||||||
(define-error 'doom-profile-error "Error while processing profiles" 'doom-error)
|
|
||||||
|
|
||||||
;; Load just the... bear necessities~
|
;;
|
||||||
(require 'cl-lib)
|
;;; Startup optimizations
|
||||||
(require 'subr-x)
|
|
||||||
;; ...then load *the* one
|
;; Here are Doom's hackiest (and least offensive) startup optimizations. They
|
||||||
(require 'doom-lib)
|
;; exploit implementation details and unintended side-effects, and will change
|
||||||
|
;; often between major Emacs releases. I've (roughly) ordered them from most to
|
||||||
|
;; least effective (on Linux), and disable them if this is a daemon session
|
||||||
|
;; (where startup time matters less) or in debug-mode (to mitigate interference
|
||||||
|
;; with our debugging).
|
||||||
|
(unless (or (daemonp) init-file-debug)
|
||||||
|
;; PERF: `file-name-handler-alist' is consulted on each call to `require',
|
||||||
|
;; `load', or various file/io functions (like `expand-file-name' or
|
||||||
|
;; `file-remote-p'). You get a noteable boost to startup time by unsetting
|
||||||
|
;; or simplifying its value.
|
||||||
|
(let ((old-value (get 'file-name-handler-alist 'initial-value)))
|
||||||
|
(setq file-name-handler-alist
|
||||||
|
;; HACK: If the bundled elisp for this Emacs install isn't
|
||||||
|
;; byte-compiled (but is compressed), then leave the gzip file
|
||||||
|
;; handler there so Emacs won't forget how to read read them.
|
||||||
|
;;
|
||||||
|
;; calc-loaddefs.el is our heuristic for this because it is built-in
|
||||||
|
;; to all supported versions of Emacs, and calc.el explicitly loads
|
||||||
|
;; it uncompiled. This ensures that the only other, possible
|
||||||
|
;; fallback would be calc-loaddefs.el.gz.
|
||||||
|
(if (eval-when-compile
|
||||||
|
(if (locate-file-internal "calc-loaddefs.el" load-path) t))
|
||||||
|
nil
|
||||||
|
(list (rassq 'jka-compr-handler old-value))))
|
||||||
|
;; Make sure the new value survives any current let-binding.
|
||||||
|
(set-default-toplevel-value 'file-name-handler-alist file-name-handler-alist)
|
||||||
|
;; COMPAT: ...but restore `file-name-handler-alist' later, because it is
|
||||||
|
;; needed for handling encrypted or compressed files, among other things.
|
||||||
|
(defun doom-reset-file-handler-alist-h ()
|
||||||
|
(setq file-name-handler-alist
|
||||||
|
;; Merge instead of overwrite because there may have been changes to
|
||||||
|
;; `file-name-handler-alist' since startup we want to preserve.
|
||||||
|
(delete-dups (append file-name-handler-alist old-value))))
|
||||||
|
(add-hook 'emacs-startup-hook #'doom-reset-file-handler-alist-h 101))
|
||||||
|
|
||||||
|
(unless noninteractive
|
||||||
|
;; PERF: Resizing the Emacs frame (to accommodate fonts that are smaller or
|
||||||
|
;; larger than the system font) appears to impact startup time
|
||||||
|
;; dramatically. The larger the delta in font size, the greater the delay.
|
||||||
|
;; Even trivial deltas can yield a ~1000ms loss, though it varies wildly
|
||||||
|
;; depending on font size.
|
||||||
|
(setq frame-inhibit-implied-resize t)
|
||||||
|
|
||||||
|
;; PERF: Emacs supports a "default init file", which is a library named
|
||||||
|
;; "default.el" living anywhere in your `load-path' (or `$EMACSLOADPATH').
|
||||||
|
;; It's loaded after $EMACSDIR/init.el, but there really is no reason to
|
||||||
|
;; do so. Doom doesn't define one, users shouldn't use one, and it seems
|
||||||
|
;; too magical when an explicit `-l FILE' would do. I do away with it for
|
||||||
|
;; the *miniscule* savings in file IO spent trying to load it.
|
||||||
|
(setq inhibit-default-init t)
|
||||||
|
|
||||||
|
;; PERF,UX: Reduce *Message* noise at startup. An empty scratch buffer (or
|
||||||
|
;; the dashboard) is more than enough, and faster to display.
|
||||||
|
(setq inhibit-startup-screen t
|
||||||
|
inhibit-startup-echo-area-message user-login-name)
|
||||||
|
;; PERF,UX: Remove "For information about GNU Emacs..." message at startup.
|
||||||
|
;; It's redundant with our dashboard and incurs a premature redraw.
|
||||||
|
(advice-add #'display-startup-echo-area-message :override #'ignore)
|
||||||
|
|
||||||
|
;; PERF: Shave seconds off startup time by starting the scratch buffer in
|
||||||
|
;; `fundamental-mode', rather than, say, `org-mode' or `text-mode', which
|
||||||
|
;; pull in a ton of packages. `doom/open-scratch-buffer' provides a better
|
||||||
|
;; scratch buffer anyway.
|
||||||
|
(setq initial-major-mode 'fundamental-mode
|
||||||
|
initial-scratch-message nil)
|
||||||
|
|
||||||
|
;; PERF: Inexplicably, `tty-run-terminal-initialization' can sometimes take
|
||||||
|
;; 2-3s when starting up Emacs in the terminal. Whatever slows it down at
|
||||||
|
;; startup doesn't appear to affect it if it's called a little later in
|
||||||
|
;; the startup process, so that's what I do.
|
||||||
|
;; REVIEW: This optimization is not understood. Investigate this properly!
|
||||||
|
(advice-add #'tty-run-terminal-initialization :override #'ignore)
|
||||||
|
(defun doom-init-tty-h ()
|
||||||
|
(advice-remove #'tty-run-terminal-initialization #'ignore)
|
||||||
|
(tty-run-terminal-initialization (selected-frame) nil t))
|
||||||
|
(add-hook 'window-setup-hook #'doom-init-tty-h)
|
||||||
|
|
||||||
|
;; PERF,UX: Site files tend to use `load-file', which emits "Loading X..."
|
||||||
|
;; messages in the echo area. Writing to the echo-area triggers a
|
||||||
|
;; redisplay, which can be expensive during startup. This may also cause
|
||||||
|
;; an flash of white when creating the first frame.
|
||||||
|
(define-advice load-file (:override (file) silence)
|
||||||
|
(load file nil 'nomessage))
|
||||||
|
;; COMPAT: But undo our `load-file' advice later, as to limit the scope of
|
||||||
|
;; any edge cases it could induce.
|
||||||
|
(define-advice startup--load-user-init-file (:before (&rest _) undo-silence)
|
||||||
|
(advice-remove #'load-file #'load-file@silence))
|
||||||
|
|
||||||
|
;; PERF: Unset a non-trivial list of command line options that aren't
|
||||||
|
;; relevant to our current OS, but `command-line-1' still processes.
|
||||||
|
(unless IS-MAC
|
||||||
|
(setq command-line-ns-option-alist nil))
|
||||||
|
(when (or IS-MAC IS-WINDOWS)
|
||||||
|
(setq command-line-x-option-alist nil))))
|
||||||
|
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;;; Global constants
|
;;; Core globals
|
||||||
|
|
||||||
|
(defgroup doom nil
|
||||||
|
"An Emacs framework for the stubborn martian hacker."
|
||||||
|
:link '(url-link "https://doomemacs.org"))
|
||||||
|
|
||||||
|
(defconst doom-version "3.0.0-dev"
|
||||||
|
"Current version of Doom Emacs core.")
|
||||||
|
|
||||||
|
(defconst doom-modules-version "22.09.0-dev"
|
||||||
|
"Current version of Doom Emacs.")
|
||||||
|
|
||||||
|
(defconst doom-profile
|
||||||
|
(if-let (profile (getenv-internal "DOOMPROFILE"))
|
||||||
|
;; DEPRECATED Use `string-search' once 27 support is dropped
|
||||||
|
(if (string-match-p "@" profile)
|
||||||
|
profile
|
||||||
|
(concat profile "@latest"))
|
||||||
|
;; TODO Restore this when profile system is complete
|
||||||
|
;; "default@latest"
|
||||||
|
)
|
||||||
|
"The name of the active profile.")
|
||||||
|
|
||||||
|
(defconst doom-emacs-dir user-emacs-directory
|
||||||
|
"The path to the currently loaded .emacs.d directory. Must end with a slash.")
|
||||||
|
|
||||||
|
(defconst doom-core-dir (file-name-directory load-file-name)
|
||||||
|
"The root directory of Doom's core files. Must end with a slash.")
|
||||||
|
|
||||||
|
|
||||||
;; DEPRECATED
|
;; DEPRECATED
|
||||||
(defconst IS-MAC (eq system-type 'darwin))
|
(defconst IS-MAC (eq system-type 'darwin))
|
||||||
|
@ -147,10 +257,17 @@
|
||||||
(defconst MODULES (featurep 'dynamic-modules))
|
(defconst MODULES (featurep 'dynamic-modules))
|
||||||
(defconst NATIVECOMP (featurep 'native-compile)))
|
(defconst NATIVECOMP (featurep 'native-compile)))
|
||||||
|
|
||||||
|
;;; Custom error types
|
||||||
|
(define-error 'doom-error "An unexpected Doom error")
|
||||||
|
(define-error 'doom-core-error "Unexpected error in Doom's core" 'doom-error)
|
||||||
|
(define-error 'doom-hook-error "Error in a Doom startup hook" 'doom-error)
|
||||||
|
(define-error 'doom-autoload-error "Error in Doom's autoloads file" 'doom-error)
|
||||||
|
(define-error 'doom-user-error "Error caused by user's config or system" 'doom-error)
|
||||||
|
(define-error 'doom-module-error "Error in a Doom module" 'doom-error)
|
||||||
|
(define-error 'doom-package-error "Error with packages" 'doom-error)
|
||||||
|
(define-error 'doom-profile-error "Error while processing profiles" 'doom-error)
|
||||||
|
|
||||||
;;
|
;;; Platform-specific fixes
|
||||||
;;; Cross-platform fixes
|
|
||||||
|
|
||||||
;; Fix $HOME on Windows, where it's not normally defined, because many unix
|
;; Fix $HOME on Windows, where it's not normally defined, because many unix
|
||||||
;; tools expect it.
|
;; tools expect it.
|
||||||
(when IS-WINDOWS
|
(when IS-WINDOWS
|
||||||
|
@ -160,29 +277,15 @@
|
||||||
(setenv "HOME" realhome)
|
(setenv "HOME" realhome)
|
||||||
(setq abbreviated-home-dir nil)))
|
(setq abbreviated-home-dir nil)))
|
||||||
|
|
||||||
|
;;; Load Doom stdlib
|
||||||
;;
|
;; Ensure Doom's core libraries are visible for loading
|
||||||
;;; Core variables
|
(add-to-list 'load-path doom-core-dir)
|
||||||
|
;; Load just the... bear necessities~
|
||||||
(defgroup doom nil
|
(require 'doom-lib)
|
||||||
"An Emacs framework for the stubborn martian hacker."
|
|
||||||
:link '(url-link "https://doomemacs.org"))
|
|
||||||
|
|
||||||
(defconst doom-version "3.0.0-dev"
|
|
||||||
"Current version of Doom Emacs core.")
|
|
||||||
|
|
||||||
(defconst doom-modules-version "22.09.0-dev"
|
|
||||||
"Current version of Doom Emacs.")
|
|
||||||
|
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;;; Directory variables
|
;;; File/directory variables
|
||||||
|
|
||||||
(defconst doom-emacs-dir user-emacs-directory
|
|
||||||
"The path to the currently loaded .emacs.d directory. Must end with a slash.")
|
|
||||||
|
|
||||||
(defconst doom-core-dir (file-name-directory load-file-name)
|
|
||||||
"The root directory of Doom's core files. Must end with a slash.")
|
|
||||||
|
|
||||||
(defconst doom-modules-dir (expand-file-name "modules/" doom-emacs-dir)
|
(defconst doom-modules-dir (expand-file-name "modules/" doom-emacs-dir)
|
||||||
"The root directory for Doom's modules. Must end with a slash.")
|
"The root directory for Doom's modules. Must end with a slash.")
|
||||||
|
@ -201,17 +304,6 @@
|
||||||
Defaults to ~/.config/doom, ~/.doom.d or the value of the DOOMDIR envvar;
|
Defaults to ~/.config/doom, ~/.doom.d or the value of the DOOMDIR envvar;
|
||||||
whichever is found first. Must end in a slash.")
|
whichever is found first. Must end in a slash.")
|
||||||
|
|
||||||
(defconst doom-profile
|
|
||||||
(if-let (profile (getenv-internal "DOOMPROFILE"))
|
|
||||||
;; DEPRECATED Use `string-search' once 27 support is dropped
|
|
||||||
(if (string-match-p "@" profile)
|
|
||||||
profile
|
|
||||||
(concat profile "@latest"))
|
|
||||||
;; TODO Restore this when profile system is complete
|
|
||||||
;; "default@latest"
|
|
||||||
)
|
|
||||||
"The name of the active profile.")
|
|
||||||
|
|
||||||
;; TODO Use me
|
;; TODO Use me
|
||||||
(defconst doom-profiles-file
|
(defconst doom-profiles-file
|
||||||
(expand-file-name "profiles.el" user-emacs-directory)
|
(expand-file-name "profiles.el" user-emacs-directory)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue