diff --git a/early-init.el b/early-init.el index d81d63c14..ec21f4a42 100644 --- a/early-init.el +++ b/early-init.el @@ -31,158 +31,113 @@ ;; cause stuttering/freezes. (setq gc-cons-threshold most-positive-fixnum) -(eval-and-compile - ;; PERF: Don't use precious startup time checking mtime on elisp bytecode. - ;; Ensuring correctness is 'doom sync's job, not the interactive session's. - ;; Still, stale byte-code will cause *heavy* losses in startup efficiency. - (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' - -;; Prevent recursive profile processing, in case you're loading a Doom profile. -(unless (boundp 'doom-version) - ;; Not using `command-switch-alist' to process --profile and --init-directory - ;; was intentional. `command-switch-alist' is processed too late at startup to - ;; change `user-emacs-directory' in time. - - ;; DEPRECATED: Backported from Emacs 29. - (let ((initdir (or (cadr (member "--init-directory" command-line-args)) - (getenv-internal "EMACSDIR")))) - (when initdir - ;; FIX: Discard the switch to prevent "invalid option" errors later. - (push (cons "--init-directory" (lambda (_) (pop argv))) command-switch-alist) - (setq user-emacs-directory (expand-file-name initdir)))) - - (let ((profile (or (cadr (member "--profile" command-line-args)) - (getenv-internal "DOOMPROFILE")))) - (when profile - ;; FIX: Discard the switch to prevent "invalid option" errors later. - (push (cons "--profile" (lambda (_) (pop argv))) command-switch-alist) - ;; While processing the requested profile, Doom loosely expects - ;; `user-emacs-directory' to be changed. If it doesn't, then you're using - ;; profiles.el as a glorified, runtime dir-locals.el (which is fine, if - ;; intended). - (catch 'found - (let ((profiles-file (expand-file-name "profiles.el" user-emacs-directory))) - (when (file-exists-p profiles-file) - (with-temp-buffer - (let ((coding-system-for-read 'utf-8-auto)) - (insert-file-contents profiles-file)) - (condition-case-unless-debug e - (let ((profile-data (cdr (assq (intern profile) (read (current-buffer)))))) - (dolist (var profile-data (if profile-data (throw 'found t))) - (if (eq (car var) 'env) - (dolist (env (cdr var)) (setenv (car env) (cdr env))) - (set (car var) (cdr var))))) - (error (error "Failed to parse profiles.el: %s" (error-message-string e)))))) - ;; If the requested profile isn't in profiles.el, then see if - ;; $EMACSDIR/profiles/$DOOMPROFILE exists. These are implicit - ;; profiles, where `emacs --profile foo` will be equivalent to `emacs - ;; --init-directory $EMACSDIR/profile/foo', if that directory exists. - (let ((profile-dir - (expand-file-name - profile (or (getenv-internal "DOOMPROFILESDIR") - (expand-file-name "profiles/" user-emacs-directory))))) - (when (file-directory-p profile-dir) - (setq user-emacs-directory profile-dir) - (throw 'found t))) - - (user-error "No %S profile found" profile))) - - (when init-file-debug - (message "Selected profile: %s" profile)) - ;; Ensure the selected profile persists through the session - (setenv "DOOMPROFILE" profile)))) +;; PERF: Don't use precious startup time checking mtime on elisp bytecode. +;; Ensuring correctness is 'doom sync's job, not the interactive session's. +;; Still, stale byte-code will cause *heavy* losses in startup efficiency. +(setq load-prefer-newer noninteractive) ;; ;;; Bootstrap -(let (init-file) - ;; Load the heart of Doom Emacs - (if (load (expand-file-name "lisp/doom" user-emacs-directory) 'noerror 'nomessage) - ;; ...and prepare for an interactive session. - (if noninteractive - (require 'doom-cli) - (setq init-file (expand-file-name "doom-start" doom-core-dir))) - ;; ...but if that fails, then this is likely not a Doom config. - (setq early-init-file (expand-file-name "early-init" user-emacs-directory)) - (load early-init-file 'noerror 'nomessage)) +(or + ;; PERF: `file-name-handler-alist' is consulted often. Unsetting it offers a + ;; notable saving in startup time. + (let (file-name-handler-alist) + ;; 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. - ;; 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 - ;; ~/.emacs and ~/_emacs. And skips ~/.emacs.d/init.el, which won't exist if - ;; you're using Doom (fyi: doom hackers or chemacs users could then use - ;; $EMACSDIR as their $DOOMDIR, if they wanted). - ;; - Later, 'doom sync' will dynamically generate its bootstrap file, which - ;; 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) - "Initialize Doom Emacs in an interactive session." - (list (lambda () - (or init-file - (expand-file-name "init.el" user-emacs-directory))) - (when (boundp 'doom-profiles-dir) - (lambda () - (expand-file-name "safe-mode@static/init.el" doom-profiles-dir))) - (caddr args)))) + ;; REVIEW: Backported from Emacs 29. Remove when 28 support is dropped. + (let ((initdir (or (cadr (member "--init-directory" command-line-args)) + (getenv-internal "EMACSDIR")))) + (when initdir + ;; FIX: Discard the switch to prevent "invalid option" errors later. + (push (cons "--init-directory" (lambda (_) (pop argv))) command-switch-alist) + (setq user-emacs-directory (expand-file-name initdir)))) + ;; Initialize a known profile, if requested. + (let ((profile (or (cadr (member "--profile" command-line-args)) + (getenv-internal "DOOMPROFILE")))) + (when profile + ;; FIX: Discard the switch to prevent "invalid option" errors later. + (push (cons "--profile" (lambda (_) (pop argv))) command-switch-alist) + ;; While processing the requested profile, Doom loosely expects + ;; `user-emacs-directory' to be changed. If it doesn't, then you're using + ;; profiles.el as a glorified, runtime dir-locals.el (which is fine, if + ;; intended). + (catch 'found + (let ((profiles-file (expand-file-name "profiles.el" user-emacs-directory))) + (when (file-exists-p profiles-file) + (with-temp-buffer + (let ((coding-system-for-read 'utf-8-auto)) + (insert-file-contents profiles-file)) + (condition-case-unless-debug e + (let ((profile-data (cdr (assq (intern profile) (read (current-buffer)))))) + (dolist (var profile-data (if profile-data (throw 'found t))) + (if (eq (car var) 'env) + (dolist (env (cdr var)) (setenv (car env) (cdr env))) + (set (car var) (cdr var))))) + (error (error "Failed to parse profiles.el: %s" (error-message-string e)))))) + ;; If the requested profile isn't in profiles.el, then see if + ;; $EMACSDIR/profiles/$DOOMPROFILE exists. These are implicit + ;; profiles, where `emacs --profile foo` will be equivalent to `emacs + ;; --init-directory $EMACSDIR/profile/foo', if that directory exists. + (let ((profile-dir + (expand-file-name + profile (or (getenv-internal "DOOMPROFILESDIR") + (expand-file-name "profiles/" user-emacs-directory))))) + (when (file-directory-p profile-dir) + (setq user-emacs-directory profile-dir) + (throw 'found t))) + (user-error "No %S profile found" profile))) + (when init-file-debug + (message "Selected profile: %s" profile)) + ;; Ensure the selected profile persists through the session + (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. + ;; + ;; 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 + ;; `load'. See the docs of `load' for details. + (or (let ((load-suffixes '(".elc" ".el"))) + ;; Load the heart of Doom Emacs. + (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 + (doom-require 'doom-cli) + ;; HACK: This advice hijacks Emacs' initfile resolver to replace + ;; $EMACSDIR/init.el (and ~/.emacs or ~/_emacs) with a + ;; a Doom-provided init file. Later, this file will be + ;; generated by 'doom sync' for the active Doom profile; + ;; `doom-start' is its stand-in until that's implemented. + ;; + ;; This effort spares Emacs the overhead of searching for + ;; initfiles we don't care about, enables savvier hackers to + ;; use $EMACSDIR as their $DOOMDIR, and gives us an opportunity + ;; to fall back to a "safe mode", so we can present a more + ;; user-friendly failure state. + (define-advice startup--load-user-init-file (:filter-args (args) init-doom) + "Initialize Doom Emacs in an interactive session." + (list (lambda () + (file-name-concat doom-core-dir "doom-start")) + (lambda () + (file-name-concat doom-profiles-dir "safe-mode" "init.el")) + (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 diff --git a/lisp/doom-start.el b/lisp/doom-start.el index c3b442ee5..d987177af 100644 --- a/lisp/doom-start.el +++ b/lisp/doom-start.el @@ -95,47 +95,6 @@ (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 ;; 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: diff --git a/lisp/doom.el b/lisp/doom.el index a958e9ee1..d252b216c 100644 --- a/lisp/doom.el +++ b/lisp/doom.el @@ -88,37 +88,147 @@ ;; Remember these variables' initial values, so we can safely reset them at a ;; 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) - (put var 'initial-value (default-value var)))) - -;; Ensure Doom's core libraries are visible for loading -(add-to-list 'load-path (file-name-directory load-file-name)) + (put var 'initial-value (default-toplevel-value var)))) ;; Since Emacs 27, package initialization occurs before `user-init-file' is ;; loaded, but after `early-init-file'. Doom handles package initialization, so ;; we must prevent Emacs from doing it again. (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) -(require 'subr-x) -;; ...then load *the* one -(require 'doom-lib) +;; +;;; Startup optimizations + +;; Here are Doom's hackiest (and least offensive) startup optimizations. They +;; 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 (defconst IS-MAC (eq system-type 'darwin)) @@ -147,10 +257,17 @@ (defconst MODULES (featurep 'dynamic-modules)) (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) -;; -;;; Cross-platform fixes - +;;; Platform-specific fixes ;; Fix $HOME on Windows, where it's not normally defined, because many unix ;; tools expect it. (when IS-WINDOWS @@ -160,29 +277,15 @@ (setenv "HOME" realhome) (setq abbreviated-home-dir nil))) - -;; -;;; Core variables - -(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.") +;;; Load Doom stdlib +;; Ensure Doom's core libraries are visible for loading +(add-to-list 'load-path doom-core-dir) +;; Load just the... bear necessities~ +(require 'doom-lib) ;; -;;; 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.") +;;; File/directory variables (defconst doom-modules-dir (expand-file-name "modules/" doom-emacs-dir) "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; 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 (defconst doom-profiles-file (expand-file-name "profiles.el" user-emacs-directory)