                            return t))))
       (ignore (print! (green "Doom package autoloads is up-to-date"))
               (doom-initialize-autoloads doom-package-autoload-file))
-    (doom-delete-autoloads-file doom-package-autoload-file)
-    (with-temp-file doom-package-autoload-file
-      (insert ";;; -*- lexical-binding:t -*-\n"
-              ";; This file is autogenerated by `doom//reload-package-autoloads', DO NOT EDIT !!\n\n")
-      (let (case-fold-search)
+    (let (case-fold-search)
+      (doom-delete-autoloads-file doom-package-autoload-file)
+      (with-temp-file doom-package-autoload-file
+        (doom--generate-header 'doom//reload-package-autoloads)
         (save-excursion
           ;; Cache the important and expensive-to-initialize state here.
-          (doom-initialize-packages)
-          (prin1 `(setq load-path ',load-path
-                        auto-mode-alist ',auto-mode-alist
-                        Info-directory-list ',Info-directory-list
-                        doom-disabled-packages ',doom-disabled-packages
-                        package-activated-list ',package-activated-list)
-                 (current-buffer))
+          (doom--generate-var-cache)
           (print! (green "✓ Cached package state"))
-          ;; insert package autoloads
-          (dolist (spec (doom-get-package-alist))
-            (if-let* ((pkg  (car spec))
-                      (desc (cdr spec)))
-                (unless (memq pkg doom-autoload-excluded-packages)
-                  (let ((file (concat (package--autoloads-file-name desc) ".el")))
-                    (when (file-exists-p file)
-                      (insert "(let ((load-file-name " (prin1-to-string (abbreviate-file-name file)) "))\n")
-                      (insert-file-contents file)
-                      (while (re-search-forward "^\\(?:;;\\(.*\n\\)\\|\n\\|(provide '[^\n]+\\)" nil t)
-                        (unless (nth 8 (syntax-ppss))
-                          (replace-match "" t t)))
-                      (unless (bolp) (insert "\n"))
-                      (insert ")\n"))))
-              (print! (yellow "⚠ Couldn't find package desc for %s" (car spec))))))
-        (print! (green "✓ Package autoloads included"))
+          ;; Loop through packages and concatenate all their autoloads files.
+          (doom--generate-package-autoloads)
+          (print! (green "✓ Package autoloads included")))
         ;; Remove `load-path' and `auto-mode-alist' modifications (most of them,
         ;; at least); they are cached later, so all those membership checks are
         ;; unnecessary overhead.
-        (while (re-search-forward "^\\s-*\\((\\(?:add-to-list\\|\\(?:when\\|if\\) (boundp\\)\\s-+'\\(?:load-path\\|auto-mode-alist\\)\\)" nil t)
-          (goto-char (match-beginning 1))
-          (kill-sexp))
+        (doom--cleanup-package-autoloads)
         (print! (green "✓ Removed load-path/auto-mode-alist entries"))))
     (doom--byte-compile-file doom-package-autoload-file)
     (when (and noninteractive (not (daemonp)))

This should be run whenever your `doom!' block, or a module autoload file, is
modified."
  (interactive)
  (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-files-in auto-dir :match "\\.el$" :full t))
            (push file targets)))))
    (if (and (not force-p)
             (not doom-emacs-changed-p)
             (file-exists-p doom-autoload-file)

           (doom//reload-doom-autoloads force-p)
           (doom//reload-package-autoloads force-p)))))


;;
;; Doom autoloads
;;

(defun doom--generate-header (func)
  (goto-char (point-min))
  (insert ";; -*- lexical-binding:t -*-\n"
          ";; This file is autogenerated by `" (symbol-name func) "', DO NOT EDIT !!\n\n"))

(defun doom--generate-autoloads (targets)
  (require 'autoload)
  (dolist (file targets)
    (let* ((file (file-truename file))
           (generated-autoload-file doom-autoload-file)
           (generated-autoload-load-name (file-name-sans-extension file))
           (noninteractive (not doom-debug-mode))
           autoload-timestamps)
      (print!
       (cond ((not (doom-file-cookie-p file))
              "⚠ Ignoring %s")
             ((autoload-generate-file-autoloads file (current-buffer))
              (yellow "✕ Nothing in %%s"))
             ((green "✓ Scanned %%s")))
       (if (file-in-directory-p file default-directory)
           (file-relative-name file)
         (abbreviate-file-name file))))))

(defun doom--expand-autoloads ()
  (let ((load-path (append doom-modules-dirs load-path))
        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)
             path)
         t t nil 1)))))

(defun doom--generate-autodefs (targets enabled-targets)
  (goto-char (point-max))
  (search-backward ";;;***" nil t)
  (save-excursion (insert "\n"))
  (dolist (path targets)
    (insert
     (with-temp-buffer
       (insert-file-contents path)
       (let ((member-p (or (member path enabled-targets)
                           (file-in-directory-p path doom-core-dir)))
             forms sexp cond)
         (while (re-search-forward "^;;;###autodef *\\([^\n]+\\)?\n" nil t)
           (setq sexp (sexp-at-point)
                 cond (match-string 1))
           (when cond
             (setq cond (read cond)))
           (let* ((type (car sexp))
                  (name (nth 1 sexp))
                  (arglist (nth 2 sexp))
                  (docstring (format "(Actually defined in %s)\n\n%s"
                                     (abbreviate-file-name path)
                                     (if (stringp (nth 3 sexp)) (nth 3 sexp) "No docstring")))
                  (body (cdddr (if (stringp (nth 3 sexp)) (cdr sexp) sexp))))
             (cond ((not (memq type '(defun defmacro cl-defun cl-defmacro)))
                    (message "Ignoring invalid autodef %s (found %s)"
                             name type))
                   ((and member-p
                         (or (null cond)
                             (eval cond t)))
                    (push (if (memq type '(defmacro cl-defmacro))
                              sexp
                            (make-autoload sexp path))
                          forms))
                   (sexp
                    (condition-case e
                        (push (append (list 'defmacro name arglist docstring)
                                      (cl-loop for arg in arglist
                                               if (and (symbolp arg)
                                                       (not (keywordp arg))
                                                       (not (memq arg cl--lambda-list-keywords)))
                                               collect (list 'ignore arg)))
                              forms)
                      ('error
                       (message "Ignoring autodef %s (%s)"
                                name e)))))))
         (if forms
             (concat (string-join (mapcar #'prin1-to-string forms) "\n")
                     "\n")
           ""))))))

(defun doom--cleanup-autoloads ()
  (goto-char (point-min))
  (when (re-search-forward "^;;\\(;[^\n]*\\| no-byte-compile: t\\)\n" nil t)
    (replace-match "" t t)))

(defun doom//reload-doom-autoloads (&optional force-p)
  "Refreshes the autoloads.el file, specified by `doom-autoload-file', if
necessary (or if FORCE-P is non-nil).
