2018-05-20 12:21:13 +02:00
|
|
|
;;; -*- lexical-binding: t; no-byte-compile: t; -*-
|
|
|
|
|
2019-07-22 04:15:45 +02:00
|
|
|
(require 'seq)
|
|
|
|
|
|
|
|
|
2018-05-24 19:03:36 +02:00
|
|
|
(defvar doom-auto-accept (getenv "YES")
|
|
|
|
"If non-nil, Doom will auto-accept any confirmation prompts during batch
|
2018-06-17 21:35:58 +02:00
|
|
|
commands like `doom-packages-install', `doom-packages-update' and
|
|
|
|
`doom-packages-autoremove'.")
|
2018-05-20 12:21:13 +02:00
|
|
|
|
2019-07-21 15:39:45 +02:00
|
|
|
(defvar doom-cli-pre-execute-hook nil
|
|
|
|
"TODO")
|
|
|
|
(defvar doom-cli-post-execute-hook nil
|
|
|
|
"TODO")
|
|
|
|
|
|
|
|
(defvar doom--cli-commands (make-hash-table :test 'equal))
|
|
|
|
(defvar doom--cli-groups (make-hash-table :test 'equal))
|
|
|
|
(defvar doom--cli-group nil)
|
|
|
|
|
|
|
|
|
|
|
|
;;
|
|
|
|
;;; Dispatcher API
|
|
|
|
|
|
|
|
(defun doom-file-cookie-p (file)
|
|
|
|
(with-temp-buffer
|
|
|
|
(insert-file-contents-literally file nil 0 256)
|
|
|
|
(if (and (re-search-forward "^;;;###if " nil t)
|
|
|
|
(<= (line-number-at-pos) 3))
|
|
|
|
(let ((load-file-name file))
|
|
|
|
(eval (sexp-at-point) t))
|
|
|
|
t)))
|
|
|
|
|
|
|
|
(defun doom--dispatch-command (command)
|
|
|
|
(when (symbolp command)
|
|
|
|
(setq command (symbol-name command)))
|
|
|
|
(cl-check-type command string)
|
|
|
|
(intern-soft
|
|
|
|
(format "doom-cli-%s"
|
|
|
|
(if (gethash command doom--cli-commands)
|
|
|
|
command
|
|
|
|
(cl-loop for key
|
|
|
|
being the hash-keys in doom--cli-commands
|
|
|
|
for aliases = (plist-get (gethash key doom--cli-commands) :aliases)
|
|
|
|
if (member command aliases)
|
|
|
|
return key)))))
|
2018-05-20 12:21:13 +02:00
|
|
|
|
|
|
|
(defun doom--dispatch-format (desc &optional short)
|
2018-06-05 11:19:34 +02:00
|
|
|
(with-temp-buffer
|
|
|
|
(let ((fill-column 72))
|
2019-07-21 15:39:45 +02:00
|
|
|
(save-excursion
|
|
|
|
(insert desc)
|
|
|
|
(while (re-search-backward "\n\n[^ \n]" nil t)
|
|
|
|
(fill-paragraph))))
|
2018-06-05 11:19:34 +02:00
|
|
|
(if (not short)
|
|
|
|
(buffer-string)
|
2019-07-21 15:39:45 +02:00
|
|
|
(buffer-substring (line-beginning-position)
|
|
|
|
(line-end-position)))))
|
|
|
|
|
|
|
|
(defun doom--dispatch-help-1 (command)
|
2019-07-22 04:46:14 +02:00
|
|
|
(cl-destructuring-bind (&key aliases hidden _group)
|
2019-07-21 15:39:45 +02:00
|
|
|
(gethash command doom--cli-commands)
|
2019-07-22 04:46:14 +02:00
|
|
|
(unless hidden
|
|
|
|
(print! "%-11s\t%s\t%s"
|
|
|
|
command (if aliases (string-join aliases ",") "")
|
|
|
|
(doom--dispatch-format
|
|
|
|
(documentation (doom--dispatch-command command))
|
|
|
|
t)))))
|
2019-07-21 15:39:45 +02:00
|
|
|
|
|
|
|
(defun doom--dispatch-help (&optional fn &rest args)
|
|
|
|
"Display help documentation for a dispatcher command. If fn and DESC are
|
2018-05-24 19:03:36 +02:00
|
|
|
omitted, show all available commands, their aliases and brief descriptions."
|
2019-07-21 15:39:45 +02:00
|
|
|
(if fn
|
|
|
|
(princ (documentation fn))
|
|
|
|
(print! (bold "%-11s\t%s\t%s" "Command:" "Alias" "Description"))
|
|
|
|
(print-group!
|
|
|
|
(dolist (group (seq-group-by (lambda (key) (plist-get (gethash key doom--cli-commands) :group))
|
|
|
|
(hash-table-keys doom--cli-commands)))
|
|
|
|
(if (null (car group))
|
|
|
|
(mapc #'doom--dispatch-help-1 (cdr group))
|
|
|
|
(print! "%-30s\t%s" (bold (car group)) (gethash (car group) doom--cli-groups))
|
|
|
|
(print-group!
|
|
|
|
(mapc #'doom--dispatch-help-1 (cdr group))))
|
|
|
|
(terpri)))))
|
2018-05-20 12:21:13 +02:00
|
|
|
|
2018-09-27 23:08:51 -04:00
|
|
|
(defun doom-dispatch (cmd args &optional show-help)
|
|
|
|
"Parses ARGS and invokes a dispatcher.
|
|
|
|
|
|
|
|
If SHOW-HELP is non-nil, show the documentation for said dispatcher."
|
|
|
|
(when (equal cmd "help")
|
|
|
|
(setq show-help t)
|
|
|
|
(when args
|
|
|
|
(setq cmd (car args)
|
|
|
|
args (cdr args))))
|
2019-07-21 15:39:45 +02:00
|
|
|
(let ((fn (doom--dispatch-command cmd)))
|
|
|
|
(unless (fboundp fn)
|
2019-07-22 19:46:31 +02:00
|
|
|
(user-error "%S is not any command *I* know!" cmd))
|
2018-09-27 23:08:51 -04:00
|
|
|
(if show-help
|
2019-07-21 15:39:45 +02:00
|
|
|
(doom--dispatch-help fn args)
|
|
|
|
(let ((start-time (current-time)))
|
|
|
|
(run-hooks 'doom-cli-pre-execute-hook)
|
|
|
|
(when-let (ret (apply fn args))
|
|
|
|
(print!
|
|
|
|
"\n%s"
|
|
|
|
(success "Finished! (%.4fs)"
|
|
|
|
(float-time
|
|
|
|
(time-subtract (current-time)
|
|
|
|
start-time))))
|
|
|
|
(run-hooks 'doom-cli-post-execute-hook)
|
|
|
|
ret)))))
|
|
|
|
|
|
|
|
(defmacro def-command-group! (name docstring &rest body)
|
|
|
|
"TODO"
|
|
|
|
(declare (indent defun) (doc-string 2))
|
|
|
|
`(let ((doom--cli-group ,name))
|
|
|
|
(puthash doom--cli-group ,docstring doom--cli-groups)
|
|
|
|
,@body))
|
|
|
|
|
|
|
|
(defmacro def-command! (names arglist docstring &rest body)
|
2018-05-24 19:03:36 +02:00
|
|
|
"Define a dispatcher command. COMMAND is a symbol or a list of symbols
|
|
|
|
representing the aliases for this command. DESC is a string description. The
|
|
|
|
first line should be short (under 60 letters), as it will be displayed for
|
|
|
|
bin/doom help.
|
|
|
|
|
|
|
|
BODY will be run when this dispatcher is called."
|
2018-08-28 19:14:18 +02:00
|
|
|
(declare (indent defun) (doc-string 3))
|
2019-07-21 15:39:45 +02:00
|
|
|
(let* ((names (mapcar #'symbol-name (doom-enlist names)))
|
|
|
|
(fn (intern (format "doom-cli-%s" (car names))))
|
|
|
|
(plist (cl-loop while (keywordp (car body))
|
|
|
|
collect (pop body)
|
|
|
|
collect (pop body))))
|
2018-06-19 16:43:08 +02:00
|
|
|
(macroexp-progn
|
2019-07-21 15:39:45 +02:00
|
|
|
(reverse
|
2019-07-22 04:46:14 +02:00
|
|
|
`((let ((plist ',plist))
|
|
|
|
(setq plist (plist-put plist :aliases ',(cdr names)))
|
|
|
|
(unless (or (plist-member plist :group)
|
|
|
|
(null doom--cli-group))
|
|
|
|
(plist-put plist :group doom--cli-group))
|
|
|
|
(puthash ,(car names) plist doom--cli-commands))
|
2019-07-21 15:39:45 +02:00
|
|
|
(defun ,fn ,arglist
|
|
|
|
,docstring
|
|
|
|
,@body))))))
|
2018-05-24 19:03:36 +02:00
|
|
|
|
2018-05-20 12:21:13 +02:00
|
|
|
|
|
|
|
;;
|
2019-07-21 15:39:45 +02:00
|
|
|
;;; Dispatch commands
|
2019-05-01 19:12:52 -04:00
|
|
|
|
2019-07-21 15:39:45 +02:00
|
|
|
;; Load all of our subcommands
|
2019-07-22 22:36:48 +02:00
|
|
|
(def-command! (refresh re) (&rest args)
|
2019-07-21 15:39:45 +02:00
|
|
|
"Ensure Doom is properly set up.
|
2018-05-20 12:21:13 +02:00
|
|
|
|
2019-07-21 15:39:45 +02:00
|
|
|
This is the equivalent of running autoremove, install, autoloads, then
|
|
|
|
recompile. Run this whenever you:
|
2018-05-20 12:21:13 +02:00
|
|
|
|
2019-07-21 15:39:45 +02:00
|
|
|
1. Modify your `doom!' block,
|
|
|
|
2. Add or remove `package!' blocks to your config,
|
|
|
|
3. Add or remove autoloaded functions in module autoloaded files.
|
|
|
|
4. Update Doom outside of Doom (e.g. with git)
|
2018-05-20 12:21:13 +02:00
|
|
|
|
2019-07-21 15:39:45 +02:00
|
|
|
It will ensure that unneeded packages are removed, all needed packages are
|
|
|
|
installed, autoloads files are up-to-date and no byte-compiled files have gone
|
|
|
|
stale."
|
|
|
|
(print! (green "Initiating a refresh of Doom Emacs...\n"))
|
2019-07-22 22:36:48 +02:00
|
|
|
(let ((force-p (or (member "-f" args)
|
|
|
|
(member "--force" args)))
|
|
|
|
success)
|
2019-07-21 15:39:45 +02:00
|
|
|
(when (file-exists-p doom-env-file)
|
|
|
|
(doom-reload-env-file 'force))
|
|
|
|
(doom-reload-core-autoloads force-p)
|
|
|
|
(unwind-protect
|
|
|
|
(progn
|
|
|
|
(and (doom-packages-install doom-auto-accept)
|
|
|
|
(setq success t))
|
|
|
|
(and (doom-packages-rebuild doom-auto-accept)
|
|
|
|
(setq success t))
|
|
|
|
(and (doom-packages-purge doom-auto-accept)
|
|
|
|
(setq success t)))
|
|
|
|
(doom-reload-package-autoloads (or success force-p))
|
|
|
|
(doom-byte-compile nil 'recompile))
|
|
|
|
t))
|
|
|
|
|
|
|
|
|
|
|
|
;; Load all of our subcommands
|
2019-07-22 04:22:42 +02:00
|
|
|
(load! "cli/install")
|
2019-07-21 15:39:45 +02:00
|
|
|
|
|
|
|
(def-command-group! "Diagnostics"
|
|
|
|
"For troubleshooting and diagnostics"
|
|
|
|
(def-command! (doctor doc) ()
|
|
|
|
"Checks for issues with your environment & Doom config.
|
2018-09-07 21:49:49 -04:00
|
|
|
|
:boom: Replace exec-path-from-shell w/ 'bin/doom env'
IMPORTANT: This is a breaking update for Mac users, as your shell
environment will no longer be inherited correctly (with the removal of
exec-path-from-shell). The quick fix is: 'bin/doom env refresh'. Also,
the set-env! autodef now does nothing (and is deprecated), be sure to
remove calls to it in your config.
Smaller changes:
+ This update also adds --no-* switches to doom quickstart
+ Includes general improvements to the documentation of several bin/doom
commands.
+ Moves doom/reload* commands to core/autoload/config.el
+ doom/reload-project has been removed (it didn't actually do anything)
The breaking change:
This update adds an "envvar file" to Doom Emacs. This file is generated
by `doom env refresh`, populated with variables scraped from your shell
environment (from both non-interactive and interactive sessions). This
file is then (inexpensively) loaded at startup, if it exists.
+ The file is manually generated with `doom env refresh`.
+ It can be regenerated automatically whenever `doom refresh` is run by
running `doom env enable` (`doom env clear` will reverse this and
delete the env file).
+ `doom quickstart` will ask if you want to auto-generate this envvar
file. You won't need it if you're confident Emacs will always be
started from the correct environment, however.
+ Your env file can be reloaded from a running Emacs session with `M-x
doom/reload-env`. Note: this won't work if the Emacs session you're
running it in doesn't have a correct SHELL set. i.e. don't use this to
create your first env file!
The idea isn't mine -- it's borrowed from Spacemacs -- and was
introduced to me in #1053 by @yurimx. I was impressed with it. Prior to
this, I was unhappy with exec-path-from-shell (no hate to the dev, I
understand its necessity), and 'doom patch-macos' wasn't ideal for mac
users (needed to be reapplied every time you update Emacs). What's more,
many users (even Linux users) had to install exec-path-from-shell
anyway.
This solution suffers from none of their shortcomings. More reliable
than patch-macos, more performant and complete than
exec-path-from-shell, and easily handled by bin/doom.
2019-03-28 00:06:10 -04:00
|
|
|
Use the doctor to diagnose common problems or list missing dependencies in
|
|
|
|
enabled modules.")
|
2018-05-21 15:42:27 +02:00
|
|
|
|
2019-07-21 15:39:45 +02:00
|
|
|
(load! "cli/debug")
|
|
|
|
(load! "cli/test"))
|
2018-05-21 15:42:27 +02:00
|
|
|
|
2019-07-21 15:39:45 +02:00
|
|
|
(def-command-group! "Maintenance"
|
|
|
|
"For managing your config and packages"
|
|
|
|
(load! "cli/env")
|
|
|
|
(load! "cli/upgrade")
|
|
|
|
(load! "cli/packages")
|
|
|
|
(load! "cli/autoloads")
|
|
|
|
(load! "cli/patch-macos"))
|
2018-06-17 21:38:30 +02:00
|
|
|
|
2019-07-21 15:39:45 +02:00
|
|
|
(def-command-group! "Byte compilation"
|
|
|
|
"For byte-compiling Doom and your config"
|
|
|
|
(load! "cli/byte-compile"))
|
2018-05-20 12:21:13 +02:00
|
|
|
|
2019-07-21 15:39:45 +02:00
|
|
|
(def-command-group! "Utilities"
|
|
|
|
"Conveniences for interacting with Doom externally"
|
|
|
|
(def-command! run ()
|
|
|
|
"Run Doom Emacs from bin/doom's parent directory.
|
2018-05-28 12:19:58 +02:00
|
|
|
|
2019-07-21 15:39:45 +02:00
|
|
|
All arguments are passed on to Emacs (except for -p and -e).
|
2018-06-11 23:20:45 +02:00
|
|
|
|
2019-07-21 15:39:45 +02:00
|
|
|
doom run
|
|
|
|
doom run -nw init.el
|
2018-06-11 23:20:45 +02:00
|
|
|
|
2019-07-21 15:39:45 +02:00
|
|
|
WARNING: this command exists for convenience and testing. Doom will suffer
|
|
|
|
additional overhead by being started this way. For the best performance, it is
|
|
|
|
best to run Doom out of ~/.emacs.d and ~/.doom.d.")
|
:boom: Replace exec-path-from-shell w/ 'bin/doom env'
IMPORTANT: This is a breaking update for Mac users, as your shell
environment will no longer be inherited correctly (with the removal of
exec-path-from-shell). The quick fix is: 'bin/doom env refresh'. Also,
the set-env! autodef now does nothing (and is deprecated), be sure to
remove calls to it in your config.
Smaller changes:
+ This update also adds --no-* switches to doom quickstart
+ Includes general improvements to the documentation of several bin/doom
commands.
+ Moves doom/reload* commands to core/autoload/config.el
+ doom/reload-project has been removed (it didn't actually do anything)
The breaking change:
This update adds an "envvar file" to Doom Emacs. This file is generated
by `doom env refresh`, populated with variables scraped from your shell
environment (from both non-interactive and interactive sessions). This
file is then (inexpensively) loaded at startup, if it exists.
+ The file is manually generated with `doom env refresh`.
+ It can be regenerated automatically whenever `doom refresh` is run by
running `doom env enable` (`doom env clear` will reverse this and
delete the env file).
+ `doom quickstart` will ask if you want to auto-generate this envvar
file. You won't need it if you're confident Emacs will always be
started from the correct environment, however.
+ Your env file can be reloaded from a running Emacs session with `M-x
doom/reload-env`. Note: this won't work if the Emacs session you're
running it in doesn't have a correct SHELL set. i.e. don't use this to
create your first env file!
The idea isn't mine -- it's borrowed from Spacemacs -- and was
introduced to me in #1053 by @yurimx. I was impressed with it. Prior to
this, I was unhappy with exec-path-from-shell (no hate to the dev, I
understand its necessity), and 'doom patch-macos' wasn't ideal for mac
users (needed to be reapplied every time you update Emacs). What's more,
many users (even Linux users) had to install exec-path-from-shell
anyway.
This solution suffers from none of their shortcomings. More reliable
than patch-macos, more performant and complete than
exec-path-from-shell, and easily handled by bin/doom.
2019-03-28 00:06:10 -04:00
|
|
|
|
2019-07-21 15:39:45 +02:00
|
|
|
;; (load! "cli/batch")
|
|
|
|
;; (load! "cli/org")
|
|
|
|
)
|
2018-06-11 23:20:45 +02:00
|
|
|
|
2018-06-20 12:03:23 +02:00
|
|
|
(provide 'core-cli)
|
|
|
|
;;; core-cli.el ends here
|