mirror of
https://github.com/doomemacs/doomemacs
synced 2025-08-03 12:27:26 -05:00
`doom-module-load-path` will be removed in the next big refactor commit,
so as a stop gap, I simply move it to doom.el to resolve the reference
error.
This also removes the obsolete alias `doom-modules-dirs`, since it's
been deprecated long enough (and `doom-module-load-path` itself won't be
around much longer anyway).
Ref: #8147
Amend: 8cafbe4408
216 lines
9.5 KiB
EmacsLisp
216 lines
9.5 KiB
EmacsLisp
;;; lib/modules.el -*- lexical-binding: t; -*-
|
|
;;; Commentary:
|
|
;;; Code:
|
|
|
|
(defvar doom-modules nil
|
|
"A table of enabled modules and metadata. See `doom-modules-initialize'.")
|
|
|
|
;; DEPRECATED: Remove in v3, as it will be handled in the CLI
|
|
(make-obsolete-variable 'doom-obsolete-modules nil "3.0.0")
|
|
(defconst doom-obsolete-modules
|
|
'((:feature (version-control (:emacs vc) (:ui vc-gutter))
|
|
(spellcheck (:checkers spell))
|
|
(syntax-checker (:checkers syntax))
|
|
(evil (:editor evil))
|
|
(snippets (:editor snippets))
|
|
(file-templates (:editor file-templates))
|
|
(workspaces (:ui workspaces))
|
|
(eval (:tools eval))
|
|
(lookup (:tools lookup))
|
|
(debugger (:tools debugger)))
|
|
(:tools (rotate-text (:editor rotate-text))
|
|
(vterm (:term vterm))
|
|
(password-store (:tools pass))
|
|
(flycheck (:checkers syntax))
|
|
(flyspell (:checkers spell))
|
|
(macos (:os macos)))
|
|
(:emacs (electric-indent (:emacs electric))
|
|
(hideshow (:editor fold))
|
|
(eshell (:term eshell))
|
|
(term (:term term)))
|
|
(:ui (doom-modeline (:ui modeline))
|
|
(fci (:ui fill-column))
|
|
(evil-goggles (:ui ophints))
|
|
(tabbar (:ui tabs))
|
|
(pretty-code (:ui ligatures)))
|
|
(:app (email (:email mu4e))
|
|
(notmuch (:email notmuch)))
|
|
(:lang (perl (:lang raku))))
|
|
"A tree alist that maps deprecated modules to their replacement(s).
|
|
|
|
Each entry is a three-level tree. For example:
|
|
|
|
(:feature (version-control (:emacs vc) (:ui vc-gutter))
|
|
(spellcheck (:checkers spell))
|
|
(syntax-checker (:tools flycheck)))
|
|
|
|
This marks :feature version-control, :feature spellcheck and :feature
|
|
syntax-checker modules obsolete. e.g. If :feature version-control is found in
|
|
your `doom!' block, a warning is emitted before replacing it with :emacs vc and
|
|
:ui vc-gutter.")
|
|
|
|
(make-obsolete-variable 'doom-inhibit-module-warnings nil "3.0.0")
|
|
(defvar doom-inhibit-module-warnings (not noninteractive)
|
|
"If non-nil, don't emit deprecated or missing module warnings at startup.")
|
|
|
|
;;; Module file variables
|
|
(defvar doom-module-init-file "init.el"
|
|
"The filename for module early initialization config files.
|
|
|
|
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-modules-init-hook'. Related to `doom-module-config-file'.")
|
|
|
|
(defvar doom-module-config-file "config.el"
|
|
"The filename for module configuration files.
|
|
|
|
Config files are loaded later, and almost always in interactive sessions. These
|
|
run before `doom-after-modules-config-hook' and after `doom-module-init-file'.")
|
|
|
|
(defvar doom-module-packages-file "packages.el"
|
|
"The filename for the package configuration file.
|
|
|
|
Package files are read whenever Doom's package manager wants a manifest of all
|
|
desired packages. They are rarely read in interactive sessions (unless the user
|
|
uses a straight or package.el command directly).")
|
|
|
|
|
|
;;
|
|
;;; API
|
|
|
|
;;;###autoload
|
|
(defun doom-modules-initialize (&optional force?)
|
|
"Initializes module metadata."
|
|
(when (or (null doom-modules) force?)
|
|
(setq doom-modules (make-hash-table :test 'equal))
|
|
;; Register Doom's two virtual module categories, representing Doom's core
|
|
;; and the user's config; which are always enabled.
|
|
(doom-module--put '(:doom . nil) :path doom-core-dir :depth -110)
|
|
(doom-module--put '(:user . nil) :path doom-user-dir :depth '(-105 . 105))
|
|
;; DEPRECATED: I intend to phase out our internal usage of `use-package' and
|
|
;; move it to a :config use-package module. The macro is far too complex
|
|
;; and magical for our needs, but until this move is done, ':config
|
|
;; use-package' will remain a hardcoded module for backwards
|
|
;; compatibility.
|
|
(doom-module--put '(:config . use-package)
|
|
:path (doom-module-locate-path '(:config . use-package))
|
|
:depth -111)
|
|
;; Load $DOOMDIR/init.el, where the user's `doom!' lives, which will inform
|
|
;; us of all desired modules.
|
|
(doom-load (file-name-concat doom-user-dir doom-module-init-file)
|
|
'noerror)))
|
|
|
|
(cl-defun doom-module--put ((group . name) &rest plist)
|
|
"Enable GROUP NAME and associate PLIST with it.
|
|
|
|
This enables the target module, where GROUP is a keyword, NAME is a symbol, and
|
|
PLIST is a property list accepting none, any, or all of the following
|
|
properties:
|
|
|
|
:group KEYWORD
|
|
Indicating the group this module is in. This doesn't have to match GROUP, as
|
|
it could indicate a module alias.
|
|
:name SYMBOL
|
|
Indicating the name of this module. This doesn't have to match NAME, as it
|
|
could indicate a module alias.
|
|
:path STRING
|
|
Path to the directory where this module lives.
|
|
:depth INT|(INITDEPTH . CONFIGDEPTH)
|
|
Determines module load order. If a cons cell, INITDEPTH determines the load
|
|
order of the module's init.el, while CONFIGDEPTH determines the same for all
|
|
other config files (config.el, packages.el, doctor.el, etc).
|
|
:flags (SYMBOL...)
|
|
A list of activated flags for this module. Will be collapsed into
|
|
pre-existing flags for the module.
|
|
:features (SYMBOL...)
|
|
A list of active features, determined from the module's metadata. Will be
|
|
collapsed into any pre-existing features for the module. NOT IMPLEMENTED
|
|
YET.
|
|
|
|
\(fn (GROUP . NAME) &key GROUP NAME PATH DEPTH FLAGS FEATURES)"
|
|
(let ((module
|
|
(make-doom-module
|
|
:index (hash-table-count doom-modules)
|
|
:group (or (plist-get plist :group) group)
|
|
:name (or (plist-get plist :name) name)
|
|
:path (plist-get plist :path)
|
|
:flags (plist-get plist :flags)
|
|
:features () ; TODO
|
|
:depth
|
|
(if (not (plist-member plist :depth))
|
|
'(0 . 0)
|
|
(let ((depth (plist-get plist :depth)))
|
|
(cl-check-type depth (or integer cons))
|
|
(cond ((integerp depth) (cons depth depth))
|
|
((consp depth) (cons (or (car depth) 0)
|
|
(or (cdr depth) 0)))
|
|
((error "Invalid DEPTH value: %S" depth))))))))
|
|
(doom-log 2 "module-put: %s" module)
|
|
(prog1 (puthash (cons group name) module doom-modules)
|
|
;; PERF: Doom caches module index, flags, and features in symbol plists
|
|
;; for fast lookups in `modulep!' and elsewhere. plists are lighter and
|
|
;; faster than hash tables for datasets this size, and this information
|
|
;; is looked up *very* often.
|
|
(put group name (doom-module->context module)))))
|
|
|
|
(defun doom-module-mplist-map (fn mplist)
|
|
"Apply FN to each module in MPLIST."
|
|
(let ((mplist (copy-sequence mplist))
|
|
(inhibit-message doom-inhibit-module-warnings)
|
|
obsolete
|
|
results
|
|
group m)
|
|
(while mplist
|
|
(setq m (pop mplist))
|
|
(cond ((keywordp m)
|
|
(setq group m
|
|
obsolete (assq m doom-obsolete-modules)))
|
|
((null group)
|
|
(error "No module group specified for %s" m))
|
|
((and (listp m) (keywordp (car m)))
|
|
(pcase (car m)
|
|
(:cond
|
|
(cl-loop for (cond . mods) in (cdr m)
|
|
if (eval cond t)
|
|
return (prependq! mplist mods)))
|
|
(:if (if (eval (cadr m) t)
|
|
(push (caddr m) mplist)
|
|
(prependq! mplist (cdddr m))))
|
|
(test (if (xor (eval (cadr m) t)
|
|
(eq test :unless))
|
|
(prependq! mplist (cddr m))))))
|
|
((catch 'doom-modules
|
|
(let* ((module (if (listp m) (car m) m))
|
|
(flags (if (listp m) (cdr m))))
|
|
(when-let (new (assq module obsolete))
|
|
(let ((newkeys (cdr new)))
|
|
(if (null newkeys)
|
|
(print! (warn "%s module was removed"))
|
|
(if (cdr newkeys)
|
|
(print! (warn "%s module was removed and split into the %s modules")
|
|
(list group module)
|
|
(mapconcat #'prin1-to-string newkeys ", "))
|
|
(print! (warn "%s module was moved to %s")
|
|
(list group module)
|
|
(car newkeys)))
|
|
(push group mplist)
|
|
(dolist (key newkeys)
|
|
(push (if flags
|
|
(nconc (cdr key) flags)
|
|
(cdr key))
|
|
mplist)
|
|
(push (car key) mplist))
|
|
(throw 'doom-modules t))))
|
|
(doom-log "module: %s %s %s -> %s" group module (or flags "")
|
|
(doom-module-locate-path (cons group module)))
|
|
(push (funcall fn (cons group module)
|
|
:flags (if (listp m) (cdr m))
|
|
:path (doom-module-locate-path (cons group module)))
|
|
results))))))
|
|
(when noninteractive
|
|
(setq doom-inhibit-module-warnings t))
|
|
(nreverse results)))
|
|
|
|
(provide 'doom-lib '(modules))
|
|
;;; modules.el ends here
|