From cc5f49858639b48618b4205adc26899a7209fde0 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Mon, 25 May 2020 03:09:46 -0400 Subject: [PATCH] Add magic cli.el in modules & refactor module init Doom now looks for cli.el files in your private directory or modules, giving them an opportunity to customize the CLI (add commands or reconfigure existing ones) to suit their purposes. --- bin/doom | 9 +++++++ core/autoload/debug.el | 17 ++++++------- core/core-cli.el | 16 ++++++------ core/core-modules.el | 55 ++++++++++++++++++++++++++---------------- 4 files changed, 57 insertions(+), 40 deletions(-) diff --git a/bin/doom b/bin/doom index 15ca6aaf2..e41248ac7 100755 --- a/bin/doom +++ b/bin/doom @@ -78,12 +78,21 @@ with a different private module." (when (or emacsdir doomdir localdir) (load! "core/core.el" user-emacs-directory)) + ;; Load any the user's private init.el or any cli.el files in modules. This + ;; gives the user (and modules) an opportunity to define their own CLI + ;; commands, or to customize the CLI to better suit them. + (load! doom-module-init-file doom-private-dir t) + (maphash (doom-module-loader doom-cli-file) doom-modules) + (load! doom-cli-file doom-private-dir t) + (run-hooks 'doom-cli-pre-hook) + (let (print-level print-gensym print-length) (condition-case e (if (null command) (doom-cli-execute "help") (let ((start-time (current-time))) (and (doom-cli-execute command args) + (progn (run-hooks 'doom-cli-post-hook) t) (print! (success "Finished! (%.4fs)") (float-time (time-subtract (current-time) diff --git a/core/autoload/debug.el b/core/autoload/debug.el index aaf7f008d..5cfa29d2d 100644 --- a/core/autoload/debug.el +++ b/core/autoload/debug.el @@ -299,17 +299,14 @@ Some items are not supported by the `nsm.el' module." (doom-initialize) (doom-initialize-core-modules)) (setq doom-modules ',doom-modules) + (maphash (lambda (key plist) + (doom-module-put + (car key) (cdr key) + :path (doom-module-locate-path (car key) (cdr key)))) + doom-modules) (--run--) - (maphash (lambda (key plist) - (let ((doom--current-module key) - (doom--current-flags (plist-get plist :flags))) - (load! "init" (doom-module-locate-path (car key) (cdr key)) t))) - doom-modules) - (maphash (lambda (key plist) - (let ((doom--current-module key) - (doom--current-flags (plist-get plist :flags))) - (load! "config" (doom-module-locate-path (car key) (cdr key)) t))) - doom-modules) + (maphash (doom-module-loader doom-module-init-file) doom-modules) + (maphash (doom-module-loader doom-module-config-file) doom-modules) (run-hook-wrapped 'doom-init-modules-hook #'doom-try-run-hook) (doom-run-all-startup-hooks-h))) (`vanilla-doom ; only Doom core diff --git a/core/core-cli.el b/core/core-cli.el index 5f4c9c532..6b2402df0 100644 --- a/core/core-cli.el +++ b/core/core-cli.el @@ -30,6 +30,13 @@ commands like `doom-cli-packages-install', `doom-cli-packages-update' and (defvar doom-auto-discard (getenv "FORCE") "If non-nil, discard all local changes while updating.") +(defvar doom-cli-file "cli" + "The basename of CLI config files for modules. + +These are loaded when a Doom's CLI starts up. There users and modules can define +additional CLI commands, or reconfigure existing ones to better suit their +purpose.") + (defvar doom--cli-commands (make-hash-table :test 'equal)) (defvar doom--cli-groups (make-hash-table :test 'equal)) (defvar doom--cli-group nil) @@ -411,14 +418,5 @@ 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.")) - -;; -;;; Load user config - -(condition-case-unless-debug e - (load! "init" doom-private-dir t) - (error - (signal 'doom-private-error (list "init.el" e)))) - (provide 'core-cli) ;;; core-cli.el ends here diff --git a/core/core-modules.el b/core/core-modules.el index 43be58de2..7675beaed 100644 --- a/core/core-modules.el +++ b/core/core-modules.el @@ -11,6 +11,19 @@ doom-modules-dir) "A list of module root directories. Order determines priority.") +(defvar doom-module-init-file "init" + "The basename of init files for modules. + +Init files are loaded early, just after Doom core, and before modules' config +files. They are always loaded, even in non-interactive sessions, and before +`doom-before-init-modules-hook'. Related to `doom-module-config-file'.") + +(defvar doom-module-config-file "config" + "The basename of config files for modules. + +Config files are loaded later, and almost always in interactive sessions. These +run before `doom-init-modules-hook'. Relevant to `doom-module-init-file'.") + (defconst doom-obsolete-modules '((:feature (version-control (:emacs vc) (:ui vc-gutter)) (spellcheck (:checkers spell)) @@ -78,31 +91,31 @@ before the user's private module.") (require 'core-projects) (require 'core-editor)) -(defun doom-initialize-modules (&optional force-p) +(defun doom-module-loader (file) + "Return a closure that loads FILE from a module. + +This closure takes two arguments: a cons cell containing (CATEGORY . MODULE) +symbols, and that module's plist." + (declare (pure t) (side-effect-free t)) + (lambda (module plist) + (let ((doom--current-module module) + (doom--current-flags (plist-get plist :flags))) + (load! file (plist-get plist :path) t)))) + +(defun doom-initialize-modules (&optional force-p no-config-p) "Loads the init.el in `doom-private-dir' and sets up hooks for a healthy session of Dooming. Will noop if used more than once, unless FORCE-P is non-nil." (when (or force-p (not doom-init-modules-p)) - (setq doom-init-modules-p t - doom-modules nil) - (with-temp-buffer - (doom-log "Initializing core modules") - (doom-initialize-core-modules) - (when-let (init-p (load! "init" doom-private-dir t)) - (doom-log "Initializing user config") - (when doom-modules - (maphash (lambda (key plist) - (let ((doom--current-module key) - (doom--current-flags (plist-get plist :flags))) - (load! "init" (plist-get plist :path) t))) - doom-modules)) - (run-hook-wrapped 'doom-before-init-modules-hook #'doom-try-run-hook) - (when doom-modules - (maphash (lambda (key plist) - (let ((doom--current-module key) - (doom--current-flags (plist-get plist :flags))) - (load! "config" (plist-get plist :path) t))) - doom-modules)) + (setq doom-init-modules-p t) + (doom-log "Initializing core modules") + (doom-initialize-core-modules) + (when-let (init-p (load! "init" doom-private-dir t)) + (doom-log "Initializing user config") + (maphash (doom-module-loader doom-module-init-file) doom-modules) + (run-hook-wrapped 'doom-before-init-modules-hook #'doom-try-run-hook) + (unless no-config-p + (maphash (doom-module-loader doom-module-config-file) doom-modules) (run-hook-wrapped 'doom-init-modules-hook #'doom-try-run-hook) (load! "config" doom-private-dir t) (load custom-file 'noerror (not doom-debug-mode))))))