doom-emacs/lisp/cli/doctor.el

337 lines
18 KiB
EmacsLisp
Raw Normal View History

;;; lisp/cli/doctor.el --- userland heuristics and Emacs diagnostics -*- lexical-binding: t; -*-
refactor!(cli): rewrite CLI framework libraries BREAKING CHANGE: this changes Doom's CLI framework in subtle ways, which is listed in greater detail below. If you've never extended Doom's CLI, then this won't affect you, but otherwise it'd be recommended you read on below. This commit focuses on the CLI framework itself and backports some foundational changes to its DSL and how it resolves command line arguments to CLIs, validates input, displays documentation, and persists state across sessions -- and more. This is done in preparation for the final stretch towarding completing the CLI rewrite (see #4273). This is also an effort to generalize Doom's CLI (both its framework and bin/doom), to increase it versatility and make it a viable dev tool for other Doom projects (on our Github org) and beyond. However, there is a *lot* to cover so I'll try to be brief: - Refactor: generalize Doom's CLI framework by moving all bin/doom specific configuration/commands out of core-cli into bin/doom. This makes it easier to use bin/doom as a project-agnostic development tool (or for users to write their own). - Refactor: change the namespace for CLI variables/functions from doom-cli-X to doom-X. - Fix: subcommands being mistaken as arguments. "doom make index" will resolve to (defcli! (doom make index)) if it exists, otherwise (defcli! (doom make)) with "index" as an argument. Before this, it would resolve to the latter no matter what. &rest can override this; with (defcli! (doom make) (&rest args)), (defcli! (doom make index)) will never be invoked. - Refactor!: redesign our output library (was core/autoload/output.el, is now core/autoload/print.el), and how our CLI framework buffers and logs output, and now merges logs across (exit! ...) restarts. - Feat: add support for :before and :after pseudo commands. E.g. (defcli! (:before doom help) () ...) (defcli! (:after doom sync) () ...) Caveat: unlike advice, only one of each can be defined per-command. - Feat: option arguments now have rudimentary type validation (see `doom-cli-option-arg-types`). E.g. (defcli! (doom foo) ((foo ("--foo" num))) ...) If NUM is not a numeric, it will throw a validation error. Any type that isn't in `doom-cli-option-arg-types` will be treated as a wildcard string type. `num` can also be replaced with a specification, e.g. "HOST[:PORT]", and can be formatted by using symbol quotes: "`HOST'[:`PORT']". - Feat: it is no longer required that options *immediately* follow the command that defines them (but it must be somewhere after it, not before). E.g. With: (defcli! (:before doom foo) ((foo ("--foo"))) ...) (defcli! (doom foo baz) () ...) Before: FAIL: doom --foo foo baz GOOD: doom foo --foo baz FAIL: doom foo baz --foo After: FAIL: doom --foo foo baz GOOD: doom foo --foo baz GOOD: doom foo baz --foo - Refactor: CLI session state is now kept in a doom-cli-context struct (which can be bound to a CLI-local variable with &context in the arglist): (defcli! (doom sync) (&context context) (print! "Command: " (doom-cli-context-command context))) These contexts are persisted across sessions (when restarted). This is necessary to support seamless script restarting (i.e. execve emulation) in post-3.0. - Feat: Doom's CLI framework now understands "--". Everything after it will be treated as regular arguments, instead of sub-commands or options. - Refactor!: the semantics of &rest for CLIs has changed. It used to be "all extra literal, non-option arguments". It now means *all* unprocessed arguments, and its use will suppress "unrecognized option" errors, and tells the framework not to process any further subcommands. Use &args if you just want "all literal arguments following this command". - Feat: add new auxiliary keywords for CLI arglists: &context, &multiple, &flags, &args, &stdin, &whole, and &cli. - &context SYM: binds the currently running context to SYM (a `doom-cli-context` struct). Helpful for introspection or passing along state when calling subcommands by hand (with `call!`). - &stdin SYM: SYM will be bound to a string containing any input piped into the running script, or nil if none. Use `doom-cli-context-pipe-p` to detect whether the script has been piped into or out of. - &multiple OPTIONS...: allows all following OPTIONS to be repeated. E.g. "foo -x a -x b -x c" will pass (list ("-x" . "a") ("-x" . "b") ("-x" . "c")) as -x's value. - &flags OPTIONS...: All options after "&flags" get an implicit --no-* switch and cannot accept arguments. Will be set to :yes or :no depending on which flag is provided, and nil if the flag isn't provided. Otherwise, a default value can be specified in that options' arglist. E.g. (defcli! (doom foo) (&flags (foo ("--foo" :no))) ...) When called, this command sets FOO to :yes if --foo, :no if --no-foo, and defaults to :no otherwise. - &args SYM: this replaces what &rest used to be; it binds to SYM a list of all unprocessed (non-option) arguments. - &rest SYM: now binds SYM to a list of all unprocessed arguments, including options. This also suppresses "unrecognized option" errors, but will render any sub-commands inaccessible. E.g. (defcli! (doom make) (&rest rest) ...) ;; These are now inaccessible! (defcli! (doom make foo) (&rest rest) ...) (defcli! (doom make bar) (&rest rest) ...) - &cli SYM: binds SYM to the currently running `doom-cli` struct. Can also be obtained via `(doom-cli-get (doom-cli-context-command context))`. Possibly useful for introspection. - feat: add defobsolete! macro for quickly defining obsolete commands. - feat: add defalias! macro for quickly defining alias commands. - feat: add defautoload! macro for defining an autoloaded command (won't be loaded until it is called for). - refactor!: rename defcligroup! to defgroup! for consistency. - fix: CLIs will now recursively inherit plist properties from parent defcli-group!'s (but will stack :prefix). - refactor!: remove obsolete 'doom update': - refactor!: further generalize 'doom ci' - In an effort to generalize 'doom ci' (so other Doom--or non-doom--projects can use it), all its subcommands have been changed to operate on the current working directory's repo instead of $EMACSDIR. - Doom-specific CI configuration was moved to .github/ci.el. - All 'doom ci' commands will now preload one of \$CURRENT_REPO_ROOT/ci.el or \$DOOMDIR/ci.el before executing. - refactor!: changed 'doom env' - 'doom env {-c,--clear}' is now 'doom env {clear,c}' - -r/--reject and -a/--allow may now be specified multiple times - refactor!: rewrote CLI help framework and error handling to be more sophisticated and detailed. - feat: can now initiate $PAGER on output with (exit! :pager) (or use :pager? to only invoke pager is output is longer than the terminal is tall). - refactor!: changed semantics+conventions for global bin/doom options - Single-character global options are now uppercased, to distinguish them from local options: - -d (for debug mode) is now -D - -y (to suppress prompts) is now -! - -l (to load elisp) is now -L - -h (short for --help) is now -? - Replace --yes/-y switches with --force/-! - -L/--load FILE: now silently ignores file errors. - Add --strict-load FILE: does the same as -L/--load, but throws an error if FILE does not exist/is unreadable. - Add -E/--eval FORM: evaluates arbitrary lisp before commands are processed. - -L/--load, --strict-load, and -E/--eval can now be used multiple times in one command. - Add --pager COMMAND to specify an explicit pager. Will also obey $DOOMPAGER envvar. Does not obey $PAGER. - Fix #3746: which was likely caused by the generated post-script overwriting the old mid-execution. By salting the postscript filenames (with both an overarching session ID and a step counter). - Docs: document websites, environment variables, and exit codes in 'doom --help' - Feat: add imenu support for def{cli,alias,obsolete}! Ref: #4273 Fix: #3746 Fix: #3844
2022-06-18 17:16:06 +00:00
;;; Commentary:
;;; Code:
refactor!(cli): rewrite CLI framework libraries BREAKING CHANGE: this changes Doom's CLI framework in subtle ways, which is listed in greater detail below. If you've never extended Doom's CLI, then this won't affect you, but otherwise it'd be recommended you read on below. This commit focuses on the CLI framework itself and backports some foundational changes to its DSL and how it resolves command line arguments to CLIs, validates input, displays documentation, and persists state across sessions -- and more. This is done in preparation for the final stretch towarding completing the CLI rewrite (see #4273). This is also an effort to generalize Doom's CLI (both its framework and bin/doom), to increase it versatility and make it a viable dev tool for other Doom projects (on our Github org) and beyond. However, there is a *lot* to cover so I'll try to be brief: - Refactor: generalize Doom's CLI framework by moving all bin/doom specific configuration/commands out of core-cli into bin/doom. This makes it easier to use bin/doom as a project-agnostic development tool (or for users to write their own). - Refactor: change the namespace for CLI variables/functions from doom-cli-X to doom-X. - Fix: subcommands being mistaken as arguments. "doom make index" will resolve to (defcli! (doom make index)) if it exists, otherwise (defcli! (doom make)) with "index" as an argument. Before this, it would resolve to the latter no matter what. &rest can override this; with (defcli! (doom make) (&rest args)), (defcli! (doom make index)) will never be invoked. - Refactor!: redesign our output library (was core/autoload/output.el, is now core/autoload/print.el), and how our CLI framework buffers and logs output, and now merges logs across (exit! ...) restarts. - Feat: add support for :before and :after pseudo commands. E.g. (defcli! (:before doom help) () ...) (defcli! (:after doom sync) () ...) Caveat: unlike advice, only one of each can be defined per-command. - Feat: option arguments now have rudimentary type validation (see `doom-cli-option-arg-types`). E.g. (defcli! (doom foo) ((foo ("--foo" num))) ...) If NUM is not a numeric, it will throw a validation error. Any type that isn't in `doom-cli-option-arg-types` will be treated as a wildcard string type. `num` can also be replaced with a specification, e.g. "HOST[:PORT]", and can be formatted by using symbol quotes: "`HOST'[:`PORT']". - Feat: it is no longer required that options *immediately* follow the command that defines them (but it must be somewhere after it, not before). E.g. With: (defcli! (:before doom foo) ((foo ("--foo"))) ...) (defcli! (doom foo baz) () ...) Before: FAIL: doom --foo foo baz GOOD: doom foo --foo baz FAIL: doom foo baz --foo After: FAIL: doom --foo foo baz GOOD: doom foo --foo baz GOOD: doom foo baz --foo - Refactor: CLI session state is now kept in a doom-cli-context struct (which can be bound to a CLI-local variable with &context in the arglist): (defcli! (doom sync) (&context context) (print! "Command: " (doom-cli-context-command context))) These contexts are persisted across sessions (when restarted). This is necessary to support seamless script restarting (i.e. execve emulation) in post-3.0. - Feat: Doom's CLI framework now understands "--". Everything after it will be treated as regular arguments, instead of sub-commands or options. - Refactor!: the semantics of &rest for CLIs has changed. It used to be "all extra literal, non-option arguments". It now means *all* unprocessed arguments, and its use will suppress "unrecognized option" errors, and tells the framework not to process any further subcommands. Use &args if you just want "all literal arguments following this command". - Feat: add new auxiliary keywords for CLI arglists: &context, &multiple, &flags, &args, &stdin, &whole, and &cli. - &context SYM: binds the currently running context to SYM (a `doom-cli-context` struct). Helpful for introspection or passing along state when calling subcommands by hand (with `call!`). - &stdin SYM: SYM will be bound to a string containing any input piped into the running script, or nil if none. Use `doom-cli-context-pipe-p` to detect whether the script has been piped into or out of. - &multiple OPTIONS...: allows all following OPTIONS to be repeated. E.g. "foo -x a -x b -x c" will pass (list ("-x" . "a") ("-x" . "b") ("-x" . "c")) as -x's value. - &flags OPTIONS...: All options after "&flags" get an implicit --no-* switch and cannot accept arguments. Will be set to :yes or :no depending on which flag is provided, and nil if the flag isn't provided. Otherwise, a default value can be specified in that options' arglist. E.g. (defcli! (doom foo) (&flags (foo ("--foo" :no))) ...) When called, this command sets FOO to :yes if --foo, :no if --no-foo, and defaults to :no otherwise. - &args SYM: this replaces what &rest used to be; it binds to SYM a list of all unprocessed (non-option) arguments. - &rest SYM: now binds SYM to a list of all unprocessed arguments, including options. This also suppresses "unrecognized option" errors, but will render any sub-commands inaccessible. E.g. (defcli! (doom make) (&rest rest) ...) ;; These are now inaccessible! (defcli! (doom make foo) (&rest rest) ...) (defcli! (doom make bar) (&rest rest) ...) - &cli SYM: binds SYM to the currently running `doom-cli` struct. Can also be obtained via `(doom-cli-get (doom-cli-context-command context))`. Possibly useful for introspection. - feat: add defobsolete! macro for quickly defining obsolete commands. - feat: add defalias! macro for quickly defining alias commands. - feat: add defautoload! macro for defining an autoloaded command (won't be loaded until it is called for). - refactor!: rename defcligroup! to defgroup! for consistency. - fix: CLIs will now recursively inherit plist properties from parent defcli-group!'s (but will stack :prefix). - refactor!: remove obsolete 'doom update': - refactor!: further generalize 'doom ci' - In an effort to generalize 'doom ci' (so other Doom--or non-doom--projects can use it), all its subcommands have been changed to operate on the current working directory's repo instead of $EMACSDIR. - Doom-specific CI configuration was moved to .github/ci.el. - All 'doom ci' commands will now preload one of \$CURRENT_REPO_ROOT/ci.el or \$DOOMDIR/ci.el before executing. - refactor!: changed 'doom env' - 'doom env {-c,--clear}' is now 'doom env {clear,c}' - -r/--reject and -a/--allow may now be specified multiple times - refactor!: rewrote CLI help framework and error handling to be more sophisticated and detailed. - feat: can now initiate $PAGER on output with (exit! :pager) (or use :pager? to only invoke pager is output is longer than the terminal is tall). - refactor!: changed semantics+conventions for global bin/doom options - Single-character global options are now uppercased, to distinguish them from local options: - -d (for debug mode) is now -D - -y (to suppress prompts) is now -! - -l (to load elisp) is now -L - -h (short for --help) is now -? - Replace --yes/-y switches with --force/-! - -L/--load FILE: now silently ignores file errors. - Add --strict-load FILE: does the same as -L/--load, but throws an error if FILE does not exist/is unreadable. - Add -E/--eval FORM: evaluates arbitrary lisp before commands are processed. - -L/--load, --strict-load, and -E/--eval can now be used multiple times in one command. - Add --pager COMMAND to specify an explicit pager. Will also obey $DOOMPAGER envvar. Does not obey $PAGER. - Fix #3746: which was likely caused by the generated post-script overwriting the old mid-execution. By salting the postscript filenames (with both an overarching session ID and a step counter). - Docs: document websites, environment variables, and exit codes in 'doom --help' - Feat: add imenu support for def{cli,alias,obsolete}! Ref: #4273 Fix: #3746 Fix: #3844
2022-06-18 17:16:06 +00:00
(defvar doom-doctor--warnings ())
(defvar doom-doctor--errors ())
;;
;;; DSL
(defun elc-check-dir (dir)
(dolist (file (directory-files-recursively dir "\\.elc$"))
(when (file-newer-than-file-p (concat (file-name-sans-extension file) ".el")
file)
(warn! "%s is out-of-date" (abbreviate-file-name file)))))
(defmacro assert! (condition message &rest args)
`(unless ,condition
(error! ,message ,@args)))
(defmacro error! (&rest args)
`(progn (unless inhibit-message (print! (error ,@args)))
refactor!(cli): rewrite CLI framework libraries BREAKING CHANGE: this changes Doom's CLI framework in subtle ways, which is listed in greater detail below. If you've never extended Doom's CLI, then this won't affect you, but otherwise it'd be recommended you read on below. This commit focuses on the CLI framework itself and backports some foundational changes to its DSL and how it resolves command line arguments to CLIs, validates input, displays documentation, and persists state across sessions -- and more. This is done in preparation for the final stretch towarding completing the CLI rewrite (see #4273). This is also an effort to generalize Doom's CLI (both its framework and bin/doom), to increase it versatility and make it a viable dev tool for other Doom projects (on our Github org) and beyond. However, there is a *lot* to cover so I'll try to be brief: - Refactor: generalize Doom's CLI framework by moving all bin/doom specific configuration/commands out of core-cli into bin/doom. This makes it easier to use bin/doom as a project-agnostic development tool (or for users to write their own). - Refactor: change the namespace for CLI variables/functions from doom-cli-X to doom-X. - Fix: subcommands being mistaken as arguments. "doom make index" will resolve to (defcli! (doom make index)) if it exists, otherwise (defcli! (doom make)) with "index" as an argument. Before this, it would resolve to the latter no matter what. &rest can override this; with (defcli! (doom make) (&rest args)), (defcli! (doom make index)) will never be invoked. - Refactor!: redesign our output library (was core/autoload/output.el, is now core/autoload/print.el), and how our CLI framework buffers and logs output, and now merges logs across (exit! ...) restarts. - Feat: add support for :before and :after pseudo commands. E.g. (defcli! (:before doom help) () ...) (defcli! (:after doom sync) () ...) Caveat: unlike advice, only one of each can be defined per-command. - Feat: option arguments now have rudimentary type validation (see `doom-cli-option-arg-types`). E.g. (defcli! (doom foo) ((foo ("--foo" num))) ...) If NUM is not a numeric, it will throw a validation error. Any type that isn't in `doom-cli-option-arg-types` will be treated as a wildcard string type. `num` can also be replaced with a specification, e.g. "HOST[:PORT]", and can be formatted by using symbol quotes: "`HOST'[:`PORT']". - Feat: it is no longer required that options *immediately* follow the command that defines them (but it must be somewhere after it, not before). E.g. With: (defcli! (:before doom foo) ((foo ("--foo"))) ...) (defcli! (doom foo baz) () ...) Before: FAIL: doom --foo foo baz GOOD: doom foo --foo baz FAIL: doom foo baz --foo After: FAIL: doom --foo foo baz GOOD: doom foo --foo baz GOOD: doom foo baz --foo - Refactor: CLI session state is now kept in a doom-cli-context struct (which can be bound to a CLI-local variable with &context in the arglist): (defcli! (doom sync) (&context context) (print! "Command: " (doom-cli-context-command context))) These contexts are persisted across sessions (when restarted). This is necessary to support seamless script restarting (i.e. execve emulation) in post-3.0. - Feat: Doom's CLI framework now understands "--". Everything after it will be treated as regular arguments, instead of sub-commands or options. - Refactor!: the semantics of &rest for CLIs has changed. It used to be "all extra literal, non-option arguments". It now means *all* unprocessed arguments, and its use will suppress "unrecognized option" errors, and tells the framework not to process any further subcommands. Use &args if you just want "all literal arguments following this command". - Feat: add new auxiliary keywords for CLI arglists: &context, &multiple, &flags, &args, &stdin, &whole, and &cli. - &context SYM: binds the currently running context to SYM (a `doom-cli-context` struct). Helpful for introspection or passing along state when calling subcommands by hand (with `call!`). - &stdin SYM: SYM will be bound to a string containing any input piped into the running script, or nil if none. Use `doom-cli-context-pipe-p` to detect whether the script has been piped into or out of. - &multiple OPTIONS...: allows all following OPTIONS to be repeated. E.g. "foo -x a -x b -x c" will pass (list ("-x" . "a") ("-x" . "b") ("-x" . "c")) as -x's value. - &flags OPTIONS...: All options after "&flags" get an implicit --no-* switch and cannot accept arguments. Will be set to :yes or :no depending on which flag is provided, and nil if the flag isn't provided. Otherwise, a default value can be specified in that options' arglist. E.g. (defcli! (doom foo) (&flags (foo ("--foo" :no))) ...) When called, this command sets FOO to :yes if --foo, :no if --no-foo, and defaults to :no otherwise. - &args SYM: this replaces what &rest used to be; it binds to SYM a list of all unprocessed (non-option) arguments. - &rest SYM: now binds SYM to a list of all unprocessed arguments, including options. This also suppresses "unrecognized option" errors, but will render any sub-commands inaccessible. E.g. (defcli! (doom make) (&rest rest) ...) ;; These are now inaccessible! (defcli! (doom make foo) (&rest rest) ...) (defcli! (doom make bar) (&rest rest) ...) - &cli SYM: binds SYM to the currently running `doom-cli` struct. Can also be obtained via `(doom-cli-get (doom-cli-context-command context))`. Possibly useful for introspection. - feat: add defobsolete! macro for quickly defining obsolete commands. - feat: add defalias! macro for quickly defining alias commands. - feat: add defautoload! macro for defining an autoloaded command (won't be loaded until it is called for). - refactor!: rename defcligroup! to defgroup! for consistency. - fix: CLIs will now recursively inherit plist properties from parent defcli-group!'s (but will stack :prefix). - refactor!: remove obsolete 'doom update': - refactor!: further generalize 'doom ci' - In an effort to generalize 'doom ci' (so other Doom--or non-doom--projects can use it), all its subcommands have been changed to operate on the current working directory's repo instead of $EMACSDIR. - Doom-specific CI configuration was moved to .github/ci.el. - All 'doom ci' commands will now preload one of \$CURRENT_REPO_ROOT/ci.el or \$DOOMDIR/ci.el before executing. - refactor!: changed 'doom env' - 'doom env {-c,--clear}' is now 'doom env {clear,c}' - -r/--reject and -a/--allow may now be specified multiple times - refactor!: rewrote CLI help framework and error handling to be more sophisticated and detailed. - feat: can now initiate $PAGER on output with (exit! :pager) (or use :pager? to only invoke pager is output is longer than the terminal is tall). - refactor!: changed semantics+conventions for global bin/doom options - Single-character global options are now uppercased, to distinguish them from local options: - -d (for debug mode) is now -D - -y (to suppress prompts) is now -! - -l (to load elisp) is now -L - -h (short for --help) is now -? - Replace --yes/-y switches with --force/-! - -L/--load FILE: now silently ignores file errors. - Add --strict-load FILE: does the same as -L/--load, but throws an error if FILE does not exist/is unreadable. - Add -E/--eval FORM: evaluates arbitrary lisp before commands are processed. - -L/--load, --strict-load, and -E/--eval can now be used multiple times in one command. - Add --pager COMMAND to specify an explicit pager. Will also obey $DOOMPAGER envvar. Does not obey $PAGER. - Fix #3746: which was likely caused by the generated post-script overwriting the old mid-execution. By salting the postscript filenames (with both an overarching session ID and a step counter). - Docs: document websites, environment variables, and exit codes in 'doom --help' - Feat: add imenu support for def{cli,alias,obsolete}! Ref: #4273 Fix: #3746 Fix: #3844
2022-06-18 17:16:06 +00:00
(push (format! (error ,@args)) doom-doctor--errors)))
(defmacro warn! (&rest args)
`(progn (unless inhibit-message (print! (warn ,@args)))
refactor!(cli): rewrite CLI framework libraries BREAKING CHANGE: this changes Doom's CLI framework in subtle ways, which is listed in greater detail below. If you've never extended Doom's CLI, then this won't affect you, but otherwise it'd be recommended you read on below. This commit focuses on the CLI framework itself and backports some foundational changes to its DSL and how it resolves command line arguments to CLIs, validates input, displays documentation, and persists state across sessions -- and more. This is done in preparation for the final stretch towarding completing the CLI rewrite (see #4273). This is also an effort to generalize Doom's CLI (both its framework and bin/doom), to increase it versatility and make it a viable dev tool for other Doom projects (on our Github org) and beyond. However, there is a *lot* to cover so I'll try to be brief: - Refactor: generalize Doom's CLI framework by moving all bin/doom specific configuration/commands out of core-cli into bin/doom. This makes it easier to use bin/doom as a project-agnostic development tool (or for users to write their own). - Refactor: change the namespace for CLI variables/functions from doom-cli-X to doom-X. - Fix: subcommands being mistaken as arguments. "doom make index" will resolve to (defcli! (doom make index)) if it exists, otherwise (defcli! (doom make)) with "index" as an argument. Before this, it would resolve to the latter no matter what. &rest can override this; with (defcli! (doom make) (&rest args)), (defcli! (doom make index)) will never be invoked. - Refactor!: redesign our output library (was core/autoload/output.el, is now core/autoload/print.el), and how our CLI framework buffers and logs output, and now merges logs across (exit! ...) restarts. - Feat: add support for :before and :after pseudo commands. E.g. (defcli! (:before doom help) () ...) (defcli! (:after doom sync) () ...) Caveat: unlike advice, only one of each can be defined per-command. - Feat: option arguments now have rudimentary type validation (see `doom-cli-option-arg-types`). E.g. (defcli! (doom foo) ((foo ("--foo" num))) ...) If NUM is not a numeric, it will throw a validation error. Any type that isn't in `doom-cli-option-arg-types` will be treated as a wildcard string type. `num` can also be replaced with a specification, e.g. "HOST[:PORT]", and can be formatted by using symbol quotes: "`HOST'[:`PORT']". - Feat: it is no longer required that options *immediately* follow the command that defines them (but it must be somewhere after it, not before). E.g. With: (defcli! (:before doom foo) ((foo ("--foo"))) ...) (defcli! (doom foo baz) () ...) Before: FAIL: doom --foo foo baz GOOD: doom foo --foo baz FAIL: doom foo baz --foo After: FAIL: doom --foo foo baz GOOD: doom foo --foo baz GOOD: doom foo baz --foo - Refactor: CLI session state is now kept in a doom-cli-context struct (which can be bound to a CLI-local variable with &context in the arglist): (defcli! (doom sync) (&context context) (print! "Command: " (doom-cli-context-command context))) These contexts are persisted across sessions (when restarted). This is necessary to support seamless script restarting (i.e. execve emulation) in post-3.0. - Feat: Doom's CLI framework now understands "--". Everything after it will be treated as regular arguments, instead of sub-commands or options. - Refactor!: the semantics of &rest for CLIs has changed. It used to be "all extra literal, non-option arguments". It now means *all* unprocessed arguments, and its use will suppress "unrecognized option" errors, and tells the framework not to process any further subcommands. Use &args if you just want "all literal arguments following this command". - Feat: add new auxiliary keywords for CLI arglists: &context, &multiple, &flags, &args, &stdin, &whole, and &cli. - &context SYM: binds the currently running context to SYM (a `doom-cli-context` struct). Helpful for introspection or passing along state when calling subcommands by hand (with `call!`). - &stdin SYM: SYM will be bound to a string containing any input piped into the running script, or nil if none. Use `doom-cli-context-pipe-p` to detect whether the script has been piped into or out of. - &multiple OPTIONS...: allows all following OPTIONS to be repeated. E.g. "foo -x a -x b -x c" will pass (list ("-x" . "a") ("-x" . "b") ("-x" . "c")) as -x's value. - &flags OPTIONS...: All options after "&flags" get an implicit --no-* switch and cannot accept arguments. Will be set to :yes or :no depending on which flag is provided, and nil if the flag isn't provided. Otherwise, a default value can be specified in that options' arglist. E.g. (defcli! (doom foo) (&flags (foo ("--foo" :no))) ...) When called, this command sets FOO to :yes if --foo, :no if --no-foo, and defaults to :no otherwise. - &args SYM: this replaces what &rest used to be; it binds to SYM a list of all unprocessed (non-option) arguments. - &rest SYM: now binds SYM to a list of all unprocessed arguments, including options. This also suppresses "unrecognized option" errors, but will render any sub-commands inaccessible. E.g. (defcli! (doom make) (&rest rest) ...) ;; These are now inaccessible! (defcli! (doom make foo) (&rest rest) ...) (defcli! (doom make bar) (&rest rest) ...) - &cli SYM: binds SYM to the currently running `doom-cli` struct. Can also be obtained via `(doom-cli-get (doom-cli-context-command context))`. Possibly useful for introspection. - feat: add defobsolete! macro for quickly defining obsolete commands. - feat: add defalias! macro for quickly defining alias commands. - feat: add defautoload! macro for defining an autoloaded command (won't be loaded until it is called for). - refactor!: rename defcligroup! to defgroup! for consistency. - fix: CLIs will now recursively inherit plist properties from parent defcli-group!'s (but will stack :prefix). - refactor!: remove obsolete 'doom update': - refactor!: further generalize 'doom ci' - In an effort to generalize 'doom ci' (so other Doom--or non-doom--projects can use it), all its subcommands have been changed to operate on the current working directory's repo instead of $EMACSDIR. - Doom-specific CI configuration was moved to .github/ci.el. - All 'doom ci' commands will now preload one of \$CURRENT_REPO_ROOT/ci.el or \$DOOMDIR/ci.el before executing. - refactor!: changed 'doom env' - 'doom env {-c,--clear}' is now 'doom env {clear,c}' - -r/--reject and -a/--allow may now be specified multiple times - refactor!: rewrote CLI help framework and error handling to be more sophisticated and detailed. - feat: can now initiate $PAGER on output with (exit! :pager) (or use :pager? to only invoke pager is output is longer than the terminal is tall). - refactor!: changed semantics+conventions for global bin/doom options - Single-character global options are now uppercased, to distinguish them from local options: - -d (for debug mode) is now -D - -y (to suppress prompts) is now -! - -l (to load elisp) is now -L - -h (short for --help) is now -? - Replace --yes/-y switches with --force/-! - -L/--load FILE: now silently ignores file errors. - Add --strict-load FILE: does the same as -L/--load, but throws an error if FILE does not exist/is unreadable. - Add -E/--eval FORM: evaluates arbitrary lisp before commands are processed. - -L/--load, --strict-load, and -E/--eval can now be used multiple times in one command. - Add --pager COMMAND to specify an explicit pager. Will also obey $DOOMPAGER envvar. Does not obey $PAGER. - Fix #3746: which was likely caused by the generated post-script overwriting the old mid-execution. By salting the postscript filenames (with both an overarching session ID and a step counter). - Docs: document websites, environment variables, and exit codes in 'doom --help' - Feat: add imenu support for def{cli,alias,obsolete}! Ref: #4273 Fix: #3746 Fix: #3844
2022-06-18 17:16:06 +00:00
(push (format! (warn ,@args)) doom-doctor--warnings)))
(defmacro success! (&rest args)
`(print! (green ,@args)))
refactor!(cli): rewrite CLI framework libraries BREAKING CHANGE: this changes Doom's CLI framework in subtle ways, which is listed in greater detail below. If you've never extended Doom's CLI, then this won't affect you, but otherwise it'd be recommended you read on below. This commit focuses on the CLI framework itself and backports some foundational changes to its DSL and how it resolves command line arguments to CLIs, validates input, displays documentation, and persists state across sessions -- and more. This is done in preparation for the final stretch towarding completing the CLI rewrite (see #4273). This is also an effort to generalize Doom's CLI (both its framework and bin/doom), to increase it versatility and make it a viable dev tool for other Doom projects (on our Github org) and beyond. However, there is a *lot* to cover so I'll try to be brief: - Refactor: generalize Doom's CLI framework by moving all bin/doom specific configuration/commands out of core-cli into bin/doom. This makes it easier to use bin/doom as a project-agnostic development tool (or for users to write their own). - Refactor: change the namespace for CLI variables/functions from doom-cli-X to doom-X. - Fix: subcommands being mistaken as arguments. "doom make index" will resolve to (defcli! (doom make index)) if it exists, otherwise (defcli! (doom make)) with "index" as an argument. Before this, it would resolve to the latter no matter what. &rest can override this; with (defcli! (doom make) (&rest args)), (defcli! (doom make index)) will never be invoked. - Refactor!: redesign our output library (was core/autoload/output.el, is now core/autoload/print.el), and how our CLI framework buffers and logs output, and now merges logs across (exit! ...) restarts. - Feat: add support for :before and :after pseudo commands. E.g. (defcli! (:before doom help) () ...) (defcli! (:after doom sync) () ...) Caveat: unlike advice, only one of each can be defined per-command. - Feat: option arguments now have rudimentary type validation (see `doom-cli-option-arg-types`). E.g. (defcli! (doom foo) ((foo ("--foo" num))) ...) If NUM is not a numeric, it will throw a validation error. Any type that isn't in `doom-cli-option-arg-types` will be treated as a wildcard string type. `num` can also be replaced with a specification, e.g. "HOST[:PORT]", and can be formatted by using symbol quotes: "`HOST'[:`PORT']". - Feat: it is no longer required that options *immediately* follow the command that defines them (but it must be somewhere after it, not before). E.g. With: (defcli! (:before doom foo) ((foo ("--foo"))) ...) (defcli! (doom foo baz) () ...) Before: FAIL: doom --foo foo baz GOOD: doom foo --foo baz FAIL: doom foo baz --foo After: FAIL: doom --foo foo baz GOOD: doom foo --foo baz GOOD: doom foo baz --foo - Refactor: CLI session state is now kept in a doom-cli-context struct (which can be bound to a CLI-local variable with &context in the arglist): (defcli! (doom sync) (&context context) (print! "Command: " (doom-cli-context-command context))) These contexts are persisted across sessions (when restarted). This is necessary to support seamless script restarting (i.e. execve emulation) in post-3.0. - Feat: Doom's CLI framework now understands "--". Everything after it will be treated as regular arguments, instead of sub-commands or options. - Refactor!: the semantics of &rest for CLIs has changed. It used to be "all extra literal, non-option arguments". It now means *all* unprocessed arguments, and its use will suppress "unrecognized option" errors, and tells the framework not to process any further subcommands. Use &args if you just want "all literal arguments following this command". - Feat: add new auxiliary keywords for CLI arglists: &context, &multiple, &flags, &args, &stdin, &whole, and &cli. - &context SYM: binds the currently running context to SYM (a `doom-cli-context` struct). Helpful for introspection or passing along state when calling subcommands by hand (with `call!`). - &stdin SYM: SYM will be bound to a string containing any input piped into the running script, or nil if none. Use `doom-cli-context-pipe-p` to detect whether the script has been piped into or out of. - &multiple OPTIONS...: allows all following OPTIONS to be repeated. E.g. "foo -x a -x b -x c" will pass (list ("-x" . "a") ("-x" . "b") ("-x" . "c")) as -x's value. - &flags OPTIONS...: All options after "&flags" get an implicit --no-* switch and cannot accept arguments. Will be set to :yes or :no depending on which flag is provided, and nil if the flag isn't provided. Otherwise, a default value can be specified in that options' arglist. E.g. (defcli! (doom foo) (&flags (foo ("--foo" :no))) ...) When called, this command sets FOO to :yes if --foo, :no if --no-foo, and defaults to :no otherwise. - &args SYM: this replaces what &rest used to be; it binds to SYM a list of all unprocessed (non-option) arguments. - &rest SYM: now binds SYM to a list of all unprocessed arguments, including options. This also suppresses "unrecognized option" errors, but will render any sub-commands inaccessible. E.g. (defcli! (doom make) (&rest rest) ...) ;; These are now inaccessible! (defcli! (doom make foo) (&rest rest) ...) (defcli! (doom make bar) (&rest rest) ...) - &cli SYM: binds SYM to the currently running `doom-cli` struct. Can also be obtained via `(doom-cli-get (doom-cli-context-command context))`. Possibly useful for introspection. - feat: add defobsolete! macro for quickly defining obsolete commands. - feat: add defalias! macro for quickly defining alias commands. - feat: add defautoload! macro for defining an autoloaded command (won't be loaded until it is called for). - refactor!: rename defcligroup! to defgroup! for consistency. - fix: CLIs will now recursively inherit plist properties from parent defcli-group!'s (but will stack :prefix). - refactor!: remove obsolete 'doom update': - refactor!: further generalize 'doom ci' - In an effort to generalize 'doom ci' (so other Doom--or non-doom--projects can use it), all its subcommands have been changed to operate on the current working directory's repo instead of $EMACSDIR. - Doom-specific CI configuration was moved to .github/ci.el. - All 'doom ci' commands will now preload one of \$CURRENT_REPO_ROOT/ci.el or \$DOOMDIR/ci.el before executing. - refactor!: changed 'doom env' - 'doom env {-c,--clear}' is now 'doom env {clear,c}' - -r/--reject and -a/--allow may now be specified multiple times - refactor!: rewrote CLI help framework and error handling to be more sophisticated and detailed. - feat: can now initiate $PAGER on output with (exit! :pager) (or use :pager? to only invoke pager is output is longer than the terminal is tall). - refactor!: changed semantics+conventions for global bin/doom options - Single-character global options are now uppercased, to distinguish them from local options: - -d (for debug mode) is now -D - -y (to suppress prompts) is now -! - -l (to load elisp) is now -L - -h (short for --help) is now -? - Replace --yes/-y switches with --force/-! - -L/--load FILE: now silently ignores file errors. - Add --strict-load FILE: does the same as -L/--load, but throws an error if FILE does not exist/is unreadable. - Add -E/--eval FORM: evaluates arbitrary lisp before commands are processed. - -L/--load, --strict-load, and -E/--eval can now be used multiple times in one command. - Add --pager COMMAND to specify an explicit pager. Will also obey $DOOMPAGER envvar. Does not obey $PAGER. - Fix #3746: which was likely caused by the generated post-script overwriting the old mid-execution. By salting the postscript filenames (with both an overarching session ID and a step counter). - Docs: document websites, environment variables, and exit codes in 'doom --help' - Feat: add imenu support for def{cli,alias,obsolete}! Ref: #4273 Fix: #3746 Fix: #3844
2022-06-18 17:16:06 +00:00
(defmacro section! (&rest args)
`(print! (bold (blue ,@args))))
(defmacro explain! (&rest args)
`(print-group! (print! (p ,@args))))
;;
;;; CLI commands
refactor!(cli): rewrite CLI framework libraries BREAKING CHANGE: this changes Doom's CLI framework in subtle ways, which is listed in greater detail below. If you've never extended Doom's CLI, then this won't affect you, but otherwise it'd be recommended you read on below. This commit focuses on the CLI framework itself and backports some foundational changes to its DSL and how it resolves command line arguments to CLIs, validates input, displays documentation, and persists state across sessions -- and more. This is done in preparation for the final stretch towarding completing the CLI rewrite (see #4273). This is also an effort to generalize Doom's CLI (both its framework and bin/doom), to increase it versatility and make it a viable dev tool for other Doom projects (on our Github org) and beyond. However, there is a *lot* to cover so I'll try to be brief: - Refactor: generalize Doom's CLI framework by moving all bin/doom specific configuration/commands out of core-cli into bin/doom. This makes it easier to use bin/doom as a project-agnostic development tool (or for users to write their own). - Refactor: change the namespace for CLI variables/functions from doom-cli-X to doom-X. - Fix: subcommands being mistaken as arguments. "doom make index" will resolve to (defcli! (doom make index)) if it exists, otherwise (defcli! (doom make)) with "index" as an argument. Before this, it would resolve to the latter no matter what. &rest can override this; with (defcli! (doom make) (&rest args)), (defcli! (doom make index)) will never be invoked. - Refactor!: redesign our output library (was core/autoload/output.el, is now core/autoload/print.el), and how our CLI framework buffers and logs output, and now merges logs across (exit! ...) restarts. - Feat: add support for :before and :after pseudo commands. E.g. (defcli! (:before doom help) () ...) (defcli! (:after doom sync) () ...) Caveat: unlike advice, only one of each can be defined per-command. - Feat: option arguments now have rudimentary type validation (see `doom-cli-option-arg-types`). E.g. (defcli! (doom foo) ((foo ("--foo" num))) ...) If NUM is not a numeric, it will throw a validation error. Any type that isn't in `doom-cli-option-arg-types` will be treated as a wildcard string type. `num` can also be replaced with a specification, e.g. "HOST[:PORT]", and can be formatted by using symbol quotes: "`HOST'[:`PORT']". - Feat: it is no longer required that options *immediately* follow the command that defines them (but it must be somewhere after it, not before). E.g. With: (defcli! (:before doom foo) ((foo ("--foo"))) ...) (defcli! (doom foo baz) () ...) Before: FAIL: doom --foo foo baz GOOD: doom foo --foo baz FAIL: doom foo baz --foo After: FAIL: doom --foo foo baz GOOD: doom foo --foo baz GOOD: doom foo baz --foo - Refactor: CLI session state is now kept in a doom-cli-context struct (which can be bound to a CLI-local variable with &context in the arglist): (defcli! (doom sync) (&context context) (print! "Command: " (doom-cli-context-command context))) These contexts are persisted across sessions (when restarted). This is necessary to support seamless script restarting (i.e. execve emulation) in post-3.0. - Feat: Doom's CLI framework now understands "--". Everything after it will be treated as regular arguments, instead of sub-commands or options. - Refactor!: the semantics of &rest for CLIs has changed. It used to be "all extra literal, non-option arguments". It now means *all* unprocessed arguments, and its use will suppress "unrecognized option" errors, and tells the framework not to process any further subcommands. Use &args if you just want "all literal arguments following this command". - Feat: add new auxiliary keywords for CLI arglists: &context, &multiple, &flags, &args, &stdin, &whole, and &cli. - &context SYM: binds the currently running context to SYM (a `doom-cli-context` struct). Helpful for introspection or passing along state when calling subcommands by hand (with `call!`). - &stdin SYM: SYM will be bound to a string containing any input piped into the running script, or nil if none. Use `doom-cli-context-pipe-p` to detect whether the script has been piped into or out of. - &multiple OPTIONS...: allows all following OPTIONS to be repeated. E.g. "foo -x a -x b -x c" will pass (list ("-x" . "a") ("-x" . "b") ("-x" . "c")) as -x's value. - &flags OPTIONS...: All options after "&flags" get an implicit --no-* switch and cannot accept arguments. Will be set to :yes or :no depending on which flag is provided, and nil if the flag isn't provided. Otherwise, a default value can be specified in that options' arglist. E.g. (defcli! (doom foo) (&flags (foo ("--foo" :no))) ...) When called, this command sets FOO to :yes if --foo, :no if --no-foo, and defaults to :no otherwise. - &args SYM: this replaces what &rest used to be; it binds to SYM a list of all unprocessed (non-option) arguments. - &rest SYM: now binds SYM to a list of all unprocessed arguments, including options. This also suppresses "unrecognized option" errors, but will render any sub-commands inaccessible. E.g. (defcli! (doom make) (&rest rest) ...) ;; These are now inaccessible! (defcli! (doom make foo) (&rest rest) ...) (defcli! (doom make bar) (&rest rest) ...) - &cli SYM: binds SYM to the currently running `doom-cli` struct. Can also be obtained via `(doom-cli-get (doom-cli-context-command context))`. Possibly useful for introspection. - feat: add defobsolete! macro for quickly defining obsolete commands. - feat: add defalias! macro for quickly defining alias commands. - feat: add defautoload! macro for defining an autoloaded command (won't be loaded until it is called for). - refactor!: rename defcligroup! to defgroup! for consistency. - fix: CLIs will now recursively inherit plist properties from parent defcli-group!'s (but will stack :prefix). - refactor!: remove obsolete 'doom update': - refactor!: further generalize 'doom ci' - In an effort to generalize 'doom ci' (so other Doom--or non-doom--projects can use it), all its subcommands have been changed to operate on the current working directory's repo instead of $EMACSDIR. - Doom-specific CI configuration was moved to .github/ci.el. - All 'doom ci' commands will now preload one of \$CURRENT_REPO_ROOT/ci.el or \$DOOMDIR/ci.el before executing. - refactor!: changed 'doom env' - 'doom env {-c,--clear}' is now 'doom env {clear,c}' - -r/--reject and -a/--allow may now be specified multiple times - refactor!: rewrote CLI help framework and error handling to be more sophisticated and detailed. - feat: can now initiate $PAGER on output with (exit! :pager) (or use :pager? to only invoke pager is output is longer than the terminal is tall). - refactor!: changed semantics+conventions for global bin/doom options - Single-character global options are now uppercased, to distinguish them from local options: - -d (for debug mode) is now -D - -y (to suppress prompts) is now -! - -l (to load elisp) is now -L - -h (short for --help) is now -? - Replace --yes/-y switches with --force/-! - -L/--load FILE: now silently ignores file errors. - Add --strict-load FILE: does the same as -L/--load, but throws an error if FILE does not exist/is unreadable. - Add -E/--eval FORM: evaluates arbitrary lisp before commands are processed. - -L/--load, --strict-load, and -E/--eval can now be used multiple times in one command. - Add --pager COMMAND to specify an explicit pager. Will also obey $DOOMPAGER envvar. Does not obey $PAGER. - Fix #3746: which was likely caused by the generated post-script overwriting the old mid-execution. By salting the postscript filenames (with both an overarching session ID and a step counter). - Docs: document websites, environment variables, and exit codes in 'doom --help' - Feat: add imenu support for def{cli,alias,obsolete}! Ref: #4273 Fix: #3746 Fix: #3844
2022-06-18 17:16:06 +00:00
(defcli! ((doctor doc)) ()
"Diagnoses common issues on your system.
The Doom doctor is essentially one big, self-contained elisp shell script that
uses a series of simple heuristics to diagnose common issues on your system.
Issues that could intefere with Doom Emacs.
Doom modules may optionally have a doctor.el file to run their own heuristics
in."
refactor!(cli): rewrite CLI framework libraries BREAKING CHANGE: this changes Doom's CLI framework in subtle ways, which is listed in greater detail below. If you've never extended Doom's CLI, then this won't affect you, but otherwise it'd be recommended you read on below. This commit focuses on the CLI framework itself and backports some foundational changes to its DSL and how it resolves command line arguments to CLIs, validates input, displays documentation, and persists state across sessions -- and more. This is done in preparation for the final stretch towarding completing the CLI rewrite (see #4273). This is also an effort to generalize Doom's CLI (both its framework and bin/doom), to increase it versatility and make it a viable dev tool for other Doom projects (on our Github org) and beyond. However, there is a *lot* to cover so I'll try to be brief: - Refactor: generalize Doom's CLI framework by moving all bin/doom specific configuration/commands out of core-cli into bin/doom. This makes it easier to use bin/doom as a project-agnostic development tool (or for users to write their own). - Refactor: change the namespace for CLI variables/functions from doom-cli-X to doom-X. - Fix: subcommands being mistaken as arguments. "doom make index" will resolve to (defcli! (doom make index)) if it exists, otherwise (defcli! (doom make)) with "index" as an argument. Before this, it would resolve to the latter no matter what. &rest can override this; with (defcli! (doom make) (&rest args)), (defcli! (doom make index)) will never be invoked. - Refactor!: redesign our output library (was core/autoload/output.el, is now core/autoload/print.el), and how our CLI framework buffers and logs output, and now merges logs across (exit! ...) restarts. - Feat: add support for :before and :after pseudo commands. E.g. (defcli! (:before doom help) () ...) (defcli! (:after doom sync) () ...) Caveat: unlike advice, only one of each can be defined per-command. - Feat: option arguments now have rudimentary type validation (see `doom-cli-option-arg-types`). E.g. (defcli! (doom foo) ((foo ("--foo" num))) ...) If NUM is not a numeric, it will throw a validation error. Any type that isn't in `doom-cli-option-arg-types` will be treated as a wildcard string type. `num` can also be replaced with a specification, e.g. "HOST[:PORT]", and can be formatted by using symbol quotes: "`HOST'[:`PORT']". - Feat: it is no longer required that options *immediately* follow the command that defines them (but it must be somewhere after it, not before). E.g. With: (defcli! (:before doom foo) ((foo ("--foo"))) ...) (defcli! (doom foo baz) () ...) Before: FAIL: doom --foo foo baz GOOD: doom foo --foo baz FAIL: doom foo baz --foo After: FAIL: doom --foo foo baz GOOD: doom foo --foo baz GOOD: doom foo baz --foo - Refactor: CLI session state is now kept in a doom-cli-context struct (which can be bound to a CLI-local variable with &context in the arglist): (defcli! (doom sync) (&context context) (print! "Command: " (doom-cli-context-command context))) These contexts are persisted across sessions (when restarted). This is necessary to support seamless script restarting (i.e. execve emulation) in post-3.0. - Feat: Doom's CLI framework now understands "--". Everything after it will be treated as regular arguments, instead of sub-commands or options. - Refactor!: the semantics of &rest for CLIs has changed. It used to be "all extra literal, non-option arguments". It now means *all* unprocessed arguments, and its use will suppress "unrecognized option" errors, and tells the framework not to process any further subcommands. Use &args if you just want "all literal arguments following this command". - Feat: add new auxiliary keywords for CLI arglists: &context, &multiple, &flags, &args, &stdin, &whole, and &cli. - &context SYM: binds the currently running context to SYM (a `doom-cli-context` struct). Helpful for introspection or passing along state when calling subcommands by hand (with `call!`). - &stdin SYM: SYM will be bound to a string containing any input piped into the running script, or nil if none. Use `doom-cli-context-pipe-p` to detect whether the script has been piped into or out of. - &multiple OPTIONS...: allows all following OPTIONS to be repeated. E.g. "foo -x a -x b -x c" will pass (list ("-x" . "a") ("-x" . "b") ("-x" . "c")) as -x's value. - &flags OPTIONS...: All options after "&flags" get an implicit --no-* switch and cannot accept arguments. Will be set to :yes or :no depending on which flag is provided, and nil if the flag isn't provided. Otherwise, a default value can be specified in that options' arglist. E.g. (defcli! (doom foo) (&flags (foo ("--foo" :no))) ...) When called, this command sets FOO to :yes if --foo, :no if --no-foo, and defaults to :no otherwise. - &args SYM: this replaces what &rest used to be; it binds to SYM a list of all unprocessed (non-option) arguments. - &rest SYM: now binds SYM to a list of all unprocessed arguments, including options. This also suppresses "unrecognized option" errors, but will render any sub-commands inaccessible. E.g. (defcli! (doom make) (&rest rest) ...) ;; These are now inaccessible! (defcli! (doom make foo) (&rest rest) ...) (defcli! (doom make bar) (&rest rest) ...) - &cli SYM: binds SYM to the currently running `doom-cli` struct. Can also be obtained via `(doom-cli-get (doom-cli-context-command context))`. Possibly useful for introspection. - feat: add defobsolete! macro for quickly defining obsolete commands. - feat: add defalias! macro for quickly defining alias commands. - feat: add defautoload! macro for defining an autoloaded command (won't be loaded until it is called for). - refactor!: rename defcligroup! to defgroup! for consistency. - fix: CLIs will now recursively inherit plist properties from parent defcli-group!'s (but will stack :prefix). - refactor!: remove obsolete 'doom update': - refactor!: further generalize 'doom ci' - In an effort to generalize 'doom ci' (so other Doom--or non-doom--projects can use it), all its subcommands have been changed to operate on the current working directory's repo instead of $EMACSDIR. - Doom-specific CI configuration was moved to .github/ci.el. - All 'doom ci' commands will now preload one of \$CURRENT_REPO_ROOT/ci.el or \$DOOMDIR/ci.el before executing. - refactor!: changed 'doom env' - 'doom env {-c,--clear}' is now 'doom env {clear,c}' - -r/--reject and -a/--allow may now be specified multiple times - refactor!: rewrote CLI help framework and error handling to be more sophisticated and detailed. - feat: can now initiate $PAGER on output with (exit! :pager) (or use :pager? to only invoke pager is output is longer than the terminal is tall). - refactor!: changed semantics+conventions for global bin/doom options - Single-character global options are now uppercased, to distinguish them from local options: - -d (for debug mode) is now -D - -y (to suppress prompts) is now -! - -l (to load elisp) is now -L - -h (short for --help) is now -? - Replace --yes/-y switches with --force/-! - -L/--load FILE: now silently ignores file errors. - Add --strict-load FILE: does the same as -L/--load, but throws an error if FILE does not exist/is unreadable. - Add -E/--eval FORM: evaluates arbitrary lisp before commands are processed. - -L/--load, --strict-load, and -E/--eval can now be used multiple times in one command. - Add --pager COMMAND to specify an explicit pager. Will also obey $DOOMPAGER envvar. Does not obey $PAGER. - Fix #3746: which was likely caused by the generated post-script overwriting the old mid-execution. By salting the postscript filenames (with both an overarching session ID and a step counter). - Docs: document websites, environment variables, and exit codes in 'doom --help' - Feat: add imenu support for def{cli,alias,obsolete}! Ref: #4273 Fix: #3746 Fix: #3844
2022-06-18 17:16:06 +00:00
:benchmark nil
(print! "The doctor will see you now...\n")
(print! (start "Checking your Emacs version..."))
2021-05-25 14:35:08 +00:00
(print-group!
(cond ((or (> emacs-major-version 29)
(string-match-p ".\\([56]0\\|9[0-9]\\)$" emacs-version))
(warn! "Detected a development version of Emacs (%s)" emacs-version)
(if (> emacs-major-version 29)
(explain! "This is the bleeding edge of Emacs. As it is constantly changed, Doom will not "
"(officially) support it. If you've found a stable commit, great! But be "
"cautious about updating Emacs too eagerly!\n")
(explain! "A .50, .60, or .9X appended to the version string indicates that this is a version "
"of Emacs in between stable releases. These are not well supported.\n"))
(explain! "Because development builds are prone to random breakage, there will be a greater "
"burden on you to investigate and deal with issues. Please make extra sure that "
"your issue is reproducible in 29.1 before reporting them to Doom's issue tracker!\n"
"\n"
"If this doesn't phase you, read the \"Why does Doom not support Emacs HEAD\" QnA "
"in Doom's FAQ. It offers some advice for debugging and surviving issues on the "
"bleeding edge. Failing that, 29.1 is highly recommended and will always be "
"Doom's best supported version of Emacs."))
((= emacs-major-version 27)
(warn! "Emacs 27 is supported, but consider upgrading to 28.1")
(explain! "Emacs 28.1 is better supported, faster, and more stable. Plus, Doom will drop "
"27.x support sometime late-2023."))))
(print! (start "Checking for Doom's prerequisites..."))
(print-group!
(if (not (executable-find "git"))
(error! "Couldn't find git on your machine! Doom's package manager won't work.")
(save-match-data
(let* ((version
(cdr (doom-call-process "git" "version")))
(version
(and (string-match "git version \\([0-9]+\\(?:\\.[0-9]+\\)\\{2\\}\\)" version)
(match-string 1 version))))
(if version
(when (version< version "2.23")
(error! "Git %s detected! Doom requires git 2.23 or newer!"
version))
(warn! "Cannot determine Git version. Doom requires git 2.23 or newer!")))))
(unless (executable-find "rg")
(error! "Couldn't find the `rg' binary; this a hard dependecy for Doom, file searches may not work at all")))
(print! (start "Checking for Emacs config conflicts..."))
(print-group!
(unless (or (file-equal-p doom-emacs-dir "~/.emacs.d")
(file-equal-p doom-emacs-dir "~/.config/emacs"))
(print! (warn "Doom is installed in a non-standard location"))
(explain! "The standard locations are ~/.config/emacs or ~/.emacs.d. Emacs will fail "
"to load Doom if it is not explicitly told where to look for it. In Emacs 29+, "
"this is possible with the --init-directory option:\n\n"
" $ emacs --init-directory '" (abbreviate-file-name doom-emacs-dir) "'\n\n"
"However, Emacs 27-28 users have no choice but to move Doom to a standard "
"location.\n\n"
"Chemacs users may ignore this warning, however."))
(let (found?)
(dolist (file '("~/_emacs" "~/.emacs" "~/.emacs.el" "~/.emacs.d" "~/.config/emacs"))
(when (and (file-exists-p file)
(not (file-equal-p file doom-emacs-dir)))
(setq found? t)
(print! (warn "Found another Emacs config: %s (%s)")
file (if (file-directory-p file) "directory" "file"))))
(when found?
(explain! "Having multiple Emacs configs may prevent Doom from loading properly. Emacs "
"will load the first it finds and ignore the rest. If Doom isn't starting up "
"correctly (e.g. you get a vanilla splash screen), make sure that only one of "
"these exist.\n\n"
"Chemacs users may ignore this warning."))))
(print! (start "Checking for missing Emacs features..."))
(print-group!
(unless (functionp 'json-serialize)
(warn! "Emacs was not built with native JSON support")
(explain! "Users will see a substantial performance gain by building Emacs with "
"jansson support (i.e. a native JSON library), particularly LSP users. "
"You must install a prebuilt Emacs binary with this included, or compile "
"Emacs with the --with-json option."))
(unless (featurep 'native-compile)
(warn! "Emacs was not built with native compilation support")
(explain! "Users will see a substantial performance gain by building Emacs with "
"native compilation support, availible in emacs 28+."
"You must install a prebuilt Emacs binary with this included, or compile "
"Emacs with the --with-native-compilation option.")))
(print! (start "Checking for private config conflicts..."))
(print-group!
(let* ((xdg-dir (concat (or (getenv "XDG_CONFIG_HOME")
"~/.config")
"/doom/"))
(doom-dir (or (getenv "DOOMDIR")
"~/.doom.d/"))
(dir (if (file-directory-p xdg-dir)
xdg-dir
doom-dir)))
(when (file-equal-p dir doom-emacs-dir)
(print! (error "Doom was cloned to %S, not ~/.emacs.d or ~/.config/emacs"
(path dir)))
(explain! "Doom's source and your private Doom config have to live in separate directories. "
"Putting them in the same directory (without changing the DOOMDIR environment "
"variable) will cause errors on startup."))
(when (and (not (file-equal-p xdg-dir doom-dir))
(file-directory-p xdg-dir)
(file-directory-p doom-dir))
(print! (warn "Detected two private configs, in %s and %s")
(abbreviate-file-name xdg-dir)
doom-dir)
(explain! "The second directory will be ignored, as it has lower precedence."))))
2023-09-12 00:31:44 +00:00
(print! (start "Checking for common environmental issues..."))
(when (string-match-p "/fish$" shell-file-name)
(print! (warn "Detected Fish as your $SHELL"))
(explain! "Fish (and possibly other non-POSIX shells) is known to inject garbage "
"output into some of the child processes that Emacs spawns. Many Emacs "
"packages/utilities will choke on this output, causing unpredictable issues. "
"To get around this, either:\n\n"
" - Add the following to $DOOMDIR/config.el:\n\n"
" (setq shell-file-name (executable-find \"bash\"))\n\n"
" - Or change your default shell to a POSIX shell (like bash or zsh) "
" and explicitly configure your terminal apps to use the shell you "
" want.\n\n"
"If you opt for option 1 and use one of Emacs' terminal emulators, you "
"will also need to configure them to use Fish, e.g.\n\n"
" (setq-default vterm-shell (executable-find \"fish\"))\n\n"
" (setq-default explicit-shell-file-name (executable-find \"fish\"))\n"))
(print! (start "Checking for stale elc files..."))
(elc-check-dir doom-core-dir)
(elc-check-dir doom-modules-dir)
(elc-check-dir (doom-path doom-local-dir "straight" straight-build-dir))
(print! (start "Checking for problematic git global settings..."))
(if (executable-find "git")
(when (zerop (car (doom-call-process "git" "config" "--global" "--get-regexp" "^url\\.git://github\\.com")))
(warn! "Detected insteadOf rules in your global gitconfig.")
(explain! "Doom's package manager heavily relies on git. In particular, many of its packages "
"are hosted on github. Rewrite rules like these will break it:\n\n"
" [url \"git://github.com\"]\n"
" insteadOf = https://github.com\n\n"
"Please remove them from your gitconfig or use a conditional includeIf rule to "
"only apply your rewrites to specific repositories. See "
"'https://git-scm.com/docs/git-config#_includes' for more information."))
(error! "Couldn't find the `git' binary; this a hard dependecy for Doom!"))
(print! (start "Checking Doom Emacs..."))
(condition-case-unless-debug ex
(print-group!
refactor!: complete profile gen and init systems BREAKING CHANGE: This commit makes three breaking changes: - Doom now fully and dynamically generates (and byte-compiles) your profile and its init files, which includes your autoloads, loading your init files and modules, and then some. This replaces doom-initialize-modules, doom-initialize-core-modules, and doom-module-loader, which have been removed. This has also improved startup time by a bit, but if you use these functions in your CLIs, for instance, this will be a breaking change. - `doom sync` is now required for Doom to see your profiles (and must be run whenever you change them, or when you up/downgrade Emacs across major versions). - $DOOMDIR/init.el is now read much earlier than it used to be. Before any of doom-{ui,keybinds,editor,projects}, before any autoloads are loaded, and before your load-path has been populated with your packages. It now runs in the context of early-init.el, giving users freer range over what they can affect, but a more minimalistic environment to do it in. If you must have some logic run when all that is set up, add it to one of the module hooks added in e08f68b or 283308a. This also poses a significant change to Doom's load order (see the commentary change in lib/doom.el), along with the following (non breaking) changes: 1. Adds a new `doom profiles sync` command. This will forcibly resync your profiles, while `doom sync` will only do so if your profiles have changed. 2. Doom now fully and dynamically generates (and byte-compiles) your user-init-file, which includes loading all your init files, modules, and custom-file. This replaces the job of doom-initialize-modules, doom-initialize-core-modules, and doom-module-loader, which have been removed. This has also improved startup time by a bit. 3. Defines new doom-state-dir variable, though not used yet (saving that and the other breaking changes for the 3.0 release). 4. Redesigns profile directory variables (doom-profile-*-dir) to prepare for future XDG-compliance. 5. Removed unused/unimportant profile variables in doom.el. 6. Added lisp/doom-profiles.el. It's hardly feature complete, but it's enough to power the system as it is now. 7. Updates the "load order" commentary in doom.el to reflect these changes.
2022-09-15 16:53:06 +00:00
(require 'doom-start)
(print! (success "Initialized Doom Emacs %s") doom-version)
(print!
(if (hash-table-p doom-modules)
(success "Detected %d modules" (hash-table-count doom-modules))
(warn "Failed to load any modules. Do you have an private init.el?")))
(print! (success "Detected %d packages") (length doom-packages))
(print! (start "Checking Doom core for irregularities..."))
(print-group!
;; Check for oversized problem files in cache that may cause unusual/tremendous
;; delays or freezing. This shouldn't happen often.
(dolist (file (list "savehist" "projectile.cache"))
(when-let (size (ignore-errors (doom-file-size file doom-cache-dir)))
(when (> size 1048576) ; larger than 1mb
(warn! "%s is too large (%.02fmb). This may cause freezes or odd startup delays"
file (/ size 1024 1024.0))
(explain! "Consider deleting it from your system (manually)"))))
(unless (ignore-errors (executable-find doom-projectile-fd-binary))
(warn! "Couldn't find the `fd' binary; project file searches will be slightly slower"))
(require 'projectile)
(when (projectile-project-root "~")
(warn! "Your $HOME is recognized as a project root")
(explain! "Emacs will assume $HOME is the root of any project living under $HOME. If this isn't\n"
"desired, you will need to remove \".git\" from `projectile-project-root-files-bottom-up'\n"
"(a variable), e.g.\n\n"
" (after! projectile\n"
" (setq projectile-project-root-files-bottom-up\n"
" (remove \".git\" projectile-project-root-files-bottom-up)))"))
;; There should only be one
(when (and (file-equal-p doom-user-dir "~/.config/doom")
(file-directory-p "~/.doom.d"))
(print! (warn "Both %S and '~/.doom.d' exist on your system")
(path doom-user-dir))
(explain! "Doom will only load one of these (~/.config/doom takes precedence). Possessing\n"
"both is rarely intentional; you should one or the other."))
;; Check for fonts
(if (not (executable-find "fc-list"))
(warn! "Warning: unable to detect fonts because fontconfig isn't installed")
;; nerd-icons fonts
refactor!: complete profile gen and init systems BREAKING CHANGE: This commit makes three breaking changes: - Doom now fully and dynamically generates (and byte-compiles) your profile and its init files, which includes your autoloads, loading your init files and modules, and then some. This replaces doom-initialize-modules, doom-initialize-core-modules, and doom-module-loader, which have been removed. This has also improved startup time by a bit, but if you use these functions in your CLIs, for instance, this will be a breaking change. - `doom sync` is now required for Doom to see your profiles (and must be run whenever you change them, or when you up/downgrade Emacs across major versions). - $DOOMDIR/init.el is now read much earlier than it used to be. Before any of doom-{ui,keybinds,editor,projects}, before any autoloads are loaded, and before your load-path has been populated with your packages. It now runs in the context of early-init.el, giving users freer range over what they can affect, but a more minimalistic environment to do it in. If you must have some logic run when all that is set up, add it to one of the module hooks added in e08f68b or 283308a. This also poses a significant change to Doom's load order (see the commentary change in lib/doom.el), along with the following (non breaking) changes: 1. Adds a new `doom profiles sync` command. This will forcibly resync your profiles, while `doom sync` will only do so if your profiles have changed. 2. Doom now fully and dynamically generates (and byte-compiles) your user-init-file, which includes loading all your init files, modules, and custom-file. This replaces the job of doom-initialize-modules, doom-initialize-core-modules, and doom-module-loader, which have been removed. This has also improved startup time by a bit. 3. Defines new doom-state-dir variable, though not used yet (saving that and the other breaking changes for the 3.0 release). 4. Redesigns profile directory variables (doom-profile-*-dir) to prepare for future XDG-compliance. 5. Removed unused/unimportant profile variables in doom.el. 6. Added lisp/doom-profiles.el. It's hardly feature complete, but it's enough to power the system as it is now. 7. Updates the "load order" commentary in doom.el to reflect these changes.
2022-09-15 16:53:06 +00:00
(when (and (pcase system-type
(`gnu/linux (concat (or (getenv "XDG_DATA_HOME")
"~/.local/share")
"/fonts/"))
(`darwin "~/Library/Fonts/"))
(require 'nerd-icons nil t))
refactor!: complete profile gen and init systems BREAKING CHANGE: This commit makes three breaking changes: - Doom now fully and dynamically generates (and byte-compiles) your profile and its init files, which includes your autoloads, loading your init files and modules, and then some. This replaces doom-initialize-modules, doom-initialize-core-modules, and doom-module-loader, which have been removed. This has also improved startup time by a bit, but if you use these functions in your CLIs, for instance, this will be a breaking change. - `doom sync` is now required for Doom to see your profiles (and must be run whenever you change them, or when you up/downgrade Emacs across major versions). - $DOOMDIR/init.el is now read much earlier than it used to be. Before any of doom-{ui,keybinds,editor,projects}, before any autoloads are loaded, and before your load-path has been populated with your packages. It now runs in the context of early-init.el, giving users freer range over what they can affect, but a more minimalistic environment to do it in. If you must have some logic run when all that is set up, add it to one of the module hooks added in e08f68b or 283308a. This also poses a significant change to Doom's load order (see the commentary change in lib/doom.el), along with the following (non breaking) changes: 1. Adds a new `doom profiles sync` command. This will forcibly resync your profiles, while `doom sync` will only do so if your profiles have changed. 2. Doom now fully and dynamically generates (and byte-compiles) your user-init-file, which includes loading all your init files, modules, and custom-file. This replaces the job of doom-initialize-modules, doom-initialize-core-modules, and doom-module-loader, which have been removed. This has also improved startup time by a bit. 3. Defines new doom-state-dir variable, though not used yet (saving that and the other breaking changes for the 3.0 release). 4. Redesigns profile directory variables (doom-profile-*-dir) to prepare for future XDG-compliance. 5. Removed unused/unimportant profile variables in doom.el. 6. Added lisp/doom-profiles.el. It's hardly feature complete, but it's enough to power the system as it is now. 7. Updates the "load order" commentary in doom.el to reflect these changes.
2022-09-15 16:53:06 +00:00
(with-temp-buffer
(let ((errors 0))
(cl-destructuring-bind (status . output)
(doom-call-process "fc-list" "" "file")
(if (not (zerop status))
(print! (error "There was an error running `fc-list'. Is fontconfig installed correctly?"))
(insert (cdr (doom-call-process "fc-list" "" "file")))
(dolist (font nerd-icons-font-names)
refactor!: complete profile gen and init systems BREAKING CHANGE: This commit makes three breaking changes: - Doom now fully and dynamically generates (and byte-compiles) your profile and its init files, which includes your autoloads, loading your init files and modules, and then some. This replaces doom-initialize-modules, doom-initialize-core-modules, and doom-module-loader, which have been removed. This has also improved startup time by a bit, but if you use these functions in your CLIs, for instance, this will be a breaking change. - `doom sync` is now required for Doom to see your profiles (and must be run whenever you change them, or when you up/downgrade Emacs across major versions). - $DOOMDIR/init.el is now read much earlier than it used to be. Before any of doom-{ui,keybinds,editor,projects}, before any autoloads are loaded, and before your load-path has been populated with your packages. It now runs in the context of early-init.el, giving users freer range over what they can affect, but a more minimalistic environment to do it in. If you must have some logic run when all that is set up, add it to one of the module hooks added in e08f68b or 283308a. This also poses a significant change to Doom's load order (see the commentary change in lib/doom.el), along with the following (non breaking) changes: 1. Adds a new `doom profiles sync` command. This will forcibly resync your profiles, while `doom sync` will only do so if your profiles have changed. 2. Doom now fully and dynamically generates (and byte-compiles) your user-init-file, which includes loading all your init files, modules, and custom-file. This replaces the job of doom-initialize-modules, doom-initialize-core-modules, and doom-module-loader, which have been removed. This has also improved startup time by a bit. 3. Defines new doom-state-dir variable, though not used yet (saving that and the other breaking changes for the 3.0 release). 4. Redesigns profile directory variables (doom-profile-*-dir) to prepare for future XDG-compliance. 5. Removed unused/unimportant profile variables in doom.el. 6. Added lisp/doom-profiles.el. It's hardly feature complete, but it's enough to power the system as it is now. 7. Updates the "load order" commentary in doom.el to reflect these changes.
2022-09-15 16:53:06 +00:00
(if (save-excursion (re-search-backward font nil t))
(success! "Found font %s" font)
(print! (warn "%S font is not installed on your system") font)
(cl-incf errors)))
refactor!: complete profile gen and init systems BREAKING CHANGE: This commit makes three breaking changes: - Doom now fully and dynamically generates (and byte-compiles) your profile and its init files, which includes your autoloads, loading your init files and modules, and then some. This replaces doom-initialize-modules, doom-initialize-core-modules, and doom-module-loader, which have been removed. This has also improved startup time by a bit, but if you use these functions in your CLIs, for instance, this will be a breaking change. - `doom sync` is now required for Doom to see your profiles (and must be run whenever you change them, or when you up/downgrade Emacs across major versions). - $DOOMDIR/init.el is now read much earlier than it used to be. Before any of doom-{ui,keybinds,editor,projects}, before any autoloads are loaded, and before your load-path has been populated with your packages. It now runs in the context of early-init.el, giving users freer range over what they can affect, but a more minimalistic environment to do it in. If you must have some logic run when all that is set up, add it to one of the module hooks added in e08f68b or 283308a. This also poses a significant change to Doom's load order (see the commentary change in lib/doom.el), along with the following (non breaking) changes: 1. Adds a new `doom profiles sync` command. This will forcibly resync your profiles, while `doom sync` will only do so if your profiles have changed. 2. Doom now fully and dynamically generates (and byte-compiles) your user-init-file, which includes loading all your init files, modules, and custom-file. This replaces the job of doom-initialize-modules, doom-initialize-core-modules, and doom-module-loader, which have been removed. This has also improved startup time by a bit. 3. Defines new doom-state-dir variable, though not used yet (saving that and the other breaking changes for the 3.0 release). 4. Redesigns profile directory variables (doom-profile-*-dir) to prepare for future XDG-compliance. 5. Removed unused/unimportant profile variables in doom.el. 6. Added lisp/doom-profiles.el. It's hardly feature complete, but it's enough to power the system as it is now. 7. Updates the "load order" commentary in doom.el to reflect these changes.
2022-09-15 16:53:06 +00:00
(when (> errors 0)
(explain! "Some needed fonts are not properly installed on your system. To download and "
"install them, run `M-x nerd-icons-install-fonts' from within Doom Emacs. "
"However, on Windows this command will only download them; the fonts must "
"be installed manually afterwards.")))))))))
refactor!: complete profile gen and init systems BREAKING CHANGE: This commit makes three breaking changes: - Doom now fully and dynamically generates (and byte-compiles) your profile and its init files, which includes your autoloads, loading your init files and modules, and then some. This replaces doom-initialize-modules, doom-initialize-core-modules, and doom-module-loader, which have been removed. This has also improved startup time by a bit, but if you use these functions in your CLIs, for instance, this will be a breaking change. - `doom sync` is now required for Doom to see your profiles (and must be run whenever you change them, or when you up/downgrade Emacs across major versions). - $DOOMDIR/init.el is now read much earlier than it used to be. Before any of doom-{ui,keybinds,editor,projects}, before any autoloads are loaded, and before your load-path has been populated with your packages. It now runs in the context of early-init.el, giving users freer range over what they can affect, but a more minimalistic environment to do it in. If you must have some logic run when all that is set up, add it to one of the module hooks added in e08f68b or 283308a. This also poses a significant change to Doom's load order (see the commentary change in lib/doom.el), along with the following (non breaking) changes: 1. Adds a new `doom profiles sync` command. This will forcibly resync your profiles, while `doom sync` will only do so if your profiles have changed. 2. Doom now fully and dynamically generates (and byte-compiles) your user-init-file, which includes loading all your init files, modules, and custom-file. This replaces the job of doom-initialize-modules, doom-initialize-core-modules, and doom-module-loader, which have been removed. This has also improved startup time by a bit. 3. Defines new doom-state-dir variable, though not used yet (saving that and the other breaking changes for the 3.0 release). 4. Redesigns profile directory variables (doom-profile-*-dir) to prepare for future XDG-compliance. 5. Removed unused/unimportant profile variables in doom.el. 6. Added lisp/doom-profiles.el. It's hardly feature complete, but it's enough to power the system as it is now. 7. Updates the "load order" commentary in doom.el to reflect these changes.
2022-09-15 16:53:06 +00:00
(print! (start "Checking for stale elc files in your DOOMDIR..."))
(when (file-directory-p doom-user-dir)
(print-group!
(elc-check-dir doom-user-dir)))
(when doom-modules
(print! (start "Checking your enabled modules..."))
(advice-add #'require :around #'doom-shut-up-a)
(pcase-dolist (`(,group . ,name) (doom-module-list))
(doom-context-with 'doctor
(let (doom-local-errors
doom-local-warnings)
(let (doom-doctor--errors
doom-doctor--warnings)
(condition-case-unless-debug ex
(doom-module-context-with (cons group name)
(let ((doctor-file (doom-module-expand-path group name "doctor.el"))
(packages-file (doom-module-expand-path group name doom-module-packages-file)))
(when packages-file
(cl-loop with doom-output-indent = 6
for name in (doom-context-with 'packages
(let* (doom-packages
doom-disabled-packages)
(load packages-file 'noerror 'nomessage)
(mapcar #'car doom-packages)))
unless (or (doom-package-get name :disable)
(eval (doom-package-get name :ignore))
(plist-member (doom-package-get name :recipe) :local-repo)
(locate-library (symbol-name name))
(doom-package-built-in-p name)
(doom-package-installed-p name))
do (print! (error "Missing emacs package: %S") name)))
(when doctor-file
(let ((inhibit-message t))
(load doctor-file 'noerror 'nomessage)))))
(file-missing (error! "%s" (error-message-string ex)))
(error (error! "Syntax error: %s" ex)))
(when (or doom-doctor--errors doom-doctor--warnings)
(print-group!
(print! (start (bold "%s %s")) group name)
(print! "%s" (string-join (append doom-doctor--errors doom-doctor--warnings) "\n")))
(setq doom-local-errors doom-doctor--errors
doom-local-warnings doom-doctor--warnings)))
(appendq! doom-doctor--errors doom-local-errors)
(appendq! doom-doctor--warnings doom-local-warnings))))))
(error
(warn! "Attempt to load DOOM failed\n %s\n"
(or (cdr-safe ex) (car ex)))
(setq doom-modules nil)))
;; Final report
refactor!(cli): rewrite CLI framework libraries BREAKING CHANGE: this changes Doom's CLI framework in subtle ways, which is listed in greater detail below. If you've never extended Doom's CLI, then this won't affect you, but otherwise it'd be recommended you read on below. This commit focuses on the CLI framework itself and backports some foundational changes to its DSL and how it resolves command line arguments to CLIs, validates input, displays documentation, and persists state across sessions -- and more. This is done in preparation for the final stretch towarding completing the CLI rewrite (see #4273). This is also an effort to generalize Doom's CLI (both its framework and bin/doom), to increase it versatility and make it a viable dev tool for other Doom projects (on our Github org) and beyond. However, there is a *lot* to cover so I'll try to be brief: - Refactor: generalize Doom's CLI framework by moving all bin/doom specific configuration/commands out of core-cli into bin/doom. This makes it easier to use bin/doom as a project-agnostic development tool (or for users to write their own). - Refactor: change the namespace for CLI variables/functions from doom-cli-X to doom-X. - Fix: subcommands being mistaken as arguments. "doom make index" will resolve to (defcli! (doom make index)) if it exists, otherwise (defcli! (doom make)) with "index" as an argument. Before this, it would resolve to the latter no matter what. &rest can override this; with (defcli! (doom make) (&rest args)), (defcli! (doom make index)) will never be invoked. - Refactor!: redesign our output library (was core/autoload/output.el, is now core/autoload/print.el), and how our CLI framework buffers and logs output, and now merges logs across (exit! ...) restarts. - Feat: add support for :before and :after pseudo commands. E.g. (defcli! (:before doom help) () ...) (defcli! (:after doom sync) () ...) Caveat: unlike advice, only one of each can be defined per-command. - Feat: option arguments now have rudimentary type validation (see `doom-cli-option-arg-types`). E.g. (defcli! (doom foo) ((foo ("--foo" num))) ...) If NUM is not a numeric, it will throw a validation error. Any type that isn't in `doom-cli-option-arg-types` will be treated as a wildcard string type. `num` can also be replaced with a specification, e.g. "HOST[:PORT]", and can be formatted by using symbol quotes: "`HOST'[:`PORT']". - Feat: it is no longer required that options *immediately* follow the command that defines them (but it must be somewhere after it, not before). E.g. With: (defcli! (:before doom foo) ((foo ("--foo"))) ...) (defcli! (doom foo baz) () ...) Before: FAIL: doom --foo foo baz GOOD: doom foo --foo baz FAIL: doom foo baz --foo After: FAIL: doom --foo foo baz GOOD: doom foo --foo baz GOOD: doom foo baz --foo - Refactor: CLI session state is now kept in a doom-cli-context struct (which can be bound to a CLI-local variable with &context in the arglist): (defcli! (doom sync) (&context context) (print! "Command: " (doom-cli-context-command context))) These contexts are persisted across sessions (when restarted). This is necessary to support seamless script restarting (i.e. execve emulation) in post-3.0. - Feat: Doom's CLI framework now understands "--". Everything after it will be treated as regular arguments, instead of sub-commands or options. - Refactor!: the semantics of &rest for CLIs has changed. It used to be "all extra literal, non-option arguments". It now means *all* unprocessed arguments, and its use will suppress "unrecognized option" errors, and tells the framework not to process any further subcommands. Use &args if you just want "all literal arguments following this command". - Feat: add new auxiliary keywords for CLI arglists: &context, &multiple, &flags, &args, &stdin, &whole, and &cli. - &context SYM: binds the currently running context to SYM (a `doom-cli-context` struct). Helpful for introspection or passing along state when calling subcommands by hand (with `call!`). - &stdin SYM: SYM will be bound to a string containing any input piped into the running script, or nil if none. Use `doom-cli-context-pipe-p` to detect whether the script has been piped into or out of. - &multiple OPTIONS...: allows all following OPTIONS to be repeated. E.g. "foo -x a -x b -x c" will pass (list ("-x" . "a") ("-x" . "b") ("-x" . "c")) as -x's value. - &flags OPTIONS...: All options after "&flags" get an implicit --no-* switch and cannot accept arguments. Will be set to :yes or :no depending on which flag is provided, and nil if the flag isn't provided. Otherwise, a default value can be specified in that options' arglist. E.g. (defcli! (doom foo) (&flags (foo ("--foo" :no))) ...) When called, this command sets FOO to :yes if --foo, :no if --no-foo, and defaults to :no otherwise. - &args SYM: this replaces what &rest used to be; it binds to SYM a list of all unprocessed (non-option) arguments. - &rest SYM: now binds SYM to a list of all unprocessed arguments, including options. This also suppresses "unrecognized option" errors, but will render any sub-commands inaccessible. E.g. (defcli! (doom make) (&rest rest) ...) ;; These are now inaccessible! (defcli! (doom make foo) (&rest rest) ...) (defcli! (doom make bar) (&rest rest) ...) - &cli SYM: binds SYM to the currently running `doom-cli` struct. Can also be obtained via `(doom-cli-get (doom-cli-context-command context))`. Possibly useful for introspection. - feat: add defobsolete! macro for quickly defining obsolete commands. - feat: add defalias! macro for quickly defining alias commands. - feat: add defautoload! macro for defining an autoloaded command (won't be loaded until it is called for). - refactor!: rename defcligroup! to defgroup! for consistency. - fix: CLIs will now recursively inherit plist properties from parent defcli-group!'s (but will stack :prefix). - refactor!: remove obsolete 'doom update': - refactor!: further generalize 'doom ci' - In an effort to generalize 'doom ci' (so other Doom--or non-doom--projects can use it), all its subcommands have been changed to operate on the current working directory's repo instead of $EMACSDIR. - Doom-specific CI configuration was moved to .github/ci.el. - All 'doom ci' commands will now preload one of \$CURRENT_REPO_ROOT/ci.el or \$DOOMDIR/ci.el before executing. - refactor!: changed 'doom env' - 'doom env {-c,--clear}' is now 'doom env {clear,c}' - -r/--reject and -a/--allow may now be specified multiple times - refactor!: rewrote CLI help framework and error handling to be more sophisticated and detailed. - feat: can now initiate $PAGER on output with (exit! :pager) (or use :pager? to only invoke pager is output is longer than the terminal is tall). - refactor!: changed semantics+conventions for global bin/doom options - Single-character global options are now uppercased, to distinguish them from local options: - -d (for debug mode) is now -D - -y (to suppress prompts) is now -! - -l (to load elisp) is now -L - -h (short for --help) is now -? - Replace --yes/-y switches with --force/-! - -L/--load FILE: now silently ignores file errors. - Add --strict-load FILE: does the same as -L/--load, but throws an error if FILE does not exist/is unreadable. - Add -E/--eval FORM: evaluates arbitrary lisp before commands are processed. - -L/--load, --strict-load, and -E/--eval can now be used multiple times in one command. - Add --pager COMMAND to specify an explicit pager. Will also obey $DOOMPAGER envvar. Does not obey $PAGER. - Fix #3746: which was likely caused by the generated post-script overwriting the old mid-execution. By salting the postscript filenames (with both an overarching session ID and a step counter). - Docs: document websites, environment variables, and exit codes in 'doom --help' - Feat: add imenu support for def{cli,alias,obsolete}! Ref: #4273 Fix: #3746 Fix: #3844
2022-06-18 17:16:06 +00:00
(terpri)
(dolist (msg (list (list doom-doctor--warnings "warning" 'yellow)
(list doom-doctor--errors "error" 'red)))
(when (car msg)
(print! (color (nth 2 msg)
(if (cdar msg)
"There are %d %ss!"
"There is %d %s!")
(length (car msg)) (nth 1 msg)))))
refactor!(cli): rewrite CLI framework libraries BREAKING CHANGE: this changes Doom's CLI framework in subtle ways, which is listed in greater detail below. If you've never extended Doom's CLI, then this won't affect you, but otherwise it'd be recommended you read on below. This commit focuses on the CLI framework itself and backports some foundational changes to its DSL and how it resolves command line arguments to CLIs, validates input, displays documentation, and persists state across sessions -- and more. This is done in preparation for the final stretch towarding completing the CLI rewrite (see #4273). This is also an effort to generalize Doom's CLI (both its framework and bin/doom), to increase it versatility and make it a viable dev tool for other Doom projects (on our Github org) and beyond. However, there is a *lot* to cover so I'll try to be brief: - Refactor: generalize Doom's CLI framework by moving all bin/doom specific configuration/commands out of core-cli into bin/doom. This makes it easier to use bin/doom as a project-agnostic development tool (or for users to write their own). - Refactor: change the namespace for CLI variables/functions from doom-cli-X to doom-X. - Fix: subcommands being mistaken as arguments. "doom make index" will resolve to (defcli! (doom make index)) if it exists, otherwise (defcli! (doom make)) with "index" as an argument. Before this, it would resolve to the latter no matter what. &rest can override this; with (defcli! (doom make) (&rest args)), (defcli! (doom make index)) will never be invoked. - Refactor!: redesign our output library (was core/autoload/output.el, is now core/autoload/print.el), and how our CLI framework buffers and logs output, and now merges logs across (exit! ...) restarts. - Feat: add support for :before and :after pseudo commands. E.g. (defcli! (:before doom help) () ...) (defcli! (:after doom sync) () ...) Caveat: unlike advice, only one of each can be defined per-command. - Feat: option arguments now have rudimentary type validation (see `doom-cli-option-arg-types`). E.g. (defcli! (doom foo) ((foo ("--foo" num))) ...) If NUM is not a numeric, it will throw a validation error. Any type that isn't in `doom-cli-option-arg-types` will be treated as a wildcard string type. `num` can also be replaced with a specification, e.g. "HOST[:PORT]", and can be formatted by using symbol quotes: "`HOST'[:`PORT']". - Feat: it is no longer required that options *immediately* follow the command that defines them (but it must be somewhere after it, not before). E.g. With: (defcli! (:before doom foo) ((foo ("--foo"))) ...) (defcli! (doom foo baz) () ...) Before: FAIL: doom --foo foo baz GOOD: doom foo --foo baz FAIL: doom foo baz --foo After: FAIL: doom --foo foo baz GOOD: doom foo --foo baz GOOD: doom foo baz --foo - Refactor: CLI session state is now kept in a doom-cli-context struct (which can be bound to a CLI-local variable with &context in the arglist): (defcli! (doom sync) (&context context) (print! "Command: " (doom-cli-context-command context))) These contexts are persisted across sessions (when restarted). This is necessary to support seamless script restarting (i.e. execve emulation) in post-3.0. - Feat: Doom's CLI framework now understands "--". Everything after it will be treated as regular arguments, instead of sub-commands or options. - Refactor!: the semantics of &rest for CLIs has changed. It used to be "all extra literal, non-option arguments". It now means *all* unprocessed arguments, and its use will suppress "unrecognized option" errors, and tells the framework not to process any further subcommands. Use &args if you just want "all literal arguments following this command". - Feat: add new auxiliary keywords for CLI arglists: &context, &multiple, &flags, &args, &stdin, &whole, and &cli. - &context SYM: binds the currently running context to SYM (a `doom-cli-context` struct). Helpful for introspection or passing along state when calling subcommands by hand (with `call!`). - &stdin SYM: SYM will be bound to a string containing any input piped into the running script, or nil if none. Use `doom-cli-context-pipe-p` to detect whether the script has been piped into or out of. - &multiple OPTIONS...: allows all following OPTIONS to be repeated. E.g. "foo -x a -x b -x c" will pass (list ("-x" . "a") ("-x" . "b") ("-x" . "c")) as -x's value. - &flags OPTIONS...: All options after "&flags" get an implicit --no-* switch and cannot accept arguments. Will be set to :yes or :no depending on which flag is provided, and nil if the flag isn't provided. Otherwise, a default value can be specified in that options' arglist. E.g. (defcli! (doom foo) (&flags (foo ("--foo" :no))) ...) When called, this command sets FOO to :yes if --foo, :no if --no-foo, and defaults to :no otherwise. - &args SYM: this replaces what &rest used to be; it binds to SYM a list of all unprocessed (non-option) arguments. - &rest SYM: now binds SYM to a list of all unprocessed arguments, including options. This also suppresses "unrecognized option" errors, but will render any sub-commands inaccessible. E.g. (defcli! (doom make) (&rest rest) ...) ;; These are now inaccessible! (defcli! (doom make foo) (&rest rest) ...) (defcli! (doom make bar) (&rest rest) ...) - &cli SYM: binds SYM to the currently running `doom-cli` struct. Can also be obtained via `(doom-cli-get (doom-cli-context-command context))`. Possibly useful for introspection. - feat: add defobsolete! macro for quickly defining obsolete commands. - feat: add defalias! macro for quickly defining alias commands. - feat: add defautoload! macro for defining an autoloaded command (won't be loaded until it is called for). - refactor!: rename defcligroup! to defgroup! for consistency. - fix: CLIs will now recursively inherit plist properties from parent defcli-group!'s (but will stack :prefix). - refactor!: remove obsolete 'doom update': - refactor!: further generalize 'doom ci' - In an effort to generalize 'doom ci' (so other Doom--or non-doom--projects can use it), all its subcommands have been changed to operate on the current working directory's repo instead of $EMACSDIR. - Doom-specific CI configuration was moved to .github/ci.el. - All 'doom ci' commands will now preload one of \$CURRENT_REPO_ROOT/ci.el or \$DOOMDIR/ci.el before executing. - refactor!: changed 'doom env' - 'doom env {-c,--clear}' is now 'doom env {clear,c}' - -r/--reject and -a/--allow may now be specified multiple times - refactor!: rewrote CLI help framework and error handling to be more sophisticated and detailed. - feat: can now initiate $PAGER on output with (exit! :pager) (or use :pager? to only invoke pager is output is longer than the terminal is tall). - refactor!: changed semantics+conventions for global bin/doom options - Single-character global options are now uppercased, to distinguish them from local options: - -d (for debug mode) is now -D - -y (to suppress prompts) is now -! - -l (to load elisp) is now -L - -h (short for --help) is now -? - Replace --yes/-y switches with --force/-! - -L/--load FILE: now silently ignores file errors. - Add --strict-load FILE: does the same as -L/--load, but throws an error if FILE does not exist/is unreadable. - Add -E/--eval FORM: evaluates arbitrary lisp before commands are processed. - -L/--load, --strict-load, and -E/--eval can now be used multiple times in one command. - Add --pager COMMAND to specify an explicit pager. Will also obey $DOOMPAGER envvar. Does not obey $PAGER. - Fix #3746: which was likely caused by the generated post-script overwriting the old mid-execution. By salting the postscript filenames (with both an overarching session ID and a step counter). - Docs: document websites, environment variables, and exit codes in 'doom --help' - Feat: add imenu support for def{cli,alias,obsolete}! Ref: #4273 Fix: #3746 Fix: #3844
2022-06-18 17:16:06 +00:00
(unless (or doom-doctor--errors doom-doctor--warnings)
(success! "Everything seems fine, happy Emacs'ing!"))
refactor!(cli): rewrite CLI framework libraries BREAKING CHANGE: this changes Doom's CLI framework in subtle ways, which is listed in greater detail below. If you've never extended Doom's CLI, then this won't affect you, but otherwise it'd be recommended you read on below. This commit focuses on the CLI framework itself and backports some foundational changes to its DSL and how it resolves command line arguments to CLIs, validates input, displays documentation, and persists state across sessions -- and more. This is done in preparation for the final stretch towarding completing the CLI rewrite (see #4273). This is also an effort to generalize Doom's CLI (both its framework and bin/doom), to increase it versatility and make it a viable dev tool for other Doom projects (on our Github org) and beyond. However, there is a *lot* to cover so I'll try to be brief: - Refactor: generalize Doom's CLI framework by moving all bin/doom specific configuration/commands out of core-cli into bin/doom. This makes it easier to use bin/doom as a project-agnostic development tool (or for users to write their own). - Refactor: change the namespace for CLI variables/functions from doom-cli-X to doom-X. - Fix: subcommands being mistaken as arguments. "doom make index" will resolve to (defcli! (doom make index)) if it exists, otherwise (defcli! (doom make)) with "index" as an argument. Before this, it would resolve to the latter no matter what. &rest can override this; with (defcli! (doom make) (&rest args)), (defcli! (doom make index)) will never be invoked. - Refactor!: redesign our output library (was core/autoload/output.el, is now core/autoload/print.el), and how our CLI framework buffers and logs output, and now merges logs across (exit! ...) restarts. - Feat: add support for :before and :after pseudo commands. E.g. (defcli! (:before doom help) () ...) (defcli! (:after doom sync) () ...) Caveat: unlike advice, only one of each can be defined per-command. - Feat: option arguments now have rudimentary type validation (see `doom-cli-option-arg-types`). E.g. (defcli! (doom foo) ((foo ("--foo" num))) ...) If NUM is not a numeric, it will throw a validation error. Any type that isn't in `doom-cli-option-arg-types` will be treated as a wildcard string type. `num` can also be replaced with a specification, e.g. "HOST[:PORT]", and can be formatted by using symbol quotes: "`HOST'[:`PORT']". - Feat: it is no longer required that options *immediately* follow the command that defines them (but it must be somewhere after it, not before). E.g. With: (defcli! (:before doom foo) ((foo ("--foo"))) ...) (defcli! (doom foo baz) () ...) Before: FAIL: doom --foo foo baz GOOD: doom foo --foo baz FAIL: doom foo baz --foo After: FAIL: doom --foo foo baz GOOD: doom foo --foo baz GOOD: doom foo baz --foo - Refactor: CLI session state is now kept in a doom-cli-context struct (which can be bound to a CLI-local variable with &context in the arglist): (defcli! (doom sync) (&context context) (print! "Command: " (doom-cli-context-command context))) These contexts are persisted across sessions (when restarted). This is necessary to support seamless script restarting (i.e. execve emulation) in post-3.0. - Feat: Doom's CLI framework now understands "--". Everything after it will be treated as regular arguments, instead of sub-commands or options. - Refactor!: the semantics of &rest for CLIs has changed. It used to be "all extra literal, non-option arguments". It now means *all* unprocessed arguments, and its use will suppress "unrecognized option" errors, and tells the framework not to process any further subcommands. Use &args if you just want "all literal arguments following this command". - Feat: add new auxiliary keywords for CLI arglists: &context, &multiple, &flags, &args, &stdin, &whole, and &cli. - &context SYM: binds the currently running context to SYM (a `doom-cli-context` struct). Helpful for introspection or passing along state when calling subcommands by hand (with `call!`). - &stdin SYM: SYM will be bound to a string containing any input piped into the running script, or nil if none. Use `doom-cli-context-pipe-p` to detect whether the script has been piped into or out of. - &multiple OPTIONS...: allows all following OPTIONS to be repeated. E.g. "foo -x a -x b -x c" will pass (list ("-x" . "a") ("-x" . "b") ("-x" . "c")) as -x's value. - &flags OPTIONS...: All options after "&flags" get an implicit --no-* switch and cannot accept arguments. Will be set to :yes or :no depending on which flag is provided, and nil if the flag isn't provided. Otherwise, a default value can be specified in that options' arglist. E.g. (defcli! (doom foo) (&flags (foo ("--foo" :no))) ...) When called, this command sets FOO to :yes if --foo, :no if --no-foo, and defaults to :no otherwise. - &args SYM: this replaces what &rest used to be; it binds to SYM a list of all unprocessed (non-option) arguments. - &rest SYM: now binds SYM to a list of all unprocessed arguments, including options. This also suppresses "unrecognized option" errors, but will render any sub-commands inaccessible. E.g. (defcli! (doom make) (&rest rest) ...) ;; These are now inaccessible! (defcli! (doom make foo) (&rest rest) ...) (defcli! (doom make bar) (&rest rest) ...) - &cli SYM: binds SYM to the currently running `doom-cli` struct. Can also be obtained via `(doom-cli-get (doom-cli-context-command context))`. Possibly useful for introspection. - feat: add defobsolete! macro for quickly defining obsolete commands. - feat: add defalias! macro for quickly defining alias commands. - feat: add defautoload! macro for defining an autoloaded command (won't be loaded until it is called for). - refactor!: rename defcligroup! to defgroup! for consistency. - fix: CLIs will now recursively inherit plist properties from parent defcli-group!'s (but will stack :prefix). - refactor!: remove obsolete 'doom update': - refactor!: further generalize 'doom ci' - In an effort to generalize 'doom ci' (so other Doom--or non-doom--projects can use it), all its subcommands have been changed to operate on the current working directory's repo instead of $EMACSDIR. - Doom-specific CI configuration was moved to .github/ci.el. - All 'doom ci' commands will now preload one of \$CURRENT_REPO_ROOT/ci.el or \$DOOMDIR/ci.el before executing. - refactor!: changed 'doom env' - 'doom env {-c,--clear}' is now 'doom env {clear,c}' - -r/--reject and -a/--allow may now be specified multiple times - refactor!: rewrote CLI help framework and error handling to be more sophisticated and detailed. - feat: can now initiate $PAGER on output with (exit! :pager) (or use :pager? to only invoke pager is output is longer than the terminal is tall). - refactor!: changed semantics+conventions for global bin/doom options - Single-character global options are now uppercased, to distinguish them from local options: - -d (for debug mode) is now -D - -y (to suppress prompts) is now -! - -l (to load elisp) is now -L - -h (short for --help) is now -? - Replace --yes/-y switches with --force/-! - -L/--load FILE: now silently ignores file errors. - Add --strict-load FILE: does the same as -L/--load, but throws an error if FILE does not exist/is unreadable. - Add -E/--eval FORM: evaluates arbitrary lisp before commands are processed. - -L/--load, --strict-load, and -E/--eval can now be used multiple times in one command. - Add --pager COMMAND to specify an explicit pager. Will also obey $DOOMPAGER envvar. Does not obey $PAGER. - Fix #3746: which was likely caused by the generated post-script overwriting the old mid-execution. By salting the postscript filenames (with both an overarching session ID and a step counter). - Docs: document websites, environment variables, and exit codes in 'doom --help' - Feat: add imenu support for def{cli,alias,obsolete}! Ref: #4273 Fix: #3746 Fix: #3844
2022-06-18 17:16:06 +00:00
(exit! :pager? "+G"))
(provide 'doom-cli-doctor)
refactor!(cli): rewrite CLI framework libraries BREAKING CHANGE: this changes Doom's CLI framework in subtle ways, which is listed in greater detail below. If you've never extended Doom's CLI, then this won't affect you, but otherwise it'd be recommended you read on below. This commit focuses on the CLI framework itself and backports some foundational changes to its DSL and how it resolves command line arguments to CLIs, validates input, displays documentation, and persists state across sessions -- and more. This is done in preparation for the final stretch towarding completing the CLI rewrite (see #4273). This is also an effort to generalize Doom's CLI (both its framework and bin/doom), to increase it versatility and make it a viable dev tool for other Doom projects (on our Github org) and beyond. However, there is a *lot* to cover so I'll try to be brief: - Refactor: generalize Doom's CLI framework by moving all bin/doom specific configuration/commands out of core-cli into bin/doom. This makes it easier to use bin/doom as a project-agnostic development tool (or for users to write their own). - Refactor: change the namespace for CLI variables/functions from doom-cli-X to doom-X. - Fix: subcommands being mistaken as arguments. "doom make index" will resolve to (defcli! (doom make index)) if it exists, otherwise (defcli! (doom make)) with "index" as an argument. Before this, it would resolve to the latter no matter what. &rest can override this; with (defcli! (doom make) (&rest args)), (defcli! (doom make index)) will never be invoked. - Refactor!: redesign our output library (was core/autoload/output.el, is now core/autoload/print.el), and how our CLI framework buffers and logs output, and now merges logs across (exit! ...) restarts. - Feat: add support for :before and :after pseudo commands. E.g. (defcli! (:before doom help) () ...) (defcli! (:after doom sync) () ...) Caveat: unlike advice, only one of each can be defined per-command. - Feat: option arguments now have rudimentary type validation (see `doom-cli-option-arg-types`). E.g. (defcli! (doom foo) ((foo ("--foo" num))) ...) If NUM is not a numeric, it will throw a validation error. Any type that isn't in `doom-cli-option-arg-types` will be treated as a wildcard string type. `num` can also be replaced with a specification, e.g. "HOST[:PORT]", and can be formatted by using symbol quotes: "`HOST'[:`PORT']". - Feat: it is no longer required that options *immediately* follow the command that defines them (but it must be somewhere after it, not before). E.g. With: (defcli! (:before doom foo) ((foo ("--foo"))) ...) (defcli! (doom foo baz) () ...) Before: FAIL: doom --foo foo baz GOOD: doom foo --foo baz FAIL: doom foo baz --foo After: FAIL: doom --foo foo baz GOOD: doom foo --foo baz GOOD: doom foo baz --foo - Refactor: CLI session state is now kept in a doom-cli-context struct (which can be bound to a CLI-local variable with &context in the arglist): (defcli! (doom sync) (&context context) (print! "Command: " (doom-cli-context-command context))) These contexts are persisted across sessions (when restarted). This is necessary to support seamless script restarting (i.e. execve emulation) in post-3.0. - Feat: Doom's CLI framework now understands "--". Everything after it will be treated as regular arguments, instead of sub-commands or options. - Refactor!: the semantics of &rest for CLIs has changed. It used to be "all extra literal, non-option arguments". It now means *all* unprocessed arguments, and its use will suppress "unrecognized option" errors, and tells the framework not to process any further subcommands. Use &args if you just want "all literal arguments following this command". - Feat: add new auxiliary keywords for CLI arglists: &context, &multiple, &flags, &args, &stdin, &whole, and &cli. - &context SYM: binds the currently running context to SYM (a `doom-cli-context` struct). Helpful for introspection or passing along state when calling subcommands by hand (with `call!`). - &stdin SYM: SYM will be bound to a string containing any input piped into the running script, or nil if none. Use `doom-cli-context-pipe-p` to detect whether the script has been piped into or out of. - &multiple OPTIONS...: allows all following OPTIONS to be repeated. E.g. "foo -x a -x b -x c" will pass (list ("-x" . "a") ("-x" . "b") ("-x" . "c")) as -x's value. - &flags OPTIONS...: All options after "&flags" get an implicit --no-* switch and cannot accept arguments. Will be set to :yes or :no depending on which flag is provided, and nil if the flag isn't provided. Otherwise, a default value can be specified in that options' arglist. E.g. (defcli! (doom foo) (&flags (foo ("--foo" :no))) ...) When called, this command sets FOO to :yes if --foo, :no if --no-foo, and defaults to :no otherwise. - &args SYM: this replaces what &rest used to be; it binds to SYM a list of all unprocessed (non-option) arguments. - &rest SYM: now binds SYM to a list of all unprocessed arguments, including options. This also suppresses "unrecognized option" errors, but will render any sub-commands inaccessible. E.g. (defcli! (doom make) (&rest rest) ...) ;; These are now inaccessible! (defcli! (doom make foo) (&rest rest) ...) (defcli! (doom make bar) (&rest rest) ...) - &cli SYM: binds SYM to the currently running `doom-cli` struct. Can also be obtained via `(doom-cli-get (doom-cli-context-command context))`. Possibly useful for introspection. - feat: add defobsolete! macro for quickly defining obsolete commands. - feat: add defalias! macro for quickly defining alias commands. - feat: add defautoload! macro for defining an autoloaded command (won't be loaded until it is called for). - refactor!: rename defcligroup! to defgroup! for consistency. - fix: CLIs will now recursively inherit plist properties from parent defcli-group!'s (but will stack :prefix). - refactor!: remove obsolete 'doom update': - refactor!: further generalize 'doom ci' - In an effort to generalize 'doom ci' (so other Doom--or non-doom--projects can use it), all its subcommands have been changed to operate on the current working directory's repo instead of $EMACSDIR. - Doom-specific CI configuration was moved to .github/ci.el. - All 'doom ci' commands will now preload one of \$CURRENT_REPO_ROOT/ci.el or \$DOOMDIR/ci.el before executing. - refactor!: changed 'doom env' - 'doom env {-c,--clear}' is now 'doom env {clear,c}' - -r/--reject and -a/--allow may now be specified multiple times - refactor!: rewrote CLI help framework and error handling to be more sophisticated and detailed. - feat: can now initiate $PAGER on output with (exit! :pager) (or use :pager? to only invoke pager is output is longer than the terminal is tall). - refactor!: changed semantics+conventions for global bin/doom options - Single-character global options are now uppercased, to distinguish them from local options: - -d (for debug mode) is now -D - -y (to suppress prompts) is now -! - -l (to load elisp) is now -L - -h (short for --help) is now -? - Replace --yes/-y switches with --force/-! - -L/--load FILE: now silently ignores file errors. - Add --strict-load FILE: does the same as -L/--load, but throws an error if FILE does not exist/is unreadable. - Add -E/--eval FORM: evaluates arbitrary lisp before commands are processed. - -L/--load, --strict-load, and -E/--eval can now be used multiple times in one command. - Add --pager COMMAND to specify an explicit pager. Will also obey $DOOMPAGER envvar. Does not obey $PAGER. - Fix #3746: which was likely caused by the generated post-script overwriting the old mid-execution. By salting the postscript filenames (with both an overarching session ID and a step counter). - Docs: document websites, environment variables, and exit codes in 'doom --help' - Feat: add imenu support for def{cli,alias,obsolete}! Ref: #4273 Fix: #3746 Fix: #3844
2022-06-18 17:16:06 +00:00
;;; doctor.el ends here