refactor: move init helpers to core-lib

The functions have more general use-cases and should be considered part
of Doom's stdlib.
This commit is contained in:
Henrik Lissner 2021-10-08 23:31:03 +02:00
parent 91770b66e5
commit 094b4c1023
2 changed files with 108 additions and 111 deletions

View file

@ -1,5 +1,8 @@
;;; core-lib.el -*- lexical-binding: t; -*-
(require 'cl-lib)
;;
;;; Helpers
@ -112,6 +115,87 @@ at the values with which this function was called."
if (lookup-key keymap keys)
return it)))
(defun doom-load-envvars-file (file &optional noerror)
"Read and set envvars from FILE.
If NOERROR is non-nil, don't throw an error if the file doesn't exist or is
unreadable. Returns the names of envvars that were changed."
(if (null (file-exists-p file))
(unless noerror
(signal 'file-error (list "No envvar file exists" file)))
(with-temp-buffer
(insert-file-contents file)
(when-let (env (read (current-buffer)))
(setq-default
process-environment
(append env (default-value 'process-environment))
exec-path
(append (split-string (getenv "PATH") path-separator t)
(list exec-directory))
shell-file-name
(or (getenv "SHELL")
(default-value 'shell-file-name)))
env))))
(defun doom-run-hook (hook)
"Run HOOK (a hook function) with better error handling.
Meant to be used with `run-hook-wrapped'."
(condition-case-unless-debug e
(funcall hook)
(error
(signal 'doom-hook-error (list hook e))))
;; return nil so `run-hook-wrapped' won't short circuit
nil)
(defun doom-run-hooks (&rest hooks)
"Run HOOKS (a list of hook variable symbols) with better error handling.
Is used as advice to replace `run-hooks'."
(dolist (hook hooks)
(condition-case-unless-debug e
(run-hook-wrapped hook #'doom-run-hook)
(doom-hook-error
(unless debug-on-error
(lwarn hook :error "Error running hook %S because: %s"
(if (symbolp (cadr e))
(symbol-name (cadr e))
(cadr e))
(caddr e)))
(signal 'doom-hook-error (cons hook (cdr e)))))))
(defun doom-run-hook-on (hook-var trigger-hooks)
"Configure HOOK-VAR to be invoked exactly once when any of the TRIGGER-HOOKS
are invoked *after* Emacs has initialized (to reduce false positives). Once
HOOK-VAR is triggered, it is reset to nil.
HOOK-VAR is a quoted hook.
TRIGGER-HOOK is a list of quoted hooks and/or sharp-quoted functions."
(dolist (hook trigger-hooks)
(let ((fn (intern (format "%s-init-on-%s-h" hook-var hook))))
(fset
fn (lambda (&rest _)
;; Only trigger this after Emacs has initialized.
(when (and after-init-time
(or (daemonp)
;; In some cases, hooks may be lexically unset to
;; inhibit them during expensive batch operations on
;; buffers (such as when processing buffers
;; internally). In these cases we should assume this
;; hook wasn't invoked interactively.
(and (boundp hook)
(symbol-value hook))))
(doom-run-hooks hook-var)
(set hook-var nil))))
(cond ((daemonp)
;; In a daemon session we don't need all these lazy loading
;; shenanigans. Just load everything immediately.
(add-hook 'after-init-hook fn 'append))
((eq hook 'find-file-hook)
;; Advise `after-find-file' instead of using `find-file-hook'
;; because the latter is triggered too late (after the file has
;; opened and modes are all set up).
(advice-add 'after-find-file :before fn '((depth . -101))))
((add-hook hook fn -101)))
fn)))
;;
;;; Sugars

View file

@ -482,12 +482,7 @@ If this is a daemon session, load them all immediately instead."
;;
;;; Bootstrap helpers
(defun doom-finish-init-h ()
"Set `doom-init-time'."
(setq doom-init-time
(float-time (time-subtract (current-time) before-init-time))))
;;; Bootstrapper
(defun doom-display-benchmark-h (&optional return-p)
"Display a benchmark including number of packages and modules loaded.
@ -497,92 +492,9 @@ If RETURN-P, return the message as a string instead of displaying it."
"Doom loaded %d packages across %d modules in %.03fs"
(- (length load-path) (length (get 'load-path 'initial-value)))
(if doom-modules (hash-table-count doom-modules) 0)
(or doom-init-time (doom-finish-init-h))))
(defun doom-load-envvars-file (file &optional noerror)
"Read and set envvars from FILE.
If NOERROR is non-nil, don't throw an error if the file doesn't exist or is
unreadable. Returns the names of envvars that were changed."
(if (null (file-exists-p file))
(unless noerror
(signal 'file-error (list "No envvar file exists" file)))
(with-temp-buffer
(insert-file-contents file)
(when-let (env (read (current-buffer)))
(setq-default
process-environment
(append env (default-value 'process-environment))
exec-path
(append (split-string (getenv "PATH") path-separator t)
(list exec-directory))
shell-file-name
(or (getenv "SHELL")
(default-value 'shell-file-name)))
env))))
(defun doom-run-hook (hook)
"Run HOOK (a hook function) with better error handling.
Meant to be used with `run-hook-wrapped'."
(condition-case-unless-debug e
(funcall hook)
(error
(signal 'doom-hook-error (list hook e))))
;; return nil so `run-hook-wrapped' won't short circuit
nil)
(defun doom-run-hooks (&rest hooks)
"Run HOOKS (a list of hook variable symbols) with better error handling.
Is used as advice to replace `run-hooks'."
(dolist (hook hooks)
(condition-case-unless-debug e
(run-hook-wrapped hook #'doom-run-hook)
(doom-hook-error
(unless debug-on-error
(lwarn hook :error "Error running hook %S because: %s"
(if (symbolp (cadr e))
(symbol-name (cadr e))
(cadr e))
(caddr e)))
(signal 'doom-hook-error (cons hook (cdr e)))))))
(defun doom-run-hook-on (hook-var trigger-hooks)
"Configure HOOK-VAR to be invoked exactly once when any of the TRIGGER-HOOKS
are invoked *after* Emacs has initialized (to reduce false positives). Once
HOOK-VAR is triggered, it is reset to nil.
HOOK-VAR is a quoted hook.
TRIGGER-HOOK is a list of quoted hooks and/or sharp-quoted functions."
(dolist (hook trigger-hooks)
(let ((fn (intern (format "%s-init-on-%s-h" hook-var hook))))
(fset
fn (lambda (&rest _)
;; Only trigger this after Emacs has initialized.
(when (and after-init-time
(or (daemonp)
;; In some cases, hooks may be lexically unset to
;; inhibit them during expensive batch operations on
;; buffers (such as when processing buffers
;; internally). In these cases we should assume this
;; hook wasn't invoked interactively.
(and (boundp hook)
(symbol-value hook))))
(doom-run-hooks hook-var)
(set hook-var nil))))
(cond ((daemonp)
;; In a daemon session we don't need all these lazy loading
;; shenanigans. Just load everything immediately.
(add-hook 'after-init-hook fn 'append))
((eq hook 'find-file-hook)
;; Advise `after-find-file' instead of using `find-file-hook'
;; because the latter is triggered too late (after the file has
;; opened and modes are all set up).
(advice-add 'after-find-file :before fn '((depth . -101))))
((add-hook hook fn -101)))
fn)))
;;
;;; Bootstrapper
(or doom-init-time
(setq doom-init-time
(float-time (time-subtract (current-time) before-init-time))))))
(defun doom-initialize (&optional force-p)
"Bootstrap Doom, if it hasn't already (or if FORCE-P is non-nil).
@ -598,11 +510,11 @@ The overall load order of Doom is as follows:
~/.emacs.d/core/core.el
~/.doom.d/init.el
Module init.el files
`doom-before-init-modules-hook'
Module config.el files
~/.doom.d/config.el
`doom-init-modules-hook'
`doom-after-init-modules-hook' (alias for `after-init-hook')
Module config.el files
`doom-configure-modules-hook'
~/.doom.d/config.el
`after-init-hook'
`emacs-startup-hook'
`doom-init-ui-hook'
`window-setup-hook'
@ -616,7 +528,7 @@ to least)."
;; Reset as much state as possible, so `doom-initialize' can be treated like
;; a reset function. e.g. when reloading the config.
(dolist (var '(exec-path load-path process-environment))
(dolist (var '(exec-path load-path))
(set-default var (get var 'initial-value)))
;; Doom caches a lot of information in `doom-autoloads-file'. Module and
@ -645,9 +557,10 @@ to least)."
;; Load shell environment, optionally generated from 'doom env'. No need
;; to do so if we're in terminal Emacs, where Emacs correctly inherits
;; your shell environment.
(if (and (or (display-graphic-p)
(when (and (or (display-graphic-p)
(daemonp))
doom-env-file)
(setq-default process-environment (get 'process-environment 'initial-value))
(doom-load-envvars-file doom-env-file 'noerror))
;; Loads `use-package' and all the helper macros modules (and users) can use
@ -661,6 +574,7 @@ to least)."
(eval-after-load 'package '(require 'core-packages))
(eval-after-load 'straight '(doom-initialize-packages))
(unless noninteractive
;; Bootstrap the interactive session
(add-hook 'after-change-major-mode-hook #'doom-run-local-var-hooks-maybe-h 100)
(add-hook 'hack-local-variables-hook #'doom-run-local-var-hooks-h)
@ -670,8 +584,7 @@ to least)."
(doom-run-hook-on 'doom-first-file-hook '(find-file-hook dired-initial-position-hook))
(doom-run-hook-on 'doom-first-input-hook '(pre-command-hook))
;; Bootstrap our GC manager
(add-hook 'doom-first-buffer-hook #'gcmh-mode))
(add-hook 'doom-first-buffer-hook #'gcmh-mode)))
doom-init-p)