;;; 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")))