diff --git a/core/core-lib.el b/core/core-lib.el index 348141fe1..6f173459e 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -1,8 +1,7 @@ ;;; core-lib.el -*- lexical-binding: t; -*- -(let ((load-path doom--initial-load-path)) - (require 'subr-x) - (require 'cl-lib)) +(require 'cl-lib) +(require 'subr-x) ;; Polyfills (unless EMACS26+ @@ -175,7 +174,7 @@ at the values with which this function was called." "Push VALUES sequentially into PLACE, if they aren't already present. This is a variadic `cl-pushnew'." (let ((var (make-symbol "result"))) - `(dolist (,var (list ,@values)) + `(dolist (,var (list ,@values) (with-no-warnings ,place)) (cl-pushnew ,var ,place :test #'equal)))) (defmacro prependq! (sym &rest lists) @@ -338,7 +337,10 @@ If NOERROR is non-nil, don't throw an error if the file doesn't exist." (setq path (or (dir!) (error "Could not detect path to look for '%s' in" filename)))) - (let ((file (if path `(expand-file-name ,filename ,path) filename))) + (let ((file (if path + `(let (file-name-handler-alist) + (expand-file-name ,filename ,path)) + filename))) `(condition-case e (load ,file ,noerror ,(not doom-debug-mode)) ((debug doom-error) (signal (car e) (cdr e))) @@ -372,29 +374,29 @@ serve as a predicated alternative to `after!'." (put ',fn 'permanent-local-hook t) (add-hook 'after-load-functions #',fn))))) -(defmacro defer-feature! (feature &optional mode) - "Pretend FEATURE hasn't been loaded yet, until FEATURE-hook is triggered. +(defmacro defer-feature! (feature &optional fn) + "Pretend FEATURE hasn't been loaded yet, until FEATURE-hook or FN runs. Some packages (like `elisp-mode' and `lisp-mode') are loaded immediately at startup, which will prematurely trigger `after!' (and `with-eval-after-load') blocks. To get around this we make Emacs believe FEATURE hasn't been loaded yet, -then wait until FEATURE-hook (or MODE-hook, if MODE is provided) is triggered to +then wait until FEATURE-hook (or MODE-hook, if FN is provided) is triggered to reverse this and trigger `after!' blocks at a more reasonable time." (let ((advice-fn (intern (format "doom--defer-feature-%s-a" feature))) - (mode (or mode feature))) + (fn (or fn feature))) `(progn (setq features (delq ',feature features)) - (advice-add #',mode :before #',advice-fn) + (advice-add #',fn :before #',advice-fn) (defun ,advice-fn (&rest _) - ;; Some plugins (like yasnippet) will invoke a mode early to parse + ;; Some plugins (like yasnippet) will invoke a fn early to parse ;; code, which would prematurely trigger this. In those cases, well ;; behaved plugins will use `delay-mode-hooks', which we can check for: - (when (and ,(intern (format "%s-hook" mode)) + (when (and ,(intern (format "%s-hook" fn)) (not delay-mode-hooks)) ;; ...Otherwise, announce to the world this package has been loaded, ;; so `after!' handlers can react. (provide ',feature) - (advice-remove #',mode #',advice-fn)))))) + (advice-remove #',fn #',advice-fn)))))) (defmacro quiet! (&rest forms) "Run FORMS without generating any output. diff --git a/core/core.el b/core/core.el index b598d4512..df4138747 100644 --- a/core/core.el +++ b/core/core.el @@ -1,5 +1,16 @@ ;;; core.el --- the heart of the beast -*- lexical-binding: t; -*- +(defconst doom-version "2.0.9" + "Current version of Doom Emacs.") + +(defconst EMACS26+ (> emacs-major-version 25)) +(defconst EMACS27+ (> emacs-major-version 26)) +(defconst IS-MAC (eq system-type 'darwin)) +(defconst IS-LINUX (eq system-type 'gnu/linux)) +(defconst IS-WINDOWS (memq system-type '(cygwin windows-nt ms-dos))) +(defconst IS-BSD (or IS-MAC (eq system-type 'berkeley-unix))) + +;; (defvar doom-init-p nil "Non-nil if Doom has been initialized.") @@ -19,18 +30,6 @@ DEBUG envvar will enable this at startup.") "The default value to use for `gc-cons-threshold'. If you experience freezing, decrease this. If you experience stuttering, increase this.") -;;; Constants -(defconst doom-version "2.0.9" - "Current version of Doom Emacs.") - -(defconst EMACS26+ (> emacs-major-version 25)) -(defconst EMACS27+ (> emacs-major-version 26)) - -(defconst IS-MAC (eq system-type 'darwin)) -(defconst IS-LINUX (eq system-type 'gnu/linux)) -(defconst IS-WINDOWS (memq system-type '(cygwin windows-nt ms-dos))) -(defconst IS-BSD (or IS-MAC (eq system-type 'berkeley-unix))) - ;;; Directories/files (defvar doom-emacs-dir (eval-when-compile (file-truename user-emacs-directory)) @@ -63,9 +62,7 @@ dependencies or long-term shared data. Must end with a slash.") Use this for files that change often, like cache files. Must end with a slash.") (defvar doom-elpa-dir (concat doom-local-dir "elpa/") - "Where package.el and quelpa plugins (and their caches) are stored. - -Must end with a slash.") + "Where package.el plugins (and their caches) are stored. Must end with a slash.") (defvar doom-docs-dir (concat doom-emacs-dir "docs/") "Where Doom's documentation files are stored. Must end with a slash.") @@ -225,8 +222,8 @@ users).") (setq fast-but-imprecise-scrolling t) ;; Resizing the Emacs frame can be a terribly expensive part of changing the -;; font. By inhibiting this, we easily halve startup times with fonts that are -;; larger than the system default. +;; 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) ;; Don't ping things that look like domain names. @@ -323,7 +320,8 @@ This is already done by the lang/org module, however. If you want to disable incremental loading altogether, either remove `doom-load-packages-incrementally-h' from `emacs-startup-hook' or set -`doom-incremental-first-idle-timer' to nil.") +`doom-incremental-first-idle-timer' to nil. Incremental loading does not occur +in daemon sessions (they are loaded immediately at startup).") (defvar doom-incremental-first-idle-timer 2 "How long (in idle seconds) until incremental loading starts. @@ -404,7 +402,8 @@ If RETURN-P, return the message as a string instead of displaying it." (- (length load-path) (length doom--initial-load-path)) (if doom-modules (hash-table-count doom-modules) 0) (or doom-init-time - (setq doom-init-time (float-time (time-subtract (current-time) before-init-time)))))) + (setq doom-init-time + (float-time (time-subtract (current-time) before-init-time)))))) (defun doom-load-autoloads-file (file) "Tries to load FILE (an autoloads file). Return t on success, throws an error @@ -422,25 +421,28 @@ in interactive sessions, nil otherwise (but logs a warning)." (if (not (file-readable-p 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) - (while (re-search-forward "\n\\([^= \n]+\\)=" nil t) - (save-excursion - (let ((var (match-string 1)) - (value (buffer-substring-no-properties - (point) - (1- (or (when (re-search-forward "^\\([^= ]+\\)=" nil t) - (line-beginning-position)) - (point-max)))))) - (setenv var value))))) - (setq-default - exec-path (append (split-string (getenv "PATH") - (if IS-WINDOWS ";" ":")) - (list exec-directory)) - shell-file-name (or (getenv "SHELL") - shell-file-name)) - t)) + (let (vars) + (with-temp-buffer + (insert-file-contents file) + (search-forward "\n\n") + (while (re-search-forward "\n\\([^= \n]+\\)=" nil t) + (save-excursion + (let ((var (match-string 1)) + (value (buffer-substring-no-properties + (point) + (1- (or (when (re-search-forward "^\\([^= ]+\\)=" nil t) + (line-beginning-position)) + (point-max)))))) + (push (cons var value) vars) + (setenv var value))))) + (when vars + (setq-default + exec-path (append (split-string (getenv "PATH") + (if IS-WINDOWS ";" ":")) + (list exec-directory)) + shell-file-name (or (getenv "SHELL") + shell-file-name)) + (nreverse vars))))) (defun doom-initialize (&optional force-p) "Bootstrap Doom, if it hasn't already (or if FORCE-P is non-nil). @@ -510,9 +512,9 @@ to least)." (require 'core-packages) (doom-initialize-packages))) - ;; 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). + ;; Eagerly load these libraries because we may be in a session that + ;; hasn't been fully initialized (e.g. where autoloads files haven't + ;; been generated or `load-path' populated). (mapc (doom-rpartial #'load 'noerror 'nomessage) (file-expand-wildcards (concat doom-core-dir "autoload/*.el"))) @@ -533,10 +535,11 @@ to least)." force-p (not doom-interactive-mode)) (unless core-autoloads-p - (message "Your Doom core autoloads file is missing")) + (warn "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"))))) + (warn "Your package autoloads file is missing")) + (signal 'doom-autoload-error "Run `bin/doom refresh' to generate them"))) + t)) (defun doom-initialize-core () "Load Doom's core files for an interactive session."