Major refactor of Doom bootstrap process
+ New `input` and `buffer` support for :defer in def-package! can now defer packages until the first command invoked after startup or first interactive buffer switch, respectively + Exploit these new :defer techniques to lazy-load many core packages, netting Doom a 20-30% decrease in startup time + Various userland macros (like package!, def-package-hook!, packages!, and disable-packages!) will now throw an error if used incorrectly (i.e. outside of their intended files; e.g. package! should be used in packages.el files) + Removed support for multiple/nested doom! calls. There should only be THE ONE in ~/.doom.d/init.el (or ~/.config/doom/init.el) + Fix an issue where load-path and auto-mode-list modifications would not persist because doom-packages-file was cached too late. + Added package-activated-list to cached variables in doom-packages-file, thus we no longer need custom-file. + Load Doom core files from doom-initialize. Now doom-initialize can be called from state-dependent non-interactive functions, instead of reloading core/core.el, which was clumsy + Removed the doom-post-init-hook hook. There was no reason for it to exist when doom-init-hook can simply be appended to
This commit is contained in:
parent
bb4a8e98e6
commit
bec79a3d4c
6 changed files with 268 additions and 229 deletions
|
@ -59,37 +59,48 @@ fundamental-mode) for performance sake."
|
|||
(fundamental-mode))))
|
||||
(add-hook 'find-file-hook #'doom|check-large-file)
|
||||
|
||||
(push '("/LICENSE$" . text-mode) auto-mode-alist)
|
||||
|
||||
|
||||
;;
|
||||
;; Built-in plugins
|
||||
;;
|
||||
|
||||
(electric-indent-mode -1) ; enabled by default in Emacs 25+. No thanks.
|
||||
|
||||
(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p)
|
||||
|
||||
;; revert buffers for changed files
|
||||
(global-auto-revert-mode 1)
|
||||
(setq auto-revert-verbose nil)
|
||||
(def-package! autorevert
|
||||
:defer buffer
|
||||
:config
|
||||
(setq auto-revert-verbose nil)
|
||||
(global-auto-revert-mode +1))
|
||||
|
||||
;; enabled by default in Emacs 25+. No thanks.
|
||||
(electric-indent-mode -1)
|
||||
|
||||
;; savehist / saveplace
|
||||
(setq savehist-file (concat doom-cache-dir "savehist")
|
||||
;; persist variables across sessions
|
||||
(def-package! savehist
|
||||
:defer (input . 1)
|
||||
:config
|
||||
(setq savehist-file (concat doom-cache-dir "savehist")
|
||||
savehist-save-minibuffer-history t
|
||||
savehist-autosave-interval nil ; save on kill only
|
||||
savehist-additional-variables '(kill-ring search-ring regexp-search-ring)
|
||||
save-place-file (concat doom-cache-dir "saveplace"))
|
||||
(add-hook! 'doom-init-hook #'(savehist-mode save-place-mode))
|
||||
(defun doom*recenter-on-load-saveplace (&rest _)
|
||||
savehist-additional-variables '(kill-ring search-ring regexp-search-ring))
|
||||
(savehist-mode +1))
|
||||
|
||||
;; persistent point location in buffers
|
||||
(def-package! saveplace
|
||||
:defer buffer
|
||||
:config
|
||||
(setq save-place-file (concat doom-cache-dir "saveplace"))
|
||||
(defun doom*recenter-on-load-saveplace (&rest _)
|
||||
"Recenter on cursor when loading a saved place."
|
||||
(if buffer-file-name (ignore-errors (recenter))))
|
||||
(advice-add #'save-place-find-file-hook :after-while #'doom*recenter-on-load-saveplace)
|
||||
(advice-add #'save-place-find-file-hook
|
||||
:after-while #'doom*recenter-on-load-saveplace)
|
||||
(save-place-mode +1))
|
||||
|
||||
;; Keep track of recently opened files
|
||||
(def-package! recentf
|
||||
:hook (doom-init . recentf-mode)
|
||||
:defer (input . 1)
|
||||
:commands recentf-open-files
|
||||
:config
|
||||
(setq recentf-save-file (concat doom-cache-dir "recentf")
|
||||
recentf-auto-cleanup 60
|
||||
|
@ -101,7 +112,15 @@ fundamental-mode) for performance sake."
|
|||
"^/tmp/" "^/ssh:" "\\.?ido\\.last$" "\\.revive$" "/TAGS$"
|
||||
"^/var/folders/.+$"
|
||||
;; ignore private DOOM temp files (but not all of them)
|
||||
(concat "^" (file-truename doom-local-dir)))))
|
||||
(concat "^" (file-truename doom-local-dir))))
|
||||
(recentf-mode +1))
|
||||
|
||||
(def-package! server
|
||||
:when (display-graphic-p)
|
||||
:defer 2
|
||||
:config
|
||||
(unless (server-running-p)
|
||||
(server-start)))
|
||||
|
||||
|
||||
;;
|
||||
|
@ -110,10 +129,9 @@ fundamental-mode) for performance sake."
|
|||
|
||||
;; Auto-close delimiters and blocks as you type
|
||||
(def-package! smartparens
|
||||
:defer (buffer . 2)
|
||||
:config
|
||||
(smartparens-global-mode +1)
|
||||
(require 'smartparens-config)
|
||||
|
||||
(setq sp-highlight-pair-overlay nil
|
||||
sp-cancel-autoskip-on-backward-movement nil
|
||||
sp-show-pair-delay 0
|
||||
|
@ -124,12 +142,15 @@ fundamental-mode) for performance sake."
|
|||
(add-hook 'evil-replace-state-exit-hook #'turn-on-smartparens-mode)
|
||||
|
||||
(sp-local-pair '(xml-mode nxml-mode php-mode) "<!--" "-->"
|
||||
:post-handlers '(("| " "SPC"))))
|
||||
:post-handlers '(("| " "SPC")))
|
||||
|
||||
(smartparens-global-mode +1))
|
||||
|
||||
;; Branching undo
|
||||
(def-package! undo-tree
|
||||
:hook (doom-init . global-undo-tree-mode)
|
||||
:defer input
|
||||
:config
|
||||
(global-undo-tree-mode +1)
|
||||
;; persistent undo history is known to cause undo history corruption, which
|
||||
;; can be very destructive! So disable it!
|
||||
(setq undo-tree-auto-save-history nil
|
||||
|
|
|
@ -60,6 +60,7 @@ If any hook returns non-nil, all hooks after it are ignored.")
|
|||
|
||||
|
||||
(def-package! hydra
|
||||
:commands (defhydra defhydradio)
|
||||
:init
|
||||
;; In case I later need to wrap defhydra in any special functionality.
|
||||
(defalias 'def-hydra! 'defhydra)
|
||||
|
|
|
@ -73,6 +73,17 @@ missing) and shouldn't be deleted.")
|
|||
(defvar doom-disabled-packages ()
|
||||
"A list of packages that should be ignored by `def-package!'.")
|
||||
|
||||
(defvar doom-deferred-packages
|
||||
'((input)
|
||||
(buffer))
|
||||
"A alist of packages that have been deferred. The CAR is the type of deferral
|
||||
for the package, the CDR is the list of packages.
|
||||
|
||||
input will be loaded on the first action the user invokes
|
||||
after startup.
|
||||
buffer will be loaded on the first new buffer to be opened
|
||||
interactively.")
|
||||
|
||||
(defvar doom-reload-hook nil
|
||||
"A list of hooks to run when `doom/reload-load-path' is called.")
|
||||
|
||||
|
@ -87,10 +98,8 @@ missing) and shouldn't be deleted.")
|
|||
and `auto-mode-alist'.")
|
||||
|
||||
(defvar doom--current-module nil)
|
||||
(defvar doom--init-cache-p nil)
|
||||
(defvar doom--initializing nil)
|
||||
(defvar doom--refreshed-p nil)
|
||||
(defvar generated-autoload-load-name)
|
||||
(defvar doom--stage nil)
|
||||
|
||||
;;
|
||||
(setq autoload-compute-prefixes nil
|
||||
|
@ -134,11 +143,41 @@ and `auto-mode-alist'.")
|
|||
|
||||
|
||||
;;
|
||||
;; Startup benchmark
|
||||
;; Helpers 'n hooks
|
||||
;;
|
||||
|
||||
(defun doom-packages--benchmark ()
|
||||
(format "Doom loaded %s packages across %d modules in %.03fs"
|
||||
(defun doom--assert-stage-p (stage macro)
|
||||
(cl-assert (eq stage doom--stage)
|
||||
nil
|
||||
"Found %s call in non-%s.el file (%s)"
|
||||
macro (symbol-name stage)
|
||||
(if (file-in-directory-p load-file-name doom-emacs-dir)
|
||||
(file-relative-name load-file-name doom-emacs-dir)
|
||||
(abbreviate-file-name load-file-name))))
|
||||
|
||||
(defun doom|refresh-cache ()
|
||||
"Refresh `doom-packages-file', which caches `load-path',
|
||||
`Info-directory-list', `doom-disabled-packages', `auto-mode-alist' and
|
||||
`package-activated-list'."
|
||||
(doom-initialize-packages 'internal)
|
||||
(let ((coding-system-for-write 'emacs-internal))
|
||||
(with-temp-file doom-packages-file
|
||||
(insert ";;; -*- lexical-binding:t -*-\n"
|
||||
";; This file was autogenerated by `doom|refresh-cache', DO NOT EDIT!\n")
|
||||
(prin1 `(setq load-path ',load-path
|
||||
Info-directory-list ',Info-directory-list
|
||||
auto-mode-alist ',auto-mode-alist
|
||||
doom-disabled-packages ',doom-disabled-packages
|
||||
package-activated-list ',package-activated-list)
|
||||
(current-buffer)))))
|
||||
|
||||
(defun doom|display-benchmark (&optional return-p)
|
||||
"Display a benchmark, showing number of packages and modules, and how quickly
|
||||
they were loaded at startup.
|
||||
|
||||
If RETURN-P, return the message as a string instead of displaying it."
|
||||
(funcall (if return-p #'format #'message)
|
||||
"Doom loaded %s packages across %d modules in %.03fs"
|
||||
;; Certainly imprecise, especially where custom additions to
|
||||
;; load-path are concerned, but I don't mind a [small] margin of
|
||||
;; error in the plugin count in exchange for faster startup.
|
||||
|
@ -147,24 +186,14 @@ and `auto-mode-alist'.")
|
|||
(or doom-init-time
|
||||
(setq doom-init-time (float-time (time-subtract (current-time) before-init-time))))))
|
||||
|
||||
(add-hook 'emacs-startup-hook #'doom|display-benchmark)
|
||||
(add-hook 'doom-reload-hook #'doom|display-benchmark)
|
||||
|
||||
|
||||
;;
|
||||
;; Bootstrap API
|
||||
;;
|
||||
|
||||
(defun doom--refresh-cache ()
|
||||
"TODO"
|
||||
(when doom--init-cache-p
|
||||
(doom-initialize-packages 'internal)
|
||||
(unless noninteractive
|
||||
(with-temp-buffer
|
||||
(prin1 `(setq load-path ',load-path
|
||||
Info-directory-list ',Info-directory-list
|
||||
doom-disabled-packages ',doom-disabled-packages)
|
||||
(current-buffer))
|
||||
(write-file doom-packages-file))
|
||||
(setq doom--init-cache-p nil))))
|
||||
|
||||
(defun doom-initialize (&optional force-p)
|
||||
"Bootstrap the bare essentials to get Doom running, if it hasn't already. If
|
||||
FORCE-P is non-nil, do it anyway.
|
||||
|
@ -180,12 +209,14 @@ FORCE-P is non-nil, do it anyway.
|
|||
(require 'cl-lib)
|
||||
(require 'map))
|
||||
(when (or force-p (not doom-init-p))
|
||||
(unless (load doom-autoload-file t t t)
|
||||
;; autoloads file
|
||||
(unless (load doom-autoload-file 'noerror 'nomessage 'nosuffix)
|
||||
(unless noninteractive
|
||||
(error "No autoloads file! Run make autoloads")))
|
||||
(when (and noninteractive (file-exists-p doom-packages-file))
|
||||
;; packages.el cache
|
||||
(when (and force-p (file-exists-p doom-packages-file))
|
||||
(delete-file doom-packages-file))
|
||||
(when (or force-p (not (load doom-packages-file t t t)))
|
||||
(unless (load doom-packages-file 'noerror 'nomessage 'nosuffix)
|
||||
;; Ensure core folders exist, otherwise we get errors
|
||||
(dolist (dir (list doom-local-dir doom-etc-dir doom-cache-dir doom-packages-dir))
|
||||
(unless (file-directory-p dir)
|
||||
|
@ -195,7 +226,8 @@ FORCE-P is non-nil, do it anyway.
|
|||
(setq package-activated-list nil
|
||||
package--initialized nil)
|
||||
(let (byte-compile-warnings)
|
||||
(condition-case _ (package-initialize)
|
||||
(condition-case _
|
||||
(package-initialize)
|
||||
('error (package-refresh-contents)
|
||||
(setq doom--refreshed-p t)
|
||||
(package-initialize))))
|
||||
|
@ -213,8 +245,23 @@ FORCE-P is non-nil, do it anyway.
|
|||
(error "✕ Couldn't install %s" package)))
|
||||
(message "Installing core packages...done")))
|
||||
(cl-pushnew doom-core-dir load-path :test #'string=)
|
||||
(setq doom--init-cache-p t))
|
||||
(setq doom-init-p t)))
|
||||
(add-hook 'doom-internal-init-hook #'doom|refresh-cache))
|
||||
(when doom-debug-mode
|
||||
(message "Doom initialized")))
|
||||
;; initialize Doom core
|
||||
(require 'core-lib)
|
||||
(require 'core-os)
|
||||
(unless noninteractive
|
||||
(require 'core-ui)
|
||||
(require 'core-editor)
|
||||
(require 'core-projects)
|
||||
(require 'core-keybinds))
|
||||
;; load input-deferred packages on first `pre-command-hook'
|
||||
(add-transient-hook! 'pre-command-hook
|
||||
(mapc #'require (cdr (assq 'input doom-deferred-packages))))
|
||||
(add-transient-hook! 'doom-after-switch-buffer-hook
|
||||
(when (get-buffer-window)
|
||||
(mapc #'require (cdr (assq 'buffer doom-deferred-packages))))))
|
||||
|
||||
(defun doom-initialize-autoloads ()
|
||||
"Ensures that `doom-autoload-file' exists and is loaded. Otherwise run
|
||||
|
@ -222,14 +269,6 @@ FORCE-P is non-nil, do it anyway.
|
|||
(unless (file-exists-p doom-autoload-file)
|
||||
(quiet! (doom//reload-autoloads))))
|
||||
|
||||
(defun doom-initialize-modules ()
|
||||
"Bootstraps all enabled modules by loading their config.el files."
|
||||
(maphash (lambda (key plist)
|
||||
(let ((doom--current-module key))
|
||||
(load (expand-file-name "config" (plist-get plist :path))
|
||||
'noerror (not doom-debug-mode))))
|
||||
doom-modules))
|
||||
|
||||
(defun doom-initialize-packages (&optional force-p)
|
||||
"Ensures that `doom-packages', `packages-alist' and `quelpa-cache' are
|
||||
populated.
|
||||
|
@ -242,12 +281,40 @@ Use this before any of package.el, quelpa or Doom's package management's API to
|
|||
ensure all the necessary package metadata is initialized and available for
|
||||
them."
|
||||
(with-temp-buffer ; prevent buffer-local settings from propagating
|
||||
(let ((load-prefer-newer t))
|
||||
;; package.el and quelpa handle themselves if their state changes during
|
||||
;; the current session, but if you change an packages.el file in a module,
|
||||
;; there's no non-trivial way to detect that, so we give you a way to
|
||||
;; reload only doom-packages (by passing 'internal as FORCE-P).
|
||||
;; `doom-packages'
|
||||
(when (or force-p (not doom-packages))
|
||||
(unless (eq force-p 'internal)
|
||||
;; `package-alist'
|
||||
(when (or force-p (not (bound-and-true-p package-alist)))
|
||||
(setq load-path doom-site-load-path)
|
||||
(require 'package)
|
||||
(setq package-activated-list nil
|
||||
package--initialized nil)
|
||||
(let (byte-compile-warnings)
|
||||
(condition-case _
|
||||
(package-initialize)
|
||||
('error (package-refresh-contents)
|
||||
(setq doom--refreshed-p t)
|
||||
(package-initialize)))))
|
||||
|
||||
;; `quelpa-cache'
|
||||
(when (or force-p (not (bound-and-true-p quelpa-cache)))
|
||||
(require 'quelpa)
|
||||
(setq quelpa-initialized-p nil)
|
||||
(or (quelpa-setup-p)
|
||||
(error "Could not initialize quelpa"))))
|
||||
|
||||
(setq doom-packages nil)
|
||||
(cl-flet
|
||||
((_load
|
||||
(file &optional noerror interactive)
|
||||
(condition-case-unless-debug ex
|
||||
(let ((load-prefer-newer t)
|
||||
(noninteractive (not interactive)))
|
||||
(let ((noninteractive (not interactive)))
|
||||
(load file noerror 'nomessage 'nosuffix))
|
||||
('error
|
||||
(lwarn 'doom-initialize-packages :warning
|
||||
|
@ -255,13 +322,7 @@ them."
|
|||
(car ex)
|
||||
(file-relative-name file doom-emacs-dir)
|
||||
(error-message-string ex))))))
|
||||
;; package.el and quelpa handle themselves if their state changes during
|
||||
;; the current session, but if you change an packages.el file in a module,
|
||||
;; there's no non-trivial way to detect that, so we give you a way to
|
||||
;; reload only doom-packages.
|
||||
;; `doom-packages'
|
||||
(when (or force-p (not doom-packages))
|
||||
(setq doom-packages nil)
|
||||
(let ((doom--stage 'packages))
|
||||
(_load (expand-file-name "packages.el" doom-core-dir))
|
||||
(cl-loop for key being the hash-keys of doom-modules
|
||||
for path = (doom-module-expand-file (car key) (cdr key) "packages.el")
|
||||
|
@ -270,23 +331,7 @@ them."
|
|||
(cl-loop for dir in doom-psuedo-module-dirs
|
||||
for path = (expand-file-name "packages.el" dir)
|
||||
if (file-exists-p path)
|
||||
do (_load path)))
|
||||
|
||||
(unless (eq force-p 'internal)
|
||||
;; `package-alist'
|
||||
(when (or force-p (not (bound-and-true-p package-alist)))
|
||||
(setq load-path doom-site-load-path)
|
||||
(require 'package)
|
||||
(setq package-activated-list nil)
|
||||
(let (byte-compile-warnings)
|
||||
(package-initialize)))
|
||||
|
||||
;; `quelpa-cache'
|
||||
(when (or force-p (not (bound-and-true-p quelpa-cache)))
|
||||
(require 'quelpa)
|
||||
(setq quelpa-initialized-p nil)
|
||||
(or (quelpa-setup-p)
|
||||
(error "Could not initialize quelpa")))))))
|
||||
do (_load path))))))))
|
||||
|
||||
|
||||
;;
|
||||
|
@ -387,7 +432,8 @@ added, if the file exists."
|
|||
"Bootstraps DOOM Emacs and its modules.
|
||||
|
||||
MODULES is an malformed plist of modules to load."
|
||||
(let (load-forms module file-name-handler-alist)
|
||||
(let (init-forms config-forms file-name-handler-alist)
|
||||
(let (module)
|
||||
(dolist (m modules)
|
||||
(cond ((keywordp m) (setq module m))
|
||||
((not module) (error "No namespace specified in `doom!' for %s" m))
|
||||
|
@ -400,15 +446,20 @@ MODULES is an malformed plist of modules to load."
|
|||
(doom-module-set module submodule :flags flags :path path)
|
||||
(push `(let ((doom--current-module ',(cons module submodule)))
|
||||
(load! init ,path t))
|
||||
load-forms)))))))
|
||||
init-forms)
|
||||
(push `(let ((doom--current-module ',(cons module submodule)))
|
||||
(load! config ,path t))
|
||||
config-forms))))))))
|
||||
`(let (file-name-handler-alist)
|
||||
(setq doom-modules ',doom-modules)
|
||||
(let ((doom--initializing t))
|
||||
,@(nreverse load-forms))
|
||||
,(unless doom--initializing
|
||||
'(unless noninteractive
|
||||
(doom--refresh-cache)
|
||||
(doom-initialize-modules))))))
|
||||
(let ((doom--stage 'init))
|
||||
,@(nreverse init-forms))
|
||||
(unless noninteractive
|
||||
(run-hooks 'doom-internal-init-hook)
|
||||
(let ((doom--stage 'config))
|
||||
,@(nreverse config-forms)
|
||||
(when doom-private-dir
|
||||
(load ,(concat doom-private-dir "config") t t)))))))
|
||||
|
||||
(defmacro def-package! (name &rest plist)
|
||||
"A thin wrapper around `use-package'."
|
||||
|
@ -419,10 +470,17 @@ MODULES is an malformed plist of modules to load."
|
|||
;; If byte-compiling, ignore this package if it doesn't meet the condition.
|
||||
;; This avoids false-positive load errors.
|
||||
(unless (and (bound-and-true-p byte-compile-current-file)
|
||||
(or (and (plist-member plist :if) (not (eval (plist-get plist :if))))
|
||||
(and (plist-member plist :when) (not (eval (plist-get plist :when))))
|
||||
(and (plist-member plist :unless) (eval (plist-get plist :unless)))))
|
||||
`(use-package ,name ,@plist)))
|
||||
(or (and (plist-member plist :if) (not (eval (plist-get plist :if) t)))
|
||||
(and (plist-member plist :when) (not (eval (plist-get plist :when) t)))
|
||||
(and (plist-member plist :unless) (eval (plist-get plist :unless) t))))
|
||||
`(progn
|
||||
,(when-let* ((defer (plist-get plist :defer))
|
||||
(type (or (car-safe defer) defer)))
|
||||
(setq plist (plist-put plist :defer (or (cdr-safe defer) t)))
|
||||
(when (and (not doom-init-p)
|
||||
(assq type doom-deferred-packages))
|
||||
`(push ',name (cdr (assq ',type doom-deferred-packages)))))
|
||||
(use-package ,name ,@plist))))
|
||||
|
||||
(defmacro def-package-hook! (package when &rest body)
|
||||
"Reconfigures a package's `def-package!' block.
|
||||
|
@ -439,6 +497,7 @@ WARNING: If :pre-init or :pre-config hooks return nil, the original
|
|||
`def-package!''s :init/:config block (respectively) is overwritten, so remember
|
||||
to have them return non-nil (or exploit that to overwrite Doom's config)."
|
||||
(declare (indent defun))
|
||||
(doom--assert-stage-p 'init #'package!)
|
||||
(cond ((eq when :disable)
|
||||
(message "Using :disable with `def-package-hook!' is deprecated. Use :disable in `package!' instead.")
|
||||
(ignore (push package doom-disabled-packages)))
|
||||
|
@ -533,16 +592,6 @@ omitted. eg. (featurep! +flag1)"
|
|||
;; Module package macros
|
||||
;;
|
||||
|
||||
(defun doom--assert-file-p (file-name macro)
|
||||
(cl-assert (string= (file-name-nondirectory load-file-name) file-name)
|
||||
nil
|
||||
"Found %s call in non-%s file (%s)"
|
||||
macro
|
||||
file-name
|
||||
(if (file-in-directory-p load-file-name doom-emacs-dir)
|
||||
(file-relative-name load-file-name doom-emacs-dir)
|
||||
(abbreviate-file-name load-file-name))))
|
||||
|
||||
(defmacro package! (name &rest plist)
|
||||
"Declares a package and how to install it (if applicable).
|
||||
|
||||
|
@ -568,7 +617,7 @@ Accepts the following properties:
|
|||
:freeze FORM
|
||||
Do not update this package if FORM is non-nil."
|
||||
(declare (indent defun))
|
||||
(doom--assert-file-p "packages.el" #'package!)
|
||||
(doom--assert-stage-p 'packages #'package!)
|
||||
(cond ((memq name doom-disabled-packages) nil)
|
||||
((let ((disable (plist-get plist :disable)))
|
||||
(and disable (eval disable)))
|
||||
|
@ -599,7 +648,7 @@ Accepts the following properties:
|
|||
packages at once.
|
||||
|
||||
Only use this macro in a module's packages.el file."
|
||||
(doom--assert-file-p "packages.el" #'packages!)
|
||||
(doom--assert-stage-p 'packages #'packages!)
|
||||
`(progn ,@(cl-loop for desc in packages collect `(package! ,@desc))))
|
||||
|
||||
(defmacro disable-packages! (&rest packages)
|
||||
|
@ -607,7 +656,7 @@ Only use this macro in a module's packages.el file."
|
|||
packages at once.
|
||||
|
||||
Only use this macro in a module's packages.el file."
|
||||
(doom--assert-file-p "packages.el" #'disable-packages!)
|
||||
(doom--assert-stage-p 'packages #'disable-packages!)
|
||||
`(setq doom-disabled-packages (append ',packages doom-disabled-packages)))
|
||||
|
||||
(defmacro depends-on! (module submodule &optional flags)
|
||||
|
@ -617,7 +666,7 @@ Only use this macro in a module's packages.el file.
|
|||
|
||||
MODULE is a keyword, and SUBMODULE is a symbol. Under the hood, this simply
|
||||
loads MODULE SUBMODULE's packages.el file."
|
||||
(doom--assert-file-p "packages.el" #'depends-on!)
|
||||
(doom--assert-stage-p 'packages #'depends-on!)
|
||||
`(let ((doom-modules ,doom-modules)
|
||||
(flags ,flags))
|
||||
(when flags
|
||||
|
@ -680,6 +729,7 @@ call `doom//reload-load-path' remotely (through emacsclient)."
|
|||
(message "%d packages reloaded" (length package-alist))
|
||||
(run-hooks 'doom-reload-hook))))
|
||||
|
||||
(defvar generated-autoload-load-name)
|
||||
(defun doom//reload-autoloads ()
|
||||
"Refreshes the autoloads.el file, specified by `doom-autoload-file'.
|
||||
|
||||
|
@ -805,12 +855,11 @@ If RECOMPILE-P is non-nil, only recompile out-of-date files."
|
|||
;; pertinent to files compiled later.
|
||||
(let (noninteractive)
|
||||
;; Core libraries aren't fully loaded in a noninteractive session, so
|
||||
;; we reload it with `noninteractive' set to nil to force them to.
|
||||
(load (expand-file-name "core.el" doom-core-dir) nil t t)
|
||||
;; we pretend to be interactive and reinitialize
|
||||
(doom-initialize)
|
||||
;; In case autoloads.el hasn't been properly generated at this point.
|
||||
(dolist (file (file-expand-wildcards (expand-file-name "autoload/*.el" doom-core-dir)))
|
||||
(load file t t t)))
|
||||
(doom-initialize-modules)
|
||||
(unless (file-exists-p doom-autoload-file)
|
||||
(mapc #'load (file-expand-wildcards (expand-file-name "autoload/*.el" doom-core-dir)))))
|
||||
;; Assemble el files we want to compile; taking into account that
|
||||
;; MODULES may be a list of MODULE/SUBMODULE strings from the command
|
||||
;; line.
|
||||
|
@ -819,6 +868,7 @@ If RECOMPILE-P is non-nil, only recompile out-of-date files."
|
|||
in (or modules (append (list doom-core-dir) (doom-module-load-path)))
|
||||
if (equal target "core")
|
||||
nconc (nreverse (doom-packages--files doom-core-dir "\\.el$"))
|
||||
and collect (expand-file-name "init.el" doom-private-dir)
|
||||
else if (file-directory-p target)
|
||||
nconc (nreverse (doom-packages--files target "\\.el$"))
|
||||
else if (cl-member target doom-psuedo-module-dirs :test #'file-in-directory-p)
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
projectile-ignored-projects '("~/" "/tmp"))
|
||||
|
||||
:config
|
||||
(projectile-mode +1)
|
||||
(add-hook 'dired-before-readin-hook #'projectile-track-known-projects-find-file-hook)
|
||||
(add-hook 'find-file-hook #'doom|autoload-project-mode)
|
||||
(projectile-mode +1)
|
||||
|
||||
;; a more generic project root file
|
||||
(push ".project" projectile-project-root-files-bottom-up)
|
||||
|
|
|
@ -280,15 +280,19 @@ DEFAULT is non-nil, set the default mode-line for all buffers."
|
|||
(add-hook 'isearch-mode-end-hook #'doom|enable-ui-keystrokes)
|
||||
|
||||
;; undo/redo changes to Emacs' window layout
|
||||
(defvar winner-dont-bind-my-keys t) ; I'll bind keys myself
|
||||
(autoload 'winner-mode "winner" nil t)
|
||||
(add-hook 'doom-init-ui-hook #'winner-mode)
|
||||
(def-package! winner
|
||||
:defer buffer
|
||||
:preface (defvar winner-dont-bind-my-keys t) ; I'll bind keys myself
|
||||
:config (winner-mode +1))
|
||||
|
||||
;; highlight matching delimiters
|
||||
(setq show-paren-delay 0.1
|
||||
(def-package! paren
|
||||
:defer input
|
||||
:config
|
||||
(setq show-paren-delay 0.1
|
||||
show-paren-highlight-openparen t
|
||||
show-paren-when-point-inside-paren t)
|
||||
(add-hook 'doom-init-ui-hook #'show-paren-mode)
|
||||
(show-paren-mode +1))
|
||||
|
||||
;;; More reliable inter-window border
|
||||
;; The native border "consumes" a pixel of the fringe on righter-most splits,
|
||||
|
@ -352,10 +356,12 @@ from the default."
|
|||
(prog1 (apply orig-fn args)
|
||||
(run-hooks 'doom-after-switch-buffer-hook)))
|
||||
|
||||
(advice-add #'select-frame :around #'doom*switch-frame-hooks)
|
||||
(advice-add #'select-window :around #'doom*switch-window-hooks)
|
||||
(advice-add #'switch-to-buffer :around #'doom*switch-buffer-hooks)
|
||||
(advice-add #'display-buffer :around #'doom*switch-buffer-hooks)
|
||||
(defun doom|init-custom-hooks ()
|
||||
(advice-add #'select-frame :around #'doom*switch-frame-hooks)
|
||||
(advice-add #'select-window :around #'doom*switch-window-hooks)
|
||||
(advice-add #'switch-to-buffer :around #'doom*switch-buffer-hooks)
|
||||
(advice-add #'display-buffer :around #'doom*switch-buffer-hooks))
|
||||
(add-hook 'doom-init-hook #'doom|init-custom-hooks)
|
||||
|
||||
(defun doom*load-theme-hooks (theme &rest _)
|
||||
(setq doom-theme theme)
|
||||
|
|
103
core/core.el
103
core/core.el
|
@ -82,6 +82,7 @@ XDG directory conventions if ~/.config/doom exists.")
|
|||
abbrev-file-name (concat doom-local-dir "abbrev.el")
|
||||
auto-save-list-file-name (concat doom-cache-dir "autosave")
|
||||
backup-directory-alist (list (cons "." (concat doom-cache-dir "backup/")))
|
||||
custom-file (concat doom-etc-dir "custom.el")
|
||||
pcache-directory (concat doom-cache-dir "pcache/")
|
||||
mc/list-file (concat doom-etc-dir "mc-lists.el")
|
||||
server-auth-dir (concat doom-cache-dir "server/")
|
||||
|
@ -92,10 +93,6 @@ XDG directory conventions if ~/.config/doom exists.")
|
|||
url-cache-directory (concat doom-cache-dir "url/")
|
||||
url-configuration-directory (concat doom-etc-dir "url/"))
|
||||
|
||||
;; move custom defs out of init.el
|
||||
(setq custom-file (concat doom-etc-dir "custom.el"))
|
||||
(load custom-file t t t)
|
||||
|
||||
;; be quiet at startup; don't load or display anything unnecessary
|
||||
(unless noninteractive
|
||||
(advice-add #'display-startup-echo-area-message :override #'ignore)
|
||||
|
@ -108,56 +105,17 @@ XDG directory conventions if ~/.config/doom exists.")
|
|||
;; Custom init hooks; clearer than `after-init-hook', `emacs-startup-hook', and
|
||||
;; `window-setup-hook'.
|
||||
(defvar doom-init-hook nil
|
||||
"A list of hooks run when DOOM is initialized, before `doom-post-init-hook'.
|
||||
Use this for essential functionality.")
|
||||
"A list of hooks run when DOOM is initialized.")
|
||||
|
||||
(defvar doom-post-init-hook nil
|
||||
"A list of hooks run after DOOM initialization is complete, and after
|
||||
`doom-init-hook'. Use this for extra, non-essential functionality.")
|
||||
|
||||
(defun doom-try-run-hook (fn hook)
|
||||
"Runs a hook wrapped in a `condition-case-unless-debug' block; its objective
|
||||
is to include more information in the error message, without sacrificing your
|
||||
ability to invoke the debugger in debug mode."
|
||||
(condition-case-unless-debug ex
|
||||
(if noninteractive
|
||||
(quiet! (funcall fn))
|
||||
(funcall fn))
|
||||
('error
|
||||
(lwarn hook :error
|
||||
"%s in '%s' -> %s"
|
||||
(car ex) fn (error-message-string ex))))
|
||||
nil)
|
||||
|
||||
(defun doom|after-init ()
|
||||
"Run `doom-init-hook' and `doom-post-init-hook', start the Emacs server, and
|
||||
display the loading benchmark."
|
||||
(unless noninteractive
|
||||
(load (concat doom-private-dir "config") t t))
|
||||
(dolist (hook '(doom-init-hook doom-post-init-hook))
|
||||
(run-hook-wrapped hook #'doom-try-run-hook hook))
|
||||
(unless noninteractive
|
||||
(when (display-graphic-p)
|
||||
(require 'server)
|
||||
(unless (server-running-p)
|
||||
(server-start)))
|
||||
(message "%s" (doom-packages--benchmark))))
|
||||
|
||||
(defun doom|finalize ()
|
||||
"Resets garbage collection settings to reasonable defaults (if you don't do
|
||||
this, you'll get stuttering and random freezes), and resets
|
||||
`file-name-handler-alist'."
|
||||
(setq gc-cons-threshold 16777216
|
||||
gc-cons-percentage 0.1
|
||||
file-name-handler-alist doom--file-name-handler-alist)
|
||||
t)
|
||||
(defvar doom-internal-init-hook nil
|
||||
"Hooks run after Doom has loaded all init.el files, and is ready to load
|
||||
modules.")
|
||||
|
||||
|
||||
;;
|
||||
;; Emacs fixes/hacks
|
||||
;;
|
||||
|
||||
;; Automatic minor modes
|
||||
(defvar doom-auto-minor-mode-alist '()
|
||||
"Alist mapping filename patterns to corresponding minor mode functions, like
|
||||
`auto-mode-alist'. All elements of this alist are checked, meaning you can
|
||||
|
@ -195,36 +153,39 @@ with functions that require it (like modeline segments)."
|
|||
(advice-add #'make-indirect-buffer :around #'doom*set-indirect-buffer-filename)
|
||||
|
||||
|
||||
;;;
|
||||
;; Initialize
|
||||
(eval-and-compile
|
||||
(defvar doom--file-name-handler-alist file-name-handler-alist)
|
||||
(unless (or after-init-time noninteractive)
|
||||
;; A big contributor to long startup times is the garbage collector, so we
|
||||
;; up its memory threshold, temporarily and reset it later in
|
||||
;; `doom|finalize'.
|
||||
;;
|
||||
;; Bootstrap
|
||||
;;
|
||||
|
||||
(defvar doom--file-name-handler-alist file-name-handler-alist)
|
||||
(unless (or after-init-time noninteractive)
|
||||
;; A big contributor to long startup times is the garbage collector, so we up
|
||||
;; its memory threshold, temporarily and reset it later in `doom|finalize'.
|
||||
(setq gc-cons-threshold 402653184
|
||||
gc-cons-percentage 0.6
|
||||
gc-cons-percentage 1.0
|
||||
;; consulted on every `require', `load' and various file reading
|
||||
;; functions. You get a minor speed up by nooping this.
|
||||
file-name-handler-alist nil))
|
||||
|
||||
(when doom-private-dir
|
||||
(load (concat doom-private-dir "early-init") t t))
|
||||
|
||||
(require 'core-packages (concat doom-core-dir "core-packages"))
|
||||
(doom-initialize noninteractive)
|
||||
(load! core-lib)
|
||||
(load! core-os) ; consistent behavior across OSes
|
||||
(defun doom|finalize ()
|
||||
"Resets garbage collection settings to reasonable defaults (if you don't do
|
||||
this, you'll get stuttering and random freezes) and resets
|
||||
`file-name-handler-alist'."
|
||||
(unless noninteractive
|
||||
(load! core-ui) ; draw me like one of your French editors
|
||||
(load! core-editor) ; baseline configuration for text editing
|
||||
(load! core-projects) ; making Emacs project-aware
|
||||
(load! core-keybinds)) ; centralized keybind system + which-key
|
||||
(run-hooks 'doom-init-hook))
|
||||
(setq doom-init-p t
|
||||
file-name-handler-alist doom--file-name-handler-alist
|
||||
gc-cons-threshold 16777216
|
||||
gc-cons-percentage 0.15))
|
||||
|
||||
(add-hook! '(emacs-startup-hook doom-reload-hook) #'doom|finalize)
|
||||
(add-hook 'emacs-startup-hook #'doom|after-init)
|
||||
;;
|
||||
(require 'core-packages (concat doom-core-dir "core-packages"))
|
||||
(doom-initialize noninteractive)
|
||||
|
||||
(when doom-private-dir
|
||||
(load (concat doom-private-dir "init") t t)))
|
||||
(add-hook! '(emacs-startup-hook doom-reload-hook)
|
||||
#'doom|finalize)
|
||||
(when doom-private-dir
|
||||
(load (concat doom-private-dir "init") t t))
|
||||
|
||||
(provide 'core)
|
||||
;;; core.el ends here
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue