From bbdbe2f9fdf60b7c970b52ca47b077bfc57f05f6 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Mon, 29 May 2017 00:26:41 +0200 Subject: [PATCH] modules/README.md => README.org --- README.md | 2 +- modules/README.md | 88 ------------------------ modules/README.org | 167 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 89 deletions(-) delete mode 100644 modules/README.md create mode 100644 modules/README.org diff --git a/README.md b/README.md index 986928b36..2b49b7255 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ These can also be invoked from within emacs: So you want to grok this madness. Here are a few suggestions: * **[init.example.el](init.example.el)**: a birds eye view of available modules -* **[modules/README.md](modules/README.md)**: a primer into module structure +* **[modules/README.org](modules/README.org)**: a primer into module structure * **[modules/private/hlissner/+bindings.el](modules/private/hlissner/+bindings.el)**: my custom keybinds. * **[modules/private/hlissner/+commands.el](modules/private/hlissner/+commands.el)**: diff --git a/modules/README.md b/modules/README.md deleted file mode 100644 index a9599d857..000000000 --- a/modules/README.md +++ /dev/null @@ -1,88 +0,0 @@ -# Modules - -Modules are made up of four parts, **all of which are optional**: - -```text -modules/category/submodule/ -modules/category/submodule/config.el -modules/category/submodule/packages.el -modules/category/submodule/autoload.el -modules/category/submodule/autoload/*.el -``` - -## config.el - -The main configuration file and the first loaded when the module is activated -(using `doom!` or `require!`). - -## packages.el - -How modules inform DOOM what packages to install and where from. These should be -declarative, pure and idempotent. That means running them directly should have -no side-effects (besides affecting the variables `doom-modules` and -`doom-packages`) and whose results should alway be deterministic. - -By default, packages are retrieved from ELPA. Otherwise, a MELPA-style recipe -can determine how to fetch it: - -```emacs-lisp -;; from modules/tools/rotate-text/packages.el -(package! rotate-text :recipe (:fetcher github :repo "debug-ito/rotate-text.el")) -``` - -Other modules' packages.el files can be depended on, through `depends-on!`: - -```emacs-lisp -;; from modules/feature/file-templates/packages.el -(depends-on! :feature snippets) -``` - -## autoload.el OR autoload/*.el - -These are scanned by `doom/reload-autoloads`, whose functions are lazily-loaded, -given that they're marked with an `;;;###autoload` cookie: - -```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 "") - [...]) -``` - -## Other files - -My convention for extra configuration files is a `+` prefix, e.g. -`modules/feature/version-control/+git.el`. These are **not** automatically -loaded, and must be loaded manually with `load!` from within `config.el`: - -```emacs-lisp -;; from modules/feature/version-control/config.el -(load +git) -``` - ----- - -# What modules aren't - -Modules loosely take after Spacemacs' notion of layers, but are not intended to -be interchangeable. Their purpose is _almost_ purely organizational. - -Use `featurep!` to check for module availability: - -```emacs-lisp -;; from modules/lang/go/packages.el -(when (featurep! :completion company) - (package! company-go)) - -;; from modules/lang/go/config.el -(def-package! company-go - :when (featurep! :completion company) - [...]) -``` diff --git a/modules/README.org b/modules/README.org new file mode 100644 index 000000000..f7603e20b --- /dev/null +++ b/modules/README.org @@ -0,0 +1,167 @@ +#+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~ +