dev: merge branch 'master' into emenel

This commit is contained in:
Matt Nish-Lapidus 2024-03-25 09:20:09 -04:00
commit d02c7a8b4c
25 changed files with 250 additions and 932 deletions

View file

@ -146,8 +146,6 @@ commands you should know about:
+ `doom env` to dump a snapshot of your shell environment to a file that Doom + `doom env` to dump a snapshot of your shell environment to a file that Doom
will load at startup. This allows Emacs to inherit your `PATH`, among other will load at startup. This allows Emacs to inherit your `PATH`, among other
things. things.
+ `doom build` to recompile all installed packages (use this if you up/downgrade
Emacs).
# Roadmap # Roadmap

View file

@ -271,10 +271,8 @@ SEE ALSO:
(defcli-autoload! ((profiles profile))) (defcli-autoload! ((profiles profile)))
(defcli-autoload! ((upgrade up))) (defcli-autoload! ((upgrade up)))
(defcli-autoload! (env)) (defcli-autoload! (env))
(defcli-autoload! ((build b purge p rollback)) "packages") (defcli-autoload! ((build b purge p gc rollback)) "packages")
(defcli-autoload! ((install i))) (defcli-autoload! ((install i)))
(defcli-autoload! ((compile c)))
(defcli-autoload! (clean) "compile")
;; TODO Post-3.0 commands ;; TODO Post-3.0 commands
;; (load! "gc" dir) ;; (load! "gc" dir)
@ -282,8 +280,6 @@ SEE ALSO:
;; (load! "nuke" dir) ;; (load! "nuke" dir)
;; (load! "package" dir) ;; (load! "package" dir)
;; (load! "profile" dir) ;; (load! "profile" dir)
;; (defcli-obsolete! ((compile c)) (sync "--compile") "v3.0.0")
;; (defcli-obsolete! ((build b)) (sync "--rebuild") "v3.0.0")
) )
(defcli-group! "Diagnostics" (defcli-group! "Diagnostics"

View file

@ -402,14 +402,13 @@ This command is never needed for changes to =$DOOMDIR/config.el=.
** Copy or sync my config to another system? ** Copy or sync my config to another system?
*Short answer:* it is safe to sync =$DOOMDIR= across systems, but not *Short answer:* it is safe to sync =$DOOMDIR= across systems, but not
=$EMACSDIR=. Once moved, use ~$ doom sync && doom build~ to ensure everything is =$EMACSDIR=. Once moved, use ~$ doom sync~ to ensure everything is set up
set up correctly. correctly.
*Long answer:* packages can contain baked-in absolute paths and non-portable *Long answer:* packages can contain baked-in absolute paths and non-portable
byte-code. It is never a good idea to mirror it across multiple systems, unless byte-code. It is never a good idea to mirror it across multiple systems, unless
they are all the same (same OS, same version of Emacs, same paths). Most issues they are all the same (same OS, same version of Emacs, same paths). Most issues
should be solved by running ~$ doom sync && doom build~ on the other end, once should be solved by running ~$ doom sync~ on the other end, once moved.
moved.
** Start over, in case something went terribly wrong? ** Start over, in case something went terribly wrong?
Delete =$EMACSDIR/.local/straight= and run ~$ doom sync~. Delete =$EMACSDIR/.local/straight= and run ~$ doom sync~.

View file

@ -1,214 +0,0 @@
;;; lisp/cli/commands/byte-compile.el -*- lexical-binding: t; -*-
;;
;;; Variables
;; None yet!
;;
;;; Commands
(defcli! ((compile c))
((recompile-p ("-r" "--recompile"))
(core-p ("-c" "--core"))
(private-p ("-p" "--private"))
(verbose-p ("-v" "--verbose")))
"Byte-compiles your config or selected modules.
compile [TARGETS...]
compile :core :user lang/python
compile feature lang
Accepts :core and :user as special arguments, which target Doom's core files
and your private config files, respectively. To recompile your packages, use
'doom build' instead."
(doom-cli-compile
(if (or core-p private-p)
(append (if core-p (doom-glob doom-emacs-dir "init.el"))
(if core-p (list doom-core-dir))
(if private-p (list doom-user-dir)))
(or (y-or-n-p
(concat "WARNING: Changes made to your config after compiling it won't take effect until\n"
"this command is rerun or you run 'doom clean'! It will also make error backtraces\n"
"much more difficult to decipher.\n\n"
"If you intend to use it anyway, remember this or it will come back to bite you!\n\n"
"Continue anyway?"))
(user-error "Aborted"))
(append (doom-glob doom-emacs-dir "init.el")
(list doom-core-dir)
(seq-filter
;; Only compile Doom's modules
(doom-rpartial #'file-in-directory-p doom-emacs-dir)
;; Omit `doom-user-dir', which is always first
(doom-module-load-path))))
recompile-p
verbose-p))
(defcli! clean ()
"Delete all *.elc files."
(doom-compile-clean))
;;
;;; Helpers
(cl-defun doom-cli-compile (&optional targets recompile-p verbose-p)
"Byte compiles your emacs configuration.
init.el is always byte-compiled by this.
If TARGETS is specified, as a list of direcotries
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.
WARNING: byte-compilation yields marginal gains and makes debugging new issues
difficult. It is recommended you don't use it unless you understand the
reprecussions.
Use `doom-compile-clean' or `make clean' to reverse
byte-compilation.
If RECOMPILE-P is non-nil, only recompile out-of-date files."
(let* ((default-directory doom-emacs-dir)
(targets (nreverse (delete-dups targets)))
;; In case it is changed during compile-time
(auto-mode-alist auto-mode-alist)
kill-emacs-hook kill-buffer-query-functions)
(let ((after-load-functions
(if (null targets)
after-load-functions
;; Assemble el files we want to compile, and preserve in the order
;; they are loaded in, so we don't run into any scary catch-22s
;; while byte-compiling, like missing macros.
(cons (let ((target-dirs (seq-filter #'file-directory-p targets)))
(lambda (path)
(and (not (doom-compile--ignore-file-p path))
(seq-find (doom-partial #'file-in-directory-p path)
target-dirs)
(cl-pushnew path targets))))
after-load-functions))))
(doom-log "Reloading Doom in preparation for byte-compilation")
;; But first we must be sure that Doom and your private config have been
;; fully loaded. Which usually aren't so in an noninteractive session.
(let ((load-prefer-newer t))
(require 'doom-start)))
(if (null targets)
(print! (item "No targets to %scompile" (if recompile-p "re" "")))
(print! (start "%scompiling your config...")
(if recompile-p "Re" "Byte-"))
(dolist (dir
(cl-remove-if-not #'file-directory-p targets)
(setq targets (cl-remove-if #'file-directory-p targets)))
(prependq! targets
(doom-files-in
dir :match "\\.el" :filter #'doom-compile--ignore-file-p)))
(print-group!
(require 'use-package)
(condition-case-unless-debug e
(let* ((total-ok 0)
(total-fail 0)
(total-noop 0)
(byte-compile-verbose nil)
(byte-compile-warnings '(not free-vars unresolved noruntime lexical make-local))
(byte-compile-dynamic-docstrings t)
(use-package-compute-statistics nil)
(use-package-defaults use-package-defaults)
(use-package-expand-minimally t)
(targets (delete-dups targets))
(modules (seq-group-by #'doom-module-from-path targets))
(total-files (length targets))
(total-modules (length modules))
(i 0)
last-module)
;; Prevent packages from being loaded at compile time if they
;; don't meet their own predicates.
(push (list :no-require t
(lambda (_name args)
(or (when-let (pred (or (plist-get args :if)
(plist-get args :when)))
(not (eval pred t)))
(when-let (pred (plist-get args :unless))
(eval pred t)))))
use-package-defaults)
(dolist (module-files modules)
(cl-incf i)
(dolist (target (cdr module-files))
(let ((elc-file (byte-compile-dest-file target)))
(cl-incf
(if (and recompile-p (not (file-newer-than-file-p target elc-file)))
total-noop
(pcase (if (not (doom-file-cookie-p target "if" t))
'no-byte-compile
(unless (equal last-module (car module-files))
(print! (success "(% 3d/%d) Compiling %s")
i total-modules
(if-let (m (caar module-files))
(format "%s %s module..." m (cdar module-files))
(format "%d stand alone elisp files..."
(length (cdr module-files))))
(caar module-files) (cdar module-files))
(setq last-module (car module-files)))
(if verbose-p
(byte-compile-file target)
(quiet! (byte-compile-file target))))
(`no-byte-compile
(doom-log "(% 3d/%d) Ignored %s" i total-modules target)
total-noop)
(`nil
(print! (error "(% 3d/%d) Failed to compile %s")
i total-modules (relpath target))
total-fail)
(_ total-ok)))))))
(print! (class (if (= total-fail 0) 'success 'warn)
"%s %d/%d file(s) (%d ignored)")
(if recompile-p "Recompiled" "Byte-compiled")
total-ok total-files
total-noop)
(= total-fail 0))
((debug error)
(print! (error "There were breaking errors.\n\n%s")
"Reverting changes...")
(signal 'doom-error (list 'byte-compile e))))))))
(defun doom-compile--ignore-file-p (path)
(let ((filename (file-name-nondirectory path)))
(or (not (equal (file-name-extension path) "el"))
(member filename (list doom-module-packages-file "doctor.el"))
(string-prefix-p "." filename)
(string-prefix-p "test-" filename)
(string-prefix-p "flycheck_" filename)
(string-suffix-p ".example.el" filename))))
(defun doom-compile-clean ()
"Delete all the compiled elc files in your Emacs configuration and private
module. This does not include your byte-compiled, third party packages.'"
(require 'doom-modules)
(print! (start "Cleaning .elc files"))
(print-group!
(cl-loop with default-directory = doom-emacs-dir
with success = 0
with esc = (if init-file-debug "" "\033[1A")
for path
in (append (doom-glob doom-emacs-dir "*.elc")
(doom-files-in doom-user-dir :match "\\.elc$" :depth 1)
(doom-files-in doom-core-dir :match "\\.elc$")
(doom-files-in doom-module-load-path :match "\\.elc$" :depth 4))
if (file-exists-p path)
do (delete-file path)
and do (print! (success "\033[KDeleted %s%s") (relpath path) esc)
and do (cl-incf success)
finally do
(print! (if (> success 0)
(success "\033[K%d elc files deleted" success)
(item "\033[KNo elc files to clean"))))
t))
(provide 'doom-cli-compile)
;;; compile.el ends here

View file

@ -1,466 +0,0 @@
;;; lisp/cli/help.el -*- lexical-binding: t; -*-
;;; Commentary:
;;
;; This file defines special commands that the Doom CLI will invoke when a
;; command is passed with -?, --help, or --version. They can also be aliased to
;; a sub-command to make more of its capabilities accessible to users, with:
;;
;; (defcli-alias! (myscript (help h)) (:help))
;;
;; You can define your own command-specific help handlers, e.g.
;;
;; (defcli! (:help myscript subcommand) () ...)
;;
;; And it will be invoked instead of the generic one.
;;
;;; Code:
;;
;;; Variables
(defvar doom-help-commands '("%p %c {-?,--help}")
"A list of help commands recognized for the running script.
Recognizes %p (for the prefix) and %c (for the active command).")
;;
;;; Commands
(defcli! (:root :help)
((localonly? ("-g" "--no-global") "Hide global options")
(manpage? ("--manpage") "Generate in manpage format")
(commands? ("--commands") "List all known commands")
&multiple
(sections ("--synopsis" "--subcommands" "--similar" "--envvars"
"--postamble")
"Show only the specified sections.")
&context context
&args command)
"Show documentation for a Doom CLI command.
OPTIONS:
--synopsis, --subcommands, --similar, --envvars, --postamble
TODO"
(doom-cli-load-all)
(when (doom-cli-context-error context)
(terpri))
(let* ((command (cons (doom-cli-context-prefix context) command))
(cli (doom-cli-get command t))
(rcli (doom-cli-get cli))
(fallbackcli (cl-loop with targets = (doom-cli--command-expand (butlast command) t)
for cmd in (cons command targets)
if (doom-cli-get cmd t)
return it)))
(cond (commands?
(let ((cli (or cli (doom-cli-get (doom-cli-context-prefix context)))))
(print! "Commands under '%s':\n%s"
(doom-cli-command-string cli)
(indent (doom-cli-help--render-commands
(or (doom-cli-subcommands cli)
(user-error "No commands found"))
:prefix (doom-cli-command cli)
:inline? t
:docs? t)))))
((null sections)
(if (null cli)
(signal 'doom-cli-command-not-found-error command)
(doom-cli-help--print cli context manpage? localonly?)
(exit! :pager?)))
((dolist (section sections)
(unless (equal section (car sections)) (terpri))
(pcase section
("--synopsis"
(print! "%s" (doom-cli-help--render-synopsis
(doom-cli-help--synopsis cli)
"Usage: ")))
("--subcommands"
(print! "%s\n%s" (bold "Available commands:")
(indent (doom-cli-help--render-commands
(doom-cli-subcommands rcli 1)
:prefix command
:grouped? t
:docs? t)
doom-print-indent-increment)))
("--similar"
(unless command
(user-error "No command specified"))
(let ((similar (doom-cli-help-similar-commands command 0.4)))
(print! "Similar commands:")
(if (not similar)
(print! (indent (warn "Can't find any!")))
(dolist (command (seq-take similar 10))
(print! (indent (item "(%d%%) %s"))
(* (car command) 100)
(doom-cli-command-string (cdr command)))))))
("--envvars"
(let* ((key "ENVIRONMENT VARIABLES")
(clis (if command (doom-cli-find command) (hash-table-values doom-cli--table)))
(clis (seq-remove #'doom-cli-alias clis))
(clis (seq-filter (fn! (cdr (assoc key (doom-cli-docs %)))) clis))
(clis (seq-group-by #'doom-cli-command clis)))
(print! "List of environment variables for %s:\n" command)
(if (null clis)
(print! (indent "None!"))
(dolist (group clis)
(print! (bold "%s%s:"
(doom-cli-command-string (car group))
(if (doom-cli-fn (doom-cli-get (car group)))
"" " *")))
(dolist (cli (cdr group))
(print! (indent "%s") (markup (cdr (assoc key (doom-cli-docs cli))))))))))
("--postamble"
(print! "See %s for documentation."
(join (cl-loop with spec =
`((?p . ,(doom-cli-context-prefix context))
(?c . ,(doom-cli-command-string (cdr (doom-cli-command (or cli fallbackcli))))))
for cmd in doom-help-commands
for formatted = (trim (format-spec cmd spec))
collect (replace-regexp-in-string
" +" " " (format "'%s'" formatted)))
" or ")))))))))
(defcli! (:root :version)
((simple? ("--simple"))
&context context)
"Show installed versions of Doom, Doom modules, and Emacs."
(doom/version)
(unless simple?
(terpri)
(with-temp-buffer
(insert-file-contents (doom-path doom-emacs-dir "LICENSE"))
(re-search-forward "^Copyright (c) ")
(print! "%s\n" (trim (thing-at-point 'line t)))
(print! (p "Doom Emacs uses the MIT license and is provided without warranty "
"of any kind. You may redistribute and modify copies if "
"given proper attribution. See the LICENSE file for details.")))))
;;
;;; Helpers
(defun doom-cli-help (cli)
"Return an alist of documentation summarizing CLI (a `doom-cli')."
(let* ((rcli (doom-cli-get cli))
(docs (doom-cli-docs rcli)))
`((command . ,(doom-cli-command-string cli))
(summary . ,(or (cdr (assoc "SUMMARY" docs)) "TODO"))
(description . ,(or (cdr (assoc "MAIN" docs)) "TODO"))
(synopsis . ,(doom-cli-help--synopsis cli))
(arguments . ,(doom-cli-help--arguments rcli))
(options . ,(doom-cli-help--options rcli))
(commands . ,(doom-cli-subcommands cli 1))
(sections . ,(seq-filter #'cdr (cddr docs))))))
(defun doom-cli-help-similar-commands (command &optional maxscore)
"Return N commands that are similar to COMMAND."
(seq-take-while
(fn! (>= (car %) (or maxscore 0.0)))
(seq-sort-by
#'car #'>
(cl-loop with prefix = (seq-find #'doom-cli-get (nreverse (doom-cli--command-expand command t)))
with input = (doom-cli-command-string (cdr (doom-cli--command command t)))
for command in (hash-table-keys doom-cli--table)
if (doom-cli-fn (doom-cli-get command))
if (equal prefix (seq-take command (length prefix)))
collect (cons (doom-cli-help--similarity
input (doom-cli-command-string (cdr command)))
command)))))
(defun doom-cli-help--similarity (s1 s2)
;; Ratcliff-Obershelp similarity
(let* ((s1 (downcase s1))
(s2 (downcase s2))
(s1len (length s1))
(s2len (length s2)))
(if (or (zerop s1len)
(zerop s2len))
0.0
(/ (let ((i 0) (j 0) (score 0) jlast)
(while (< i s1len)
(unless jlast (setq jlast j))
(if (and (< j s2len)
(= (aref s1 i) (aref s2 j)))
(progn (cl-incf score)
(cl-incf i)
(cl-incf j))
(setq m 0)
(cl-incf j)
(when (>= j s2len)
(setq j (or jlast j)
jlast nil)
(cl-incf i))))
(* 2.0 score))
(+ (length s1)
(length s2))))))
;;; Help: printers
;; TODO Parameterize optional args with `cl-defun'
(defun doom-cli-help--print (cli context &optional manpage? noglobal?)
"Write CLI's documentation in a manpage-esque format to stdout."
(let-alist (doom-cli-help cli)
(let* ((alist
`(,@(if manpage?
`((nil . ,(let* ((title (cadr (member "--load" command-line-args)))
(width (floor (/ (- (doom-cli-context-width context)
(length title))
2.0))))
;; FIXME Who am I fooling?
(format (format "%%-%ds%%s%%%ds" width width)
"DOOM(1)" title "DOOM(1)")))
("NAME" . ,(concat .command " - " .summary))
("SYNOPSIS" . ,(doom-cli-help--render-synopsis .synopsis nil t))
("DESCRIPTION" . ,.description))
`((nil . ,(doom-cli-help--render-synopsis .synopsis "Usage: "))
(nil . ,(string-join (seq-remove #'string-empty-p (list .summary .description))
"\n\n"))))
("ARGUMENTS" . ,(doom-cli-help--render-arguments .arguments))
("COMMANDS"
. ,(doom-cli-help--render-commands
.commands :prefix (doom-cli-command cli) :grouped? t :docs? t))
("OPTIONS"
. ,(doom-cli-help--render-options
(if (or (not (doom-cli-fn cli)) noglobal?)
`(,(assq 'local .options))
.options)
cli))))
(command (doom-cli-command cli)))
(letf! (defun printsection (section)
(print! "%s\n"
(if (null section)
(dark "TODO")
(markup
(format-spec
section `((?p . ,(car command))
(?c . ,(doom-cli-command-string (cdr command))))
'ignore)))))
(pcase-dolist (`(,label . ,contents) alist)
(when (and contents (not (string-blank-p contents)))
(when label
(print! (bold "%s%s") label (if manpage? "" ":")))
(print-group! :if label (printsection contents))))
(pcase-dolist (`(,label . ,contents) .sections)
(when (and contents (not (assoc label alist)))
(print! (bold "%s:") label)
(print-group! (printsection contents))))))))
;;; Help: synopsis
(defun doom-cli-help--synopsis (cli &optional all-options?)
(let* ((rcli (doom-cli-get cli))
(opts (doom-cli-help--options rcli))
(opts (mapcar #'car (if all-options? (mapcan #'cdr opts) (alist-get 'local opts))))
(opts (cl-loop for opt in opts
for args = (cdar opt)
for switches = (mapcar #'car opt)
for multi? = (member "..." args)
if args
collect (format (if multi? "[%s %s]..." "[%s %s]")
(string-join switches "|")
(string-join (remove "..." args) "|"))
else collect (format "[%s]" (string-join switches "|"))))
(args (doom-cli-arguments rcli))
(subcommands? (doom-cli-subcommands rcli 1 :predicate? t)))
`((command . ,(doom-cli-command cli))
(options ,@opts)
(required ,@(mapcar (fn! (upcase (format "`%s'" %))) (if subcommands? '(command) (alist-get '&required args))))
(optional ,@(mapcar (fn! (upcase (format "[`%s']" %)))(alist-get '&optional args)))
(rest ,@(mapcar (fn! (upcase (format "[`%s'...]" %))) (if subcommands? '(args) (alist-get '&args args)))))))
(defun doom-cli-help--render-synopsis (synopsis &optional prefix)
(let-alist synopsis
(let ((doom-print-indent 0)
(prefix (or prefix ""))
(command (doom-cli-command-string .command)))
(string-trim-right
(format! "%s\n\n"
(fill (concat (bold prefix)
(format "%s " command)
(markup
(join (append .options
(and .options
(or .required
.optional
.rest)
(list (dark "[--]")))
.required
.optional
.rest))))
80 (1+ (length (concat prefix command)))))))))
;;; Help: arguments
(defun doom-cli-help--arguments (cli &optional all?)
(doom-cli-help--parse-docs (doom-cli-find cli t) "ARGUMENTS"))
(defun doom-cli-help--render-arguments (arguments)
(mapconcat (lambda (arg)
(format! "%-20s\n%s"
(underscore (car arg))
(indent (if (equal (cdr arg) "TODO")
(dark (cdr arg))
(cdr arg))
doom-print-indent-increment)))
arguments
"\n"))
;;; Help: commands
(cl-defun doom-cli-help--render-commands (commands &key prefix grouped? docs? (inline? t))
(with-temp-buffer
(let* ((doom-print-indent 0)
(commands (seq-group-by (fn! (if grouped? (doom-cli-prop (doom-cli-get % t) :group)))
(nreverse commands)))
(toplevel (assq nil commands))
(rest (remove toplevel commands))
(drop (if prefix (length prefix) 0))
(minwidth
(apply
#'max (or (cl-loop for cmd in (apply #'append (mapcar #'cdr commands))
for cmd = (seq-drop cmd drop)
collect (length (doom-cli-command-string cmd)))
(list 15))))
(ellipsis (doom-print--style 'dark " […]"))
(ellipsislen (- (length ellipsis) (if (eq doom-print-backend 'ansi) 2 4))))
(dolist (group (cons toplevel rest))
(let ((label (if (car-safe group) (cdr commands))))
(when label
(insert! ((bold "%s:") (car group)) "\n"))
(print-group! :if label
(dolist (command (cdr group))
(let* ((cli (doom-cli-get command t))
(rcli (doom-cli-get command))
(summary (doom-cli-short-docs rcli))
(subcommands? (doom-cli-subcommands cli 1 :predicate? t)))
(insert! ((format "%%-%ds%%s%%s"
(+ (- minwidth doom-print-indent)
doom-print-indent-increment
(if subcommands? ellipsislen 0)))
(concat (doom-cli-command-string (seq-drop command drop))
(if subcommands? ellipsis))
(if inline? " " "\n")
(indent (if (and (doom-cli-alias cli)
(not (doom-cli-type rcli)))
(dark "-> %s" (doom-cli-command-string cli))
(when docs?
(if summary (markup summary) (dark "TODO"))))))
"\n")))
(when (cdr rest)
(insert "\n")))))
(string-trim-right (buffer-string)))))
;;; Help: options
(defun doom-cli-help--options (cli &optional noformatting?)
"Return an alist summarizing CLI's options.
The alist's CAR are lists of formatted switches plus their arguments, e.g.
'((\"`--foo'\" \"`BAR'\") ...). Their CDR is their formatted documentation."
(let* ((docs (doom-cli-help--parse-docs (doom-cli-find cli t) "OPTIONS"))
(docs (mapcar (fn! (cons (split-string (car %) ", ")
(cdr %)))
docs))
(strfmt (if noformatting? "%s" "`%s'"))
local-options
global-options
seen)
(dolist (neighbor (nreverse (doom-cli-find cli)))
(dolist (option (doom-cli-options neighbor))
(when-let* ((switches (cl-loop for sw in (doom-cli-option-switches option)
if (and (doom-cli-option-flag-p option)
(string-prefix-p "--" sw))
collect (format "--[no-]%s" (substring sw 2))
else collect sw))
(switches (seq-difference switches seen)))
(dolist (switch switches) (push switch seen))
(push (cons (cl-loop for switch in switches
if (doom-cli-option-arguments option)
collect (cons (format strfmt switch)
(append (doom-cli-help--parse-args it noformatting?)
(when (doom-cli-option-multiple-p option)
(list "..."))))
else collect (list (format strfmt switch)))
(string-join
(or (delq
nil (cons (when-let (docs (doom-cli-option-docs option))
(concat docs "."))
(cl-loop for (flags . docs) in docs
unless (equal (seq-difference flags switches) flags)
collect docs)))
'("TODO"))
"\n\n"))
(if (equal (doom-cli-command neighbor)
(doom-cli-command cli))
local-options
global-options)))))
`((local . ,(nreverse local-options))
(global . ,(nreverse global-options)))))
(defun doom-cli-help--render-options (options &optional cli)
(let ((doom-print-indent 0)
(local (assq 'local options))
(global (assq 'global options)))
(when (or (cdr local) (cdr global))
(letf! (defun printopts (opts)
(pcase-dolist (`(,switches . ,docs) (cdr opts))
(let (multiple?)
(insert!
("%s%s\n%s"
(mapconcat
(fn! (when (member "..." (cdr %))
(setq multiple? t))
(string-trim-right
(format "%s %s"
(doom-print--cli-markup (car %))
(doom-print--cli-markup
(string-join (remove "..." (cdr %)) "|")))))
switches
", ")
(if multiple? ", ..." "")
(indent (fill (markup docs)) doom-print-indent-increment))
"\n\n"))))
(with-temp-buffer
(if (null (cdr local))
(insert (if global "This command has no local options.\n" "") "\n")
(printopts local))
(when (cdr global)
(insert! ((bold "Global options:\n")))
(print-group! (printopts global)))
(string-trim-right (buffer-string)))))))
;;; Help: internal
(defun doom-cli-help--parse-args (args &optional noformatting?)
(cl-loop for arg in args
if (listp arg)
collect (string-join (doom-cli-help--parse-args arg noformatting?) "|")
else if (symbolp arg)
collect (format (if noformatting? "%s" "`%s'") (upcase (symbol-name arg)))
else collect arg))
(defun doom-cli-help--parse-docs (cli-list section-name)
(cl-check-type section-name string)
(let (alist)
(dolist (cli cli-list (nreverse alist))
(when-let (section (cdr (assoc section-name (doom-cli-docs cli))))
(with-temp-buffer
(save-excursion (insert section))
(let ((lead (current-indentation))
(buffer (current-buffer)))
(while (not (eobp))
(let ((heading (string-trim (buffer-substring (point-at-bol) (point-at-eol))))
(beg (point-at-bol 2))
end)
(forward-line 1)
(while (and (not (eobp))
(/= (current-indentation) lead)
(forward-line 1)))
(setf (alist-get heading alist nil nil #'equal)
(string-join
(delq
nil (list (alist-get heading alist nil nil #'equal)
(let ((end (point)))
(with-temp-buffer
(insert-buffer-substring buffer beg end)
(goto-char (point-min))
(indent-rigidly (point-min) (point-max) (- (current-indentation)))
(string-trim-right (buffer-string))))))
"\n\n"))))))))))
(provide 'doom-cli-help)
;;; help.el ends here

View file

@ -96,7 +96,7 @@ Change `$DOOMDIR' with the `--doomdir' option, e.g.
(if (eq install? :no) (if (eq install? :no)
(print! (warn "Not installing plugins, as requested")) (print! (warn "Not installing plugins, as requested"))
(print! "Installing plugins") (print! "Installing plugins")
(doom-packages-install)) (doom-packages-ensure))
(print! "Regenerating autoloads files") (print! "Regenerating autoloads files")
(doom-profile-generate) (doom-profile-generate)

View file

@ -13,28 +13,12 @@
;; ;;
;;; Commands ;;; Commands
(defcli! (:before (build b purge p)) (&context context) (defcli-obsolete! ((build b)) (sync "--rebuild") "v3.0.0")
(require 'comp nil t)
(doom-initialize-core-packages))
;; DEPRECATED Replace with "doom sync --rebuild" (defcli-obsolete! ((purge p)) (gc) "v3.0.0")
(defcli! ((build b))
((rebuild-p ("-r") "Only rebuild packages that need rebuilding")
(jobs ("-j" "--jobs" num) "How many CPUs to use for native compilation"))
"Byte-compiles & symlinks installed packages.
This ensures that all needed files are symlinked from their package repo and
their elisp files are byte-compiled. This is especially necessary if you upgrade
Emacs (as byte-code is generally not forward-compatible)."
:benchmark t
(when jobs
(setq native-comp-async-jobs-number (truncate jobs)))
(when (doom-packages-build (not rebuild-p))
(doom-profile-generate))
t)
;; TODO Rename to "doom gc" and move to its own file ;; TODO Rename to "doom gc" and move to its own file
(defcli! ((purge p)) (defcli! (gc)
((nobuilds-p ("-b" "--no-builds") "Don't purge unneeded (built) packages") ((nobuilds-p ("-b" "--no-builds") "Don't purge unneeded (built) packages")
(noelpa-p ("-p" "--no-elpa") "Don't purge ELPA packages") (noelpa-p ("-p" "--no-elpa") "Don't purge ELPA packages")
(norepos-p ("-r" "--no-repos") "Don't purge unused straight repos") (norepos-p ("-r" "--no-repos") "Don't purge unused straight repos")
@ -50,6 +34,8 @@ possible.
It is a good idea to occasionally run this doom purge -g to ensure your package It is a good idea to occasionally run this doom purge -g to ensure your package
list remains lean." list remains lean."
:benchmark t :benchmark t
(require 'comp nil t)
(doom-initialize-core-packages)
(straight-check-all) (straight-check-all)
(when (doom-packages-purge (when (doom-packages-purge
(not noelpa-p) (not noelpa-p)
@ -242,154 +228,149 @@ list remains lean."
(defun doom-packages--write-missing-eln-errors () (defun doom-packages--write-missing-eln-errors ()
"Write .error files for any expected .eln files that are missing." "Write .error files for any expected .eln files that are missing."
(when (featurep 'native-compile) (cl-loop for file in doom-packages--eln-output-expected
(cl-loop for file in doom-packages--eln-output-expected for eln-name = (doom-packages--eln-file-name file)
for eln-name = (doom-packages--eln-file-name file) for eln-file = (doom-packages--eln-output-file eln-name)
for eln-file = (doom-packages--eln-output-file eln-name) for error-file = (doom-packages--eln-error-file eln-name)
for error-file = (doom-packages--eln-error-file eln-name) for error-dir = (file-name-directory error-file)
for error-dir = (file-name-directory error-file) unless (or (file-exists-p eln-file)
unless (or (file-exists-p eln-file) (file-newer-than-file-p error-file file)
(file-newer-than-file-p error-file file) (not (file-writable-p error-dir)))
(not (file-writable-p error-dir))) do (make-directory error-dir 'parents)
do (make-directory error-dir 'parents) (write-region "" nil error-file)
(write-region "" nil error-file) (doom-log "Wrote %s" error-file))
(doom-log "Wrote %s" error-file)) (setq doom-packages--eln-output-expected nil))
(setq doom-packages--eln-output-expected nil)))
(defun doom-packages--compile-site-files () (defun doom-packages--compile-site-files ()
"Queue async compilation for all non-doom Elisp files." "Queue async compilation for all non-doom Elisp files."
(when (featurep 'native-compile) (cl-loop with paths = (cl-loop for path in load-path
(cl-loop with paths = (cl-loop for path in load-path unless (file-in-directory-p path doom-local-dir)
unless (file-in-directory-p path doom-local-dir) collect path)
collect path) for file in (doom-files-in paths :match "\\.el\\(?:\\.gz\\)?$")
for file in (doom-files-in paths :match "\\.el\\(?:\\.gz\\)?$") if (and (file-exists-p (byte-compile-dest-file file))
if (and (file-exists-p (byte-compile-dest-file file)) (not (doom-packages--find-eln-file (doom-packages--eln-file-name file)))
(not (doom-packages--find-eln-file (doom-packages--eln-file-name file))) (not (cl-some (fn! (string-match-p % file))
(not (cl-some (fn! (string-match-p % file)) native-comp-deferred-compilation-deny-list))) do
native-comp-deferred-compilation-deny-list))) do (doom-log "Compiling %s" file)
(doom-log "Compiling %s" file) (native-compile-async file)))
(native-compile-async file))))
(defun doom-packages-install () (defun doom-packages-ensure (&optional force-p)
"Installs missing packages. "Ensure packages are installed, built"
This function will install any primary package (i.e. a package with a `package!'
declaration) or dependency thereof that hasn't already been."
(doom-initialize-packages) (doom-initialize-packages)
(print! (start "Installing packages...")) (if (not (file-directory-p (straight--repos-dir)))
(let ((pinned (doom-package-pinned-list))) (print! (start "Installing all packages for the first time (this may take a while)..."))
(print-group! (if force-p
(add-hook 'native-comp-async-cu-done-functions #'doom-packages--native-compile-done-h) (print! (start "Rebuilding all packages (this may take a while)..."))
(if-let (built (print! (start "Ensuring packages are installed and built..."))))
(doom-packages--with-recipes (doom-package-recipe-list)
(recipe package type local-repo)
(unless (file-directory-p (straight--repos-dir local-repo))
(doom-packages--cli-recipes-update))
(condition-case-unless-debug e
(let ((straight-use-package-pre-build-functions
(cons (lambda (pkg &rest _)
(when-let (commit (cdr (assoc pkg pinned)))
(print! (item "Checked out %s: %s") pkg commit)))
straight-use-package-pre-build-functions)))
(straight-use-package (intern package))
;; HACK Line encoding issues can plague repos with dirty
;; worktree prompts when updating packages or "Local
;; variables entry is missing the suffix" errors when
;; installing them (see hlissner/doom-emacs#2637), so
;; have git handle conversion by force.
(when (and doom--system-windows-p (stringp local-repo))
(let ((default-directory (straight--repos-dir local-repo)))
(when (file-in-directory-p default-directory straight-base-dir)
(straight--process-run "git" "config" "core.autocrlf" "true")))))
(error
(signal 'doom-package-error (list package e))))))
(progn
(when (featurep 'native-compile)
(doom-packages--compile-site-files)
(doom-packages--wait-for-native-compile-jobs)
(doom-packages--write-missing-eln-errors))
(print! (success "\033[KInstalled %d packages") (length built)))
(print! (item "No packages need to be installed"))
nil))))
(defun doom-packages-build (&optional force-p)
"(Re)build all packages."
(doom-initialize-packages)
(print! (start "(Re)building %spackages...") (if force-p "all " ""))
(print-group! (print-group!
(let ((straight-check-for-modifications (let ((straight-check-for-modifications
(when (file-directory-p (straight--modified-dir)) (when (file-directory-p (straight--modified-dir))
'(find-when-checking))) '(find-when-checking)))
(straight--allow-find (straight--allow-find
(and straight-check-for-modifications (and straight-check-for-modifications
(executable-find straight-find-executable) (executable-find straight-find-executable)
t)) t))
(straight--packages-not-to-rebuild (straight--packages-not-to-rebuild
(or straight--packages-not-to-rebuild (make-hash-table :test #'equal))) (or straight--packages-not-to-rebuild (make-hash-table :test #'equal)))
(straight--packages-to-rebuild (straight--packages-to-rebuild
(or (if force-p :all straight--packages-to-rebuild) (or (if force-p :all straight--packages-to-rebuild)
(make-hash-table :test #'equal))) (make-hash-table :test #'equal)))
(recipes (doom-package-recipe-list))) (recipes (doom-package-recipe-list))
(add-hook 'native-comp-async-cu-done-functions #'doom-packages--native-compile-done-h) (pinned (doom-package-pinned-list)))
(unless force-p (add-hook 'native-comp-async-cu-done-functions #'doom-packages--native-compile-done-h)
(straight--make-build-cache-available)) (straight--make-build-cache-available)
(if-let (built (if-let (built
(doom-packages--with-recipes recipes (package local-repo recipe) (doom-packages--with-recipes recipes (package local-repo recipe)
(unless force-p (let ((repo-dir (straight--repos-dir (or local-repo package)))
;; Ensure packages with outdated files/bytecode are rebuilt (build-dir (straight--build-dir package)))
(let* ((build-dir (straight--build-dir package)) (unless force-p
(repo-dir (straight--repos-dir local-repo)) ;; Ensure packages with outdated files/bytecode are rebuilt
(build (if (plist-member recipe :build) (let* ((build (if (plist-member recipe :build)
(plist-get recipe :build) (plist-get recipe :build)
t)) t))
(want-byte-compile (want-byte-compile
(or (eq build t) (or (eq build t)
(memq 'compile build))) (memq 'compile build)))
(want-native-compile (want-native-compile
(or (eq build t) (or (eq build t)
(memq 'native-compile build)))) (memq 'native-compile build))))
(and (eq (car-safe build) :not) (and (eq (car-safe build) :not)
(setq want-byte-compile (not want-byte-compile) (setq want-byte-compile (not want-byte-compile)
want-native-compile (not want-native-compile))) want-native-compile (not want-native-compile)))
(unless (featurep 'native-compile) (unless (featurep 'native-compile)
(setq want-native-compile nil)) (setq want-native-compile nil))
(and (or want-byte-compile want-native-compile) (and (or want-byte-compile want-native-compile)
(or (file-newer-than-file-p repo-dir build-dir) (or (file-newer-than-file-p repo-dir build-dir)
(file-exists-p (straight--modified-dir (or local-repo package))) (file-exists-p (straight--modified-dir (or local-repo package)))
(cl-loop with outdated = nil (cl-loop with outdated = nil
for file in (doom-files-in build-dir :match "\\.el$" :full t) for file in (doom-files-in build-dir :match "\\.el$" :full t)
if (or (if want-byte-compile (doom-packages--elc-file-outdated-p file)) if (or (if want-byte-compile (doom-packages--elc-file-outdated-p file))
(if want-native-compile (doom-packages--eln-file-outdated-p file))) (if want-native-compile (doom-packages--eln-file-outdated-p file)))
do (setq outdated t) do (setq outdated t)
(when want-native-compile (when want-native-compile
(push file doom-packages--eln-output-expected)) (push file doom-packages--eln-output-expected))
finally return outdated)) finally return outdated))
(puthash package t straight--packages-to-rebuild)))) (puthash package t straight--packages-to-rebuild))))
(straight-use-package (intern package)))) (unless (file-directory-p repo-dir)
(progn (doom-packages--cli-recipes-update))
(when (featurep 'native-compile) (condition-case-unless-debug e
(doom-packages--compile-site-files) (let ((straight-vc-git-post-clone-hook
(doom-packages--wait-for-native-compile-jobs) (cons (lambda! (&key repo-dir commit)
(doom-packages--write-missing-eln-errors)) (print-group!
;; HACK Every time you save a file in a package that straight tracks, (if-let (pin (cdr (assoc package pinned)))
;; it is recorded in ~/.emacs.d/.local/straight/modified/. (print! (item "Pinned to %s") pin)
;; Typically, straight will clean these up after rebuilding, but (print! (item "Checked out %s") commit)))
;; Doom's use-case circumnavigates that, leaving these files ;; HACK: Line encoding issues can plague
;; there and causing a rebuild of those packages each time `doom ;; repos with dirty worktree prompts
;; sync' or similar is run, so we clean it up ourselves: ;; when updating packages or "Local
(delete-directory (straight--modified-dir) 'recursive) ;; variables entry is missing the
(print! (success "\033[KRebuilt %d package(s)") (length built))) ;; suffix" errors when installing them
(print! (item "No packages need rebuilding")) ;; (see #2637), so have git handle
nil)))) ;; conversion by force.
(when (and doom--system-windows-p (stringp repo-dir))
(let ((default-directory repo-dir))
(when (file-in-directory-p default-directory straight-base-dir)
(straight--process-run "git" "config" "core.autocrlf" "true")))))
straight-vc-git-post-clone-hook)))
(straight-use-package (intern package))
;; HACK: Straight can sometimes fail to clone a repo,
;; leaving behind an empty directory which, in future
;; invocations, it will assume indicates a successful
;; clone (causing load errors later).
(let ((try 0))
(while (or (not (file-directory-p repo-dir))
(directory-empty-p repo-dir))
(when (= try 3)
(error "Failed to clone package"))
(print! "Failed to clone %S, trying again (attempt #%d)..." package (1+ try))
(delete-directory repo-dir t)
(delete-directory build-dir t)
(straight-use-package (intern package))
(cl-incf try))))
(error
(signal 'doom-package-error (list package e)))))))
(progn
(when (featurep 'native-compile)
(doom-packages--compile-site-files)
(doom-packages--wait-for-native-compile-jobs)
(doom-packages--write-missing-eln-errors))
;; HACK: Every time you save a file in a package that straight
;; tracks, it is recorded in ~/.emacs.d/.local/straight/modified/.
;; Typically, straight will clean these up after rebuilding, but
;; Doom's use-case circumnavigates that, leaving these files there
;; and causing a rebuild of those packages each time `doom sync'
;; or similar is run, so we clean it up ourselves:
(delete-directory (straight--modified-dir) 'recursive)
(print! (success "\033[KBuilt %d package(s)") (length built)))
(print! (item "No packages need attention"))
nil))))
(defun doom-packages-update () (defun doom-packages-update (&optional pinned-only-p)
"Updates packages." "Updates packages."
(doom-initialize-packages) (doom-initialize-packages)
(doom-packages--barf-if-incomplete) (doom-packages--barf-if-incomplete)
(doom-packages--cli-recipes-update)
(let* ((repo-dir (straight--repos-dir)) (let* ((repo-dir (straight--repos-dir))
(pinned (doom-package-pinned-list)) (pinned (doom-package-pinned-list))
(recipes (doom-package-recipe-list)) (recipes (doom-package-recipe-list))
@ -397,9 +378,10 @@ declaration) or dependency thereof that hasn't already been."
(repos-to-rebuild (make-hash-table :test 'equal)) (repos-to-rebuild (make-hash-table :test 'equal))
(total (length recipes)) (total (length recipes))
(esc (unless init-file-debug "\033[1A")) (esc (unless init-file-debug "\033[1A"))
(i 0) (i 0))
errors) (if pinned-only-p
(print! (start "Updating packages (this may take a while)...")) (print! (start "Updating pinned packages..."))
(print! (start "Updating all packages (this may take a while)...")))
(doom-packages--with-recipes recipes (recipe package type local-repo) (doom-packages--with-recipes recipes (recipe package type local-repo)
(cl-incf i) (cl-incf i)
(print-group! (print-group!
@ -412,11 +394,13 @@ declaration) or dependency thereof that hasn't already been."
(cl-return)) (cl-return))
(let ((default-directory (straight--repos-dir local-repo))) (let ((default-directory (straight--repos-dir local-repo)))
(unless (file-in-directory-p default-directory repo-dir) (unless (file-in-directory-p default-directory repo-dir)
(print! (warn "(%d/%d) Skipping %s because it is local") i total package) (print! (warn "(%d/%d) Skipping %s because it is out-of-tree...") i total package)
(cl-return)) (cl-return))
(when (eq type 'git) (when (eq type 'git)
(unless (file-exists-p ".git") (unless (file-exists-p ".git")
(error "%S is not a valid repository" package))) (error "%S is not a valid repository" package)))
(when (and pinned-only-p (not (assoc local-repo pinned)))
(cl-return))
(condition-case-unless-debug e (condition-case-unless-debug e
(let ((ref (straight-vc-get-commit type local-repo)) (let ((ref (straight-vc-get-commit type local-repo))
(target-ref (target-ref
@ -430,13 +414,6 @@ declaration) or dependency thereof that hasn't already been."
(doom-packages--straight-with (straight-vc-fetch-from-remote recipe) (doom-packages--straight-with (straight-vc-fetch-from-remote recipe)
(when .it (when .it
(straight-merge-package package) (straight-merge-package package)
;; (condition-case e
;; (straight-merge-package package)
;; (wrong-type-argument
;; (if (not (equal (cdr e) '(arrayp nil)))
;; (signal (car e) (cdr e))
;; (delete-directory (straight--build-dir local-repo) t)
;; (straight-use-package (intern package)))))
(setq target-ref (straight-vc-get-commit type local-repo)) (setq target-ref (straight-vc-get-commit type local-repo))
(setq output (doom-packages--commit-log-between ref target-ref) (setq output (doom-packages--commit-log-between ref target-ref)
commits (length (split-string output "\n" t))) commits (length (split-string output "\n" t)))
@ -464,7 +441,7 @@ declaration) or dependency thereof that hasn't already been."
(straight-vc-git-default-clone-depth 'full)) (straight-vc-git-default-clone-depth 'full))
(delete-directory repo 'recursive) (delete-directory repo 'recursive)
(print-group! (print-group!
(straight-use-package (intern package) nil 'no-build)) (straight-use-package (intern package) nil 'no-build))
(prog1 (file-directory-p repo) (prog1 (file-directory-p repo)
(or (not (eq type 'git)) (or (not (eq type 'git))
(setq output (doom-packages--commit-log-between ref target-ref) (setq output (doom-packages--commit-log-between ref target-ref)
@ -520,13 +497,14 @@ declaration) or dependency thereof that hasn't already been."
(princ "\033[K") (princ "\033[K")
(if (hash-table-empty-p packages-to-rebuild) (if (hash-table-empty-p packages-to-rebuild)
(ignore (print! (success "All %d packages are up-to-date") total)) (ignore (print! (success "All %d packages are up-to-date") total))
(doom-packages--cli-recipes-update)
(straight--transaction-finalize) (straight--transaction-finalize)
(let ((default-directory (straight--build-dir))) (let ((default-directory (straight--build-dir)))
(mapc (doom-rpartial #'delete-directory 'recursive) (mapc (doom-rpartial #'delete-directory 'recursive)
(hash-table-keys packages-to-rebuild))) (hash-table-keys packages-to-rebuild)))
(print! (success "Updated %d package(s)") (print! (success "Updated %d package(s)")
(hash-table-count packages-to-rebuild)) (hash-table-count packages-to-rebuild))
(doom-packages-build) (doom-packages-ensure)
t)))) t))))

View file

@ -14,18 +14,21 @@
(defvar doom-before-sync-hook () (defvar doom-before-sync-hook ()
"Hooks run before 'doom sync' synchronizes the user's config with Doom.") "Hooks run before 'doom sync' synchronizes the user's config with Doom.")
(defvar doom-cli-sync-info-file (file-name-concat doom-profile-data-dir "sync"))
;; ;;
;;; Commands ;;; Commands
(defcli-alias! (:before (sync s)) (:before build))
(defcli! ((sync s)) (defcli! ((sync s))
((noenvvar? ("-e") "Don't regenerate the envvar file") ((noenvvar? ("-e") "Don't regenerate the envvar file")
(noelc? ("-c") "Don't recompile config") (update? ("-u") "Update all installed packages after syncing")
(update? ("-u") "Update installed packages after syncing") (noupdate? ("-U") "Don't update any packages")
(purge? ("-p") "Purge orphaned package repos & regraft them") (purge? ("--gc") "Purge orphaned package repos & regraft them")
(jobs ("-j" "--jobs" num) "How many CPUs to use for native compilation")) (jobs ("-j" "--jobs" num) "How many threads to use for native compilation")
(rebuild? ("-b" "--rebuild") "Rebuild, compile, & symlink installed packages")
(auto? ("-B") "Rebuild packages, but only if necessary")
&context context)
"Synchronize your config with Doom Emacs. "Synchronize your config with Doom Emacs.
This is the equivalent of running autoremove, install, autoloads, then This is the equivalent of running autoremove, install, autoloads, then
@ -33,8 +36,10 @@ recompile. Run this whenever you:
1. Modify your `doom!' block, 1. Modify your `doom!' block,
2. Add or remove `package!' blocks to your config, 2. Add or remove `package!' blocks to your config,
3. Add or remove autoloaded functions in module autoloaded files. 3. Add or remove autoloaded functions in module autoloaded files,
4. Update Doom outside of Doom (e.g. with git) 4. Update Doom outside of Doom (e.g. with git),
5. Move your Doom config (either $EMACSDIR or $DOOMDIR) to a new location.
6. When you up (or down) grade Emacs itself.
It will ensure that unneeded packages are removed, all needed packages are It will ensure that unneeded packages are removed, all needed packages are
installed, autoloads files are up-to-date and no byte-compiled files have gone installed, autoloads files are up-to-date and no byte-compiled files have gone
@ -47,26 +52,45 @@ OPTIONS:
:benchmark t :benchmark t
(when (doom-profiles-bootloadable-p) (when (doom-profiles-bootloadable-p)
(call! '(profiles sync "--reload"))) (call! '(profiles sync "--reload")))
(run-hooks 'doom-before-sync-hook) (when (doom-cli-context-suppress-prompts-p context)
(add-hook 'kill-emacs-hook #'doom-sync--abort-warning-h) (setq auto? t))
(when jobs (when jobs
(setq native-comp-async-jobs-number (truncate jobs))) (setq native-comp-async-jobs-number (truncate jobs)))
(print! (start "Synchronizing %S profile..." ) (run-hooks 'doom-before-sync-hook)
(or (car doom-profile) "default")) (add-hook 'kill-emacs-hook #'doom-sync--abort-warning-h)
(print! (item "Using Emacs %s @ %s") emacs-version (path invocation-directory invocation-name))
(print! (start "Synchronizing %S profile..." ) (or (car doom-profile) "default"))
(unwind-protect (unwind-protect
(print-group! (print-group!
(when (and (not noenvvar?) ;; If the user has up/downgraded Emacs since last sync, or copied their
(file-exists-p doom-env-file)) ;; config to a different system, then their packages need to be
(call! '(env))) ;; recompiled. This is necessary because Emacs byte-code is not
(doom-packages-install) ;; necessarily back/forward compatible across major versions, and many
(doom-packages-build) ;; packages bake in hardcoded data at compile-time.
(when update? (pcase-let ((`(,old-version . ,old-host) (doom-file-read doom-cli-sync-info-file :by 'read :noerror t))
(doom-packages-update)) (to-rebuild nil))
(doom-packages-purge purge? purge? purge? purge? purge?) (when (and old-version (not (equal old-version emacs-version)))
(when (doom-profile-generate) (print! (warn "Emacs version has changed since last sync (from %s to %s)") old-version emacs-version)
(print! (item "Restart Emacs or use 'M-x doom/reload' for changes to take effect")) (setq to-rebuild t))
(run-hooks 'doom-after-sync-hook)) (when (and old-host (not (equal old-host (system-name))))
t) (print! (warn "Your system has changed since last sync"))
(setq to-rebuild t))
(when (and to-rebuild (not auto?))
(or (y-or-n-p
(format! " %s" "Your installed packages will need to be recompiled. Do so now?"))
(exit! 0))
(setq rebuild? t)))
(when (and (not noenvvar?)
(file-exists-p doom-env-file))
(call! '(env)))
(doom-packages-ensure rebuild?)
(unless noupdate? (doom-packages-update (not update?)))
(doom-packages-purge purge? purge? purge? purge? purge?)
(when (doom-profile-generate)
(print! (item "Restart Emacs or use 'M-x doom/reload' for changes to take effect"))
(run-hooks 'doom-after-sync-hook))
(with-temp-file doom-cli-sync-info-file (prin1 (cons emacs-version (system-name)) (current-buffer)))
t)
(remove-hook 'kill-emacs-hook #'doom-sync--abort-warning-h))) (remove-hook 'kill-emacs-hook #'doom-sync--abort-warning-h)))

View file

@ -3,7 +3,6 @@
;;; Code: ;;; Code:
(load! "packages") (load! "packages")
(load! "compile")
;; ;;
@ -33,7 +32,7 @@ following shell commands:
doom clean doom clean
doom sync -u" doom sync -u"
(let* ((force? (doom-cli-context-suppress-prompts-p context)) (let* ((force? (doom-cli-context-suppress-prompts-p context))
(sync-cmd (append '("sync" "-u") (if jobs `("-j" ,num))))) (sync-cmd (append '("sync" "-u" "-B") (if jobs `("-j" ,num)))))
(cond (cond
(packages? (packages?
;; HACK It's messy to use straight to upgrade straight, due to the ;; HACK It's messy to use straight to upgrade straight, due to the

View file

@ -1783,7 +1783,7 @@ See `defcli!' for information about COMMANDSPEC.
TARGET is simply a command list. TARGET is simply a command list.
WHEN specifies what version this command was rendered obsolete." WHEN specifies what version this command was rendered obsolete."
`(let ((ncommand (doom-cli-command-normalize (backquote ,target) doom-cli--group-plist))) `(let ((ncommand (doom-cli-command-normalize (backquote ,target) doom-cli--group-plist)))
(defcli! ,commandspec (&context context &cli cli &rest args) (defcli! ,commandspec (&context _context &cli cli &rest args)
:docs (format "An obsolete alias for '%s'." (doom-cli-command-string ncommand)) :docs (format "An obsolete alias for '%s'." (doom-cli-command-string ncommand))
:hide t :hide t
(print! (warn "'%s' was deprecated in %s") (print! (warn "'%s' was deprecated in %s")

View file

@ -15,6 +15,12 @@
"An alternative leader prefix key, used for Insert and Emacs states, and for "An alternative leader prefix key, used for Insert and Emacs states, and for
non-evil users.") non-evil users.")
(defvar doom-leader-key-states '(normal visual motion)
"which evil modes to activate the leader key for")
(defvar doom-leader-alt-key-states '(emacs insert)
"which evil modes to activate the alternative leader key for")
(defvar doom-localleader-key "SPC m" (defvar doom-localleader-key "SPC m"
"The localleader prefix key, for major-mode specific commands.") "The localleader prefix key, for major-mode specific commands.")
@ -259,12 +265,9 @@ localleader prefix."
(set-keymap-parent doom-leader-map mode-specific-map)) (set-keymap-parent doom-leader-map mode-specific-map))
((equal doom-leader-alt-key "C-x") ((equal doom-leader-alt-key "C-x")
(set-keymap-parent doom-leader-map ctl-x-map))) (set-keymap-parent doom-leader-map ctl-x-map)))
(define-key map (kbd doom-leader-alt-key) #'doom-leader-map) (define-key map (kbd doom-leader-alt-key) 'doom/leader))
(define-key map (kbd doom-localleader-alt-key) #'doom-localleader-map)) (evil-define-key* doom-leader-key-states map (kbd doom-leader-key) 'doom/leader)
(evil-define-key* '(normal visual motion) map (kbd doom-leader-key) #'doom-leader-map) (evil-define-key* doom-leader-alt-key-states map (kbd doom-leader-alt-key) 'doom/leader))
(evil-define-key* '(emacs insert) map (kbd doom-leader-alt-key) #'doom-leader-map)
(evil-define-key* '(normal visual motion) map (kbd doom-localleader-key) #'doom-localleader-map)
(evil-define-key* '(emacs insert) map (kbd doom-localleader-alt-key) #'doom-localleader-map))
(general-override-mode +1)))) (general-override-mode +1))))

View file

@ -23,6 +23,10 @@ debian, and derivatives). On most it's 'fd'.")
;; ;;
;;; Packages ;;; Packages
(after! project
(setq project-list-file (file-name-concat doom-data-dir "projects")))
;; DEPRECATED: Will be replaced with project.el
(use-package! projectile (use-package! projectile
:commands (projectile-project-root :commands (projectile-project-root
projectile-project-name projectile-project-name

View file

@ -84,7 +84,8 @@ and `format!' into colored output, where COLOR is any car of this list (or
(doom-print--indent (doom-print--indent
(if args (apply #'format str args) str) (if args (apply #'format str args) str)
"> "))) "> ")))
(path . abbreviate-file-name) (path . (lambda (&rest segments)
(abbreviate-file-name (apply #'doom-path segments))))
(symbol . symbol-name) (symbol . symbol-name)
(relpath . (lambda (str &optional dir) (relpath . (lambda (str &optional dir)
(if (or (not str) (if (or (not str)

View file

@ -2,8 +2,13 @@
;;; lisp/packages.el ;;; lisp/packages.el
;; doom.el ;; doom.el
(package! auto-minor-mode :pin "17cfa1b54800fdef2975c0c0531dad34846a5065") (package! auto-minor-mode
(package! gcmh :pin "0089f9c3a6d4e9a310d0791cf6fa8f35642ecfd9") :pin "17cfa1b54800fdef2975c0c0531dad34846a5065")
(package! compat
:recipe (:host github :repo "emacs-compat/compat")
:pin "8d4e8a366681def88751f5e9975738ecd3180deb")
(package! gcmh
:pin "0089f9c3a6d4e9a310d0791cf6fa8f35642ecfd9")
;; doom-packages.el ;; doom-packages.el
(package! straight (package! straight
@ -13,10 +18,10 @@
:branch ,straight-repository-branch :branch ,straight-repository-branch
:local-repo "straight.el" :local-repo "straight.el"
:files ("straight*.el")) :files ("straight*.el"))
:pin "b3760f5829dba37e855add7323304561eb57a3d4") :pin "b1062df10ba4c10ff7a3c61b9e124b3242b11bb2")
;; doom-ui.el ;; doom-ui.el
(package! nerd-icons :pin "c6a4acf19454b415cba1c43daf4bfca8fccdd9ba") (package! nerd-icons :pin "8095215a503d8048739de8b4ea4066598edb8cbb")
(package! hide-mode-line :pin "bc5d293576c5e08c29e694078b96a5ed85631942") (package! hide-mode-line :pin "bc5d293576c5e08c29e694078b96a5ed85631942")
(package! highlight-numbers :pin "8b4744c7f46c72b1d3d599d4fb75ef8183dee307") (package! highlight-numbers :pin "8b4744c7f46c72b1d3d599d4fb75ef8183dee307")
(package! rainbow-delimiters :pin "f40ece58df8b2f0fb6c8576b527755a552a5e763") (package! rainbow-delimiters :pin "f40ece58df8b2f0fb6c8576b527755a552a5e763")
@ -24,10 +29,10 @@
;; doom-editor.el ;; doom-editor.el
(package! better-jumper :pin "47622213783ece37d5337dc28d33b530540fc319") (package! better-jumper :pin "47622213783ece37d5337dc28d33b530540fc319")
(package! dtrt-indent :pin "0230ec503283b895bd3df6c1e30b35a01aa0b9af") (package! dtrt-indent :pin "5d1b44f9a1a484ca229cc14f8062609a10ef4891")
(package! helpful :pin "a32a5b3d959a7fccf09a71d97b3d7c888ac31c69") (package! helpful :pin "a32a5b3d959a7fccf09a71d97b3d7c888ac31c69")
(package! pcre2el :pin "018531ba0cf8e2b28d1108136a0e031b6a45f1c1") (package! pcre2el :pin "380723b2701cceb75c266440fb8db918f3340d50")
(package! smartparens :pin "0778a8a84064cf2bc3a9857bd0e7a4619cc1e5c3") (package! smartparens :pin "ddc6233ea6fc2da7a3a8e44face465c15631b02b")
(package! ws-butler (package! ws-butler
;; Use my fork of ws-butler, which has a few choice improvements and ;; Use my fork of ws-butler, which has a few choice improvements and
;; optimizations (the original has been abandoned). ;; optimizations (the original has been abandoned).
@ -35,13 +40,9 @@
:pin "572a10c11b6cb88293de48acbb59a059d36f9ba5") :pin "572a10c11b6cb88293de48acbb59a059d36f9ba5")
;; doom-projects.el ;; doom-projects.el
(package! projectile :pin "e45f0b0cc43fdc066e7971ff3ed3bf4c78015ed0") (package! projectile :pin "0163b335a18af0f077a474d4dc6b36e22b5e3274")
(package! project :pin "10a6b691e36ff897fb2a4b48896e08818afa77b0") (package! project :pin "b6989856abe9411872bdff5c8aa190bef4d86409")
;; doom-keybinds.el ;; doom-keybinds.el
(package! general :pin "bda777cd303db217fd2fbf2087eff40ec4aafda1") (package! general :pin "ced143c30de8e20f5a3761a465e684a1dc48471e")
(package! which-key :pin "4d20bc852545a2e602f59084a630f888542052b1") (package! which-key :pin "96911a1d3faf8426a33241f4821319e98421f380")
(package! compat
:recipe (:host github :repo "emacs-compat/compat")
:pin "eb8fbfa5582a8e5880e2eaa66d15d498bca6a45a")

View file

@ -36,7 +36,7 @@
(doom-modeline-def-modeline 'emacs-everywhere (doom-modeline-def-modeline 'emacs-everywhere
'(bar modals emacs-everywhere buffer-position '(bar modals emacs-everywhere buffer-position
word-count parrot selection-info) word-count parrot selection-info)
'(input-method major-mode checker '(input-method major-mode check
#("" 0 1 ; "Exit to app" icon + a little padding #("" 0 1 ; "Exit to app" icon + a little padding
(rear-nonsticky t (rear-nonsticky t
display (raise -0.25) display (raise -0.25)

View file

@ -199,10 +199,13 @@ orderless."
(use-package! consult-dir (use-package! consult-dir
:bind (([remap list-directory] . consult-dir) :defer t
:init
(map! [remap list-directory] #'consult-dir
(:after vertico
:map vertico-map :map vertico-map
("C-x C-d" . consult-dir) "C-x C-d" #'consult-dir
("C-x C-j" . consult-dir-jump-file)) "C-x C-j" #'consult-dir-jump-file))
:config :config
(when (modulep! :tools docker) (when (modulep! :tools docker)
;; TODO: Replace with `tramp-container--completion-function' when we drop ;; TODO: Replace with `tramp-container--completion-function' when we drop

View file

@ -432,10 +432,11 @@
;;; <leader> c --- code ;;; <leader> c --- code
(:prefix-map ("c" . "code") (:prefix-map ("c" . "code")
(:when (and (modulep! :tools lsp) (not (modulep! :tools lsp +eglot))) (:when (and (modulep! :tools lsp) (not (modulep! :tools lsp +eglot)))
:desc "LSP" "l" #'+default/lsp-command-map
:desc "LSP Execute code action" "a" #'lsp-execute-code-action :desc "LSP Execute code action" "a" #'lsp-execute-code-action
:desc "LSP Organize imports" "o" #'lsp-organize-imports :desc "LSP Organize imports" "o" #'lsp-organize-imports
:desc "LSP" "l" #'+default/lsp-command-map
:desc "LSP Rename" "r" #'lsp-rename :desc "LSP Rename" "r" #'lsp-rename
:desc "Symbols" "S" #'lsp-treemacs-symbols
(:when (modulep! :completion ivy) (:when (modulep! :completion ivy)
:desc "Jump to symbol in current workspace" "j" #'lsp-ivy-workspace-symbol :desc "Jump to symbol in current workspace" "j" #'lsp-ivy-workspace-symbol
:desc "Jump to symbol in any workspace" "J" #'lsp-ivy-global-workspace-symbol) :desc "Jump to symbol in any workspace" "J" #'lsp-ivy-global-workspace-symbol)
@ -449,10 +450,7 @@
:desc "Errors list" "X" #'lsp-treemacs-errors-list :desc "Errors list" "X" #'lsp-treemacs-errors-list
:desc "Incoming call hierarchy" "y" #'lsp-treemacs-call-hierarchy :desc "Incoming call hierarchy" "y" #'lsp-treemacs-call-hierarchy
:desc "Outgoing call hierarchy" "Y" (cmd!! #'lsp-treemacs-call-hierarchy t) :desc "Outgoing call hierarchy" "Y" (cmd!! #'lsp-treemacs-call-hierarchy t)
:desc "References tree" "R" (cmd!! #'lsp-treemacs-references t) :desc "References tree" "R" (cmd!! #'lsp-treemacs-references t)))
:desc "Symbols" "S" #'lsp-treemacs-symbols
:desc "LSP" "l" #'+default/lsp-command-map
:desc "LSP Rename" "r" #'lsp-rename))
(:when (modulep! :tools lsp +eglot) (:when (modulep! :tools lsp +eglot)
:desc "LSP Execute code action" "a" #'eglot-code-actions :desc "LSP Execute code action" "a" #'eglot-code-actions
:desc "LSP Rename" "r" #'eglot-rename :desc "LSP Rename" "r" #'eglot-rename

View file

@ -95,14 +95,8 @@ C-x C-f /docker:$USER@$CONTAINER:/path/to/file
Thanks to [[https://github.com/magit/magit-popup][magit-popup]], all the popups default arguments can be customized. For Thanks to [[https://github.com/magit/magit-popup][magit-popup]], all the popups default arguments can be customized. For
example, here is how to customize the arguments for =docker-image-run-popup=: example, here is how to customize the arguments for =docker-image-run-popup=:
#+begin_src emacs-lisp #+begin_src emacs-lisp
(setq docker-image-run-arguments '("-i" "-t" "--rm")) (after! docker
#+end_src (setq docker-image-run-arguments '("-i" "-t" "--rm")))
or inside a =use-package= declaration:
#+begin_src emacs-lisp
(use-package! docker
:bind ("C-c d" . docker)
:custom (docker-image-run-arguments '("-i" "-t" "--rm")))
#+end_src #+end_src
*** Other useful variables *** Other useful variables

View file

@ -2,9 +2,9 @@
;;; tools/tree-sitter/packages.el ;;; tools/tree-sitter/packages.el
(package! tree-sitter :pin "3cfab8a0e945db9b3df84437f27945746a43cc71") (package! tree-sitter :pin "3cfab8a0e945db9b3df84437f27945746a43cc71")
(package! tree-sitter-langs :pin "20fbbb85735a9196ba3e7fb33f99b3a904b363ba") (package! tree-sitter-langs :pin "c56cb511045d50e30f78508c54494e025d6af2cb")
(package! tree-sitter-indent :pin "4ef246db3e4ff99f672fe5e4b416c890f885c09e") (package! tree-sitter-indent :pin "4ef246db3e4ff99f672fe5e4b416c890f885c09e")
(when (modulep! :editor evil +everywhere) (when (modulep! :editor evil +everywhere)
(package! evil-textobj-tree-sitter (package! evil-textobj-tree-sitter
:pin "220ceae065852ef4f717fa41efd1ab51ca2346d3")) :pin "a19ab9d89a00f4a04420f9b5d61b66f04fea5261"))

View file

@ -1,4 +1,4 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; ui/deft/packages.el ;;; ui/deft/packages.el
(package! deft :pin "28be94d89bff2e1c7edef7244d7c5ba0636b1296") (package! deft :pin "bb1a16b87c3e0fe70fade6227e47dd7712b89bf6")

View file

@ -1,5 +1,5 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; ui/doom/packages.el ;;; ui/doom/packages.el
(package! doom-themes :pin "ff26f26ea3d761375f5fc4070438fbd0f3473d33") (package! doom-themes :pin "37d2182f5078d29fb22bbace346e523bb84b2c4e")
(package! solaire-mode :pin "8af65fbdc50b25ed3214da949b8a484527c7cc14") (package! solaire-mode :pin "8af65fbdc50b25ed3214da949b8a484527c7cc14")

View file

@ -96,7 +96,7 @@ Some possible solutions:
(after! doom-modeline (after! doom-modeline
(doom-modeline-def-modeline 'main (doom-modeline-def-modeline 'main
'(bar matches buffer-info remote-host buffer-position parrot selection-info) '(bar matches buffer-info remote-host buffer-position parrot selection-info)
'(misc-info minor-modes checker input-method buffer-encoding major-mode process vcs " "))) ; <-- added padding here '(misc-info minor-modes check input-method buffer-encoding major-mode process vcs " "))) ; <-- added padding here
#+end_src #+end_src
2. Use another font for the mode line (or a different ~:height~) (source) 2. Use another font for the mode line (or a different ~:height~) (source)

View file

@ -2,7 +2,7 @@
;;; ui/modeline/packages.el ;;; ui/modeline/packages.el
(unless (modulep! +light) (unless (modulep! +light)
(package! doom-modeline :pin "bf880ae56f3f6aab7bd334de9bd9b455c63a24c0")) (package! doom-modeline :pin "e09b8e989fa5fc1d98320aaa29d7138631b20ae5"))
(package! anzu :pin "26fb50b429ee968eb944b0615dd0aed1dd66172c") (package! anzu :pin "26fb50b429ee968eb944b0615dd0aed1dd66172c")
(when (modulep! :editor evil) (when (modulep! :editor evil)
(package! evil-anzu :pin "d1e98ee6976437164627542909a25c6946497899")) (package! evil-anzu :pin "d1e98ee6976437164627542909a25c6946497899"))

View file

@ -1,7 +1,7 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; ui/treemacs/packages.el ;;; ui/treemacs/packages.el
(package! treemacs :pin "df26b6ab9a0f467e5ff99f7ed97551ccf756e06c") (package! treemacs :pin "8c6df39f01a4d47fda2cc943645fa067f771b748")
(package! treemacs-nerd-icons :pin "9876cb478145a0ec4e36f64ff6583f3de7126216") (package! treemacs-nerd-icons :pin "9876cb478145a0ec4e36f64ff6583f3de7126216")
;; These packages have no :pin because they're in the same repo ;; These packages have no :pin because they're in the same repo
(when (modulep! :editor evil +everywhere) (when (modulep! :editor evil +everywhere)

View file

@ -2,5 +2,5 @@
;;; ui/vc-gutter/packages.el ;;; ui/vc-gutter/packages.el
(if (modulep! +diff-hl) (if (modulep! +diff-hl)
(package! diff-hl :pin "b8b2727a72fdf64ac98e6cfa136a43cb0cacf72f") (package! diff-hl :pin "96620839430c1205cbb8c92dd54973397f70f9d2")
(package! git-gutter-fringe :pin "648cb5b57faec55711803cdc9434e55a733c3eba")) (package! git-gutter-fringe :pin "648cb5b57faec55711803cdc9434e55a733c3eba"))