refactor(profiles): bootstrap script
- Swap out the funcall+alist lookup for a pcase (which is expanded to a cond, which is is faster and easier to read). - Wrap bootstrap file to $EMACSDIR/profiles/init.el, but byte-compile it to $EMACSDIR/profiles/init.X.el where X is emacs-major-version. - Make doom-profiles-save's second argument optional (defaults to doom-profiles-bootstrap-file). - Make doom-profiles-save throw a error if byte-compilation fails for some reason. - Rename the tempvars to include 'doom' in their name, so debuggers know where they originate.
This commit is contained in:
parent
09d24cd68a
commit
6dffa09c71
3 changed files with 89 additions and 87 deletions
|
@ -81,9 +81,9 @@
|
|||
;; $XDG_CONFIG_HOME/doom-profiles.el, and ~/.doom-profiles.el. All it
|
||||
;; needs is for `$DOOMPROFILE' to be set.
|
||||
(setenv "DOOMPROFILE" profile)
|
||||
(or (load (expand-file-name (format "profiles/init.%d" emacs-major-version)
|
||||
(or (load (expand-file-name (format "profiles/init.%d.elc" emacs-major-version)
|
||||
user-emacs-directory)
|
||||
'noerror (not init-file-debug) nil 'must-suffix)
|
||||
'noerror (not init-file-debug) 'nosuffix)
|
||||
(user-error "Profiles not initialized yet; run 'doom sync' first"))))
|
||||
|
||||
;; PERF: When `load'ing or `require'ing files, each permutation of
|
||||
|
|
|
@ -70,8 +70,8 @@
|
|||
(dolist (p removed) (print! (item "Removed %S") (car p)))
|
||||
(dolist (p changed) (print! (item "Changed %S") (car p)))
|
||||
(doom-file-write doom-cli-known-profiles-file (list new-profiles) :mode #o600)
|
||||
(doom-profiles-save new-profiles doom-profiles-bootstrap-file)
|
||||
(print! (success "Regenerated profile init file: %s")
|
||||
(doom-profiles-save new-profiles)
|
||||
(print! (success "Regenerated profile bootstrapper: %s")
|
||||
(path doom-profiles-bootstrap-file)))))))))
|
||||
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ files, and will write a summary profiles.el to the first entry in this
|
|||
variable.")
|
||||
|
||||
(defvar doom-profiles-bootstrap-file
|
||||
(file-name-concat doom-emacs-dir (format "profiles/init.%d.el" emacs-major-version))
|
||||
"Where Doom writes its profile bootstrap script.")
|
||||
(file-name-concat doom-emacs-dir (format "profiles/init.el" emacs-major-version))
|
||||
"Where Doom writes its interactive profile bootstrap script.")
|
||||
|
||||
(defvar doom-profile-init-file-name (format "init.%d.el" emacs-major-version)
|
||||
"TODO")
|
||||
|
@ -150,91 +150,93 @@ is non-nil, refresh the cache."
|
|||
;; TODO (defun doom-profile-initialize (profile-name &optional ref)
|
||||
;; )
|
||||
|
||||
(defun doom-profiles-save (profiles file)
|
||||
(defun doom-profiles-save (profiles &optional file)
|
||||
"Generate a profile bootstrapper for Doom to load at startup."
|
||||
(unless file
|
||||
(setq file doom-profiles-bootstrap-file))
|
||||
(doom-file-write
|
||||
file `(";; -*- lexical-binding: t; tab-width: 8; -*-\n"
|
||||
";; Updated: " ,(format-time-string "%Y-%m-%d %H:%M:%S") "\n"
|
||||
";; Generated by 'doom profiles sync' or 'doom sync'.\n"
|
||||
";; DO NOT EDIT THIS BY HAND!\n"
|
||||
,(format "%S" doom-version)
|
||||
(funcall
|
||||
(alist-get
|
||||
(intern (getenv-internal "DOOMPROFILE"))
|
||||
(list
|
||||
,@(cl-loop
|
||||
with deferred?
|
||||
= (seq-find (fn! (memq (car-safe %) '(:prepend :prepend? :append :append?)))
|
||||
(mapcar #'cdr profiles))
|
||||
with deferred-varsym = (make-symbol "deferred-vars")
|
||||
for (name . bindings) in profiles
|
||||
collect
|
||||
`(cons ',name
|
||||
(lambda ()
|
||||
(let ,(if deferred? '(--deferred-vars--))
|
||||
,@(cl-loop
|
||||
for (var . val) in bindings
|
||||
collect
|
||||
(pcase (car-safe val)
|
||||
(:path
|
||||
`(,(if (stringp var) 'setenv 'set)
|
||||
',var ,(cl-loop with form = `(expand-file-name ,(cadr val) user-emacs-directory)
|
||||
for dir in (cddr val)
|
||||
do (setq form `(expand-file-name ,dir ,form))
|
||||
finally return form)))
|
||||
(:eval
|
||||
(if (eq var '_)
|
||||
(macroexp-progn (cdr val))
|
||||
`(,(if (stringp var) 'setenv 'set)
|
||||
',var ,(macroexp-progn (cdr val)))))
|
||||
(:plist
|
||||
`(,(if (stringp var) 'setenv 'set)
|
||||
',var ',(if (stringp var)
|
||||
(prin1-to-string (cadr val))
|
||||
(cadr val))))
|
||||
((or :prepend :prepend?)
|
||||
(if (stringp var)
|
||||
`(setenv ',var (concat ,val (getenv ,var)))
|
||||
(setq deferred? t)
|
||||
`(push (cons ',var
|
||||
(lambda ()
|
||||
(dolist (item (list ,@(cdr val)))
|
||||
,(if (eq (car val) :append?)
|
||||
`(add-to-list ',var item)
|
||||
`(push item ',var)))))
|
||||
--deferred-vars--)))
|
||||
((or :append :append?)
|
||||
(if (stringp var)
|
||||
`(setenv ,var (concat (getenv ,var) ,val))
|
||||
(setq deferred? t)
|
||||
`(push (cons ',var
|
||||
(lambda ()
|
||||
(dolist (item (list ,@(cdr val)))
|
||||
,(if (eq (car val) :append?)
|
||||
`(add-to-list ',var item 'append)
|
||||
`(setq ',var (append ',var (list item)))))))
|
||||
--deferred-vars--)))
|
||||
(_ `(,(if (stringp var) 'setenv 'set) ',var ',val))))
|
||||
,@(when deferred?
|
||||
`((defun --defer-vars-- (_)
|
||||
(dolist (var --deferred-vars--)
|
||||
(when (boundp (car var))
|
||||
(funcall (cdr var))
|
||||
(setq --deferred-vars-- (delete var --deferred-vars--))))
|
||||
(unless --deferred-vars--
|
||||
(remove-hook 'after-load-functions #'--defer-vars--)
|
||||
(unintern '--defer-vars-- obarray)))
|
||||
(add-hook 'after-load-functions #'--defer-vars--)
|
||||
(--defer-vars--))))))))
|
||||
(lambda ()
|
||||
(if (or noninteractive
|
||||
(,(symbol-function #'doom-profiles-bootloadable-p)))
|
||||
(user-error "Failed to find profile: %s" (getenv "DOOMPROFILE"))
|
||||
(user-error "To be a bootloader, Doom must be installed in ~/.config/emacs or ~/.emacs.d"))))))
|
||||
file (let ((profilesym (make-symbol "profile"))
|
||||
(deferredsym (make-symbol "deferred-vars")))
|
||||
`(";; -*- lexical-binding: t; tab-width: 8; -*-\n"
|
||||
";; Updated: " ,(format-time-string "%Y-%m-%d %H:%M:%S") "\n"
|
||||
";; Generated by 'doom profiles sync' or 'doom sync'.\n"
|
||||
";; DO NOT EDIT THIS BY HAND!\n"
|
||||
,(format "%S" doom-version)
|
||||
(pcase (intern (getenv-internal "DOOMPROFILE"))
|
||||
,@(cl-loop
|
||||
for (profile-name . bindings) in profiles
|
||||
for deferred?
|
||||
= (seq-find (fn! (and (memq (car-safe (cdr %)) '(:prepend :prepend? :append :append?))
|
||||
(not (stringp (car-safe %)))))
|
||||
bindings)
|
||||
collect
|
||||
`(',profile-name
|
||||
(let ,(if deferred? '(--deferred-vars--))
|
||||
,@(cl-loop
|
||||
for (var . val) in bindings
|
||||
collect
|
||||
(pcase (car-safe val)
|
||||
(:path
|
||||
`(,(if (stringp var) 'setenv 'setq)
|
||||
,var ,(cl-loop with form = `(expand-file-name ,(cadr val) user-emacs-directory)
|
||||
for dir in (cddr val)
|
||||
do (setq form `(expand-file-name ,dir ,form))
|
||||
finally return form)))
|
||||
(:eval
|
||||
(if (eq var '_)
|
||||
(macroexp-progn (cdr val))
|
||||
`(,(if (stringp var) 'setenv 'setq)
|
||||
,var ,(macroexp-progn (cdr val)))))
|
||||
(:plist
|
||||
`(,(if (stringp var) 'setenv 'setq)
|
||||
,var ',(if (stringp var)
|
||||
(prin1-to-string (cadr val))
|
||||
(cadr val))))
|
||||
((or :prepend :prepend?)
|
||||
(if (stringp var)
|
||||
`(setenv ,var (concat ,val (getenv ,var)))
|
||||
(setq deferred? t)
|
||||
`(push (cons ',var
|
||||
(lambda ()
|
||||
(dolist (item (list ,@(cdr val)))
|
||||
,(if (eq (car val) :append?)
|
||||
`(add-to-list ',var item)
|
||||
`(push item ,var)))))
|
||||
--deferred-vars--)))
|
||||
((or :append :append?)
|
||||
(if (stringp var)
|
||||
`(setenv ,var (concat (getenv ,var) ,val))
|
||||
(setq deferred? t)
|
||||
`(push (cons ',var
|
||||
(lambda ()
|
||||
(dolist (item (list ,@(cdr val)))
|
||||
,(if (eq (car val) :append?)
|
||||
`(add-to-list ',var item 'append)
|
||||
`(set ',var (append ,var (list item)))))))
|
||||
--deferred-vars--)))
|
||||
(_ `(,(if (stringp var) 'setenv 'setq) ,var ',val))))
|
||||
,@(when deferred?
|
||||
`((defun --doom-profile-set-deferred-vars-- (_)
|
||||
(dolist (var --deferred-vars--)
|
||||
(when (boundp (car var))
|
||||
(funcall (cdr var))
|
||||
(setq --deferred-vars-- (delete var --deferred-vars--))))
|
||||
(unless --deferred-vars--
|
||||
(remove-hook 'after-load-functions #'--doom-profile-set-deferred-vars--)
|
||||
(unintern '--doom-profile-set-deferred-vars-- obarray)))
|
||||
(add-hook 'after-load-functions #'--doom-profile-set-deferred-vars--)
|
||||
(--doom-profile-set-deferred-vars-- nil)))))))))
|
||||
:mode #o600
|
||||
:printfn #'pp)
|
||||
(let ((byte-compile-warnings (if init-file-debug byte-compile-warnings)))
|
||||
(print-group! (byte-compile-file file))))
|
||||
(print-group!
|
||||
(or (let ((byte-compile-warnings (if init-file-debug byte-compile-warnings))
|
||||
(byte-compile-dest-file-function
|
||||
(lambda (_) (format "%s.%d.elc" (file-name-sans-extension file) emacs-major-version))))
|
||||
(byte-compile-file file))
|
||||
;; Do it again? So the errors/warnings are visible?
|
||||
;; (let ((byte-compile-warnings t))
|
||||
;; (byte-compile-file file))
|
||||
(signal 'doom-profile-error (list file "Failed to byte-compile bootstrap file")))))
|
||||
|
||||
(defun doom-profile-p (profile-name)
|
||||
"Return t if PROFILE-NAME is a valid and existing profile."
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue