Move batch commands from core-packages to autoload/modules
This commit is contained in:
parent
1d99ee5017
commit
a46e7655dc
2 changed files with 289 additions and 346 deletions
288
core/autoload/modules.el
Normal file
288
core/autoload/modules.el
Normal file
|
@ -0,0 +1,288 @@
|
|||
;;; core/autoload/modules.el -*- lexical-binding: t; -*-
|
||||
|
||||
;;;###autoload
|
||||
(defun doom//reload ()
|
||||
"Reload your private Doom config. Experimental!"
|
||||
(interactive)
|
||||
(let ((load-prefer-newer t))
|
||||
(message "Reloading your private config...")
|
||||
(setq doom-modules (make-hash-table :test #'equal :size 100 :rehash-threshold 1.0))
|
||||
(doom-initialize t)
|
||||
(doom//reload-autoloads))
|
||||
(message "✓ Done!"))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom//reload-load-path ()
|
||||
"Reload `load-path' and recompile files (if necessary).
|
||||
|
||||
Use this when `load-path' is out of sync with your plugins. This should only
|
||||
happen if you manually modify/update/install packages from outside Emacs, while
|
||||
an Emacs session is running.
|
||||
|
||||
This isn't necessary if you use Doom's package management commands because they
|
||||
call `doom//reload-load-path' remotely (through emacsclient)."
|
||||
(interactive)
|
||||
(unless doom--inhibit-reload
|
||||
(when (file-exists-p doom-packages-file)
|
||||
(delete-file doom-packages-file))
|
||||
(cond ((and noninteractive (not (daemonp)))
|
||||
(require 'server)
|
||||
(when (server-running-p)
|
||||
(message "Reloading active Emacs session...")
|
||||
(server-eval-at server-name '(doom//reload-load-path))))
|
||||
(t
|
||||
(doom-initialize t)
|
||||
(message "%d packages reloaded" (length package-alist))
|
||||
(run-hooks 'doom-reload-hook)))))
|
||||
|
||||
(defvar generated-autoload-load-name)
|
||||
;;;###autoload
|
||||
(defun doom//reload-autoloads (&optional force)
|
||||
"Refreshes the autoloads.el file, specified by `doom-autoload-file'.
|
||||
|
||||
It scans and reads core/autoload/*.el, modules/*/*/autoload.el and
|
||||
modules/*/*/autoload/*.el, and generates an autoloads file at the path specified
|
||||
by `doom-autoload-file'. This file tells Emacs where to find lazy-loaded
|
||||
functions.
|
||||
|
||||
This should be run whenever init.el or an autoload file is modified. Running
|
||||
'make autoloads' from the commandline executes this command."
|
||||
(interactive)
|
||||
;; This function must not use autoloaded functions or external dependencies.
|
||||
;; It must assume nothing is set up!
|
||||
(let ((default-directory doom-emacs-dir)
|
||||
(targets
|
||||
(file-expand-wildcards
|
||||
(expand-file-name "autoload/*.el" doom-core-dir)))
|
||||
(generate-autoload-section-continuation "")
|
||||
(generate-autoload-section-header "")
|
||||
(generate-autoload-section-trailer "")
|
||||
(doom--stage 'autoloads)
|
||||
outdated)
|
||||
(doom-initialize)
|
||||
(dolist (path (doom-module-load-path))
|
||||
(let ((auto-dir (expand-file-name "autoload" path))
|
||||
(auto-file (expand-file-name "autoload.el" path)))
|
||||
(when (file-exists-p auto-file)
|
||||
(push auto-file targets))
|
||||
(when (file-directory-p auto-dir)
|
||||
(dolist (file (doom-files-under auto-dir :match "\\.el$"))
|
||||
(push file targets)))))
|
||||
(when (file-exists-p doom-autoload-file)
|
||||
(delete-file doom-autoload-file)
|
||||
(ignore-errors (delete-file (byte-compile-dest-file doom-autoload-file)))
|
||||
(message "Deleted old autoloads.el"))
|
||||
(message "Generating new autoloads.el")
|
||||
(dolist (file (mapcar #'file-truename (reverse targets)))
|
||||
(let ((generated-autoload-load-name (file-name-sans-extension file)))
|
||||
(message
|
||||
(cond ((not (doom-file-cookie-p file))
|
||||
"⚠ Ignoring %s")
|
||||
((update-file-autoloads file nil doom-autoload-file)
|
||||
"✕ Nothing in %s")
|
||||
("✓ Scanned %s"))
|
||||
(if (file-in-directory-p file default-directory)
|
||||
(file-relative-name file)
|
||||
(abbreviate-file-name file)))))
|
||||
(make-directory (file-name-directory doom-autoload-file) t)
|
||||
(let ((buf (find-file-noselect doom-autoload-file t))
|
||||
(load-path (append doom-psuedo-module-dirs
|
||||
doom-modules-dirs
|
||||
load-path))
|
||||
case-fold-search)
|
||||
;; FIXME Make me faster
|
||||
(unwind-protect
|
||||
(with-current-buffer buf
|
||||
(goto-char (point-min))
|
||||
(insert ";;; -*- lexical-binding:t -*-\n"
|
||||
";; This file is autogenerated by `doom//reload-autoloads', DO NOT EDIT !!\n\n")
|
||||
|
||||
;; Replace autoload paths (only for module autoloads) with
|
||||
;; absolute paths for faster resolution during load and simpler
|
||||
;; `load-path'
|
||||
(save-excursion
|
||||
(let (cache)
|
||||
(while (re-search-forward "^\\s-*(autoload\\s-+'[^ ]+\\s-+\"\\([^\"]*\\)\"" nil t)
|
||||
(let ((path (match-string 1)))
|
||||
(replace-match
|
||||
(or (cdr (assoc path cache))
|
||||
(when-let* ((libpath (locate-library path))
|
||||
(libpath (file-name-sans-extension libpath)))
|
||||
(push (cons path (abbreviate-file-name libpath)) cache)
|
||||
libpath)
|
||||
(progn
|
||||
(warn "Couldn't find absolute path for: %s" path)
|
||||
path))
|
||||
t t nil 1))))
|
||||
(message "✓ Autoload paths expanded"))
|
||||
|
||||
;; insert package autoloads
|
||||
(save-excursion
|
||||
(dolist (spec package-alist)
|
||||
(let ((pkg (car spec)))
|
||||
(unless (memq pkg doom-autoload-excluded-packages)
|
||||
(let ((file
|
||||
(abbreviate-file-name
|
||||
(concat (package--autoloads-file-name (cadr spec)) ".el"))))
|
||||
(insert "(let ((load-file-name " (prin1-to-string file) "))\n")
|
||||
(insert-file-contents file)
|
||||
(while (re-search-forward "^\\(?:;;\\(.*\n\\)\\|\n\\)" nil t)
|
||||
(unless (nth 8 (syntax-ppss))
|
||||
(replace-match "" t t)))
|
||||
(unless (bolp) (insert "\n"))
|
||||
(insert ")\n")))))
|
||||
(message "✓ Package autoloads included"))
|
||||
|
||||
;; Remove `load-path' and `auto-mode-alist' modifications (most
|
||||
;; of them, at least); they are cached elsewhere, so these are
|
||||
;; unnecessary overhead.
|
||||
(while (re-search-forward (concat "^\\s-*(\\(add-to-list\\s-+'\\(?:load-path\\|auto-mode-alist\\)\\)")
|
||||
nil t)
|
||||
(beginning-of-line)
|
||||
(skip-chars-forward " \t")
|
||||
(kill-sexp))
|
||||
(message "✓ load-path/auto-mode-alist entries removed")
|
||||
|
||||
;; Remove byte-compile inhibiting file variables so we can
|
||||
;; byte-compile the file.
|
||||
(when (re-search-forward "^;; no-byte-compile: t\n$" nil t)
|
||||
(replace-match "" t t))
|
||||
(save-buffer)
|
||||
|
||||
;; Byte compile it to give the file a chance to reveal errors.
|
||||
(condition-case-unless-debug ex
|
||||
(quiet! (byte-compile-file doom-autoload-file 'load))
|
||||
('error
|
||||
(delete-file doom-autoload-file)
|
||||
(message "Deleting autoloads file!")
|
||||
(error "Error in autoloads.el: %s -- %s"
|
||||
(car ex) (error-message-string ex))))
|
||||
(message "Done!"))
|
||||
(kill-buffer buf)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom//byte-compile (&optional modules recompile-p)
|
||||
"Byte compiles your emacs configuration.
|
||||
|
||||
init.el is always byte-compiled by this.
|
||||
|
||||
If MODULES is specified (a list of module strings, e.g. \"lang/php\"), those are
|
||||
byte-compiled. Otherwise, all enabled modules are byte-compiled, including Doom
|
||||
core. It always ignores unit tests and files with `no-byte-compile' enabled.
|
||||
|
||||
Doom was designed to benefit from byte-compilation, but the process may take a
|
||||
while. Also, while your config files are byte-compiled, changes to them will not
|
||||
take effect! Use `doom//clean-byte-compiled-files' or `make clean' to remove
|
||||
these files.
|
||||
|
||||
If RECOMPILE-P is non-nil, only recompile out-of-date files."
|
||||
(interactive
|
||||
(list nil current-prefix-arg))
|
||||
(let ((default-directory doom-emacs-dir)
|
||||
(recompile-p (or recompile-p (and (member "-r" (cdr argv)) t)))
|
||||
(argv (delete "-r" argv)))
|
||||
(unless recompile-p
|
||||
(doom//clean-byte-compiled-files))
|
||||
(let ((total-ok 0)
|
||||
(total-fail 0)
|
||||
(total-noop 0)
|
||||
(modules (or modules (cdr argv)))
|
||||
compile-plugins
|
||||
compile-targets)
|
||||
;; Ensure that Doom has been fully loaded, some of its state may be
|
||||
;; pertinent to files compiled later.
|
||||
(let ((doom--stage 'compile)
|
||||
noninteractive)
|
||||
;; Core libraries aren't fully loaded in a noninteractive session, so we
|
||||
;; pretend to be interactive and reinitialize
|
||||
(doom-initialize))
|
||||
;; Assemble el files we want to compile; taking into account that MODULES
|
||||
;; may be a list of MODULE/SUBMODULE strings from the command line.
|
||||
(setq
|
||||
modules (or modules (append (list doom-core-dir) (doom-module-load-path)))
|
||||
compile-targets
|
||||
(cl-loop for target in modules
|
||||
if (equal target ":core")
|
||||
nconc (nreverse (doom-files-under doom-core-dir :match "\\.el$"))
|
||||
and collect (expand-file-name "init.el" doom-private-dir)
|
||||
if (equal target ":private")
|
||||
nconc (nreverse (doom-files-under doom-private-dir :match "\\.el$"))
|
||||
if (equal target ":plugins")
|
||||
do (setq compile-plugins t)
|
||||
else if (file-directory-p target)
|
||||
nconc (nreverse (doom-files-under target :match "\\.el$"))
|
||||
else if (cl-member target doom-psuedo-module-dirs :test #'file-in-directory-p)
|
||||
nconc (nreverse (doom-files-under it :match "\\.el$"))
|
||||
else if (string-match "^\\([^/]+\\)/\\([^/]+\\)$" target)
|
||||
nconc (nreverse (doom-files-under
|
||||
(doom-module-locate-path
|
||||
(intern (format ":%s" (match-string 1 target)))
|
||||
(intern (match-string 2 target)))
|
||||
:match "\\.el$"))
|
||||
else if (file-exists-p target)
|
||||
collect target
|
||||
finally do (setq argv nil)))
|
||||
(if compile-plugins
|
||||
(byte-recompile-directory package-user-dir 0 t)
|
||||
(if (not compile-targets)
|
||||
(message "No targets to compile")
|
||||
(condition-case ex
|
||||
(let ((use-package-expand-minimally t))
|
||||
(push (expand-file-name "init.el" doom-emacs-dir) compile-targets)
|
||||
(dolist (target (cl-delete-duplicates (mapcar #'file-truename compile-targets) :test #'equal))
|
||||
(when (or (not recompile-p)
|
||||
(let ((elc-file (byte-compile-dest-file target)))
|
||||
(and (file-exists-p elc-file)
|
||||
(file-newer-than-file-p target elc-file))))
|
||||
(let ((result (cond ((string-match-p "/\\(packages\\|doctor\\)\\.el$" target)
|
||||
'no-byte-compile)
|
||||
((doom-file-cookie-p target)
|
||||
(byte-compile-file target))
|
||||
('no-byte-compile)))
|
||||
(short-name (if (file-in-directory-p target doom-emacs-dir)
|
||||
(file-relative-name target doom-emacs-dir)
|
||||
(abbreviate-file-name target))))
|
||||
(cl-incf
|
||||
(cond ((eq result 'no-byte-compile)
|
||||
(message! (dark (white "⚠ Ignored %s" short-name)))
|
||||
total-noop)
|
||||
((null result)
|
||||
(message! (red "✕ Failed to compile %s" short-name))
|
||||
total-fail)
|
||||
(t
|
||||
(message! (green "✓ Compiled %s" short-name))
|
||||
(quiet! (load target t t))
|
||||
total-ok))))))
|
||||
(message!
|
||||
(bold
|
||||
(color (if (= total-fail 0) 'green 'red)
|
||||
"%s %d/%d file(s) (%d ignored)"
|
||||
(if recompile-p "Recompiled" "Compiled")
|
||||
total-ok (- (length compile-targets) total-noop)
|
||||
total-noop))))
|
||||
(error
|
||||
(message! (red "\n%%s\n\n%%s\n\n%%s")
|
||||
"There were breaking errors."
|
||||
(error-message-string ex)
|
||||
"Reverting changes...")
|
||||
(quiet! (doom//clean-byte-compiled-files))
|
||||
(message! (green "Finished (nothing was byte-compiled)")))))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom//clean-byte-compiled-files ()
|
||||
"Delete all the compiled elc files in your Emacs configuration. This excludes
|
||||
compiled packages.'"
|
||||
(interactive)
|
||||
(cl-loop with default-directory = doom-emacs-dir
|
||||
for path in (append (doom-files-in doom-emacs-dir :match "\\.elc$")
|
||||
(doom-files-in doom-psuedo-module-dirs :match "\\.elc$" :full t)
|
||||
(doom-files-under doom-core-dir :match "\\.elc$")
|
||||
(doom-files-under doom-modules-dirs :match "\\.elc$"))
|
||||
for truepath = (file-truename path)
|
||||
do (delete-file path)
|
||||
and do
|
||||
(message "✓ Deleted %s"
|
||||
(if (file-in-directory-p truepath default-directory)
|
||||
(file-relative-name truepath)
|
||||
(abbreviate-file-name path)))
|
||||
finally do (message "Everything is clean")))
|
|
@ -717,352 +717,7 @@ loads MODULE SUBMODULE's packages.el file."
|
|||
(flags ,flags))
|
||||
(when flags
|
||||
(doom-module-put ,module ',submodule :flags flags))
|
||||
(load! packages ,(doom-module-find-path module submodule) t)))
|
||||
|
||||
|
||||
;;
|
||||
;; Commands
|
||||
;;
|
||||
|
||||
(defun doom//reload ()
|
||||
"Reload your private Doom config. Experimental!"
|
||||
(interactive)
|
||||
(message "Reloading your private config...")
|
||||
(load (concat doom-private-dir "init.el") nil nil 'nosuffix)
|
||||
(doom-packages--async-run #'doom//reload-packages)
|
||||
(let ((doom--stage 'config))
|
||||
(load (concat doom-private-dir "config.el") nil nil 'nosuffix))
|
||||
(message "✓ Done!"))
|
||||
|
||||
(defun doom-packages--read-if-cookies (file)
|
||||
"Returns the value of the ;;;###if predicate form in FILE."
|
||||
(with-temp-buffer
|
||||
(insert-file-contents-literally file nil 0 256)
|
||||
(if (and (re-search-forward "^;;;###if " nil t)
|
||||
(<= (line-number-at-pos) 3))
|
||||
(let ((load-file-name file))
|
||||
(eval (sexp-at-point)))
|
||||
t)))
|
||||
|
||||
(defun doom-packages--async-run (fn)
|
||||
(let* ((default-directory doom-emacs-dir))
|
||||
(compile (format "%s --quick --batch -l core/core.el -f %s"
|
||||
(executable-find "emacs")
|
||||
(symbol-name fn)))
|
||||
(while compilation-in-progress
|
||||
(sit-for 1))))
|
||||
|
||||
(defun doom-packages--files (dir pattern)
|
||||
"Like `directory-files-recursively', but traverses symlinks."
|
||||
(cl-letf (((symbol-function #'file-symlink-p) #'ignore))
|
||||
(directory-files-recursively dir pattern)))
|
||||
|
||||
(defun doom//reload-load-path ()
|
||||
"Reload `load-path' and recompile files (if necessary).
|
||||
|
||||
Use this when `load-path' is out of sync with your plugins. This should only
|
||||
happen if you manually modify/update/install packages from outside Emacs, while
|
||||
an Emacs session is running.
|
||||
|
||||
This isn't necessary if you use Doom's package management commands because they
|
||||
call `doom//reload-load-path' remotely (through emacsclient)."
|
||||
(interactive)
|
||||
(unless doom--inhibit-reload
|
||||
(when (file-exists-p doom-packages-file)
|
||||
(delete-file doom-packages-file))
|
||||
(cond ((and noninteractive (not (daemonp)))
|
||||
(require 'server)
|
||||
(when (server-running-p)
|
||||
(message "Reloading active Emacs session...")
|
||||
(server-eval-at server-name '(doom//reload-load-path))))
|
||||
(t
|
||||
(doom-initialize t)
|
||||
(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'.
|
||||
|
||||
It scans and reads core/autoload/*.el, modules/*/*/autoload.el and
|
||||
modules/*/*/autoload/*.el, and generates an autoloads file at the path specified
|
||||
by `doom-autoload-file'. This file tells Emacs where to find lazy-loaded
|
||||
functions.
|
||||
|
||||
This should be run whenever init.el or an autoload file is modified. Running
|
||||
'make autoloads' from the commandline executes this command."
|
||||
(interactive)
|
||||
;; This function must not use autoloaded functions or external dependencies.
|
||||
;; It must assume nothing is set up!
|
||||
(if (not noninteractive)
|
||||
;; This is done in another instance to protect the current session's state
|
||||
;; in case this function has side effects.
|
||||
(progn
|
||||
(doom-packages--async-run 'doom//reload-autoloads)
|
||||
(load doom-autoload-file 'noerror nil 'nosuffix))
|
||||
(let ((default-directory doom-emacs-dir)
|
||||
(targets
|
||||
(file-expand-wildcards
|
||||
(expand-file-name "autoload/*.el" doom-core-dir))))
|
||||
(dolist (path (doom-module-load-path))
|
||||
(let ((auto-dir (expand-file-name "autoload" path))
|
||||
(auto-file (expand-file-name "autoload.el" path)))
|
||||
(when (file-exists-p auto-file)
|
||||
(push auto-file targets))
|
||||
(when (file-directory-p auto-dir)
|
||||
(dolist (file (doom-packages--files auto-dir "\\.el$"))
|
||||
(push file targets)))))
|
||||
(when (file-exists-p doom-autoload-file)
|
||||
(delete-file doom-autoload-file)
|
||||
(ignore-errors (delete-file (byte-compile-dest-file doom-autoload-file)))
|
||||
(message "Deleted old autoloads.el"))
|
||||
(message "Generating new autoloads.el")
|
||||
(dolist (file (mapcar #'file-truename (reverse targets)))
|
||||
(let ((generated-autoload-load-name (file-name-sans-extension file)))
|
||||
(message
|
||||
(cond ((not (doom-packages--read-if-cookies file))
|
||||
"⚠ Ignoring %s")
|
||||
((update-file-autoloads file nil doom-autoload-file)
|
||||
"✕ Nothing in %s")
|
||||
("✓ Scanned %s"))
|
||||
(if (file-in-directory-p file default-directory)
|
||||
(file-relative-name file)
|
||||
(abbreviate-file-name file)))))
|
||||
(make-directory (file-name-directory doom-autoload-file) t)
|
||||
(let ((buf (find-file-noselect doom-autoload-file t))
|
||||
(load-path (append doom-psuedo-module-dirs
|
||||
doom-modules-dirs
|
||||
load-path))
|
||||
case-fold-search)
|
||||
;; FIXME Make me faster
|
||||
(unwind-protect
|
||||
(with-current-buffer buf
|
||||
(goto-char (point-min))
|
||||
(insert ";;; -*- lexical-binding:t -*-\n"
|
||||
";; This file is autogenerated by `doom//reload-autoloads', DO NOT EDIT !!\n\n")
|
||||
|
||||
;; Replace autoload paths (only for module autoloads) with
|
||||
;; absolute paths for faster resolution during load and simpler
|
||||
;; `load-path'
|
||||
(save-excursion
|
||||
(let (cache)
|
||||
(while (re-search-forward "^\\s-*(autoload\\s-+'[^ ]+\\s-+\"\\([^/][^\"]*\\)\"" nil t)
|
||||
(let ((path (match-string 1)))
|
||||
(replace-match
|
||||
(or (cdr (assoc path cache))
|
||||
(when-let* ((libpath (locate-library path))
|
||||
(libpath (file-name-sans-extension libpath)))
|
||||
(push (cons path libpath) cache)
|
||||
libpath)
|
||||
(progn
|
||||
(warn "Couldn't find absolute path for: %s" path)
|
||||
path))
|
||||
t t nil 1))))
|
||||
(message "✓ Autoload paths expanded"))
|
||||
|
||||
;; insert package autoloads
|
||||
(save-excursion
|
||||
(dolist (spec package-alist)
|
||||
(let ((pkg (car spec)))
|
||||
(unless (memq pkg doom-autoload-excluded-packages)
|
||||
(let ((file (concat (package--autoloads-file-name (cadr spec)) ".el")))
|
||||
(insert "(let ((load-file-name " (prin1-to-string file) "))")
|
||||
(insert-file-contents file)
|
||||
(while (re-search-forward "^;;\\(.*\n\\)" nil t)
|
||||
(replace-match "" t t))
|
||||
(unless (bolp) (insert "\n"))
|
||||
(insert ")\n")))))
|
||||
(message "✓ Package autoloads included"))
|
||||
|
||||
;; Remove `load-path' and `auto-mode-alist' modifications (most
|
||||
;; of them, at least); they are cached elsewhere, so these are
|
||||
;; unnecessary overhead.
|
||||
(while (re-search-forward (concat "^\\s-*(\\("
|
||||
"add-to-list\\s-+'\\(?:load-path\\|auto-mode-alist\\)\\|"
|
||||
"if (fboundp 'register-definition-prefixes)"
|
||||
"\\)")
|
||||
nil t)
|
||||
(beginning-of-line)
|
||||
(skip-chars-forward " \t")
|
||||
(kill-sexp))
|
||||
(message "✓ load-path/auto-mode-alist entries removed")
|
||||
|
||||
;; Remove byte-compile inhibiting file variables so we can
|
||||
;; byte-compile the file.
|
||||
(when (re-search-forward "^;; no-byte-compile: t\n$" nil t)
|
||||
(replace-match "" t t))
|
||||
(save-buffer)
|
||||
|
||||
;; Byte compile it to give the file a chance to reveal errors.
|
||||
(condition-case-unless-debug ex
|
||||
(quiet! (byte-compile-file doom-autoload-file 'load))
|
||||
('error
|
||||
(delete-file doom-autoload-file)
|
||||
(message "Deleting autoloads file!")
|
||||
(error "Error in autoloads.el: %s -- %s"
|
||||
(car ex) (error-message-string ex))))
|
||||
(message "Done!"))
|
||||
(kill-buffer buf))))))
|
||||
|
||||
(defun doom//byte-compile (&optional modules recompile-p)
|
||||
"Byte compiles your emacs configuration.
|
||||
|
||||
init.el is always byte-compiled by this.
|
||||
|
||||
If MODULES is specified (a list of module strings, e.g. \"lang/php\"), those are
|
||||
byte-compiled. Otherwise, all enabled modules are byte-compiled, including Doom
|
||||
core. It always ignores unit tests and files with `no-byte-compile' enabled.
|
||||
|
||||
Doom was designed to benefit from byte-compilation, but the process may take a
|
||||
while. Also, while your config files are byte-compiled, changes to them will not
|
||||
take effect! Use `doom//clean-byte-compiled-files' or `make clean' to remove
|
||||
these files.
|
||||
|
||||
If RECOMPILE-P is non-nil, only recompile out-of-date files."
|
||||
(interactive
|
||||
(list nil current-prefix-arg))
|
||||
(let ((default-directory doom-emacs-dir)
|
||||
(recompile-p (or recompile-p (and (member "-r" (cdr argv)) t)))
|
||||
(argv (delete "-r" argv)))
|
||||
(if (not noninteractive)
|
||||
;; This is done in another instance to protect the current session's
|
||||
;; state, because this function has side effects.
|
||||
(doom-packages--async-run 'doom//byte-compile)
|
||||
(let ((total-ok 0)
|
||||
(total-fail 0)
|
||||
(total-noop 0)
|
||||
(modules (or modules (cdr argv)))
|
||||
compile-targets)
|
||||
;; Ensure that Doom has been fully loaded, some of its state may be
|
||||
;; pertinent to files compiled later.
|
||||
(let (noninteractive)
|
||||
;; Core libraries aren't fully loaded in a noninteractive session, so
|
||||
;; we pretend to be interactive and reinitialize
|
||||
(doom-initialize)
|
||||
;; In case autoloads.el hasn't been properly generated at this point.
|
||||
(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.
|
||||
(setq compile-targets
|
||||
(cl-loop for target
|
||||
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)
|
||||
nconc (nreverse (doom-packages--files it "\\.el$"))
|
||||
else if (string-match "^\\([^/]+\\)/\\([^/]+\\)$" target)
|
||||
nconc (nreverse (doom-packages--files
|
||||
(doom-module-find-path
|
||||
(intern (format ":%s" (match-string 1 target)))
|
||||
(intern (match-string 2 target)))
|
||||
"\\.el$"))
|
||||
else if (file-exists-p target)
|
||||
collect target
|
||||
finally do (setq argv nil)))
|
||||
(if (not compile-targets)
|
||||
(message "No targets to compile")
|
||||
(condition-case ex
|
||||
(let ((use-package-expand-minimally t))
|
||||
(push (expand-file-name "init.el" doom-emacs-dir) compile-targets)
|
||||
(dolist (target (cl-delete-duplicates (mapcar #'file-truename compile-targets) :test #'equal))
|
||||
(when (and (not (string-match-p "/\\(packages\\|doctor\\)\\.el$" target))
|
||||
(or (not recompile-p)
|
||||
(let ((elc-file (byte-compile-dest-file target)))
|
||||
(and (file-exists-p elc-file)
|
||||
(file-newer-than-file-p target elc-file)))))
|
||||
(let ((result (if (doom-packages--read-if-cookies target)
|
||||
(byte-compile-file target)
|
||||
'no-byte-compile))
|
||||
(short-name (if (file-in-directory-p target doom-emacs-dir)
|
||||
(file-relative-name target doom-emacs-dir)
|
||||
(abbreviate-file-name target))))
|
||||
(cl-incf
|
||||
(cond ((eq result 'no-byte-compile)
|
||||
(message! (dark (white "⚠ Ignored %s" short-name)))
|
||||
total-noop)
|
||||
((null result)
|
||||
(message! (red "✕ Failed to compile %s" short-name))
|
||||
total-fail)
|
||||
(t
|
||||
(message! (green "✓ Compiled %s" short-name))
|
||||
(quiet! (load target t t))
|
||||
total-ok))))))
|
||||
(message!
|
||||
(bold
|
||||
(color (if (= total-fail 0) 'green 'red)
|
||||
"%s %s file(s) %s"
|
||||
(if recompile-p "Recompiled" "Compiled")
|
||||
(format "%d/%d" total-ok (- (length compile-targets) total-noop))
|
||||
(format "(%s ignored)" total-noop)))))
|
||||
(error
|
||||
(message! (red "\n%%s\n\n%%s\n\n%%s")
|
||||
"There were breaking errors."
|
||||
(error-message-string ex)
|
||||
"Reverting changes...")
|
||||
(quiet! (doom//clean-byte-compiled-files))
|
||||
(message! (green "Finished (nothing was byte-compiled)")))))))))
|
||||
|
||||
(defun doom//byte-compile-core (&optional recompile-p)
|
||||
"Byte compile the core Doom files.
|
||||
|
||||
This is faster than `doom//byte-compile', still yields considerable performance
|
||||
benefits, and is more reliable in an ever-changing Emacs config (since you won't
|
||||
likely change core files directly).
|
||||
|
||||
If RECOMPILE-P is non-nil, only recompile out-of-date core files."
|
||||
(interactive "P")
|
||||
(if (not noninteractive)
|
||||
;; This is done in another instance to protect the current session's
|
||||
;; state. `doom-initialize-packages' will have side effects otherwise.
|
||||
(doom-packages--async-run 'doom//byte-compile-core)
|
||||
(doom//byte-compile (list "core") recompile-p)))
|
||||
|
||||
(defun doom//byte-recompile-plugins ()
|
||||
"Recompile all installed plugins. If you're getting odd errors after upgrading
|
||||
(or downgrading) Emacs, this may fix it."
|
||||
(interactive)
|
||||
(if (not noninteractive)
|
||||
;; This is done in another instance to protect the current session's
|
||||
;; state. `doom-initialize-packages' will have side effects otherwise.
|
||||
(doom-packages--async-run 'doom//byte-recompile-plugins)
|
||||
(byte-recompile-directory package-user-dir 0 t)))
|
||||
|
||||
(defun doom//clean-byte-compiled-files ()
|
||||
"Delete all the compiled elc files in your Emacs configuration. This excludes
|
||||
compiled packages.'"
|
||||
(interactive)
|
||||
(unless
|
||||
(cl-loop with default-directory = doom-emacs-dir
|
||||
for path
|
||||
in (append (file-expand-wildcards "*.elc" t)
|
||||
(doom-packages--files doom-core-dir "\\.elc$")
|
||||
(cl-loop for dir in (doom-module-load-path)
|
||||
nconc (doom-packages--files dir "\\.elc$")))
|
||||
for truepath = (file-truename path)
|
||||
if (file-exists-p truepath)
|
||||
collect path
|
||||
and do (delete-file truepath)
|
||||
and do
|
||||
(message "✓ Deleted %s"
|
||||
(if (file-in-directory-p truepath default-directory)
|
||||
(file-relative-name truepath)
|
||||
(abbreviate-file-name path))))
|
||||
(message "Everything is clean")))
|
||||
|
||||
(defun doom//reload-packages ()
|
||||
"Runs `doom//reload-autoloads', `doom//packages-autoremove' and
|
||||
`doom//packages-install' before reloading your Emacs session."
|
||||
(interactive)
|
||||
(let ((doom--inhibit-reload t))
|
||||
(doom//packages-autoremove)
|
||||
(doom//packages-install)
|
||||
(doom//reload-autoloads))
|
||||
(doom//reload-load-path))
|
||||
(load! packages ,(doom-module-locate-path module submodule) t)))
|
||||
|
||||
|
||||
;;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue