+ enable lexical-scope everywhere (lexical-binding = t): ~5-10% faster startup; ~5-20% general boost + reduce consing, function calls & garbage collection by preferring cl-loop & dolist over lambda closures (for mapc[ar], add-hook, and various cl-lib filter/map/reduce functions) -- where possible + prefer functions with dedicated opcodes, like assq (see byte-defop's in bytecomp.el for more) + prefer pcase & cond (faster) over cl-case + general refactor for code readability + ensure naming & style conventions are adhered to + appease byte-compiler by marking unused variables with underscore + defer minor mode activation to after-init, emacs-startup or window-setup hooks; a customization opportunity for users + ensures custom functionality won't interfere with startup. |
||
---|---|---|
.. | ||
app | ||
completion | ||
feature | ||
lang | ||
private | ||
tools | ||
ui | ||
README.org |
DOOM Modules
Introduction
DOOM is comprised of its core files and then its modules. These modules loosely take after Spacemacs' layers, utilizing a small list of macros to manage and configure plugins and DOOM Emacs.
These macros are:
-
Package management
(featurep! MODULE SUBMODULE)
: returnst
if:module submodule
is activated(load! NAME)
: loads NAME.el, relative to the current file(require! MODULE SUBMODULE &optional RELOAD-P)
: activates a module & loads its config.el(package! NAME &key recipe pin)
: declares a package and where to get it(depends-on! MODULE SUBMODULE)
: loads a module's packages.el
-
Configuration
(set! SETTING &rest ARGS)
: safely cross-configure other modules(def-package! NAME &rest PLIST)
: configure a package (wrapper arounduse-package
)(def-setting! SETTING &rest ARGS)
: defines a setting other modules canset!
The TL;DR of this document is:
- Modules are comprised of:
config.el
,packages.el
, eitherautoload.el
orautoload/*.el
, and+*.el
files; these are all optional. config.el
is the only file loaded when a module is activated, and is where you configure the module and its plugins.packages.el
files inform DOOM what plugins to install and where from, using thepackage!
macro. This macro accepts a MELPA-style recipe plist to specify a location other than the ELPA for fetching plugins.- Use
set!
to safely cross-configure modules;doom/describe-setting
can help you discover what settings are available. - Packages are deferred by default; add
:demand t
to theirdef-package!
declaration to load them immediately.
Overview
These modules are in their ideal load order.
- :feature
- Broad modules that bring essential functionality to Emacs as an editor.
- :completion
- Swappable completion modules for narrowing down candidate lists quickly.
- :ui
- Aesthetic modules that affect the Emacs interface or user experience.
- :tools
- Small modules that add specific, non-essential functionality to Emacs.
- :lang
- Modules that bring support for a language or group of languages to Emacs.
- :app
- Opinionated and heavy modules that totally transform Emacs' UI to serve a specific purpose.
- :private
- Private configuration modules that are untracked by version control (except for my personal one; use it as a reference).
Enabling/disabling modules
Change the doom!
block in your init.el
file to enable/disable modules on startup. You'll need to restart Emacs.
Don't forget to run make
afterwards to ensure that the needed packages are installed (and unneeded ones are uninstalled).
Remember: if you've byte-compiled your config, your changes won't take effect until you recompile or delete the \*.elc files.
The structure of a module
Modules are made up of four optional parts:
- config.el
- The heart of a module; loaded when the module is activated.
- packages.el
- Tells DOOM what packages to install and where from. Isn't loaded until package management commands are used.
- autoload.el (or autoload/*.el)
- Lazily-loaded functions for that module.
- +*.el
- Additional config files; not automatically loaded.
config.el
config.el is loaded immediately. It is the only file proactively loaded by the DOOM module system. Additional files must be explicitly loaded using load!
.
It should expect dependencies (in packages.el
) to be installed and available, but shouldn't make assumptions about what modules are activated (use featurep!
for this).
Packages should be configured using after!
or def-package!
(an alias for use-package
).
;; from modules/completion/company/config.el
(def-package! company
:commands (company-mode global-company-mode company-complete
company-complete-common company-manual-begin company-grab-line)
:config
(setq company-idle-delay nil
company-tooltip-limit 10
company-dabbrev-downcase nil
company-dabbrev-ignore-case nil)
[...])
- Packages are deferred by default: add
:demand t
todef-package!
blocks to load them immediately. - Use
featurep!
to test DOOM module availability -
Use
set!
to cross-configure modules safely, e.g. company backends:;; from modules/lang/python/config.el (set! :company-backend 'python-mode '(company-anaconda))
packages.el
This file isn't loaded until you use DOOM's package management commands.
Evaluating them should be deterministic, idempotent, and without side-effects (besides updating doom-modules
and doom-packages
).
Packages are declared with the package!
macro, e.g.
;; from modules/lang/org/packages.el
(package! org-bullets)
;; from modules/tools/rotate-text/packages.el
(package! rotate-text :recipe (:fetcher github :repo "debug-ito/rotate-text.el"))
The packages.el of another module can loaded with depends-on!
:
;; from modules/feature/file-templates/packages.el
(depends-on! :feature snippets)
autoload.el OR autoload/*.el
Functions in these files are lazily loaded. doom/reload-autoloads
will scan these and produce an autoloads.el
file, which tells Emacs where to find these functions.
For example:
;; from modules/lang/org/autoload/org.el
;;;###autoload
(defun +org/toggle-checkbox ()
(interactive)
[...])
;; from modules/lang/org/autoload/evil.el
;;;###autoload (autoload '+org:attach "lang/org/autoload/evil" nil t)
(evil-define-command +org:attach (&optional uri)
(interactive "<a>")
[...])
Autoload files named evil*.el
will be ignored if :feature evil
isn't loaded.
Additional files
The only convention is to prefix additional elisp files with a +
, e.g.
modules/feature/version-control/+git.el
.
These are not loaded automatically. Use load!
from config.el
to do so.
;; from modules/feature/version-control/config.el
(load +git)
Appendix
-
Macros
(featurep! CATEGORY MODULE)
(load! NAME)
(package! NAME &key recipe pin)
(require! CATEGORY MODULE &optional RELOAD-P)
(def-package! NAME &rest PLIST)
(set! SETTING &rest ARGS)
(def-setting! NAME ARGLIST &rest BODY)
-
Commands
doom/reload
doom/reload-autoloads
doom/compile
doom/recompile
doom/compile-lite
doom/clean-cache
doom/clean-compiled