An effort to make our documentation clearer, more concise in places, simpler where possible and highlight caveats so folks aren't caught by surprise by strange behavior. - Remove --with-modern-cg433n-icon (#3554), as the default icon is a reasonable default, and I'd like to keep things simple. - Mention "could not find package in recipe repositories" error and what to do about it. - Mention that 'doom sync -u' is necessary for Doom's package manager to see recipe changes. - Mention :no-byte-compile for installing local packages; to save you the hassle of running 'doom sync' every time you change them. - Clarify Emacs 27 install instructions where possible (particularly for nixOS and Ubuntu)
1448 lines
55 KiB
Org Mode
1448 lines
55 KiB
Org Mode
#+TITLE: Getting Started Guide
|
|
#+STARTUP: nofold
|
|
|
|
GNU Emacs is one grand ol' adventure, let alone Doom Emacs. Before you start
|
|
you'll need to set up Emacs, Doom, and its packages, then learn how to take care
|
|
of your new puppy/operating system. This guide will walk you through installing,
|
|
using, configuring and troubleshooting all of these things, to smooth you into
|
|
your Emacs journey.
|
|
|
|
This guide will gloss over many technicalities so you can get up and running as
|
|
soon as possible. A more technical user manual is in the works for aspiring
|
|
contributors who want a deeper understanding of how Doom Emacs works.
|
|
|
|
#+begin_quote
|
|
If you feel like we've missed something, [[https://discord.gg/qvGgnVx][join us on our Discord server]] and let
|
|
us know!
|
|
#+end_quote
|
|
|
|
* Table of Contents :TOC_4:
|
|
- [[#install][Install]]
|
|
- [[#emacs--dependencies][Emacs & dependencies]]
|
|
- [[#on-linux][On Linux]]
|
|
- [[#ubuntu][Ubuntu]]
|
|
- [[#fedora][Fedora]]
|
|
- [[#arch-linux][Arch Linux]]
|
|
- [[#nixos][NixOS]]
|
|
- [[#opensuse][openSUSE]]
|
|
- [[#on-macos][On macOS]]
|
|
- [[#with-homebrew][With Homebrew]]
|
|
- [[#with-macports][With MacPorts]]
|
|
- [[#on-windows][On Windows]]
|
|
- [[#chocolatey--scoop][chocolatey / scoop]]
|
|
- [[#wsl][WSL]]
|
|
- [[#wsl2][WSL2]]
|
|
- [[#doom-emacs][Doom Emacs]]
|
|
- [[#the-bindoom-utility][The ~bin/doom~ utility]]
|
|
- [[#install-doom-manually][Install Doom Manually]]
|
|
- [[#install-doom-alongside-other-configs-with-chemacs][Install Doom alongside other configs (with Chemacs)]]
|
|
- [[#externalsystem-dependencies][External/system dependencies]]
|
|
- [[#update--rollback][Update & Rollback]]
|
|
- [[#rollback][Rollback]]
|
|
- [[#updowngrading-emacs][Up/Downgrading Emacs]]
|
|
- [[#migrate][Migrate]]
|
|
- [[#from-vanilla-emacs][From vanilla Emacs]]
|
|
- [[#from-spacemacs][From Spacemacs]]
|
|
- [[#configure][Configure]]
|
|
- [[#modules][Modules]]
|
|
- [[#package-management][Package management]]
|
|
- [[#installing-packages][Installing packages]]
|
|
- [[#installing-packages-from-external-sources][Installing packages from external sources]]
|
|
- [[#pinning-packages-to-specific-commits][Pinning packages to specific commits]]
|
|
- [[#disabling-packages][Disabling packages]]
|
|
- [[#changing-a-recipe-for-a-included-package][Changing a recipe for a included package]]
|
|
- [[#usingloading-local-packages][Using/loading local packages]]
|
|
- [[#adjust-your-load-path][Adjust your ~load-path~]]
|
|
- [[#local-repo][:local-repo]]
|
|
- [[#configuring-doom][Configuring Doom]]
|
|
- [[#configuring-packages][Configuring packages]]
|
|
- [[#reloading-your-config][Reloading your config]]
|
|
- [[#binding-keys][Binding keys]]
|
|
- [[#writing-your-own-modules][Writing your own modules]]
|
|
- [[#load-order][Load order]]
|
|
- [[#location][Location]]
|
|
- [[#file-structure][File structure]]
|
|
- [[#initel][=init.el=]]
|
|
- [[#configel][=config.el=]]
|
|
- [[#packagesel][=packages.el=]]
|
|
- [[#autoloadel-or-autoloadel][=autoload/*.el= OR =autoload.el=]]
|
|
- [[#doctorel][=doctor.el=]]
|
|
- [[#additional-files][Additional files]]
|
|
- [[#flags][Flags]]
|
|
- [[#module-cookies][Module cookies]]
|
|
- [[#autodefs][Autodefs]]
|
|
- [[#common-mistakes-when-configuring-doom-emacs][Common mistakes when configuring Doom Emacs]]
|
|
- [[#packages-are-eagerly-loaded][Packages are eagerly loaded]]
|
|
- [[#manual-package-management][Manual package management]]
|
|
- [[#using-org-babel-do-load-languages-to-load-your-babel-packages][Using ~org-babel-do-load-languages~ to load your babel packages]]
|
|
- [[#using-delete-trailing-whitespaces-or-whitespace-cleanup-to-manage-leftover-whitespace][Using ~delete-trailing-whitespaces~ or ~whitespace-cleanup~ to manage leftover whitespace]]
|
|
- [[#troubleshoot][Troubleshoot]]
|
|
- [[#looking-up-documentation-and-state-from-within-emacs][Looking up documentation and state from within Emacs]]
|
|
- [[#variables-functions-faces-etc][Variables, functions, faces, etc.]]
|
|
- [[#for-doom-modules-packages-autodefs-etc][For Doom Modules, packages, autodefs, etc.]]
|
|
- [[#how-to-extract-a-backtrace-from-an-error][How to extract a backtrace from an error]]
|
|
- [[#enabling-debug-on-error][Enabling ~debug-on-error~]]
|
|
- [[#a-backtrace-from-bindoom][A backtrace from ~bin/doom~]]
|
|
- [[#evaluating-elisp-on-the-fly][Evaluating Elisp on-the-fly]]
|
|
- [[#how-to-determine-the-origin-of-a-bug][How to determine the origin of a bug]]
|
|
- [[#testing-in-dooms-sandbox][Testing in Doom's sandbox]]
|
|
- [[#opening-the-sandbox][Opening the sandbox]]
|
|
- [[#launching-the-sandbox][Launching the sandbox]]
|
|
- [[#testing-packages-in-the-sandbox][Testing packages in the sandbox]]
|
|
- [[#bisecting-your-private-config][Bisecting your private config]]
|
|
- [[#bisecting-doom-emacs][Bisecting Doom Emacs]]
|
|
|
|
* Install
|
|
This is what you'll have installed by the end of this section:
|
|
|
|
- Git 2.23+
|
|
- Emacs 26.1+ *(27.x is recommended)*
|
|
- [[https://github.com/BurntSushi/ripgrep][ripgrep]] 11.0+
|
|
- GNU Find
|
|
- (Optional) [[https://github.com/sharkdp/fd][fd]] 7.3.0+ (known as ~fd-find~ on Debian, Ubuntu & derivatives) --
|
|
improves performance for many file indexing commands
|
|
|
|
These packages ought to be available through the package managers of your
|
|
operating system; i.e. homebrew & macports on macOS, scoop/chocolatey on
|
|
Windows, or pacman/aptitude/etc on the various Linux distributions.
|
|
|
|
#+begin_quote
|
|
While Doom does claim to support 26.x, 27.x is recommended because it is faster,
|
|
especially for LSP users. The installation guides below will touch on installing
|
|
27 if there is a simple way to do so on that particular operating system.
|
|
#+end_quote
|
|
|
|
** Emacs & dependencies
|
|
*** On Linux
|
|
In the unusual case that Emacs 26.x is unavailable through your package manager,
|
|
you'll have to [[https://www.gnu.org/software/emacs/manual/html_node/efaq/Installing-Emacs.html][build it from source]]. Otherwise:
|
|
|
|
**** Ubuntu
|
|
Since only Emacs 25.3 is available on Ubuntu 18.04 (and 24.3 on Ubuntu 14 or
|
|
16), extra steps are necessary to acquire 26.3:
|
|
#+BEGIN_SRC bash
|
|
add-apt-repository ppa:kelleyk/emacs
|
|
apt-get update
|
|
apt-get install emacs26
|
|
#+END_SRC
|
|
|
|
Then install the dependencies:
|
|
#+BEGIN_SRC bash
|
|
# required dependencies
|
|
apt-get install git ripgrep
|
|
# optional dependencies
|
|
apt-get install fd-find
|
|
#+END_SRC
|
|
|
|
To install Emacs 27 on Ubuntu, you'll need to build it from source.
|
|
|
|
**** Fedora
|
|
#+BEGIN_SRC bash
|
|
# required dependencies
|
|
dnf install emacs git ripgrep
|
|
# optional dependencies
|
|
dnf install fd-find # is 'fd' in Fedora <28
|
|
#+END_SRC
|
|
|
|
**** Arch Linux
|
|
#+BEGIN_SRC bash
|
|
# required dependencies
|
|
pacman -S git emacs ripgrep
|
|
# optional dependencies
|
|
pacman -S fd
|
|
#+END_SRC
|
|
|
|
The above installs Emacs 26.3 (at the time of writing). To acquire Emacs 27
|
|
[[https://aur.archlinux.org/packages/emacs27-git/][emacs27-git]] is available on the AUR.
|
|
|
|
**** NixOS
|
|
On NixOS Emacs 26.3 can be installed via ~nix-env -Ai nixos.emacs~, or
|
|
permanently with the following added to ~etc/nixos/configuration.nix~:
|
|
#+BEGIN_SRC nix
|
|
environment.systemPackages = with pkgs; [
|
|
# required dependencies
|
|
git
|
|
emacs # Emacs 26.3
|
|
ripgrep
|
|
# optional dependencies
|
|
coreutils # basic GNU utilities
|
|
fd
|
|
clang
|
|
];
|
|
#+END_SRC
|
|
|
|
Installing Emacs 27 will require [[https://github.com/nix-community/emacs-overlay/issues][nix-community/emacs-overlay]]:
|
|
#+BEGIN_SRC nix
|
|
nixpkgs.overlays = [
|
|
(import (builtins.fetchTarball https://github.com/nix-community/emacs-overlay/archive/master.tar.gz))
|
|
];
|
|
|
|
environment.systemPackages = with pkgs; [
|
|
emacsUnstable # Installs Emacs 27
|
|
];
|
|
#+END_SRC
|
|
|
|
**** openSUSE
|
|
***** Emacs 26.3
|
|
Emacs can be installed from the [[https://software.opensuse.org/download.html?project=editors&package=emacs][package list]], or manually via zypper.
|
|
|
|
For example, to install on openSUSE Leap 15.1 (requires root):
|
|
#+BEGIN_SRC bash
|
|
zypper addrepo https://download.opensuse.org/repositories/editors/openSUSE_Leap_15.1/editors.repo
|
|
zypper refresh
|
|
zypper install emacs
|
|
#+END_SRC
|
|
|
|
If you already have an older version of Emacs installed, you will be prompted to
|
|
install the update candidate (Emacs 26.3).
|
|
|
|
***** ripgrep
|
|
Download ripgrep 11.0.2 from [[https://software.opensuse.org/download/package?package=ripgrep&project=openSUSE%3AFactory][the package list]] or installed manually (requires
|
|
root).
|
|
#+BEGIN_SRC bash
|
|
zypper addrepo https://download.opensuse.org/repositories/openSUSE:Factory/standard/openSUSE:Factory.repo
|
|
zypper refresh
|
|
zypper install ripgrep
|
|
#+END_SRC
|
|
|
|
Only ripgrep 0.8.1 is officially available on Leap 15.1 and 15.2, so you will
|
|
need to install Rust to build ripgrep from source. Rust can be downloaded [[https://software.opensuse.org/package/rust][from
|
|
the package list]] or installed manually via zypper (requires root), e.g.
|
|
#+BEGIN_SRC bash
|
|
zypper addrepo https://download.opensuse.org/repositories/openSUSE:Leap:15.1:Update/standard/openSUSE:Leap:15.1:Update.repo
|
|
zypper refresh
|
|
zypper install rust
|
|
#+END_SRC
|
|
|
|
See the [[https://github.com/BurntSushi/ripgrep#building][ripgrep documentation]] for instructions on building from source.
|
|
|
|
*** On macOS
|
|
MacOS users have many options for installing Emacs, but not all of them are well
|
|
suited to Doom. Before we get to that you'll need either the Homebrew or
|
|
MacPorts package manager installed (you only need one):
|
|
|
|
+ [[http://brew.sh/][How to install Homebrew]]
|
|
+ [[https://www.macports.org/install.php][How to install MacPorts]]
|
|
|
|
**** With Homebrew
|
|
First, Doom's dependencies:
|
|
#+BEGIN_SRC bash
|
|
# required dependencies
|
|
brew install git ripgrep
|
|
# optional dependencies
|
|
brew install coreutils fd
|
|
# Installs clang
|
|
xcode-select --install
|
|
#+END_SRC
|
|
|
|
For Emacs itself, these three formulas are the best options, ordered from most
|
|
to least recommended for Doom (based on compatibility).
|
|
|
|
- [[https://github.com/d12frosted/homebrew-emacs-plus][emacs-plus]]:
|
|
#+BEGIN_SRC bash
|
|
brew tap d12frosted/emacs-plus
|
|
brew install emacs-plus
|
|
ln -s /usr/local/opt/emacs-plus/Emacs.app /Applications/Emacs.app
|
|
#+END_SRC
|
|
|
|
Replace =emacs-plus= with =emacs-plus@27= to install Emacs 27.x instead.
|
|
|
|
- [[https://bitbucket.org/mituharu/emacs-mac/overview][emacs-mac]] is another acceptable option. It offers slightly better integration
|
|
with macOS, native emojis and better childframe support. However, at the time
|
|
of writing, it [[https://github.com/railwaycat/homebrew-emacsmacport/issues/52][lacks multi-tty support]] (which impacts daemon usage):
|
|
#+BEGIN_SRC bash
|
|
brew tap railwaycat/emacsmacport
|
|
brew install emacs-mac --with-modules
|
|
ln -s /usr/local/opt/emacs-mac/Emacs.app /Applications/Emacs.app
|
|
#+END_SRC
|
|
|
|
- [[https://formulae.brew.sh/formula/emacs][emacs]] is another acceptable option, **but does not provide a Emacs.app**:
|
|
#+BEGIN_SRC bash
|
|
brew install emacs
|
|
#+END_SRC
|
|
|
|
***** Where *not* to install Emacs from
|
|
These builds/forks have known compatibility issues with Doom and are *very
|
|
likely* to cause issues later on. They are not recommended:
|
|
|
|
+ emacsformacosx.com
|
|
+ ~brew cask install emacs~ (installs from emacsformacosx.com)
|
|
+ AquaMacs
|
|
+ XEmacs
|
|
|
|
**** With MacPorts
|
|
There are four ports (at time of writing) available through MacPorts, and they
|
|
are all acceptable options:
|
|
|
|
+ [[https://ports.macports.org/port/emacs/summary][emacs]] (26.3) and [[https://ports.macports.org/port/emacs-devel/summary][emacs-devel]] (27) -- Installs terminal-only Emacs
|
|
+ [[https://ports.macports.org/port/emacs-app/summary][emacs-app]] (26.3), [[https://ports.macports.org/port/emacs-app-devel/summary][emacs-app-devel]] (27) -- Installs GUI Emacs
|
|
+ [[https://ports.macports.org/port/emacs-mac-app/summary][emacs-mac-app]] (26.3) -- the [[https://bitbucket.org/mituharu/emacs-mac][Mitsuharu Yamamoto mac port]]
|
|
|
|
Some of these ports do not add an =emacs= binary to your ~PATH~, which is
|
|
necessary for Doom's installation process. You'll have to do so yourself by
|
|
adding this to your shell config:
|
|
|
|
#+BEGIN_SRC sh
|
|
# Add this to ~/.zshrc or ~/.bash_profile
|
|
export PATH="/Applications/MacPorts/Emacs.app/Contents/MacOS:$PATH"
|
|
#+END_SRC
|
|
|
|
Or by replacing ~/usr/local/bin/emacs~ with a shim script containing:
|
|
#+BEGIN_SRC
|
|
#!/bin/sh
|
|
/Applications/MacPorts/Emacs.app/Contents/MacOS/Emacs "$@"
|
|
#+END_SRC
|
|
|
|
*** On Windows
|
|
*Support for Windows is immature* so your mileage there will vary. Some have
|
|
reported success using Doom with WSL or WSL2. The maintainer has only (lightly)
|
|
tested installing Doom with chocolatey through [[https://gitforwindows.org/][git-bash]].
|
|
|
|
#+BEGIN_QUOTE
|
|
If you manage to get Doom running on Windows and found this guide wasn't enough
|
|
or could be improved, please help us expand this section!
|
|
#+END_QUOTE
|
|
|
|
**** [[https://chocolatey.org/][chocolatey]] / scoop
|
|
Chocolatey is the simplest to get Doom up and running with:
|
|
|
|
#+BEGIN_SRC sh
|
|
choco install git emacs ripgrep fd llvm
|
|
#+END_SRC
|
|
|
|
#+begin_quote
|
|
Scoop is also a viable way of installing Emacs. However, because Emacs is a GUI
|
|
application, it is relegated to the 'extras' Scoop bucket and that will need to
|
|
be enabled.
|
|
#+end_quote
|
|
|
|
#+BEGIN_SRC sh
|
|
scoop bucket add extras
|
|
scoop install git emacs ripgrep fd llvm
|
|
#+END_SRC
|
|
|
|
You will need [[https://mywindowshub.com/how-to-edit-system-environment-variables-for-a-user-in-windows-10/][the ~HOME~ system variable]] set to =C:\Users\USERNAME\=, otherwise
|
|
Emacs will treat =C:\Users\USERNAME\AppData\Roaming= as your ~HOME~, which
|
|
causes issues.
|
|
|
|
It's also a good idea to add =C:\Users\USERNAME\.emacs.d\bin= to your ~PATH~.
|
|
|
|
#+begin_quote
|
|
A pre-existing PATH variable should already exist among your system variables.
|
|
It contains a string of file paths separated by colons; ~pathA:pathB:pathC~.
|
|
Prepend the path to bin/doom to that string:
|
|
~C:\Users\username\.emacs.d\bin:pathA:pathB:pathC~
|
|
#+end_quote
|
|
|
|
**** TODO WSL
|
|
|
|
**** TODO WSL2
|
|
|
|
** Doom Emacs
|
|
With Emacs and Doom's dependencies installed, next is to install Doom Emacs
|
|
itself:
|
|
|
|
#+BEGIN_SRC bash
|
|
git clone https://github.com/hlissner/doom-emacs ~/.emacs.d
|
|
~/.emacs.d/bin/doom install
|
|
#+END_SRC
|
|
|
|
=doom install= will set up your =DOOMDIR= at =~/.doom.d= (if it doesn't already
|
|
exist) and will work you through the first-time setup of Doom Emacs. Carefully
|
|
follow any instructions it puts out.
|
|
|
|
If this is your first time, you should run ~doom doctor~. This will diagnose
|
|
common issues with your system or config.
|
|
|
|
#+BEGIN_QUOTE
|
|
If you'd like a more technical break down of ~doom install~, it's been
|
|
translated into shell commands below, in the "Install Doom Manually" section.
|
|
#+END_QUOTE
|
|
|
|
*** The ~bin/doom~ utility
|
|
This utility is your new best friend. It won't spot you a beer, but it'll
|
|
shoulder much of the work associated with managing and maintaining your Doom
|
|
Emacs configuration, and then some. Not least of which is installation of and
|
|
updating Doom and your installed packages.
|
|
|
|
It exposes a variety of commands. ~bin/doom help~ will list them all, but here
|
|
is a summary of the most important ones:
|
|
|
|
+ ~doom sync~: This synchronizes your config with Doom Emacs. It ensures that
|
|
needed packages are installed, orphaned packages are removed and necessary
|
|
metadata correctly generated. Run this whenever you modify your ~doom!~ block
|
|
or =packages.el= file. You'll need ~doom sync -u~ if you override the recipe
|
|
of package installed by another module.
|
|
+ ~doom upgrade~: Updates Doom Emacs (if available) and all its packages.
|
|
+ ~doom env~: (Re)generates an "envvar file", which is a snapshot of your
|
|
shell environment that Doom loads at startup. If your app launcher or OS
|
|
launches Emacs in the wrong environment you will need this. **This is required
|
|
for GUI Emacs users on MacOS.**
|
|
+ ~doom doctor~: If Doom misbehaves, the doc will diagnose common issues with
|
|
your installation, system and environment.
|
|
+ ~doom purge~: Over time, the repositories for Doom's plugins will accumulate.
|
|
Run this command from time to time to delete old, orphaned packages, and with
|
|
the ~-g~ switch to compact existing package repos.
|
|
|
|
Use ~doom help~ to see an overview of the available commands that =doom=
|
|
provides, and ~doom help COMMAND~ to display documentation for a particular
|
|
~COMMAND~.
|
|
|
|
#+begin_quote
|
|
I recommend you add =~/.emacs.d/bin= to your ~PATH~ so you can call =doom=
|
|
directly and from anywhere. Accomplish this by adding this to your .bashrc or
|
|
.zshrc file: ~export PATH=~/.emacs.d/bin:$PATH~
|
|
#+end_quote
|
|
|
|
*** Install Doom Manually
|
|
If you'd rather install Doom yourself, instead of rely on the magic of =doom
|
|
install=, here is its equivalent in bash shell commands (assuming
|
|
=hlissner/doom-emacs= has been cloned to =~/.emacs.d=):
|
|
|
|
#+BEGIN_SRC bash
|
|
# So we don't have to write ~/.emacs.d/bin/doom every time
|
|
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
|
|
cp ~/.emacs.d/core/templates/config.example.el ~/.doom.d/config.el
|
|
cp ~/.emacs.d/core/templates/packages.example.el ~/.doom.d/packages.el
|
|
|
|
# You might want to edit ~/.doom.d/init.el here and make sure you only have the
|
|
# modules you want enabled.
|
|
|
|
# Then synchronize Doom with your config:
|
|
doom sync
|
|
|
|
# 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 create an envvar file to ensure Doom correctly inherits your shell
|
|
# environment.
|
|
#
|
|
# If you don't know whether you need this or not, there's no harm in doing it
|
|
# anyway. `doom install` will have prompted you to generate one. If you
|
|
# responded no, you can generate it later with the following command:
|
|
doom env
|
|
|
|
# Lastly, install the icon fonts Doom uses:
|
|
emacs --batch -f all-the-icons-install-fonts
|
|
# On Windows, `all-the-icons-install-fonts` will only download the fonts, you'll
|
|
# have to install them by hand afterwards!
|
|
#+END_SRC
|
|
|
|
To understand the purpose of the =~/.doom.d= directory and =~/.doom.d/init.el=
|
|
file, see the [[#configure][Configure]] section further below.
|
|
|
|
*** Install Doom alongside other configs (with Chemacs)
|
|
[[https://github.com/plexus/chemacs][Chemacs]] is a bootloader for Emacs. It allows you to switch between multiple
|
|
Emacs configurations. Here is a quick guide for setting it up with Doom Emacs as
|
|
the default config:
|
|
|
|
1. First, install Doom somewhere:
|
|
#+BEGIN_SRC sh :eval no
|
|
git clone https://github.com/hlissner/doom-emacs ~/doom-emacs
|
|
~/doom-emacs/bin/doom install
|
|
#+END_SRC
|
|
|
|
2. Download [[https://raw.githubusercontent.com/plexus/chemacs/master/.emacs][the Chemacs' startup script]] to =~/.emacs=:
|
|
#+BEGIN_SRC bash :eval no
|
|
wget -O ~/.emacs https://raw.githubusercontent.com/plexus/chemacs/master/.emacs
|
|
#+END_SRC
|
|
|
|
#+begin_quote
|
|
*WARNING:* the =~/.emacs.d= directory must not exist for this to work.
|
|
#+end_quote
|
|
|
|
3. 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:
|
|
#+BEGIN_SRC emacs-lisp :eval no
|
|
(("default" . ((user-emacs-directory . "~/doom-emacs")))
|
|
("spacemacs" . ((user-emacs-directory . "~/spacemacs")))
|
|
("prelude" . ((user-emacs-directory . "~/prelude"))))
|
|
#+END_SRC
|
|
|
|
To start Emacs with a specific config, use the =--with-profile= option:
|
|
|
|
#+BEGIN_SRC bash
|
|
emacs --with-profile spacemacs
|
|
#+END_SRC
|
|
|
|
If no profile is specified, the =default= profile is used.
|
|
|
|
** External/system dependencies
|
|
Doom is comprised of approximately 160 modules which provide its features,
|
|
language support and integration with external tools. Many of these have
|
|
external dependencies that you must install yourself. You'll find what a module
|
|
needs and how to install them in that module's README.org file or by running
|
|
~bin/doom doctor~.
|
|
|
|
The [[file:modules.org][Module Index]] lists all Doom's available modules, with links to their
|
|
documentation. Documentation is a work-in-progrees; some modules may not have
|
|
README.org files yet!
|
|
|
|
#+begin_quote
|
|
Use ~M-x doom/help-modules~ (bound to =SPC h d m= or =C-h d m=) to jump to a
|
|
module's documentation from within Doom, otherwise, place your cursor on a
|
|
module in your ~doom!~ block (in =~/.doom.d/init.el=) and press =K= to jump to
|
|
its documentation (or =gd= to jump to its source code). =C-c g k= and =C-c g d=
|
|
for non-evil users, respectively.
|
|
#+end_quote
|
|
|
|
* Update & Rollback
|
|
Doom is an active project and many of its 300+ packages are in active
|
|
development as well. It is wise to occasionally update:
|
|
#+BEGIN_SRC bash
|
|
doom upgrade # or 'doom up'
|
|
#+END_SRC
|
|
|
|
If you want to update Doom manually, ~doom upgrade~ is equivalent to:
|
|
#+BEGIN_SRC bash
|
|
cd ~/.emacs.d
|
|
git pull # updates Doom
|
|
doom clean # Ensure your config isn't byte-compiled
|
|
doom sync # synchronizes your config with Doom Emacs
|
|
doom update # updates installed packages
|
|
#+END_SRC
|
|
|
|
To upgrade only your packages (and not Doom itself):
|
|
|
|
#+BEGIN_SRC bash
|
|
doom upgrade --packages
|
|
#+END_SRC
|
|
|
|
#+begin_quote
|
|
To minimize issues while upgrading, avoid modifying Doom's source files in
|
|
=~/.emacs.d=. All your customization should be kept in your =DOOMDIR= (e.g.
|
|
=~/.doom.d=). Read the [[#Configure][Configure]] section for more on configuring Doom.
|
|
#+end_quote
|
|
|
|
** TODO Rollback
|
|
The =bin/doom= script doesn't currently offer rollback support for Doom or its
|
|
packages (yet).
|
|
|
|
** Up/Downgrading Emacs
|
|
*You may encounter errors after up/downgrading Emacs.* Run ~doom sync~ on the
|
|
command line after changing the installed version of Emacs. If you've changed
|
|
the major version (e.g. 26 -> 27 or vice versa) run ~doom build~ too.
|
|
|
|
+ ~doom sync~ will re-index any built-in/site loaddef files. This is especially
|
|
necessary if paths to built-in libraries have changed.
|
|
+ ~doom build~ will recompile all your installed packages, which is necessary
|
|
because Emacs bytecode not generally forward compatible across major releases
|
|
(e.g. 26 -> 27). Alternatively, reinstall all your packages by deleting
|
|
=~/.emacs.d/.local=, then run ~doom sync~.
|
|
|
|
* TODO Migrate
|
|
If you're here from another Emacs distribution (or your own), here are a few
|
|
things to be aware of while you convert your old config to Doom:
|
|
|
|
+ Doom does not use =package.el= to manage its packages, but ~use-package~ does!
|
|
You will see errors if you have ~:ensure ...~ properties in your ~use-package~
|
|
blocks. Remove these and, instead, add ~package!~ declarations to
|
|
=~/.doom.d/packages.el= to install your packages.
|
|
|
|
See [[#package-management]["Package Management"]], further in this guide.
|
|
|
|
(This section is incomplete)
|
|
|
|
** TODO From vanilla Emacs
|
|
#+begin_quote
|
|
Have you migrated from your own config? Help me flesh out this section by
|
|
letting me know what kind of hurdles you faced in doing so. You'll find me [[https://discord.gg/qvGgnVx][on
|
|
our Discord server]].
|
|
#+end_quote
|
|
|
|
** TODO From Spacemacs
|
|
#+begin_quote
|
|
Have you migrated from Spacemacs? Help me flesh out this section by letting me
|
|
know what kind of hurdles you faced in doing so. You'll find me [[https://discord.gg/qvGgnVx][on our Discord
|
|
server]].
|
|
#+end_quote
|
|
|
|
* Configure
|
|
You can configure Doom by tweaking the files found in your =DOOMDIR=. Doom
|
|
expects this directory to be found in one of:
|
|
|
|
1. =~/.config/doom= (respects ~$XDG_CONFIG_HOME~)
|
|
2. or =~/.doom.d=
|
|
|
|
This directory is referred to as your =DOOMDIR=. Only one of these directories
|
|
should exist (Doom will only recognize one).
|
|
|
|
#+begin_quote
|
|
Change the =DOOMDIR= environment variable to change where Doom looks for this
|
|
directory. Symlinks will work as well.
|
|
#+end_quote
|
|
|
|
When you ran ~doom install~, it deployed a simple Doom configuration to your
|
|
=DOOMDIR=, comprised of these three files:
|
|
|
|
+ init.el :: Where you'll find your ~doom!~ block, which controls what Doom
|
|
modules are enabled and in what order they will be loaded.
|
|
|
|
This file is evaluated early when Emacs is starting up; before any other
|
|
module has loaded. You generally shouldn't add code to this file unless you're
|
|
targeting Doom's CLI or something that needs to be configured very early in
|
|
the startup process.
|
|
+ config.el :: Here is where 99.99% of your private configuration should go.
|
|
Anything in here is evaluated /after/ all other modules have loaded, when
|
|
starting up Emacs.
|
|
+ packages.el :: Package management is done from this file; where you'll declare
|
|
what packages to install and where from.
|
|
|
|
#+begin_quote
|
|
Note: do not use ~M-x customize~ or the customize API in general. Doom is
|
|
designed to be configured programmatically from your config.el, which can
|
|
conflict with Customize's way of modifying variables.
|
|
|
|
If you're concerned about ~defcustom~ setters, Doom has a ~setq!~ macro that
|
|
will trigger them.
|
|
#+end_quote
|
|
|
|
** Modules
|
|
Doom consists of around 160 modules and growing. A Doom module is a bundle of
|
|
packages, configuration and commands, organized into a unit that can be toggled
|
|
easily by tweaking your ~doom!~ block (found in =$DOOMDIR/init.el=).
|
|
|
|
#+begin_quote
|
|
If =$DOOMDIR/init.el= doesn't exist, you haven't run ~doom install~ yet. See [[#install][the
|
|
"Install" section]] above.
|
|
#+end_quote
|
|
|
|
Your ~doom!~ block should look something like this:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
;; To comment something out, you insert at least one semicolon before it and the
|
|
;; Emacs Lisp interpreter will ignore everything until the end of the line.
|
|
(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
|
|
#+END_SRC
|
|
|
|
It controls what modules are enabled and in what order they are loaded. Some
|
|
modules have *optional features* that can be enabled by passing them flags,
|
|
denoted by a plus prefix:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(doom! :completion
|
|
(company +auto)
|
|
:lang
|
|
(csharp +unity)
|
|
(org +brain +dragndrop +gnuplot +hugo +jupyter)
|
|
(sh +fish))
|
|
#+END_SRC
|
|
|
|
Different modules support different flags. You'll find a comprehensive list of
|
|
available modules and their supported flags in [[file:index.org::*Module list][the Module Index]]. Flags that a
|
|
module does not recognize will be silently ignored.
|
|
|
|
#+begin_quote
|
|
*IMPORTANT:* any changes to your ~doom!~ block won't take effect until you run
|
|
~doom sync~ on the command line.
|
|
#+end_quote
|
|
|
|
#+begin_quote
|
|
~doom doctor~ will detect issues with your ~doom!~ block, such as duplicate or
|
|
misspelled modules and flags.
|
|
#+end_quote
|
|
|
|
** Package management
|
|
**Doom Emacs does not use package.el** (the package manager built into Emacs).
|
|
Instead, it uses its own declarative package manager built on top of
|
|
[[https://github.com/raxod502/straight.el][straight.el]].
|
|
|
|
Packages are declared in ~packages.el~ files. You'll find one in your =DOOMDIR=
|
|
and in many of Doom's modules. Read on to learn how to use this system to
|
|
install your own packages.
|
|
|
|
#+begin_quote
|
|
*WARNING:* Do not install packages directly (with ~M-x package-install~ or ~M-x
|
|
straight-use-package~). Without an accompanying ~package!~ declaration somewhere
|
|
these packages will be forgotten when you restart Emacs and uninstalled the next
|
|
time you run ~doom sync~ or ~doom purge~.
|
|
#+end_quote
|
|
|
|
#+begin_quote
|
|
*WARNING:* If you're here from another Emacs distro (or vanilla Emacs), be wary
|
|
of the ~:ensure~ property in ~use-package~ blocks, because it will attempt (and
|
|
fail) to install packages through package.el. Tutorials will recommend you
|
|
install packages this way too!
|
|
#+end_quote
|
|
|
|
*** Installing packages
|
|
To install a package, add a ~package!~ declaration for it to
|
|
=DOOMDIR/packages.el=:
|
|
#+BEGIN_SRC emacs-lisp
|
|
;; Install a package named "example" from ELPA, MELPA, or Emacsmirror
|
|
(package! example)
|
|
#+END_SRC
|
|
|
|
If a package could not be found in any known repo you will get an error like:
|
|
|
|
#+begin_quote
|
|
Could not find package X in recipe repositories: (org-elpa melpa gnu-elpa-mirror
|
|
emacsmirror-mirror)
|
|
#+end_quote
|
|
|
|
The most likely cause for this is either:
|
|
|
|
- You've misspelled the package's name.
|
|
- Or the package really doesn't exist on ELPA, MELPA, or EmacsMirror and you'll
|
|
need to [[*Installing packages from external sources][specify a recipe for it]].
|
|
|
|
~package!~ will return non-nil if the package is cleared for install and hasn't
|
|
been disabled elsewhere. Use this fact to chain package dependencies together.
|
|
e.g.
|
|
#+BEGIN_SRC elisp
|
|
(when (package! example)
|
|
(package! plugin-that-example-depends-on))
|
|
#+END_SRC
|
|
|
|
#+begin_quote
|
|
*IMPORTANT:* New packages won't be installed until you run ~doom sync~.
|
|
#+end_quote
|
|
|
|
*** Installing packages from external sources
|
|
To install a package straight from an external source (like github, gitlab,
|
|
etc), you'll need to specify a [[https://github.com/raxod502/straight.el#the-recipe-format][MELPA-style straight recipe]]:
|
|
|
|
Here are a few examples:
|
|
#+BEGIN_SRC elisp
|
|
;; Install it directly from a github repository. For this to work, the package
|
|
;; must have an appropriate PACKAGENAME.el file which must contain 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, use
|
|
;; `:files' to target them.
|
|
(package! example :recipe
|
|
(:host github
|
|
:repo "username/my-example-fork"
|
|
:files ("*.el" "src/lisp/*.el")))
|
|
|
|
;; To grab a particular branch or tag:
|
|
(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 the rest of the recipe 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))
|
|
|
|
;; A package can be installed straight from a git repo by setting :host to nil:
|
|
(package! example
|
|
:recipe (:host nil :repo "https://some/git/repo"))
|
|
#+END_SRC
|
|
|
|
The specification for the ~package!~ macro's ~:recipe~ is laid out [[https://github.com/raxod502/straight.el#the-recipe-format][in
|
|
Straight.el's README]].
|
|
|
|
#+begin_quote
|
|
*IMPORTANT:* Run ~bin/doom sync~ whenever you modify packages.el files to
|
|
ensure your changes take effect.
|
|
#+end_quote
|
|
|
|
*** Pinning packages to specific commits
|
|
All of Doom's packages are pinned by default. A pinned package is a package
|
|
locked to a specific commit, like so:
|
|
#+BEGIN_SRC elisp
|
|
(package! evil :pin "e00626d9fd")
|
|
#+END_SRC
|
|
|
|
To unpin a package, use the ~unpin!~ macro:
|
|
#+BEGIN_SRC elisp
|
|
(unpin! evil)
|
|
|
|
;; It can be used to unpin multiple packages at once
|
|
(unpin! evil helm org-mode)
|
|
|
|
;; Or to unpin all packages in modules
|
|
(unpin! (:lang python ruby rust) (:tools docker))
|
|
|
|
;; Or to unpin an entire category of modules
|
|
(unpin! :completion :lang :tools)
|
|
|
|
;; This will work too, if you prefer the syntax, but it provides no concise
|
|
;; syntax for unpinning multiple packages:
|
|
(package! helm :pin nil)
|
|
#+END_SRC
|
|
|
|
Though it is *highly* discouraged, you may unpin all packages and make Doom
|
|
Emacs rolling release:
|
|
#+BEGIN_SRC elisp
|
|
(unpin! t)
|
|
#+END_SRC
|
|
|
|
#+begin_quote
|
|
Unpinning all packages is discouraged because Doom's modules are designed
|
|
against the pinned versions of its packages. More volatile packages (like
|
|
lsp-mode, ein and org) change rapidly, and are likely to cause breakages if
|
|
unpinned.
|
|
|
|
Instead, it's a better to selectively unpin packages, or repin them to the exact
|
|
commit you want.
|
|
#+end_quote
|
|
|
|
*** Disabling packages
|
|
The ~package!~ macro possesses a ~:disable~ property:
|
|
#+BEGIN_SRC emacs-lisp
|
|
(package! irony :disable t)
|
|
(package! rtags :disable t)
|
|
#+END_SRC
|
|
|
|
Once a package is disabled, ~use-package!~ and ~after!~ blocks for it will be
|
|
ignored, and the package is removed the next time you run ~bin/doom sync~. Use
|
|
this to disable Doom's packages that you don't want or need.
|
|
|
|
There is also the ~disable-packages!~ macro for conveniently disabling multiple
|
|
packages:
|
|
#+BEGIN_SRC elisp
|
|
(disable-packages! irony rtags)
|
|
#+END_SRC
|
|
|
|
#+begin_quote
|
|
*IMPORTANT:* Run ~bin/doom sync~ whenever you modify packages.el files to
|
|
ensure your changes take effect.
|
|
#+end_quote
|
|
|
|
*** Changing a recipe for a included package
|
|
If a Doom module installs package X from one place, but you'd like to install it
|
|
from another (say, a superior fork), add a ~package!~ declaration for it in your
|
|
=DOOMDIR/packages.el=. Your private declarations always have precedence over
|
|
modules (even your own).
|
|
#+BEGIN_SRC elisp
|
|
;; in modules/editor/evil/packages.el
|
|
(package! evil) ; installs from MELPA
|
|
|
|
;; in DOOMDIR/packages.el
|
|
(package! evil :recipe (:host github :repo "username/my-evil-fork"))
|
|
#+END_SRC
|
|
|
|
To install a package only if a built-in package doesn't exist, use ~:built-in
|
|
'prefer~:
|
|
#+BEGIN_SRC elisp
|
|
(package! so-long :built-in 'prefer)
|
|
#+END_SRC
|
|
|
|
#+begin_quote
|
|
*IMPORTANT:* Remember to run ~doom sync -u~ after changing recipes for existing
|
|
packages. At the time of writing, ~doom sync~ alone will not pick up on recipe
|
|
changes.
|
|
#+end_quote
|
|
|
|
*** Using/loading local packages
|
|
Say you have a local elisp package that you are developing, and want to
|
|
"install" it for live testing. You have two options:
|
|
|
|
**** Adjust your ~load-path~
|
|
Emacs searches for packages in your ~load-path~. Add the path to your package
|
|
and Emacs will find it when it tries to load it. e.g.
|
|
|
|
#+BEGIN_SRC elisp
|
|
(add-load-path! "lisp/package")
|
|
|
|
;; or
|
|
|
|
(use-package my-package
|
|
:load-path "/path/to/my/package")
|
|
#+END_SRC
|
|
|
|
**** :local-repo
|
|
Alternatively, you can specify a ~:local-repo~ in a ~package!~'s ~:recipe~
|
|
declaration:
|
|
|
|
#+BEGIN_SRC elisp
|
|
(package! my-package :recipe (:local-repo "/path/to/my/package"))
|
|
|
|
;; Don't forget to use :files to include files in an unconventional project structure:
|
|
(package! my-package
|
|
:recipe (:local-repo "/path/to/my/package"
|
|
:files ("*.el" "src/lisp/*.el")))
|
|
|
|
;; It is recommended you use ':no-byte-compile t' as well, so you don't have to
|
|
;; run `doom build -r` every time you make a change to your package.
|
|
(package! my-package
|
|
:recipe (:local-repo "/path/to/my/package"
|
|
:files ("*.el" "src/lisp/*.el")
|
|
:no-byte-compile t))
|
|
#+END_SRC
|
|
|
|
#+begin_quote
|
|
*IMPORTANT:* Remember to run ~doom sync~ to rebuild your package after you've
|
|
changed it, and to re-index any autoloads in it.
|
|
#+end_quote
|
|
|
|
** Configuring Doom
|
|
*** Configuring packages
|
|
If your configuration needs are simple, the ~use-package!~, ~after!~,
|
|
~add-hook!~ and ~setq-hook!~ macros are your bread and butter.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
;;; ~/.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 ":"))
|
|
#+END_SRC
|
|
|
|
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.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
;;; ~/.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
|
|
#+END_SRC
|
|
|
|
*** Reloading your config
|
|
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 run ~eval-last-sexp~, as well as ~M-x
|
|
+eval/buffer-or-region~ (on =SPC 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-:= or =SPC ;=, which invokes ~eval-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.
|
|
|
|
*** TODO Binding keys
|
|
+ define-key
|
|
+ global-set-key
|
|
+ map!
|
|
+ undefine-key!
|
|
+ define-key!
|
|
|
|
** Writing your own modules
|
|
*** Load order
|
|
Module files are loaded in a precise order:
|
|
|
|
1. =~/.emacs.d/early-init.el= (Emacs 27+ only)
|
|
2. =~/.emacs.d/init.el=
|
|
3. =$DOOMDIR/init.el=
|
|
4. ={~/.emacs.d,$DOOMDIR}/modules/*/*/init.el=
|
|
5. ={~/.emacs.d,$DOOMDIR}/modules/*/*/config.el=
|
|
6. =$DOOMDIR/config.el=
|
|
|
|
*** Location
|
|
Doom searches for modules in =~/.emacs.d/modules/CATEGORY/MODULE/= and
|
|
=$DOOMDIR/modules/CATEGORY/MODULE/=. If you have a private module with the same
|
|
name as an included Doom module, yours will shadow the included one (as if the
|
|
included one never existed).
|
|
|
|
#+begin_quote
|
|
Doom refers to modules in one of two formats: ~:category module~ or
|
|
~category/module~.
|
|
#+end_quote
|
|
|
|
*** File structure
|
|
A module consists of several files, all of which are optional. They are:
|
|
|
|
#+begin_example
|
|
modules/
|
|
category/
|
|
module/
|
|
test/*.el
|
|
autoload/*.el
|
|
autoload.el
|
|
init.el
|
|
config.el
|
|
packages.el
|
|
doctor.el
|
|
#+end_example
|
|
|
|
**** =init.el=
|
|
This file is loaded early, before anything else, but after Doom core is loaded.
|
|
|
|
Use this file to:
|
|
|
|
+ Configure Emacs or perform setup/teardown operations that must be set early;
|
|
before other modules are (or this module is) loaded.
|
|
+ Reconfigure packages defined in Doom modules with ~use-package-hook!~ (as a
|
|
last resort, when ~after!~ and hooks aren't enough).
|
|
+ To change the behavior of ~bin/doom~.
|
|
|
|
Do *not* use this file to:
|
|
|
|
+ Configure packages with ~use-package!~ or ~after!~
|
|
+ Preform expensive or error-prone operations; these files are evaluated
|
|
whenever ~bin/doom~ is used.
|
|
|
|
**** =config.el=
|
|
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!~ to detect them).
|
|
|
|
Packages should be configured using ~after!~ or ~use-package!~:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
;; 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)
|
|
[...])
|
|
#+END_SRC
|
|
|
|
#+begin_quote
|
|
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.
|
|
#+end_quote
|
|
|
|
**** =packages.el=
|
|
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.
|
|
|
|
See the "[[#package-management][Package Management]]" section for details.
|
|
|
|
**** =autoload/*.el= OR =autoload.el=
|
|
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:
|
|
|
|
#+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 "<a>")
|
|
[...])
|
|
#+END_SRC
|
|
|
|
**** =doctor.el=
|
|
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:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
;; 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"))
|
|
#+END_SRC
|
|
|
|
**** Additional files
|
|
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:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
;; from modules/feature/version-control/config.el
|
|
(load! +git)
|
|
#+END_SRC
|
|
|
|
The ~load!~ macro will try to load a =+git.el= relative to the current file.
|
|
|
|
*** Flags
|
|
A module flag is an arbitrary symbol. By convention, these symbols are prefixed
|
|
with a ~+~ or a ~-~, to respectively denote the addition or removal of a
|
|
feature. There is no functional significance to this notation.
|
|
|
|
A module may choose to interpret flags however it likes. They can be tested for
|
|
with the ~featurep!~ macro:
|
|
|
|
#+BEGIN_SRC elisp
|
|
;; Has the current module been enabled with the +my-feature flag?
|
|
(when (featurep! +my-feature) ...)
|
|
|
|
;; It can be used to check the presence of flags in other modules:
|
|
(when (featurep! :lang python +lsp) ...)
|
|
#+END_SRC
|
|
|
|
*** Module cookies
|
|
A special syntax exists called module cookies. Like autoload cookies
|
|
(~;;;###autoload~), module files may have ~;;;###if FORM~ at or near the top of
|
|
the file. FORM is read determine whether or not to ignore this file when
|
|
scanning it for autoloads (~doom sync~) or byte-compiling it (~doom compile~).
|
|
|
|
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.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
;;;###if (featurep! +lsp)
|
|
#+END_SRC
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
;;;###if (not (locate-library "so-long"))
|
|
#+END_SRC
|
|
|
|
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.
|
|
|
|
*** Autodefs
|
|
An autodef is a special kind of autoloaded function or macro which Doom
|
|
guarantees will always be defined, whether or not its containing module is
|
|
enabled (but will no-op without evaluating its arguments when it is disabled).
|
|
|
|
You can browse the available autodefs in your current session with ~M-x
|
|
doom/help-autodefs~ (=SPC h d u= or =C-h d u=).
|
|
|
|
What distinguishes an autodef from a regular autoload is the ~;;;###autodef~
|
|
cookie:
|
|
|
|
#+BEGIN_SRC elisp
|
|
;;;###autodef
|
|
(defun set-something! (value)
|
|
...)
|
|
#+END_SRC
|
|
|
|
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:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(set-company-backend! 'python-mode '(company-anaconda))
|
|
#+END_SRC
|
|
|
|
** Common mistakes when configuring Doom Emacs
|
|
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:
|
|
|
|
*** Packages are eagerly loaded
|
|
Using ~use-package!~ without a deferring keyword (one of: ~:defer :after
|
|
:commands :defer-incrementally :after-call~) will load the package immediately.
|
|
This causes 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.
|
|
|
|
*** Manual package management
|
|
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 sync~ to sync your config).
|
|
|
|
*** Using ~org-babel-do-load-languages~ to load your babel packages
|
|
You don't need ~org-babel-do-load-languages~. Doom lazy loads babel packages
|
|
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 [[file:../modules/lang/org/README.org][:lang
|
|
org module documentation]] for details on how to add support for it.
|
|
|
|
*** Using ~delete-trailing-whitespaces~ or ~whitespace-cleanup~ to manage leftover whitespace
|
|
#+BEGIN_SRC elisp
|
|
(add-hook 'after-save-hook #'delete-trailing-whitespace)
|
|
;; or
|
|
(add-hook 'after-save-hook #'whitespace-cleanup)
|
|
#+END_SRC
|
|
|
|
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:
|
|
|
|
1. 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~ and ~M-x
|
|
whitespace-cleanup~ are available to be called =deliberately=, instead.
|
|
|
|
2. =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.
|
|
|
|
* Troubleshoot
|
|
When problems arise, you should be prepared to collect information in order to
|
|
solve them, or for the bug report you're about to write. Both Emacs and Doom
|
|
provide tools to make this easier. Here are a few things you can try, first:
|
|
|
|
+ Investigate the =*Messages*= log for warnings or error messages. This log can
|
|
be opened with =SPC h e=, =C-h e= or =M-x view-echo-area-messages=.
|
|
|
|
+ Look up errors/warnings [[file:faq.org::Common Issues][on the FAQ]] and [[https://github.com/hlissner/doom-emacs/issues][Doom's issue tracker]]. It is possible
|
|
that a solution for your issue already exists. The FAQ can be searched from
|
|
inside Doom with =SPC h d f= (or =C-h d f= for non-evil users).
|
|
|
|
+ Run ~bin/doom doctor~ on the command line to diagnose common issues with your
|
|
environment and config. It will suggest solutions for them as well.
|
|
|
|
+ ~bin/doom clean~ will ensure the problem isn't stale bytecode in your private
|
|
config or Doom core. If you haven't used ~bin/doom compile~, there's no need
|
|
to do this.
|
|
|
|
+ ~bin/doom sync~ will ensure the problem isn't missing packages or outdated
|
|
autoloads files
|
|
|
|
+ ~bin/doom build~ will ensure the problem isn't stale package bytecode or
|
|
broken symlinks.
|
|
|
|
+ ~bin/doom update~ will ensure that your packages are up-to-date, eliminating
|
|
issues that originate from upstream.
|
|
|
|
+ If you happen to know what module(s) are relevant to your issue, check their
|
|
documentation (press =<leader> h m= to jump to a module's documentation). Your
|
|
issue may be documented.
|
|
|
|
+ If possible, see if the issue can be reproduced in vanilla Emacs (Emacs
|
|
without Doom) and/or vanilla Doom (Doom without your private config). [[#testing-in-dooms-sandbox][Doom's
|
|
sandbox can help you check]].
|
|
|
|
+ Ask for help on [[https://discord.gg/qvGgnVx][our Discord server]]. It is the quickest way to get help,
|
|
sometimes straight from Doom's maintainer, who is very active there.
|
|
|
|
If none of these things have helped you, then it's time to open a bug report.
|
|
See "[[file:contributing.org::*Reporting issues][Reporting Issues]]" in the [[file:contributing.org][contributing guidelines]] on how to file an
|
|
effective bug report.
|
|
|
|
** Looking up documentation and state from within Emacs
|
|
...
|
|
|
|
*** Variables, functions, faces, etc.
|
|
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 ;=).
|
|
|
|
*** TODO For Doom Modules, packages, autodefs, etc.
|
|
+ ~doom/open-news~ (=SPC h n=) ::
|
|
...
|
|
+ ~doom/help~ (=SPC h d h=) ::
|
|
Open the index of Doom's manual.
|
|
+ ~doom/help-modules~ (=SPC h d m=) ::
|
|
Jumps to a module's documentation.
|
|
+ ~doom/help-autodefs~ (=SPC h u=) ::
|
|
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/help-packages~ (=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~ ::
|
|
...
|
|
|
|
** How to extract a backtrace from an error
|
|
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 [[https://discord.gg/qvGgnVx][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.
|
|
|
|
*** Enabling ~debug-on-error~
|
|
There are three ways to enable ~debug-on-error~:
|
|
|
|
1. Start Emacs with ~emacs --debug-init~. Use this for errors that occur at
|
|
startup.
|
|
2. Evil users can press =SPC h d d= and non-evil users can press =C-h d d=.
|
|
3. 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.
|
|
|
|
*** A backtrace from ~bin/doom~
|
|
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.
|
|
|
|
#+BEGIN_SRC sh
|
|
doom -d sync
|
|
doom --debug install
|
|
DEBUG=1 doom update
|
|
#+END_SRC
|
|
|
|
#+BEGIN_QUOTE
|
|
Note: switch order is important. ~-d~ / ~--debug~ /must/ come right after ~doom~
|
|
and before the subcommand. This will be fixed eventually.
|
|
#+END_QUOTE
|
|
|
|
** Evaluating Elisp on-the-fly
|
|
Often, you may find it helpful for debugging to evaluate some Emacs Lisp. Here
|
|
are couple things you can do:
|
|
|
|
+ Use =M-;= (bound to ~eval-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,
|
|
|
|
** How to determine the origin of a bug
|
|
** Testing in Doom's sandbox
|
|
"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 packages 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.
|
|
|
|
*** Opening the sandbox
|
|
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.
|
|
|
|
*** Launching the sandbox
|
|
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.
|
|
|
|
#+BEGIN_QUOTE
|
|
All new instances will inherit your ~load-path~ so you can access any packages
|
|
you have installed.
|
|
#+END_QUOTE
|
|
*** Testing packages in the sandbox
|
|
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.
|
|
|
|
#+BEGIN_SRC elisp
|
|
(require 'magit)
|
|
(find-file "~/some/file/in/a/repo")
|
|
(call-interactively #'magit-status)
|
|
#+END_SRC
|
|
|
|
** TODO Bisecting your private config
|
|
** TODO Bisecting Doom Emacs
|