;;; lisp/lib/autoloads.el -*- lexical-binding: t; -*- ;;; Commentary: ;;; Code: (defvar doom-autoloads-excluded-packages () "Which packages to exclude from Doom's autoloads files. Use this for packages with problematic autoloads; e.g. they autoload too much or hoist buggy forms into autoloads.") (defvar doom-autoloads-excluded-files () "List of regexps whose matching files won't be indexed for autoloads.") (defvar doom-autoloads-cached-vars '(load-path auto-mode-alist interpreter-mode-alist magic-mode-alist magic-fallback-mode-alist Info-directory-list) "A list of variables to be cached in `doom-autoloads-file'.") (defvar doom-autoloads-files () "A list of additional files or file globs to scan for autoloads.") ;; ;;; Library (defun doom-autoloads--write (file &rest forms) (make-directory (file-name-directory file) 'parents) (condition-case-unless-debug e (with-temp-file file (setq-local coding-system-for-write 'utf-8) (let ((standard-output (current-buffer)) (print-quoted t) (print-level nil) (print-length nil)) (insert ";; -*- lexical-binding: t; coding: utf-8; no-native-compile: t -*-\n" ";; This file is autogenerated by 'doom sync', DO NOT EDIT IT!!\n") (dolist (form (delq nil forms)) (mapc #'prin1 form)) t)) (error (delete-file file) (signal 'doom-autoload-error (list file e))))) (defun doom-autoloads--compile-file (file) (condition-case-unless-debug e (let ((byte-compile-warnings (if init-file-debug byte-compile-warnings))) (and (byte-compile-file file) (load (byte-compile-dest-file file) nil t))) (error (delete-file (byte-compile-dest-file file)) (signal 'doom-autoload-error (list file e))))) (defun doom-autoloads--cleanup-form (form &optional expand) (let ((func (car-safe form))) (cond ((memq func '(provide custom-autoload register-definition-prefixes)) nil) ((and (eq func 'add-to-list) (memq (doom-unquote (cadr form)) doom-autoloads-cached-vars)) nil) ((not (eq func 'autoload)) form) ((and expand (not (file-name-absolute-p (nth 2 form)))) (defvar doom--autoloads-path-cache nil) (setf (nth 2 form) (let ((path (nth 2 form))) (or (cdr (assoc path doom--autoloads-path-cache)) (when-let* ((libpath (locate-library path)) (libpath (file-name-sans-extension libpath)) (libpath (abbreviate-file-name libpath))) (push (cons path libpath) doom--autoloads-path-cache) libpath) path))) form) (form)))) (defun doom-autoloads--scan-autodefs (file buffer module &optional module-enabled-p) (with-temp-buffer (insert-file-contents file) (while (re-search-forward "^;;;###autodef *\\([^\n]+\\)?\n" nil t) (let* ((standard-output buffer) (form (read (current-buffer))) (altform (match-string 1)) (definer (car-safe form)) (symbol (doom-unquote (cadr form)))) (cond ((and (not module-enabled-p) altform) (print (read altform))) ((memq definer '(defun defmacro cl-defun cl-defmacro)) (print (if module-enabled-p (make-autoload form (abbreviate-file-name file)) (seq-let (_ _ arglist &rest body) form (if altform (read altform) (append (list (pcase definer (`defun 'defmacro) (`cl-defun `cl-defmacro) (_ type)) symbol arglist (format "THIS FUNCTION DOES NOTHING BECAUSE %s IS DISABLED\n\n%s" module (if (stringp (car body)) (pop body) "No documentation."))) (cl-loop for arg in arglist if (symbolp arg) if (not (keywordp arg)) if (not (memq arg cl--lambda-list-keywords)) collect arg into syms else if (listp arg) collect (car arg) into syms finally return (if syms `((ignore ,@syms))))))))) (print `(put ',symbol 'doom-module ',module))) ((eq definer 'defalias) (seq-let (_ _ target docstring) form (unless module-enabled-p (setq target #'ignore docstring (format "THIS FUNCTION DOES NOTHING BECAUSE %s IS DISABLED\n\n%s" module docstring))) (print `(put ',symbol 'doom-module ',module)) (print `(defalias ',symbol #',(doom-unquote target) ,docstring)))) (module-enabled-p (print form))))))) (defvar autoload-timestamps) (defvar generated-autoload-load-name) (defun doom-autoloads--scan-file (file) (let* (;; Prevent `autoload-find-file' from firing file hooks, e.g. adding ;; to recentf. find-file-hook write-file-functions ;; Prevent a possible source of crashes when there's a syntax error in ;; the autoloads file. debug-on-error ;; Non-nil interferes with autoload generation in Emacs < 29. See ;; radian-software/straight.el#904. (left-margin 0) ;; The following bindings are in `package-generate-autoloads'. ;; Presumably for a good reason, so I just copied them. (backup-inhibited t) (version-control 'never) case-fold-search ; reduce magic autoload-timestamps ; reduce noise in generated files autoload-compute-prefixes ;; So `autoload-generate-file-autoloads' knows where to write it (target-buffer (current-buffer)) (module (doom-module-from-path file)) (generated-autoload-load-name (abbreviate-file-name (file-name-sans-extension file))) (module-enabled-p (and (doom-module-p (car module) (cdr module)) (doom-file-cookie-p file "if" t)))) (save-excursion (when module-enabled-p (quiet! (autoload-generate-file-autoloads file target-buffer))) (doom-autoloads--scan-autodefs file target-buffer module module-enabled-p)))) (defun doom-autoloads--scan (files &optional exclude literal) "Scan and return all autoloaded forms in FILES. Autoloads will be generated from autoload cookies in FILES (except those that match one of the regexps in EXCLUDE -- a list of strings). If LITERAL is non-nil, treat FILES as pre-generated autoload files instead." (require 'autoload) (let (autoloads) (dolist (file files (nreverse (delq nil autoloads))) (when (and (not (seq-find (doom-rpartial #'string-match-p file) exclude)) (file-readable-p file)) (doom-log "loaddefs:scan: %s" file) (setq file (file-truename file)) (with-temp-buffer (if literal (insert-file-contents file) (doom-autoloads--scan-file file)) (save-excursion (while (re-search-forward "\\_" nil t) ;; `load-file-name' is meaningless in a concatenated ;; mega-autoloads file, but also essential in isolation, so we ;; replace references to it with the file they came from. (let ((ppss (save-excursion (syntax-ppss)))) (or (nth 3 ppss) (nth 4 ppss) (replace-match (prin1-to-string (abbreviate-file-name file)) t t))))) (let ((load-file-name file) (load-path (append (list doom-user-dir) doom-modules-dirs load-path))) (condition-case _ (while t (push (doom-autoloads--cleanup-form (read (current-buffer)) (not literal)) autoloads)) (end-of-file)))))))) (provide 'doom-lib '(autoloads)) ;;; autoloads.el end here