- Install
- Update
- Customize
- Troubleshoot
To embark on this grand Emacs adventure, you’ll need a couple things installed, including Emacs (shocking, I know), Doom Emacs, the plugins Doom depends on, and any external tools they depend on as well.
In summary, you’ll be installing:
- git
- Emacs 26.1+
- ripgrep
- all-the-icons fonts – unnecessary for exclusive use of terminal Emacs
And then some optional dependencies that you will likely want, as the will optimize Doom’s performance and stability.
- fd
- GNU ls (BSD ls on macOS/BSD Linux has some limitations)
- clang – with which to compile certain external dependencies, like the emacsqlite binary, irony server (requires clang), or vterm module
The following sections will cover how to install Emacs and these dependencies across various operating systems.
If any of these install instructions are outdated, or your OS is missing, please help us by letting us know (or correcting it yourself; pull requests are welcome).
Emacs should be available through your distribution’s package manager. Otherwise, it can be built from source.
pacman -S git tar clang emacs ripgrep fd
Emacs 27 (HEAD) can be installed through emacs-git, available on the AUR.
apt-get install git tar clang ripgrep fd-find
On Ubuntu 18.04, the latest version of Emacs available is 25.3 (and 24.3 on Ubuntu 16 or 14). Therefore, we have a few extra steps to install 26.1+:
add-apt-repository ppa:kelleyk/emacs
apt-get update
apt-get install emacs26
On NixOS Emacs 26.x can be installed via nix-env --install emacs
, or more
permanently by adding the following entry to etc/nixos/configuration.nix
:
environment.systemPackages = with pkgs; [
coreutils # basic GNU utilities
git
clang
emacs
ripgrep
fd
];
Mac users several options to install Emacs, but only a few of them are recommended for Doom Emacs (you’ll need to install Homebrew first). To start with:
brew install git clang ripgrep fd coreutils
As for Emacs, there are several formulas to choose from. There are the best options, in order from most to least recommended for Doom.
- emacs-plus (the safest option):
brew tap d12frosted/emacs-plus brew install emacs-plus ln -s /usr/local/opt/emacs-plus/Emacs.app /Applications/Emacs.app
- emacs is another acceptable option.
brew install emacs
- emacs-mac is also acceptable. It offers slightly better integration into
macOS, with native emojis and better childframe support. However, at the time
of writing, it lacks multi-tty support (which impacts daemon usage). Use it if
you experience crashing or performance issues with emacs-plus.
brew tap railwaycat/emacsmacport brew install emacs-mac ln -s /usr/local/opt/emacs-mac/Emacs.app /Applications/Emacs.app
These builds/forks have known compatibility issues with Doom and are likely to cause you issues later on. Do not use them:
- emacsformacosx.com
brew cask install emacs
(installs from emacsformacosx.com)- AquaMacs
- XEmacs
Support for Windows is immature, so your mileage will vary. Some have reported success with installing Doom via WSL, chocolatey on git-bash or cygwin.
If you manage to get Doom on Windows and found this wasn’t enough, or could be improved, please help us expand this section!
chocolatey / scoop
Chocolatey is the simplest to get Doom up and running with:
choco install git llvm emacs ripgrep fd
You can also use scoop by simply replacing
choco
withscoop
in the above snippet to achieve the same result. This hasn’t been tested, however.
You will also need to add a HOME
system variable, pointing to
C:\Users\USERNAME\
, otherwise Emacs will treat
C:\Users\USERNAME\AppData\Roaming
is your HOME
, which causes issues.
It’s also a good idea to add C:\Users\USERNAME\.emacs.d\bin
to your PATH
.
The quickest way to get Doom up and running is:
git clone https://github.com/hlissner/doom-emacs ~/.emacs.d
~/.emacs.d/bin/doom install
doom install
performs the following for you:
- It creates your
DOOMDIR
at~/.doom.d
, if it (or~/.config/doom
) don’t already exist. - Copies
~/.emacs.d/init.example.el
to$DOOMDIR/init.el
, which contains adoom!
statement that controls what modules to enable and in what order they are loaded. - Creates dummy config.el and packages.el files in
$DOOMDIR
. - Optionally generates an envvar file (equivalent to using
doom env
), which stores your shell environment in an env file that Doom will load at startup. This is essential for macOS users! - Installs all dependencies for enabled modules (specified by
$DOOMDIR/init.el
), - And prompts to install the icon fonts required by the all-the-icons package.
You’ll find a break down of
doom install
into shell commands in the next section.
Consider the ~/.emacs.d/bin/doom
script your new best friend. It performs a
variety of essential functions to help you manage your Doom Emacs configuration,
not least of which is installing or updating it or its plugins. If nothing else,
get to know these four commands:
doom refresh
: Ensures that Doom is in a proper state to be used (i.e. needed packages are installed, orphaned packages are removed and necessary metadata correctly generated).doom upgrade
: Updates Doom Emacs (if available) and its packages.doom env
: Generates an “envvar file”, which scrapes your shell environment into a file that is loaded by Doom Emacs at startup. This is especially necessary for macOS users who open Emacs through an Emacs.app bundle.doom doctor
: If Doom misbehaves, the doc will diagnose common issues with your installation and environment. If all else fails, you’ll find help on Doom’s Discord server and issue tracker.
Run doom help <COMMAND>
for documentation on these commands, or doom help
for an overview of what the bin/doom
script is capable of.
I recommend you add
~/.emacs.d/bin
to yourPATH
so you can calldoom
directly, from anywhere. You don’t need to be CDed into~/.emacs.d/bin
to use it. A quick way to do so is to add this to your .bashrc or .zshrc file:
export PATH="$HOME/.emacs.d/bin:$PATH"
If you’d rather install Doom yourself, without the magic of bin/doom install
,
here is its equivalent in bash shell commands:
git clone https://github.com/hlissner/doom-emacs ~/.emacs.d
# So we don't have to write ~/.emacs.d/bin/doom every time
export PATH="$HOME/.emacs.d/bin:$PATH"
# Create a directory for our private config
mkdir ~/.doom.d # or ~/.config/doom
# The init.example.el file contains an example doom! call, which tells Doom what
# modules to load and in what order.
cp ~/.emacs.d/init.example.el ~/.doom.d/init.el
# If your ISP or proxy doesn't allow you to install from
# raw.githubusercontent.com, then you'll have to install straight (our package
# manager) manually:
mkdir -p ~/.emacs.d/.local/straight/repos
git clone -b develop https://github.com/raxod502/straight.el ~/.emacs.d/.local/straight/repos/straight.el
# Edit ~/.doom.d/init.el and adjust the modules list to your liking before
# running this:
doom install
# If you know Emacs won't be launched from your shell environment (e.g. you're
# on macOS or use an app launcher that doesn't launch programs with the correct
# shell), then creating an envvar file is necessary to ensure Doom inherits your
# shell environment.
#
# If you don't know whether you need this or not, no harm in doing it anyway.
# `doom install` will prompt you to generate an envvar file. If you responded
# no, you can generate it later with the following command:
doom env
# Install the icon fonts Doom uses
emacs --batch -f all-the-icons-install-fonts
To understand the purpose of the ~/.doom.d
directory and ~/.doom.d/init.el
file, see the Customize section further below.
Chemacs is a bootloader for Emacs. It makes it easy to switch between multiple Emacs configurations. Here is a quick guide for setting it up with Doom Emacs as the default config.
After you’ve followed the installation instructions for Doom and Emacs, outlined
above, deploy the Chemacs’ startup script to ~/.emacs
:
wget -O ~/.emacs https://raw.githubusercontent.com/plexus/chemacs/master/.emacs
Warning: the =~/.emacs.d= directory must not exist for this to work.
Then create ~/.emacs-profiles.el
with a list of your Emacs profiles. This file
is structured like a .dir-locals.el
file. Here is an example with Doom (as the
default), Spacemacs, and Prelude:
(("default" . ((user-emacs-directory . "~/doom-emacs")))
("spacemacs" . ((user-emacs-directory . "~/spacemacs")))
("prelude" . ((user-emacs-directory . "~/prelude"))))
To start Emacs with a specific config, use the --with-profile
option:
emacs --with-profile spacemacs
If no profile is specified, the default
profile is used.
Your system, your rules. There are as many ways to set up a programming environment as there are dislikes on Youtube Rewind 2018, so Doom entrusts this task to you, dear user.
Doom is comprised of modules which provide most of its features, including language support and integration with external tools. However, some of these have external dependencies that you must install yourself. You’ll find what modules need what and how to install them in that module’s README.org file. If you find a module without a README file, helps us out by creating one for us!
doom doctor
will provide an overview of missing dependencies (only for the
modules you have enabled) by reporting which ones haven’t been installed yet.
Once you know what’s missing, have a look at the documentation for that module.
Use M-x doom/help-modules
(bound to SPC h d m
) to quickly jump to a module’s
documentation from inside Doom. Otherwise, check out the Module Index.
Doom is an active project and many of its 300+ plugins are in active development as well. It is wise to occasionally update them. The following section will go over how to do so.
Important: you may encounter errors after up/downgrading Emacs. Emacs bytecode is not forward compatible, so you must recompile or reinstall your plugins to fix this, i.e.
doom build
, to rebuild all your installed plugins,- Or delete
~/.emacs.d/.local
thendoom refresh
to reinstall them
The bin/doom
script provides a simple command for upgrading Doom (which will
also update your plugins):
doom upgrade # short version: doom up
If you want to update Doom manually, doom upgrade
is equivalent to:
cd ~/.emacs.d
git pull # updates Doom
doom refresh # refreshes plugins & autoloads
doom update # updates installed plugins
To minimize issues while upgrading, avoid modifying Doom’s source files. All
your customization should be kept in your DOOMDIR
(typically, ~/.doom.d
).
Read the Customize section for more on configuring Doom.
To update only your plugins (i.e. not Doom), run doom update
(short version:
doom u
).
The bin/doom
script doesn’t currently offer rollback support for Doom or its
plugins (yet).
Your private configuration is located in ~/.doom.d
, by default (if
~/.config.d/doom
exists, that will be used instead). This directory is
referred to as your $DOOMDIR
or your “private module”.
doom install
will create three files in your DOOMDIR to start you off:
- init.el
- This is where you’ll find your
doom!
block, which controls what modules are enabled and in what order they are loaded. This is copied from~/.emacs.d/init.example.el
. - config.el
- This is where the bulk of your private configuration will go.
- packages.el
- This is where you tell Doom what packages you want to install and where from.
Every private config starts with a doom!
block, found in $DOOMDIR/init.el
.
If you followed the Doom installation instructions and ran doom install
, this
file should exist and will contain one.
This block controls what modules are enabled and in what order they are loaded. To enable a module, add it to this list. To disable it, either remove it or comment it out (in Emacs Lisp, anything following a semicolon is ignored by the Elisp interpreter; i.e. it’s “commented out”).
;; To comment something out, you insert at least one semicolon before it. The
;; Emacs Lisp interpreter will ignore whatever follows.
(doom! :lang
python ; this module is not commented, therefore enabled
;;javascript ; this module is commented out, therefore disabled
;;lua ; this module is disabled
ruby ; this module is enabled
php) ; this module is enabled
Some modules have optional features that can be enabled by passing them flags like so:
(doom! :completion
(company +auto)
:lang
(csharp +unity)
(org +attach +babel +capture +export +present +protocol)
(sh +fish))
Different modules support different flags. To see a quick list of what modules support what flags in the Module Index.
WARNING: when changing your doom!
block you must run ~/.emacs.d/bin/doom
refresh
and restart Emacs for the changes to take effect. This ensures the
needed packages are installed, orphaned packages are removed, and necessary
metadata for your Doom Emacs config has been generated.
Doom’s package manager is declarative. Your DOOMDIR
is a module, and modules
may optionally possess a packages.el file, where you may declare what packages
you want to install (and where from) using the package!
macro. It can be used
to:
- Install packages (conditionally, even),
- Disable packages (uninstalling them and disabling their configuration),
- Or change where a package is installed from.
If a package is installed via ELPA and does not have a package!
declaration,
Doom will assume the package is unwanted and uninstall it for you next time
doom refresh
is executed.
Remember to run
doom refresh
after modifying your packages, to ensure they are installed and properly integrated into Doom.
To install a package, add a package!
declaration for it to
DOOMDIR/packages.el
:
;; Install a package named "example" from ELPA or MELPA
(package! example)
;; Tell Doom to install it from a particular archive (e.g. elpa). By default, it
;; will search orgmode.org and melpa.org before searching elpa.gnu.org. See
;; `package-archives' to adjust this order (or to see what values :pin will
;; accept).
(package! example :pin "elpa")
;; Instruct Doom to install this package once, but never update it when you run
;; `doom update` or `doom upgrade`:
(package! example :freeze t)
;; Or tell Doom to not manage a particular package at all.
(package! example :ignore t)
package!
will return non-nil if the package isn’t disabled and is cleared for
install. Use this fact to conditionally install other packages, e.g.
(when (package! example)
(package! plugin-that-example-depends-on))
To install a package straight from an external source (like github, gitlab, etc), you’ll need to specify a MELPA-style straight recipe:
Here are a few examples:
;; Install it directly from a github repository. For this to work, the package
;; must have an appropriate .el and must have at least a Package-Version
;; or Version line in its header.
(package! example :recipe (:host github :repo "username/my-example-fork"))
;; If the source files for a package are in a subdirectory in said repo, you'll
;; need to specify what files to pull in.
(package! example :recipe
(:host github
:repo "username/my-example-fork"
:files ("*.el" "src/lisp/*.el")))
;; To grab a particular commit:
(package! example :recipe
(:host gitlab
:repo "username/my-example-fork"
:branch "develop"))
;; If a package has a default recipe on MELPA or emacsmirror, you may omit
;; keywords and the recipe will inherit from their original.
(package! example :recipe (:branch "develop"))
;; If the repo pulls in many unneeded submodules, you can disable recursive cloning
(package! example :recipe (:nonrecursive t))
The package!
macro possesses a :disable
property.
(package! irony :disable t)
(package! rtags :disable t)
Once a package is disabled, use-packages!
and after!
blocks for it will be
ignored, and the package will be removed the next time you run doom refresh
.
Use this to disable undesirable packages included with the built-in modules.
Alternatively, the disable-packages!
macro exists for more concisely disabling
multiple packages:
(disable-packages! irony rtags)
If a module installs package X, but you’d like to install it from somewhere else
(say, a superior fork or a fork with a bugfix), simple add a package!
declaration for it in your DOOMDIR/packages.el
. Your private declarations
always have precedence over modules (even your own modules).
;; modules/editor/evil/packages.el
(package! evil) ; installs from MELPA
;; DOOMDIR/packages.el
(package! evil :recipe (:host github :repo "username/my-evil-fork"))
You will need to run doom refresh
for this change to take effect.
If your configuration needs are simple, the use-package!
, after!
,
add-hook!
and setq-hook!
emacros can help you reconfigure packages:
;;; ~/.doom.d/config.el (example)
(setq doom-font (font-spec :family "Fira Mono" :size 12))
;; Takes a feature symbol or a library name (string)
(after! evil
(setq evil-magic nil))
;; Takes a major-mode, a quoted hook function or a list of either
(add-hook! python-mode
(setq python-shell-interpreter "bpython"))
;; These are equivalent
(setq-hook! 'python-mode-hook python-indent-offset 2)
(setq-hook! python-mode python-indent-offset 2)
(use-package! hl-todo
;; if you omit :defer, :hook, :commands, or :after, then the package is loaded
;; immediately. By using :hook here, the `hl-todo` package won't be loaded
;; until prog-mode-hook is triggered (by activating a major mode derived from
;; it, e.g. python-mode)
:hook (prog-mode . hl-todo-mode)
:init
;; code here will run immediately
:config
;; code here will run after the package is loaded
(setq hl-todo-highlight-punctuation ":"))
For more flexibility, the use-package-hook!
is another option, but should be
considered a last resort (because there is usually a better way). It allows you
to disable, append/prepend to and/or overwrite Doom’s use-package!
blocks.
These are powered by use-package
’s inject-hooks under the hood.
use-package-hook!
must be used before that package’s ~use-package!~ block.
Therefore it must be used from your private init.el file.
;;; ~/.doom.d/init.el (example)
;; If a :pre-init / :pre-config hook returns nil, it overwrites that package's
;; original :init / :config block. Exploit this to overwrite Doom's config.
(use-package-hook! doom-themes
:pre-config
(setq doom-neotree-file-icons t)
nil)
;; ...otherwise, make sure they always return non-nil!
(use-package-hook! evil
:pre-init
(setq evil-magic nil)
t)
;; `use-package-hook' also has :post-init and :post-config hooks
You may find it helpful to have your changes take effect immediately. For things that don’t require a complete restart of Doom Emacs (like changing your enabled modules or installed packages), you can evaluate Emacs Lisp code on-the-fly.
- Evil users can use the
gr
operator to evaluate a segment of code. The return value is displayed in the minibuffer or in a popup (if the result is large enough to warrant one).gr
works for most languages, but using it on Elisp is a special case; it’s executed within your current session of Emacs. You can use this to modify Emacs’ state on the fly. - Non-evil users can use
C-x C-e
to runeval-last-sexp
, as well asM-x +eval/buffer-or-region
(onSPC c e
). - Another option is to open a scratch buffer with
SPC x
, change its major mode (M-x emacs-lisp-mode
), and use the above keys to evaluate your code. - An ielm REPL is available by pressing
SPC o r
(+eval/open-repl-other-window
). - There’s also
M-:
orSPC ;
, which invokeseval-expression
, which you can use to run elisp code inline.
While all this is helpful for reconfiguring your running Emacs session, it can also be helpful for debugging.
- define-key
- global-set-key
- map!
- unmap!
- define-key!
Modules are made up of several files, all of which are optional. This is a comprehensive list of what they are:
modules/ category/ module/ test/*.el autoload/*.el autoload.el init.el config.el packages.el doctor.el
By default, doom looks for modules in two places: .emacs.d/modules/
where doom’s
own modules are located and $DOOMDIR/modules/
where you can define your
own private modules.
This file is loaded first, before anything else, but after Doom core is loaded.
Use this file to:
- Configure Emacs or perform setup/teardown operations that must be set before
other modules are (or this module is) loaded. Tampering with
load-path
, for instance. - Reconfigure packages defined in Doom modules with
use-package-hook!
(as a last resort, whenafter!
and hooks aren’t enough). - To change the behavior of
bin/doom
.
Do not use this file to:
- Configure packages with
use-package!
orafter!
- Preform expensive or error-prone operations; these files are evaluated
whenever
bin/doom
is used.
This file is the heart of every module.
Code in this file should expect that dependencies (in packages.el
) are
installed and available, but shouldn’t make assumptions about what modules are
activated (use featurep!
for this).
Packages should be configured using after!
or use-package!
.
;; from modules/completion/company/config.el
(use-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)
[...])
For anyone already familiar with
use-package
,use-package!
is merely a thin wrapper around it. It supports all the same keywords and can be used in much the same way.
This file is where package declarations belong. It’s also a good place to look if you want to see what packages a module manages (and where they are installed from).
A packages.el
file shouldn’t contain complex logic. Mostly conditional
statements and package!
, disable-packages!
or depend-on!
calls. It
shouldn’t produce side effects and should be deterministic. Because this file
gets evaluated in an environment isolated from your interactive session, code
within should make no assumptions about the current session.
The package!
macro is the star of the show in packages.el
files:
;; from modules/lang/org/packages.el
(package! org-bullets)
;; from modules/tools/rotate-text/packages.el
(package! rotate-text :recipe (:host github :repo "debug-ito/rotate-text.el"))
Its :recipe
property accepts a MELPA recipe, which provides a lot of control
over where to fetch a package, including specific commit, tags or branches:
(package! rotate-text
:recipe (:host github
:repo "debug-ito/rotate-text.el"
:commit "1a2b3c4d"))
You can also use this package!
to disable other packages:
;; Uninstalls evil, keeps it uninstalled, and tells Doom to ignore any
;; use-package! and after! blocks for it
(package! evil :disable t)
;; disable-packages! can be used to disable multiple packages in one statement
(disable-packages! evil evil-snipe evil-escape)
Functions marked with an autoload cookie (;;;###autoload
) in these files will
be lazy loaded.
When you run bin/doom autoloads
, Doom scans these files to populate autoload file
in ~/.emacs.d/.local/autoloads.el
, which will tell Emacs where to find these
functions when they are called.
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>")
[...])
This file is used by make doctor
, and should test for all that module’s
dependencies. If it is missing one, it should use the warn!
, error!
and
explain!
macros to inform the user why it’s a problem and, ideally, a way to
fix it.
For example, the :lang cc
module’s doctor checks to see if the irony server is
installed:
;; from lang/cc/doctor.el
(require 'irony)
(unless (file-directory-p irony-server-install-prefix)
(warn! "Irony server isn't installed. Run M-x irony-install-server"))
Sometimes, it is preferable that a module’s config.el file be split up into
multiple files. The convention is to name these additional files with a leading
+
, e.g. modules/feature/version-control/+git.el
.
There is no syntactical or functional significance to this convention. Directories do not have to follow this convention, nor do files within those directories.
These additional files are not loaded automatically. You will need to use the
load!
macro to do so:
;; from modules/feature/version-control/config.el
(load! +git)
The load!
macro will try to load a +git.el
relative to the current file.
Module files are loaded in a precise order:
~/.emacs.d/early-init.el # in Emacs 27+ only
~/.emacs.d/init.el
$DOOMDIR/init.el
{~/.emacs.d,$DOOMDIR}/modules/*/*/init.el
{~/.emacs.d,$DOOMDIR}/modules/*/*/config.el
$DOOMDIR/config.el
In the code examples of the previous section, you may have noticed something odd
about that haskell entry: (haskell +intero)
. +intero
is a module flag. You
may specify these for any module that supports them. Unsupported flags are
ignored.
You can find out what flags a module supports by looking at its documentation (a
README.org in the module’s directory; which can be jumped to quickly with M-x
doom/describe-module
).
For example, the haskell module supports the +intero
and +dante
flags, which
represent the two Haskell backends available to Emacs. You may choose one or the
other (or neither, or both) by specifying the appropriate flags in you doom!
block:
(doom! :lang (haskell +dante))
You may specify as many flags are you like:
(doom! :lang (org +attach +babel +capture +export +present))
+flagname
is simply a naming convention and has no syntactical or functional significance.
Modules are free to interpret flags however they like. If you are writing your
own module(s), you can test for flags using the featurep! MODULE SUBMODULE
&optional FLAG
macro:
(when (featurep! :lang haskell +dante)
[...])
The first two arguments if featurep!
may be skipped if it is used from inside
a module. For example:
;; In modules/lang/haskell/config.el
(when (featurep! +dante) ; same as (featurep! :lang haskell +dante)
[...])
Some modules expose settings that can be configured from other modules. Use M-x
doom/help-autdefs
(SPC h d a
or C-h d a
) to see what is available and how
to use them.
An example would be the set-company-backend!
function that the :completion
company
module exposes. It lets you register company completion backends with
certain major modes. For instance:
(set-company-backend! 'python-mode '(company-anaconda))
You’ll find what settings a module exposes in its documentation (remember to use
M-x doom/help-modules
on SPC h d m
or C-h d m
).
There is a special syntax available to module files called module cookies. Like
autoload cookies (;;;###autoload
), module files may have ;;;###if FORM
at or
near the top of the file. FORM is read by doom refresh
and doom compile
to
determine whether or not to ignore this file.
If FORM returns nil, the file won’t be scanned for autoloads nor will it be byte-compiled. Use this to prevent errors that may occur if that file contains (for example) calls to functions that won’t exist if a certain feature isn’t available to that module, e.g.
;;;###if (featurep! +intero)
;;;###if (not (featurep 'evil-mode))
Remember that these run in a limited, non-interactive sub-session, so do not call anything that wouldn’t be available in a Doom session without any modules enabled.
Having helped many users configure Doom, I’ve spotted a few recurring oversights that I will list here, in the hopes that it will help you avoid the same mistakes:
Using use-package!
without a deferring keyword (one of: :defer :after
:commands :defer-incrementally :after-call
) will load the package immediately.
This can cause other packages to be pulled in and loaded, which will compromise
many of Doom’s startup optimizations.
This is usually by accident. Choosing which keyword to use depends on the needs of the package, so there is no simple answer to this.
A lot of Emacs documentation and help will contain advice to install packages
with package.el’s API (e.g. package-install
) or with use-package’s :ensure
keyword). You are free to do this, if it is your preference, but otherwise, Doom
has its own package management system.
Migrating use-package
code to Doom is usually a case of removing the :ensure
keyword and adding a (package! PACKAGENAME)
to ~/.doom.d/packages.el
(and
running doom refresh
to sync your config).
You don’t need org-babel-do-load-languages
. Doom lazy loads babel plugins
based on the language name in #+BEGIN_SRC
blocks needed. As long as the babel
plugin is installed and the plugin is named after its language (e.g.
#+BEGIN_SRC rust
will load ob-rust
), you don’t need to do anything else.
There may be some special cases, however. Doom tries to handle a couple of them (e.g. with ob-jupyter, ob-ipython and ob-async). If you are experiencing errors while trying to use a certain language in org src blocks, check out the :lang org module documentation for details on how to add support for it.
(add-hook 'after-save-hook #'delete-trailing-whitespace)
;; or
(add-hook 'after-save-hook #'whitespace-cleanup)
These two lines are a common sight in Emacs configs, but they are unnecessary
for Doom Emacs. We already use the more sophisticated wsbutler
to manage
extraneous whitespace. However, you might have the impression that it isn’t
working. That’s because wsbutler
works in two unusual ways, meant to be less
imposing than its alternatives:
- It only cleans up trailing whitespace on lines that you’ve touched (but
always strips newlines at EOF).
Why do this? Because I believe file-wide reformatting should be a deliberate act (and not blindly automated). If it is necessary, chances are you’re working on somebody else’s project – or with other people, but here, large scale whitespace changes could cause problems or simply be rude. We don’t endorse PRs that are 1% contribution and 99% whitespace!
However, if it’s truly deliberate,
M-x delete-trailing-whitespaces
andM-x whitespace-cleanup
are available to be calleddeliberately
, instead. wsbutler
replaces trailing whitespace and newlines with virtual whitespace. This is whitespace that only exists in the Emacs buffer, but isn’t actually written to the file.Why do this? Because you might have wanted to use that space for something in your current editing session, and it would be inconvenient for the editor to delete it before you got to it.
If you use it, it’s there. If you don’t, it isn’t written to the file.
When problems arise, and they will, you will need to debug them. Fortunately, Emacs (and Doom) provide you with tools to make this easier. I recommend becoming acquainted with them. They will be yours (and our) best tool for understanding the problem.
Before you file a bug report, there are a number of things you should try first:
- You’ll find a list of common issues & errors in the FAQ. That is a good place
to start. You can access and search this FAQ from inside Doom with
SPC h d f
(orC-h d f
for non-evil users). - Run
doom doctor
to diagnose any common issues with your environment or config. - Run
doom refresh
to ensure the problem isn’t caused by missing packages or outdated autoloads files. - See if your issue is mentioned in the Common Issues section below.
- Search Doom’s issue tracker to see if your issue is mentioned there.
- Ask for help on our Discord server. This may not be immediately available to everyone, so I won’t fault you for skipping this step, but you’ll sometimes find help there quicker. In many cases, Henrik fixes issues.
…
Emacs is a Lisp interpreter whose state you can access on-the-fly with tools
provided to you by Emacs itself. They’re available on the SPC h
prefix by
default. Use them to debug your sessions.
Here are some of the more important ones:
describe-variable
(SPC h v
)describe-function
(SPC h f
)describe-face
(SPC h F
)describe-bindings
(SPC h b
)describe-key
(SPC h k
)describe-char
(SPC h '
)find-library
(SPC h P
)
You can also evaluate code with eval-expression
(M-;
or SPC ;
).
doom/open-news
(SPC h n
)- …
doom/open-manual
(SPC h D
)- …
doom/describe-module
(SPC h d
)- Jumps to a module’s documentation.
doom/describe-autodefs
(SPC h A
)- Jumps to the documentation for an autodef function/macro. These are special functions that are always defined, whether or not their containing modules are enabled.
doom/describe-package
(SPC h p
)- Look up packages that are installed, by whom (what modules) and where jump to all the places it is being configured.
doom/info
- …
If you encounter an error while using Doom Emacs, you’re probably about to head off and file a bug report (or request help on our Discord server). Before you do, please generate a backtrace to include with it.
To do so you must enable debug-on-error
then recreate the error.
There are three ways to enable debug-on-error
:
- Start Emacs with
emacs --debug-init
. Use this for errors that occur at startup. - Evil users can press
SPC h d d
and non-evil users can pressC-h d d
. - If the above don’t work, there’s always:
M-x toggle-debug-on-error
Now that debug-on-error
is on, recreate the error. A window should pop up with
a backtrace.
If the error you’ve encountered is emitted from bin/doom
, you can re-run the
same command with the -d
or --debug
switches to force it to emit a backtrace
when an error occurs. The DEBUG
environment variable will work to.
doom -d refresh
doom --debug install
DEBUG=1 doom update
Note: switch order is important.
-d
/--debug
must come right afterdoom
and before the subcommand. This will be fixed eventually.
Often, you may find it helpful for debugging to evaluate some Emacs Lisp. Here are couple things you can do:
- Use
M-;
(bound toeval-expression
), SPC x
will open a scratch buffer.M-x emacs-lisp-mode
will change it to the appropriate major mode, then use+eval:region
(gr
) and+eval:buffer
(gR
) to evaluate code,
“The sandbox” is one of Doom Emacs’ features; it is a test bed for running elisp in a fresh instance of Emacs with varying amounts of Doom loaded (none at all, all of it, or somewhere in between). This can be helpful for isolating bugs to determine who you should report a bug to.
If you can recreate a bug in vanilla Emacs than it should be reported to the developers of the relevant plugins or, perhaps, the Emacs devs themselves.
Otherwise, it is best to bring it up on the Doom Emacs issue list, rather than confusing and inundating the Emacs community with Doom-specific issues.
There are three common ways to access the sandbox:
SPC h E
(for evil users)C-h E
(for non-evil users)M-x doom/sandbox
Doing any of the above will pop up a *doom:sandbox*
window. What you enter
into this buffer will be executed in the new instance of Emacs when you decide
to launch it.
You have four options when it comes to launching the sandbox:
C-c C-c
- This launches “vanilla Emacs”. Vanilla means nothing is loaded; purely Emacs and nothing else. If you can reproduce an error here, then the issue likely lies in the plugin(s) you are testing or in Emacs itself.
C-c C-d
- This launches “vanilla Doom”, which is vanilla Emacs plus Doom’s core. This does not load your private config, nor any of Doom’s (or your) modules.
C-c C-p
- This launches “vanilla Doom+”. That is, Doom core plus the
modules that you have specified in the
doom!
block of your private config (in~/.doom.d/init.el
). This does not load your private config, however. C-c C-f
- This launches “full Doom”. It loads Doom’s core, your enabled modules, and your private config. This instance should be identical to the instance you launched it from.
All new instances will inherit your
load-path
so you can access any packages you have installed.
Instances of Emacs launched from the sandbox have inherited your load-path
.
This means you can load packages – even in Vanilla Emacs – without worrying
about installing or setting them up. Just (require PACKAGE)
and launch the
sandbox. e.g.
(require 'magit)
(find-file "~/some/file/in/a/repo")
(call-interactively #'magit-status)