#+TITLE: DOOM Modules * Table of Contents :TOC:noexport: - [[#introduction][Introduction]] - [[#overview][Overview]] - [[#enablingdisabling-modules][Enabling/disabling modules]] - [[#the-structure-of-a-module][The structure of a module]] - [[#configel][config.el]] - [[#packagesel][packages.el]] - [[#autoloadel-or-autoloadel][autoload.el OR autoload/*.el]] - [[#additional-files][Additional files]] - [[#appendix][Appendix]] * 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)~: returns =t= 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 around ~use-package~) + ~(def-setting! SETTING &rest ARGS)~: defines a setting other modules can ~set!~ The TL;DR of this document is: + Modules are comprised of: =config.el=, =packages.el=, either =autoload.el= or =autoload/*.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 the ~package!~ 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 their ~def-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 :: Modules that affect the DOOM user interface or 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). #+begin_quote *Remember*: if you've byte-compiled your config, your changes won't take effect until you recompile or delete the \*.elc files. #+end_quote * 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~). #+BEGIN_SRC emacs-lisp ;; 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) [...]) #+END_SRC + Packages are *deferred* by default: add ~:demand t~ to ~def-package!~ blocks to load them immediately. + Use ~featurep!~ to test DOOM module availability + Use ~set!~ to cross-configure modules safely, e.g. company backends: #+BEGIN_SRC emacs-lisp ;; from modules/lang/python/config.el (set! :company-backend 'python-mode '(company-anaconda)) #+END_SRC ** 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. #+BEGIN_SRC emacs-lisp ;; 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")) #+END_SRC The packages.el of another module can loaded with ~depends-on!~: #+BEGIN_SRC emacs-lisp ;; from modules/feature/file-templates/packages.el (depends-on! :feature snippets) #+END_SRC ** 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: #+BEGIN_SRC emacs-lisp ;; 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 "") [...]) #+END_SRC 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. #+BEGIN_SRC emacs-lisp ;; from modules/feature/version-control/config.el (load +git) #+END_SRC * 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~