#+TITLE: Frequently Asked Questions

#+begin_quote
*Doom's FAQs have [[https://discourse.doomemacs.org/faq][moved to Discourse]].* This file will be removed soon.
#+end_quote

* Table of Contents :TOC:
- [[#general][General]]
  - [[#why-is-it-called-doom][Why is it called Doom?]]
  - [[#is-doom-a-fork-of-spacemacspreludeetc][Is Doom a fork of Spacemacs/Prelude/etc?]]
  - [[#does-doom-work-on-windows][Does Doom work on Windows?]]
  - [[#is-doom-only-for-vimmers][Is Doom only for vimmers?]]
  - [[#i-am-a-beginner-can-i-use-doom][I am a beginner. Can I use Doom?]]
  - [[#how-does-doom-compare-to-spacemacs][How does Doom compare to Spacemacs?]]
  - [[#why-such-a-complicated-package-management-system][Why such a complicated package management system?]]
  - [[#how-does-doom-start-up-so-quickly][How does Doom start up so quickly?]]
  - [[#why-is-startup-time-important-why-not-use-the-daemon][Why is startup time important? Why not use the daemon?]]
  - [[#how-do-i-use-doom-alongside-other-emacs-configs][How do I use Doom alongside other Emacs configs?]]
  - [[#why-should-i-use-doom-instead-of-rolling-my-own-config][Why should I use Doom instead of rolling my own config?]]
  - [[#what-is-the-meaning-behind-dooms-naming-convention-in-its-source-code][What is the meaning behind Doom's naming convention in its source code?]]
  - [[#what-version-of-doom-am-i-running][What version of Doom am I running?]]
  - [[#is-discord-the-only-option-for-interacting-with-your-community][Is Discord the only option for interacting with your community?]]
  - [[#why-is-emacsdoom-slow][Why is Emacs/Doom slow?]]
- [[#configuration][Configuration]]
  - [[#how-do-i-configure-doom-emacs][How do I configure Doom Emacs?]]
  - [[#does-doom-respect-xdg-directory-conventions][Does Doom respect XDG directory conventions]]
  - [[#how-do-i-enable-or-disable-a-doom-module][How do I enable or disable a Doom module?]]
  - [[#how-do-i-change-the-theme][How do I change the theme?]]
  - [[#how-do-i-change-the-fonts][How do I change the fonts?]]
  - [[#how-do-i-bind-my-own-keys-or-change-existing-ones][How do I bind my own keys (or change existing ones)?]]
  - [[#how-do-i-get-motions-to-treat-underscores-as-word-delimiters][How do I get motions to treat underscores as word delimiters?]]
  - [[#how-do-i-change-the-leaderlocalleader-keys][How do I change the leader/localleader keys?]]
  - [[#how-do-i-change-the-style-of-line-numbers-or-disable-them-altogether][How do I change the style of line-numbers (or disable them altogether)?]]
  - [[#how-do-i-change-the-behavior-and-appearance-of-popup-windows][How do I change the behavior and appearance of popup windows?]]
  - [[#how-do-i-customize-a-theme-or-faces][How do I customize a theme or face(s)?]]
  - [[#how-do-i-make-a-new-theme][How do I make a new theme?]]
  - [[#can-doom-be-customized-without-restarting-emacs][Can Doom be customized without restarting Emacs?]]
  - [[#can-vimevil-be-removed-for-a-more-vanilla-emacs-experience][Can Vim/Evil be removed for a more vanilla Emacs experience?]]
  - [[#when-should-and-shouldnt-i-use-bindoom][When should and shouldn't I use ~bin/doom~?]]
  - [[#when-to-run-doom-sync][When to run ~doom sync~]]
  - [[#how-to-suppress-confirmation-prompts-while-bindoom-is-running][How to suppress confirmation prompts while ~bin/doom~ is running]]
  - [[#which-terminal-should-i-use][Which terminal should I use?]]
  - [[#how-do-i-enable-lsp-support-for-insert-language-here][How do I enable LSP support for <insert language here>?]]
  - [[#how-to-disable-smartparensautomatic-parentheses-completion][How to disable smartparens/automatic parentheses completion?]]
  - [[#how-do-i-maximizefullscreen-emacs-on-startup][How do I maximize/fullscreen Emacs on startup?]]
  - [[#how-do-i-sharesync-my-config-between-multiple-computers][How do I share/sync my config between multiple computers?]]
- [[#package-management][Package Management]]
  - [[#how-do-i-install-a-package-from-elpa][How do I install a package from ELPA?]]
  - [[#how-do-i-install-a-package-from-githubanother-source][How do I install a package from github/another source?]]
  - [[#how-do-i-change-where-an-existing-package-is-installed-from][How do I change where an existing package is installed from?]]
  - [[#how-do-i-disable-a-package-completely][How do I disable a package completely?]]
  - [[#how-do-i-reconfigure-a-package-included-in-doom][How do I reconfigure a package included in Doom?]]
  - [[#where-does-straight-clonebuild-packages-to][Where does straight clone/build packages to?]]
- [[#defaults][Defaults]]
  - [[#why-ivy-over-helm][Why Ivy over Helm?]]
  - [[#why-are-there-no-default-keybinds-for-smartparens-for-evil-users][Why are there no default keybinds for Smartparens (for evil users)?]]
  - [[#why-do-non-evil-users-get-expand-region-but-not-evil-users][Why do non-evil users get expand-region, but not evil users?]]
  - [[#why-not-use-exec-path-from-shell-instead-of-doom-env][Why not use exec-path-from-shell instead of ~doom env~?]]
  - [[#why-wsbutler-over-delete-trailing-whitespace-or-whitespace-cleanup][Why wsbutler over delete-trailing-whitespace or whitespace-cleanup?]]
- [[#emacs-lisp][Emacs Lisp]]
  - [[#why-do-you-quote-some-symbols-with-symbol][Why do you quote some symbols with ~#'symbol~?]]
- [[#common-issues][Common Issues]]
  - [[#i-get-the-vanilla-emacs-splash-screen-at-startup][I get the vanilla Emacs splash screen at startup]]
  - [[#i-see-a-blank-scratch-buffer-at-startup][I see a blank scratch buffer at startup]]
  - [[#strange-or-incorrect-icons-are-displayed-everywhere][Strange (or incorrect) icons are displayed everywhere]]
  - [[#void-variable-and-void-function-errors-on-startup][~void-variable~ and ~void-function~ errors on startup]]
  - [[#doom-cant-find-my-executablesdoesnt-inherit-the-correct-path][Doom can't find my executables/doesn't inherit the correct ~PATH~]]
  - [[#theres-artefacting-on-my-icon-fonts-in-gui-emacs-956][There's artefacting on my icon fonts in GUI Emacs (#956)]]
  - [[#the-s-and-s-keys-dont-behave-like-they-do-in-vimevil-1307][The =s= and =S= keys don't behave like they do in vim/evil (#1307)]]
  - [[#changes-to-my-config-arent-taking-effect][Changes to my config aren't taking effect]]
  - [[#the-frame-goes-black-on-macos-while-in-full-screen-mode][The frame goes black on MacOS, while in full-screen mode]]
  - [[#doom-crashes-when][Doom crashes when...]]
  - [[#cant-load-my-theme-unable-to-find-theme-file-for-x-errors][Can't load my theme; ~unable to find theme file for X~ errors]]
  - [[#tramp-connections-hang-forever-when-connecting][TRAMP connections hang forever when connecting]]
  - [[#an-upstream-package-was-broken-and-i-cant-update-it][An upstream package was broken and I can't update it]]
  - [[#why-do-i-see-ugly-indentation-highlights-for-tabs][Why do I see ugly indentation highlights for tabs?]]
  - [[#clipetty--emit-opening-output-file-permission-denied-devpts29-error]["clipetty--emit: Opening output file: Permission denied, /dev/pts/29" error]]
  - [[#the-directory-emacsdserver-is-unsafe-error-at-startup]["The directory ~/.emacs.d/server is unsafe" error at startup]]
  - [[#my-new-keybinds-dont-work][My new keybinds don't work]]

* General
** Why is it called Doom?
It's an homage to idsoftware's classic game, whose [[https://github.com/id-Software/DOOM][source code]] was my first
exposure to programming, back in the Cretaceous period (1999).

Also, Emacs is an all consuming black hole. Its users doom themselves,
eternally.

** Is Doom a fork of Spacemacs/Prelude/etc?
No. I started it from scratch in mid-2014. I hadn't heard of other distros until
some years later, when a Doom user suggested this was a Spacemacs fork. I still
see this misconception pop up from time to time.

However, that's not to say Doom hasn't taken any inspiration from these since.
Early versions of Doom drew inspiration from prelude's project structure (until
Doom introduced a module system) and some concepts (like SPC as a leader key)
were adopted from Spacemacs or PRed from migrating users.

As our userbase grows, more similarities (and differences) will no doubt emerge.

** Does Doom work on Windows?
It does, /but/ there are caveats:

+ Emacs is inherently slower on Windows.
+ There are more steps to setting up Emacs (and Doom) on Windows.
+ Windows support will always lag behind macOS/Linux support, because I (and
  many of Doom's users) don't use Windows. That means fewer guinea p--I mean,
  pioneers, willing to test Doom on Windows.

That said, Doom does have happy Windows users (using WSL or scoop/chocolatey).
[[file:getting_started.org::On Windows][The Getting Starting guide]] will walk you through what we know.

Help us improve our documentation if you managed to get Doom running on Windows!

** Is Doom only for vimmers?
No, *vim/evil emulation is optional*. However, its maintainer /is/ a
dyed-in-the-wool vimmer with almost two decades of vim muscle memory, so the
non-vim experience will be less polished. Still, our growing user base of
non-vim users continue to improve the situation, and we welcome suggestions and
contributions!

If you'd like a go at it, see the [[file:../modules/editor/evil/README.org::Removing evil-mode][removing evil-mode]] section in the [[file:../modules/editor/evil/README.org][:editor evil]]
module's documentation.

** I am a beginner. Can I use Doom?
This isn't a choice I can make for you. How new is "new"? Are you new to the
shell? To programming in general? Or just Emacs/vim?

If all of the above is true then Emacs is a rough place to start. Doom or not.

Emacs' main draw is its unparalleled extensibility, but anything so extensible
has a learning curve. Not to suggest it's impossible -- and we'll try to help
you [[https://discord.gg/qvGgnVx][if you ask]] -- but expect a hefty commitment and a bumpy journey. Don't pass
up on the [[file:index.org][Documentation]]: it'll work you through setting Doom up and includes
links to external resources created by myself or the community.

** How does Doom compare to Spacemacs?
To paraphrase (and expand upon) a [[https://www.reddit.com/r/emacs/comments/6pa0oq/quickstart_tutorial_for_emacs_newbies_with_doom/dkp1bhd/][reddit answer]] to this question by [[https://github.com/gilbertw1][@gilbertw1]]:

+ *Doom is lighter than Spacemacs.* Doom starts up faster and is better
  optimized, but Spacemacs has more features.
+ *Doom is thinner than Spacemacs.* There are fewer abstractions between you and
  vanilla Emacs, and what abstractions do exist are thin by design. This means
  there's less to understand and it's easier to hack.
+ *Doom is much more opinionated than Spacemacs.* Doom does not strive to be a
  one-size-fits-all, beginner-friendly solution, nor is it configured by
  consensus. It is [mostly] the work of one developer and caters to his
  vim-slanted tastes. Doom's defaults enforce very particular (albeit optional)
  workflows.
+ *Doom lacks manpower.* Bugs stick around longer, documentation is lighter and
  development is at the mercy of it's maintainer's schedule, health and whims.
+ *Doom is not beginner friendly.* Doom lacks a large community to constantly
  improve and produce tutorials/guides for it. Spacemacs is more likely to work
  right out of the box. Doom also holds your hand less. A little elisp, shell
  and git-fu will go a long way to ease you into Doom.
+ *Doom is managed through it's command line interface.* The ~bin/doom~ script
  allows you to script package management, manage your config, or utilize elisp
  functionality externally, like org tangling or batch processing.
+ *Doom's package manager is declarative and rolling release is opt-in.* Doom
  takes a little after nix, striving for as much config reproducibility as Emacs
  (and git) will permit. Spacemacs uses package.el, which is only rolling
  release.

** Why such a complicated package management system?
Doom had +four+ *five* goals for its package management system:

1. *Scriptability:* package management should be shell-scriptable, so updating
   can be automated.
2. *Reach:* allow users to install packages from sources other than ELPA (like
   github or gitlab), and from specific commits, branches or tags. Some plugins
   are out-of-date through official channels, have changed hands, have a
   superior fork, or aren't available in ELPA repos.
3. *Performance:* lazy-loading the package management system is a tremendous
   boon to start up speed. Initializing package.el and straight (and/or checking
   that your packages are installed) or loading package autoloads files each
   time you start up is expensive.
4. *Organization:* an Emacs configuration grows so quickly, in complexity and
   size. A clear separation of concerns (configuration of packages from their
   installation) is easier to manage.
5. *Reproducibility:* Emacs is a tumultuous ecosystem; packages break left and
   right, and we rely on hundreds of them. By pinning our packages we achieve a
   degree of (optional) config reproducibility and significantly limit the
   damage upstream changes can do. Better yet, we stave off having to deal with
   those issues until we are ready to. Although technical limitations prevent us
   from achieving true reproducibility, this is better than nothing.

** How does Doom start up so quickly?
Doom employs a number of techniques to cut down startup time. Here are its most
effective techniques:

*** Avoid garbage collection at startup
The GC can easily double startup time, so we suppress it at startup by turning
up ~gc-cons-threshold~ (and perhaps ~gc-cons-percentage~) temporarily:

#+BEGIN_SRC emacs-lisp
(setq gc-cons-threshold most-positive-fixnum ; 2^61 bytes
      gc-cons-percentage 0.6)

;; ... your emacs config here ...
#+END_SRC

However, it is important to reset it eventually. Not doing so will cause garbage
collection freezes during long-term interactive use. Conversely, a
~gc-cons-threshold~ that is too small will cause stuttering. We use 16mb as our
default.

#+BEGIN_SRC emacs-lisp
(add-hook 'emacs-startup-hook
  (lambda ()
    (setq gc-cons-threshold 16777216 ; 16mb
          gc-cons-percentage 0.1)))
#+END_SRC

It may also be wise to raise ~gc-cons-threshold~ while the minibuffer is active,
so the GC doesn't slow down expensive commands (or completion frameworks, like
helm and ivy). Here is how Doom does it:

#+BEGIN_SRC emacs-lisp
(defun doom-defer-garbage-collection-h ()
  (setq gc-cons-threshold most-positive-fixnum))

(defun doom-restore-garbage-collection-h ()
  ;; Defer it so that commands launched immediately after will enjoy the
  ;; benefits.
  (run-at-time
   1 nil (lambda () (setq gc-cons-threshold doom-gc-cons-threshold))))

(add-hook 'minibuffer-setup-hook #'doom-defer-garbage-collection-h)
(add-hook 'minibuffer-exit-hook #'doom-restore-garbage-collection-h)
#+END_SRC

Another alternative (which is [[https://github.com/hlissner/doom-emacs/blob/develop/core/core.el#L269-L274][what Doom uses]]) is the [[https://gitlab.com/koral/gcmh/][gcmh]] package; which staves
off the GC until you are idle. Doom also triggers GC when you unfocus the Emacs
frame.

*** Concatenate package autoloads
When you install a package, a PACKAGE-autoloads.el file is generated. This file
maps autoloaded functions and snippets to their containing package so Emacs will
know where to find them when they are used. In your conventional Emacs config,
every one of these autoloads files are loaded immediately at startup (when
~package-initialize~ is called).

Since you'll commonly have hundreds of packages, loading hundreds of autoloads
file can hurt startup times, especially without an SSD. We get around this by
concatenating these files into one giant one when you run ~doom sync~.

Emacs 27+ introduces a ~package-quickstart~ command that does this for you, and
=straight= (which powers our package manager) does this for you too, but [[https://github.com/hlissner/doom-emacs/tree/develop/core/cli/autoloads.el][Doom
Emacs has its own specialized mechanism]] for this, topped off with a few
Doom-specific optimizations.

*** Lazy load package management system(s)
Initializing package.el or straight.el at startup is expensive. We can save some
time by delaying that initialization until we actually need these libraries (and
load them only when we're doing package management, e.g. when we run ~doom
sync~).

Among other things, ~doom sync~ does a lot for us. It generates concatenated
autoloads files; caches expensive variables like caches ~load-path~,
~Info-directory-list~ and ~auto-mode-alist~; and preforms all your package
management activities there -- far away from your interactive sessions.

How exactly Doom accomplishes all this is a long story, so here is a boiled-down
version you can use in your own configs (for package.el, not straight.el):

#+BEGIN_SRC emacs-lisp
(defvar cache-file "~/.emacs.d/cache/autoloads")

(defun initialize ()
  (unless (load cache-file t t)
    (setq package-activated-list nil)
    (package-initialize)
    (with-temp-buffer
      (cl-pushnew doom-core-dir load-path :test #'string=)
      (dolist (desc (delq nil (mapcar #'cdr package-alist)))
        (let ((load-file-name (concat (package--autoloads-file-name desc) ".el")))
          (when (file-readable-p load-file-name)
            (condition-case _
                (while t (insert (read (current-buffer))))
              (end-of-file)))))
      (prin1 `(setq load-path ',load-path
                    auto-mode-alist ',auto-mode-alist
                    Info-directory-list ',Info-directory-list)
             (current-buffer))
      (write-file (concat cache-file ".el"))
      (byte-compile-file cache-file))))

(initialize)
#+END_SRC

You'll need to delete ~cache-files~ any time you install, remove, or update a
new package. You could advise ~package-install~ and ~package-delete~ to call
~initialize~ when they succeed, or make ~initialize~ interactive and call it
manually when necessary. Up to you!

Note: package.el is sneaky, and will initialize itself if you're not careful.
*Not on my watch, criminal scum!*

#+BEGIN_SRC emacs-lisp
;; in ~/.emacs.d/init.el (or ~/.emacs.d/early-init.el in Emacs 27)
(setq package-enable-at-startup nil ; don't auto-initialize!
      ;; don't add that `custom-set-variables' block to my init.el!
      package--init-file-ensured t)
#+END_SRC

*** Lazy load more than everything
~use-package~ can defer your packages. Using it is a no-brainer, but Doom goes a
step further. There are some massive plugins out there for which ordinary lazy
loading techniques don't work. To name a few:

+ The =lang/org= module defers loading babel packages until their src blocks are
  executed or read. You no longer need ~org-babel-do-load-languages~ in your
  config -- in fact, you shouldn't use it at all!
+ =org-protocol= needs to be loaded to intercept requests for org-protocol://
  URLs. Since org-protocol depends on org, this can be expensive to load
  yourself, so Doom loads as soon as a org-protocol:// request is received, just
  before it is processed.
+ Company and yasnippet are loaded as late as possible (waiting until the user
  opens a non-read-only, file-visiting buffer (that isn't in fundamental-mode)).
+ The =evil-easymotion= package binds many keys, none of which are available
  until you load the package. Instead of loading it at startup, =gs= is bound to
  a command that loads the package, populates =gs=, then simulates the =gs= key
  press as though those new keys had always been there.

In addition, Doom loads some packages "incrementally". i.e. after a few seconds
of idle time post-startup, Doom loads packages piecemeal (one dependency at a
time) while Emacs. It aborts if it detects input, as to make the process as
subtle as possible.

For example, instead of loading =org= (a giant package), it will load these
dependencies, one at a time, before finally loading =org=:

#+BEGIN_SRC elisp
(calendar find-func format-spec org-macs org-compat org-faces
 org-entities org-list org-pcomplete org-src org-footnote
 org-macro ob org org-agenda org-capture)
#+END_SRC

This ensures packages load as quickly as possible when you first load an org
file.

*** Unset ~file-name-handler-alist~ temporarily
Emacs consults this variable every time a file is read or library loaded, or
when certain functions in the file API are used (like ~expand-file-name~ or
~file-truename~).

Emacs does this to check if a special handler is needed to read that file, but
none of them are (typically) necessary at startup, so we disable them
(temporarily!):

#+BEGIN_SRC emacs-lisp
(defvar doom--file-name-handler-alist file-name-handler-alist)
(setq file-name-handler-alist nil)

;; ... your whole emacs config here ...

;; Then restore it later:
(setq file-name-handler-alist doom--file-name-handler-alist)

;; Alternatively, restore it even later:
(add-hook 'emacs-startup-hook
  (lambda ()
    (setq file-name-handler-alist doom--file-name-handler-alist)))
#+END_SRC

Don't forget to restore ~file-name-handler-alist~, otherwise TRAMP won't work
and compressed/encrypted files won't open.

*** Use [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html][lexical-binding]] everywhere
Add ~;; -*- lexical-binding: t; -*-~ to the top of your elisp files. This can
break code if you've written it to depend on undeclared dynamic variables, but
I've designed Doom not to.

This buys a small improvement in performance, but every little bit helps. You'll
find more about it in:

+ [[http://nullprogram.com/blog/2017/01/30/]["How to Write Fast(er) Emacs Lisp."]]
+ [[http://nullprogram.com/blog/2016/12/22/]["Some Performance Advantages of Lexical Scope."]]

** Why is startup time important? Why not use the daemon?
It /isn't/ terribly important, but I believe a) faster software is a better user
experience, b) Emacs doesn't have to be slower than it needs to be, and c) we
shouldn't have to manage yet-another-tool simply to get sane startup times out
of Emacs.

A fast startup time also facilitates:

- Emacs as a viable alternative to vim for quick, one-shot editing in the
  terminal (without ~-Q~).
- Running multiple, independent instances of Emacs (e.g. on a per-project basis,
  or for nix-shell users, or to isolate one instance for IRC from an instance
  for writing code, etc).
- Quicker restarting of Emacs, to reload package settings or recover from
  disastrous errors which can leave Emacs in a broken state.
- Faster integration with "edit in Emacs" solutions (like [[https://github.com/alpha22jp/atomic-chrome][atomic-chrome]]), and
  without a daemon.

It's up to you to decide if these are good enough reasons not to use a daemon,
but it's nice to have more options, isn't it?

** How do I use Doom alongside other Emacs configs?
I recommend [[https://github.com/plexus/chemacs][Chemacs]]. Think of it as a bootloader for Emacs. You'll [[file:getting_started.org::*Alongside other Emacs configs (with Chemacs)][find
instructions on how to use it with Doom in the user manual]].

You will need a separate folder for personal configuration (=~/.doom.d= or
=~/.config/doom= by default). Use the ~DOOMDIR~ environment variable to use
another location:

#+BEGIN_SRC bash
# First install Doom somewhere
git clone https://github.com/hlissner/doom-emacs ~/fakehome/doom-emacs
# Then create a place to store our private doom configs. The bin/doom script
# recognizes the DOOMDIR environment variable.
export DOOMDIR=~/fakehome/doom-emacs-config
mkdir -p "$DOOMDIR"

# Set up Doom for the first time; this may take a while
cd ~/fakehome/doom-emacs
bin/doom install

# then launch Doom Emacs from this folder with:
bin/doom run
#+END_SRC

#+begin_quote
Warning: the way ~bin/doom run~ starts Doom bypasses many of its startup
optimizations. Treat it as a convenience for testing rather than a permanent
entry point.
#+end_quote

** Why should I use Doom instead of rolling my own config?
Two reasons:

1. *Doom's package manager.* It's powered by straight.el, is declarative,
   non-rolling release and (nominally) reproducible; which is unique on the Emacs
   distro scene. Don't let upstream issues surprise you. Roll back or re-pin
   packages when you don't have the time to deal with issues.

   It also integrates with command line workflows, so automate to your heart's
   content!

2. *Time.* If you care about personalizing the software you use on a daily
   basis, even half as much as I do, then you need professional help, but you
   also know it is time consuming. Emacs out-of-the-box is a wasteland of
   archaic defaults, full of plugins rife with gotchas and oddities that may or
   may not be abandonware. It will be an uphill battle. Let Doom deal with all
   that noise. Save yourself some time.

   Time you could otherwise spend attending your daughter's dance recitals, that
   baseball game your son's team almost won last Thursday, or answering the court
   summons to fight for custody of your kids.

Also, Doom's fast yo.

** What is the meaning behind Doom's naming convention in its source code?
You'll find [[file:contributing.org::*Conventions][an overview of Doom's code conventions]] in the [[file:contributing.org][contributing guide]].

** What version of Doom am I running?
The current version of Doom is displayed in the modeline on the dashboard. It
can also be retrieved using ~M-x doom/version~ (bound to =SPC h d v= or =C-h d
v= by default) or ~bin/doom version~ on the command line.

** Is Discord the only option for interacting with your community?
Yes. Discord is already woven into my social and work life, and was selected to
maximize my availability to the community. I don't want to juggle multiple
platforms (like Matrix, IRC or Slack), or add bridges for them, even if they are
better suited to the task. I already have my hands full managing the one.

I /am/ considering a [[https://www.discourse.org][discourse]], so we have a public knowledge base of workflows
and inter-user support (since Discord isn't a great archive), but it will be
some time until this is set up.

Email is a possible alternative, but is constantly swamped; expect a turn-around
time of weeks.

** Why is Emacs/Doom slow?
This comes up often. The first thing folks fresh off the boat from other editors
will notice is that Emacs has a low threshold for performance issues. It doesn't
take much to get it to scroll like molasses.

Retina/4K/high res users have it especially hard. MacOS users too, where Emacs
seem even slower. Add to that files that are large (perhaps 1mb+) or have long
lines (200 characters+) and we've got ourselves a really poor experience. And
that's before we factor in plugins and poorly optimized major modes.

There is an unfortunate but necessary adjustment of expectations new users must
undergo, when they adopt Emacs. Doom has inherited this curse. Its raison d'etre
is to improve the situation, but I can only go so far, especially if you choose
to enable all the most expensive features. You will unavoidably find cases where
Emacs *is just slow*.

What can you do about it?

1. Upgrade to Emacs 27. This should yield a noteworthy gain in general
   performance, particularly for LSP users.
2. Try out [[http://akrl.sdf.org/gccemacs.html][gccemacs]], which promises significant strides in Emacs performance,
   but can be a bit of a hassle to set up. There are packages available for
   [[https://aur.archlinux.org/packages/emacs-native-comp-git/][Arch Linux]], [[https://github.com/flatwhatson/guix-channel][Guix]] and [[https://github.com/nix-community/emacs-overlay][Nix users]]. [[https://www.emacswiki.org/emacs/GccEmacs][More information available on EmacsWiki]].
3. Disable some of Doom's slowest modules. The biggest offenders tend to be:
   =:ui tabs=, =:ui indent-guides=, =:ui ligatures=, =:editor word-wrap= and =:ui
   vc-gutter=.
4. Turn off line numbers ~(setq display-line-numbers-type nil)~. It's known to
   slow down scrolling, in particular.
5. Org users can turn off ~org-superstar-mode~: ~(remove-hook 'org-mode-hook
   #'org-superstar-mode)~. It's an aesthetic plugin that offers fancier bullets.
   Emacs seems to struggle to display those characters with some fonts.

   Org uses can also turn off the rest of org's eye candy:
   #+BEGIN_SRC elisp
   (after! org
     (setq org-fontify-quote-and-verse-blocks nil
           org-fontify-whole-heading-line nil
           org-hide-leading-stars nil
           org-startup-indented nil))
   #+END_SRC
6. Turn on =M-x so-long-minor-mode=. This is a minor mode that disables
   non-essential functionality and can be used to temporarily view files that
   would be too slow otherwise. =M-x so-long-mode= is its extreme version; it
   turns off /everything/, including syntax highlighting.
7. Try replacing the =:ui modeline= module with =:ui (modeline +light)=. There
   are aspects of the default modeline that can be unpredictably slow.
8. Don't mash =j= (or =C-n=) to scroll. Evil users can scroll long distances
   with =C-d= and =C-u=, for instance, or evil-easymotion under =gs=, to avoid
   that slowness. Otherwise, use search mechanisms to move around, like isearch
   (=C-s=) or evil-search (=/=).

* Configuration
** How do I configure Doom Emacs?
Canonically, your private config is kept in =~/.doom.d/= (or =~/.config/doom/=).
This directory is referred to as your ~$DOOMDIR~.

Your private config is typically comprised of an =init.el=, =config.el= and
=packages.el= file. Put all your config in =config.el=, install packages by
adding ~package!~ declarations to =packages.el=, and enable/disable modules in
your ~doom!~ block, which should have been created in your =init.el= when you
first ran ~doom install~.

You shouldn't need to fork Doom or modify =~/.emacs.d=. If you have to do this
to achieve something, it can be considered a bug.

Check out the [[file:getting_started.org::Customize][Customize section]] in the [[file:getting_started.org][Getting Started]] guide for details.

** Does Doom respect XDG directory conventions
Yes. Your private config (normally in =~/.doom.d=) can be moved to
=~/.config/doom=.

And as of Emacs 27, =~/.emacs.d= can be moved to =~/.config/emacs=.

** How do I enable or disable a Doom module?
Comment or uncomment the module in your ~doom!~ block, found in
=~/.doom.d/init.el=.

Remember to run ~bin/doom sync~ afterwards, on the command line, to sync your
module list with Doom.

See the "[[file:getting_started.org::*Configuration modules][Configuration modules]]" section of the [[file:getting_started.org][Getting Started]] guide for more
information.

** How do I change the theme?
There are two ways to load a theme. Both assume the theme is installed and
available. You can either set ~doom-theme~ or manually load a theme with the
~load-theme~ function.

#+BEGIN_SRC emacs-lisp
;;; add to ~/.doom.d/config.el
(setq doom-theme 'doom-tomorrow-night)
;; or
(load-theme 'doom-tomorrow-night t)
#+END_SRC

#+begin_quote
At the moment, the only difference between the two is that ~doom-theme~ is
loaded when Emacs has finished initializing at startup and ~load-theme~ loads
the theme immediately. Which you choose depends on your needs, but I recommend
setting ~doom-theme~ because, if I later discover a better way to load themes, I
can easily change how Doom uses ~doom-theme~, but I can't (easily) control how
you use the ~load-theme~ function.
#+end_quote

*** Installing a third party theme
To install a theme from a third party plugin, say, [[https://github.com/bbatsov/solarized-emacs][solarized]], you need only
install it, then load it:

#+BEGIN_SRC emacs-lisp
;;; add to ~/.doom.d/packages.el
(package! solarized-theme)

;;; add to ~/.doom.d/config.el
(setq doom-theme 'solarized-dark)
#+END_SRC

Don't forget to run ~doom sync~ after adding that ~package!~ statement to ensure
the package is installed.

** How do I change the fonts?
Doom exposes five (optional) variables for controlling fonts in Doom, they are:

+ ~doom-font~
+ ~doom-variable-pitch-font~
+ ~doom-serif-font~
+ ~doom-unicode-font~ (the fallback font for unicode symbols that your default
  font doesn't support)
+ ~doom-big-font~ (used for ~doom-big-font-mode~)

They all accept either a =font-spec=, font string (="Input Mono-12"=), or [[https://wiki.archlinux.org/index.php/X_Logical_Font_Description][xlfd
font string]].

e.g.
#+BEGIN_SRC emacs-lisp
;;; Add to ~/.doom.d/config.el
(setq doom-font (font-spec :family "Input Mono Narrow" :size 12 :weight 'semi-light)
      doom-variable-pitch-font (font-spec :family "Fira Sans") ; inherits `doom-font''s :size
      doom-unicode-font (font-spec :family "Input Mono Narrow" :size 12)
      doom-big-font (font-spec :family "Fira Mono" :size 19))
#+END_SRC

** How do I bind my own keys (or change existing ones)?
There are many options. Emacs provides a number of keybind functions:

+ ~define-key KEYMAP KEY DEF~
+ ~global-set-key KEY DEF~
+ ~local-set-key KEY DEF~
+ ~evil-define-key STATES KEYMAP KEY DEF &rest ...~

However, Doom provides a ~map!~ macro, which conveniently wraps up the above
four into a more succinct syntax. Comprehensive examples of ~map!~'s usage can
be found in its documentation (via =SPC h f map\!= or =C-h f map\!= -- or [[file:api.org][in
docs/api]]).

There are also live examples ~map!~'s usage in [[file:../modules/config/default/+evil-bindings.el][config/default/+evil-bindings.el]].

** How do I get motions to treat underscores as word delimiters?
(This explanation comes from [[https://github.com/emacs-evil/evil#underscore-_-is-not-a-word-character][emacs-evil/evil]]'s readme)

An underscore "_" is a word character in Vim. This means that word-motions like
=w= skip over underlines in a sequence of letters as if it was a letter itself.
In contrast, in Evil the underscore is often a non-word character like
operators, e.g. =+=.

The reason is that Evil uses Emacs' definition of a word and this definition
does not often include the underscore. Word characters in Emacs are determined
by the syntax-class of the buffer. The syntax-class usually depends on the
major-mode of this buffer. This has the advantage that the definition of a
"word" may be adapted to the particular type of document being edited. Evil uses
Emacs' definition and does not simply use Vim's definition in order to be
consistent with other Emacs functions. For example, word characters are exactly
those characters that are matched by the regular expression character class
~[:word:]~.

If you want the underscore to be recognized as word character, you can modify
its entry in the syntax-table:

#+BEGIN_SRC emacs-lisp
(modify-syntax-entry ?_ "w")
#+END_SRC

This gives the underscore the word syntax-class. You can use a mode-hook to
modify the syntax-table in all buffers of some mode, e.g.:

#+BEGIN_SRC emacs-lisp
;; For python
(add-hook! 'python-mode-hook (modify-syntax-entry ?_ "w"))
;; For ruby
(add-hook! 'ruby-mode-hook (modify-syntax-entry ?_ "w"))
;; For Javascript
(add-hook! 'js2-mode-hook (modify-syntax-entry ?_ "w"))
#+END_SRC

** How do I change the leader/localleader keys?
These variables control what key to use for leader and localleader keys:

+ For Evil users:
  + ~doom-leader-key~ (default: =SPC=)
  + ~doom-localleader-key~ (default: =SPC m=)
+ For Emacs and Insert state (evil users), and non-evil users:
  + ~doom-leader-alt-key~ (default: =M-SPC= for evil users, =C-c= otherwise)
  + ~doom-localleader-alt-key~ (default: =M-SPC m= for evil users, =C-c l=
    otherwise)

e.g.
#+BEGIN_SRC emacs-lisp
;;; add to ~/.doom.d/config.el
(setq doom-leader-key ","
      doom-localleader-key "\\")
#+END_SRC

** How do I change the style of line-numbers (or disable them altogether)?
Doom uses the ~display-line-numbers~ package, which is built into Emacs 26+.

*** Disabling line numbers entirely
#+BEGIN_SRC elisp
;;; add to ~/.doom.d/config.el
(setq display-line-numbers-type nil)
;; or
(remove-hook! '(prog-mode-hook text-mode-hook conf-mode-hook)
              #'display-line-numbers-mode)
#+END_SRC

*** Switching to relative line numbers (permanently)
To change the style of line numbers, change the value of the
~display-line-numbers-type~ variable. It accepts the following values:

#+begin_example
t            normal line numbers
'relative    relative line numbers
'visual      relative line numbers in screen space
nil          no line numbers
#+end_example

For example:

#+BEGIN_SRC elisp
;;; add to ~/.doom.d/config.el
(setq display-line-numbers-type 'relative)
#+END_SRC

You'll find more precise documentation on the variable through =<help> v
display-line-numbers-type= (=<help>= is =SPC h= for evil users, =C-h=
otherwise).

*** Switching the style of line numbers (temporarily)
Use ~M-x doom/toggle-line-numbers~ (bound to =SPC t l= by default) to cycle
through the available line number styles in the current buffer.

e.g. =normal -> relative -> visual -> disabled -> normal=.

** How do I change the behavior and appearance of popup windows?
The =:ui popup= module tries to standardize how Emacs handles "temporary"
windows. It includes a set of default rules that tell Emacs where to open them
(and how big they should be).

Check out the [[file:../modules/ui/popup/README.org::Configuration][:ui popup module's documentation]] for more on defining your own
rules.

You'll find more comprehensive documentation on ~set-popup-rule!~ in its
docstring (available through =SPC h f= -- or =C-h f= for non-evil users).

** How do I customize a theme or face(s)?
Doom provides the ~custom-set-faces!~ and ~custom-theme-set-faces!~ macros as a
convenience.

See =SPC h f custom-set-faces\!= (or =C-h f custom-set-faces\!=) for
documentation on and examples of its use.

#+begin_quote
Other sources may recommend ~M-x customize~, ~M-x customize-themes~ or ~M-x
customize-face~. *Do not use these commands.* Doom does not support them and
their settings could break any time.
#+end_quote

** How do I make a new theme?
Doom will look for themes in =~/.doom.d/themes/= (determined by
~custom-theme-directory~).

Its filename must take the format =XYZ-theme.el=, where =XYZ= is the theme's
name declared in that theme's ~deftheme~ or ~def-doom-theme~ call. The theme can
then be loaded with:

#+BEGIN_SRC elisp
;; add to ~/.doom.d/config.el
(setq doom-theme 'XYZ)

;; or

(load-theme 'XYZ t)
#+END_SRC

** Can Doom be customized without restarting Emacs?
Short answer: You can, but you shouldn't.

Long answer: Restarting Emacs is always your safest bet, but Doom provides a few
tools for experienced Emacs users to skirt around it (most of the time):

- Evaluate your changes on-the-fly with ~+eval/region~ (bound to the =gr=
  operator for evil users) or ~eval-last-sexp~ (bound to =C-x C-e=). Changes
  take effect immediately.
- On-the-fly evaluation won't work for all changes. e.g. Changing your ~doom!~
  block (i.e. the list of modules for Doom to enable).

  But rather than running ~doom sync~ and restarting Emacs, Doom provides ~M-x
  doom/reload~ for your convenience (bound to =SPC h r r= and =C-h r r=). This
  runs ~doom sync~, restarts the Doom initialization process and re-evaluates
  your personal config. However, this won't clear pre-existing state; Doom won't
  unload modules/packages that have already been loaded and it can't anticipate
  complications arising from your private config.
- You can quickly restart Emacs and restore the last session with
  ~doom/restart-and-restore~ (bound to =SPC q r=).

** Can Vim/Evil be removed for a more vanilla Emacs experience?
Yes! See the [[file:../modules/editor/evil/README.org::Removing evil-mode][Removing evil-mode]] section in [[file:../modules/editor/evil/README.org][:editor evil]]'s documentation.

** When should and shouldn't I use ~bin/doom~?
~bin/doom~ is your best friend. It'll keep all your secrets (mostly because it's
a shell script incapable of sentience and thus incapable of retaining, much less
divulging, your secrets to others).

You can run ~bin/doom help~ to see what it's capable of, but here are some
commands that you may find particularly useful:

+ ~doom doctor~ :: Diagnose common issues in your environment and list missing
  external dependencies for your enabled modules.
+ ~doom sync~ :: Ensures that all missing packages are installed, orphaned
  packages are removed, and metadata properly generated.
+ ~doom install~ :: Install any missing packages.
+ ~doom update~ :: Update all packages that Doom's (enabled) modules use.
+ ~doom env~ :: Regenerates your envvar file, which contains a snapshot of your
  shell environment for Doom Emacs to load on startup. You need to run this for
  changes to your shell environment to take effect.
+ ~doom purge -g~ :: Purge orphaned packages (i.e. ones that aren't needed
  anymore) and regraft your repos.
+ ~doom upgrade~ :: Upgrade Doom to the latest version (then update your
  packages). This is equivalent to:

  #+BEGIN_SRC bash
  git pull
  doom sync
  doom update
  #+END_SRC

** When to run ~doom sync~
As a rule of thumb you should run ~doom sync~ whenever you:

+ Update Doom with ~git pull~ instead of ~doom upgrade~,
+ Change your ~doom!~ block in =$DOOMDIR/init.el=,
+ Change autoload files in any module (or =$DOOMDIR=),
+ Or change the packages.el file in any module (or =$DOOMDIR=).
+ Install an Emacs package or dependency outside of Emacs (i.e. through your OS
  package manager).

If anything is misbehaving, it's a good idea to run ~doom sync~ first. ~doom
sync~ is responsible for regenerating your autoloads file (which tells Doom
where to find lazy-loaded functions and libraries), installing missing packages,
and uninstall orphaned (unneeded) packages.

** How to suppress confirmation prompts while ~bin/doom~ is running
The ~-y~ and ~--yes~ flags (or the ~YES~ environment variable) will force
~bin/doom~ to auto-accept confirmation prompts:

#+BEGIN_SRC bash
doom -y update
doom --yes update
YES=1 doom update
#+END_SRC

** Which terminal should I use?
Looking for a terminal in Emacs? Doom offers four modules:

+ =:term eshell=
+ =:term shell=,
+ =:term term=
+ =:term vterm=.

But which do you choose?

+ =eshell= is a shell completely implemented in Emacs Lisp. It's stable, works
  anywhere Emacs runs (on any OS) and has no external dependencies, /but/ lacks
  features you'll expect from mature shells, tends to be slower than them, and
  does not support command line tools with TUIs (e.g. curses, ncdu, nmtui, top,
  etc).
+ =shell= is a shell /for/ your shell. Think of it like a REPL for bash/zsh,
  rather than a terminal emulator. Due to its simplicity, you're less likely to
  encounter edge cases (e.g. against your shell config), but it has the smallest
  feature set. It also won't work with TUI programs like htop or vim.
+ =term= is Emacs' built-in terminal emulator. Term runs a shell and understand
  many (but not all) terminal escape codes, so many TUI programs (like top or
  vim) will work. However, term's performance is inferior to standalone
  terminals, especially with large bursts of output.
+ =vterm= is as good as terminal emulation gets in Emacs (at the time of
  writing), and is the most performant, as it is an external library written
  in C. However, it requires extra steps to set up. a) Emacs must be built with
  dynamic modules support and b) you'll need to compile vterm-module.so, which
  has external dependencies (libvterm). It is automatically built when you first
  open =vterm=, but this will fail on Windows, NixOS and Guix out of the box.
  Except for Windows, you'll find install instructions for nix/guix in [[file:../modules/term/vterm/README.org][the :term
  vterm module's documentation]].

For a terminal in Emacs, =eshell= and =vterm= are generally the best options.

** How do I enable LSP support for <insert language here>?
Doom supports LSP, but it is not enabled by default. To enable it, you must:

1. Enable the =:tools lsp= module,
2. Enable the =+lsp= flag for the appropriate modules you want LSP support for
   (e.g. =:lang (python +lsp)= or =:lang (rust +lsp)=),
3. Install the prerequisite LSP servers through your package manager or other
   means. You can find a list of supported servers on [[https://github.com/emacs-lsp/lsp-mode#supported-languages][the lsp-mode project page]].
4. Run ~doom sync~ on the command line and restart Emacs.

Some language modules may lack LSP support (either because it hasn't been
implemented yet or I'm not aware of it yet -- let us know!). To enable LSP for
these languages, add this to =$DOOMDIR/config.el=:

#+BEGIN_SRC elisp
(add-hook 'MAJOR-MODE-local-vars-hook #'lsp!)
;; Where =MAJOR-MODE= is the major mode you're targeting. e.g.
;; lisp-mode-local-vars-hook
#+END_SRC
** How to disable smartparens/automatic parentheses completion?
Some outdated sources may tell you to do this, *but it is no longer correct*:

#+BEGIN_SRC elisp
(after! smartparens
  (smartparens-global-mode -1))
#+END_SRC

Instead, use the following:
#+BEGIN_SRC elisp
(remove-hook 'doom-first-buffer-hook #'smartparens-global-mode)
#+END_SRC

Note that the package itself cannot be disabled with ~package!~, because it is a
core package. This may change one day, but not in the near future.
** How do I maximize/fullscreen Emacs on startup?
#+BEGIN_SRC elisp
(add-to-list 'initial-frame-alist '(fullscreen . maximized))
#+END_SRC

Some window managers may not understand/work with =maximized= (or may not
produce the desired effect), in that case try ~fullboth~ or ~fullscreen~.

** How do I share/sync my config between multiple computers?
TL;DR: it is perfectly safe to sync =~/.doom.d=, but not =~/.emacs.d=.

Long answer: =~/.emacs.d/.local= can contain baked-in absolute paths and
non-portable byte-code. It is never a good idea to sync it across multiple
computers.

If you must, for some reason, copy =~/.emacs.d= from one system to another,
remember to run ~doom sync && doom build~ on the target machine.

* Package Management
** How do I install a package from ELPA?
See the "[[file:getting_started.org::*Installing packages][Installing packages]]" section of the [[file:getting_started.org][Getting Started]] guide.

** How do I install a package from github/another source?
See the "[[file:getting_started.org::*Installing packages from external sources][Installing packages from external sources]]" section of the [[file:getting_started.org][Getting
Started]] guide.

** How do I change where an existing package is installed from?
See the "[[file:getting_started.org::*Changing a recipe for a included package][Changing a recipe for a included package]]" section of the [[file:getting_started.org][Getting
Started]] guide.

** How do I disable a package completely?
See the "[[file:getting_started.org::*Disabling packages][disabling packages]]" section of the [[file:getting_started.org][Getting Started]] guide.

** How do I reconfigure a package included in Doom?
See the "[[file:getting_started.org::*Configuring packages][configuring packages]]" section of the Getting Started guide.

** Where does straight clone/build packages to?
Doom has configured straight to clone packages to
=~/.emacs.d/.local/straight/repos/REPO-NAME=. It then builds (byte-compiles and
symlinks) them to =~/.emacs.d/.local/straight/build/PACKAGE-NAME=.

* Defaults
** Why Ivy over Helm?
Short answer: ivy is simpler to maintain.

Long answer: Features and performance appear to be the main talking points when
comparing the two, but as far as I'm concerned they are equal in both respects
(not all across the board, but on average).

Instead, maintainability is most important for someone that frequently tinkers
with their editor. When I have an issue, I spend disproportionately more time
dealing helm than I do ivy, for little or no gain. Though both frameworks are
excellent, the difference in complexity is reflected in their plugin ecosystems;
ivy plugins tend to be lighter, simpler, more consistent and significantly
easier to hack if I want to change something. Unless you like helm /just/ the
way it is out of the box, ivy is just the simpler choice.

And since I dogfood it, Ivy's integration into Doom will always be a step or
three ahead of helm's.

** Why are there no default keybinds for Smartparens (for evil users)?
Doom only uses smartparens to manage pair "completion" (it does the job better
than electric-{pair,quote}-mode or the multitude of other pair-management
solutions in the Emacs ecosystem at the time of writing).

None of smartparen's commands have default keybinds for evil users because they
are redundant with motions and text-objects provided by evil/vim. If you
disagree, I recommend trying the =:editor lispy= or =:editor parinfer= modules.

** Why do non-evil users get expand-region, but not evil users?
~expand-region~ is redundant with and less precise than evil's text objects and
motions.

- There's a text object for every "step" of expansion that expand-region
  provides (and more). To select the word at point = =viw=, symbol at point =
  =vio=, line at point = =V=, the block at point (by indentation) = =vii=, the
  block at point (by braces) = =vib=, sentence at point = =vis=, paragraph =
  =vip=, and so on.
- Selection expansion can be emulated by using text objects consecutively: =viw=
  to select a word, followed by =io= to expand to a symbol, then =ib= expands to
  the surrounding brackets/parentheses, etc. There is no reverse of this
  however; you'd have to restart visual state.

The expand-region way dictates you start at some point and expand/contract until
you have what you want selected. The vim/evil way would rather you select
exactly what you want from the get go. In the rare event a text object fails
you, a combination of =o= (swaps your cursor between the two ends of the region)
and motion keys can adjust the ends of your selection.

#+BEGIN_QUOTE
There are also text objects for xml tags (=x=), C-style function arguments
(=a=), angle brackets, and single/double quotes.
#+END_QUOTE

This is certainly more to remember compared to a pair of expand and contract
commands, but text objects (and motions) are the bread and butter of vim's modal
editing paradigm. Vimmers will feel right at home. To everyone else: mastering
them will have a far-reaching effect on your productivity. I highly recommend
putting in the time to learn them.

Otherwise, it is trivial to install expand-region and binds keys to it yourself:

#+BEGIN_SRC elisp
;;; add to ~/.doom.d/packages.el
(package! expand-region)

;;; add to ~/.doom.d/config.el
(map! :nv "C-=" #'er/contract-region
      :nv "C-+" #'er/expand-region)
#+END_SRC

** Why not use exec-path-from-shell instead of ~doom env~?
The ~doom env~ approach is a faster and more reliable solution.

1. ~exec-path-from-shell~ must spawn (at least) one process at startup to scrape
   your shell environment. This can be slow depending on the user's shell
   configuration. A single program (like pyenv or nvm) or config framework (like
   oh-my-zsh) could undo Doom's startup optimizations in one fell swoop.

2. ~exec-path-from-shell~ takes a whitelist approach and captures only ~PATH~
   and ~MANPATH~ by default. You must be proactive in order to capture all the
   envvars relevant to your development environment and tools.

~doom env~ takes the blacklist approach and captures all of your shell
environment. This front loads the debugging process, which is nicer than dealing
with it later, while you're getting work done.

That said, if you still want ~exec-path-from-shell~, it is trivial to install
yourself:

#+BEGIN_SRC emacs-lisp
;;; add to ~/.doom.d/packages.el
(package! exec-path-from-shell)

;;; add to ~/.doom.d/config.el
(require 'exec-path-from-shell)
(when (display-graphic-p)
  (exec-path-from-shell-initialize))
#+END_SRC

** Why wsbutler over delete-trailing-whitespace or whitespace-cleanup?
TL;DR: =ws-butler= is less imposing.

Don't be that guy who PRs 99 whitespace adjustments around his one-line
contribution. Don't automate this aggressive behavior by attaching
~delete-trailing-whitespace~ (or ~whitespace-cleanup~) to ~before-save-hook~. If
you have rambunctious colleagues peppering trailing whitespace into your
project, you need to have a talk (with wiffle bats, preferably) rather than play
a passive-aggressive game of whack-a-mole.

Here at Doom Inc we believe that operations that mutate entire files (or worse,
projects) should not be automated. Rather, they should be invoked deliberately,
only when and where it is needed, by someone that is aware of the consequences.
This is where =ws-butler= comes in. It only cleans up whitespace /on the lines
you've touched/ *and* it leaves behind virtual whitespace (which is never
written to the file) so your cursor doesn't get thrown around in all that
cleanup work.

In any case, if you had used =ws-butler= from the beginning, trailing whitespace
and newlines would never be a problem!

* Emacs Lisp
** Why do you quote some symbols with ~#'symbol~?
~#'symbol~ is short for ~(function symbol)~, the same way ~'symbol~ is short for
~(quote symbol)~.

In elisp there is no /functional/ difference between the two syntaxes, but the
sharp-quote does hint to the byte-compiler that "this symbol refers to a
function", which it can perform additional checks on when the code is
byte-compiled.

My reason for using it is to make it explicit to readers how I intend (or
expect) the symbol to be used. No sharp-quote means I'm using the symbol as a
literal data value.

* Common Issues
** I get the vanilla Emacs splash screen at startup
The most common cause for this is a =~/.emacs= file. If it exists, Emacs will
read this file instead of the =~/.emacs.d= directory, ignoring Doom altogether.

If this isn't the case, try running ~bin/doom doctor~. It can detect a variety
of common issues and may give you some clues as to what is wrong.

** I see a blank scratch buffer at startup
This commonly means that Emacs can't find your private doom config (in
=~/.doom.d= or =~/.config/doom=). Make sure *only one of these two* folders
exist, and that it has an init.el file with a ~doom!~ block. Running ~doom
install~ will populate your private doom directory with the bare minimum you
need to get going.

If nothing else works, try running ~bin/doom doctor~. It can detect a variety of
common issues and may give you some clues as to what is wrong.

** Strange (or incorrect) icons are displayed everywhere
Many of Doom's UI modules use the =all-the-icons= plugin, which uses special
fonts to display icons. These fonts must be installed for them to work properly,
otherwise you'll get a bunch of squares and mismatched icons. When running ~doom
install~, you will be asked whether you want these installed for you or not.

If you did not accept or need to reinstall those fonts, MacOS and Linux users
can install them with ~M-x all-the-icons-install-fonts~. Windows users will need
to use this command to download the fonts somewhere, then they must install them
manually (e.g. by double-clicking each file in explorer).

** ~void-variable~ and ~void-function~ errors on startup
The most common culprit for these types of errors are:

1. An out-of-date autoloads file. Run ~doom sync~ to regenerate them.

   To avoid this issue, remember to run ~doom sync~ whenever you modify your
   ~doom!~ block in =~/.doom.d/init.el=, or add ~package!~ declarations to
   =~/.doom.d/packages.el=. Or if you modify =~/.emacs.d/.local= by hand, for
   whatever reason.

   See ~doom help sync~ for details on what this command does and when you
   should use it.

2. Emacs byte-code isn't forward compatible. If you've recently switched to a
   newer (or older) version of Emacs, you'll need to either reinstall or
   recompile your installed plugins. This can be done by:

   + Running ~doom build~,
   + Or deleting =~/.emacs.d/.local/straight= then running ~doom install~ (this
     will take a while).

** Doom can't find my executables/doesn't inherit the correct ~PATH~
The two most common causes for PATH issues in Doom are:

1. Your shell configuration doesn't configure ~PATH~ correctly. If ~which
   <PROGRAM>~ doesn't emit the path you expect on the command line then this is
   likely the case.

2. Your app launcher (rofi, albert, docky, dmenu, sxhkd, etc) is launching Emacs
   with the wrong shell, either because it defaults to a different shell from
   the one you use or the app launcher itself inherits the wrong environment
   because /it/ was launched from the wrong shell.

3. You're a Mac user launching Emacs from an Emacs.app bundle. MacOS launches
   these apps from an isolated environment.

As long as your shell is properly configured, there is a simple solution to
issues #1 and #3: generate an envvar file by running ~doom env~. This scrapes
your shell environment into a file that is loaded when Doom Emacs starts up.
Check out ~doom help env~ for details on how this works.

For issue #2, you'll need to investigate your launcher. [[https://discord.gg/qvGgnVx][Our Discord]] is a good
place to ask about it.

** There's artefacting on my icon fonts in GUI Emacs ([[https://github.com/hlissner/doom-emacs/issues/956][#956]])
Check your font rendering settings. Changing the RGBA order to "rgba" will often
fix this issue. See [[https://github.com/hlissner/doom-emacs/issues/956][#956]] for details.

** The =s= and =S= keys don't behave like they do in vim/evil ([[https://github.com/hlissner/doom-emacs/issues/1307][#1307]])
This is intentional. =s= and =S= have been replaced by the evil-snipe plugin,
which provides 2-character versions of the f/F motion keys, ala vim-seek or
vim-sneak.

These keys were changed because they are redundant with =cl= and =cc=
respectively (and the new behavior was deemed more useful).

If you still want to restore the old behavior, simply disable evil-snipe-mode:

#+BEGIN_SRC emacs-lisp
;; in ~/.doom.d/config.el
(after! evil-snipe
  (evil-snipe-mode -1))
#+END_SRC

** Changes to my config aren't taking effect
1. Make sure you don't have both =~/.doom.d= and =~/.config/doom= directories.
   Doom will ignore the former if the latter exists.

2. Remember to run ~doom sync~ when it is necessary. To get to know when,
   exactly, you should run this command, run ~doom help sync~.

If neither of these solve your issue, try ~bin/doom doctor~. It will detect a
variety of common issues, and may give you some clues as to what is wrong.

** The frame goes black on MacOS, while in full-screen mode
There are known issues with childframes and macOS's fullscreen mode. There is no
known fix for this. To work around it, you must either:

1. Avoid MacOS native fullscreen by maximizing Emacs instead,

2. Disable childframes (controlled by the =+childframe= flag on the modules that
   support it),

3. Install Emacs via the =emacs-mac= homebrew formula.

** Doom crashes when...
Here are a few common causes for random crashes:

+ On some systems (particularly MacOS), manipulating the fringes or window
  margins can cause Emacs to crash. This is most prominent in the Doom Dashboard
  (which tries to center its contents), in org-mode buffers (which uses
  ~org-indent-mode~ to create virtual indentation), or magit. There is currently
  no known fix for this, as it can't be reliably reproduced. Your best bet is to
  reinstall/rebuild Emacs or disable the errant plugins/modules. e.g.

  To disable org-indent-mode:

  #+BEGIN_SRC emacs-lisp
  (after! org
    (setq org-startup-indented nil))
  #+END_SRC

  Or disable the =:ui doom-dashboard= & =:tools magit= modules (see [[https://github.com/hlissner/doom-emacs/issues/1170][#1170]]).
+ Ligatures and some fonts can cause Emacs to crash. You may want to try a
  different font, or disable the =:ui ligatures module.

** Can't load my theme; ~unable to find theme file for X~ errors
This means Emacs can't find the X-theme.el file for the theme you want to load.
Emacs will search for this file in ~custom-theme-load-path~ and
~custom-theme-directory~. There are a couple reasons why it can't be found:

1. It is generally expected that third party themes will [[https://github.com/hlissner/emacs-doom-themes/blob/master/doom-themes.el#L400-L405][add themselves]] to
   ~custom-theme-load-path~, but you will occasionally encounter a theme that
   does not. This should be reported upstream.

   In the meantime, you can get around this by eagerly loading the package:

   #+BEGIN_SRC elisp
   (require 'third-party-theme)
   (setq doom-theme 'third-party)
   #+END_SRC
2. You've appended ~-theme~ to the end of your theme's name.

   #+BEGIN_SRC elisp
   (setq doom-theme 'third-party-theme)
   #+END_SRC

   When you load a theme Emacs searches for ~X-theme.el~. If you set
   ~doom-theme~ to ~'third-party-theme~, it will search for
   ~third-party-theme-theme.el~. This is rarely intentional. Omit the ~-theme~
   suffix.
3. Did you run ~doom sync~ after adding your third party theme plugin's
   ~package!~ declaration to =~/.doom.d/packages.el=?

** TRAMP connections hang forever when connecting
You'll find solutions [[https://www.emacswiki.org/emacs/TrampMode#toc7][on the emacswiki]].

** An upstream package was broken and I can't update it
Sometimes, if you've installed a [[https://github.com/hlissner/doom-emacs/issues/2213][broken package]] which was subsequently fixed
upstream, you can't run ~doom update~ to get the latest fixes due to evaluation
errors.

In those cases, you need to delete the broken local copy before you can install
the new one, which is achieved by either deleting it from
=~/.emacs.d/.local/straight/repos=, or by cycling the module that installs it:

1. Comment out the broken module/package.
2. Run ~doom sync~.
3. Uncomment the module/package.
4. Run ~doom sync~.

** Why do I see ugly indentation highlights for tabs?
[[https://github.com/hlissner/doom-emacs/blob/develop/core/core-ui.el#L132-L150][Doom highlights non-standard indentation]]. i.e. Indentation that doesn't match
the indent style you've set for that file. Spaces are Doom's default style for
most languages (excluding languages where tabs are the norm, like Go).

There are a couple ways to address this:

1. Fix your indentation! If it's highlighted, you have tabs when you should have
   spaces (or spaces when you should be using tabs).

   Two easy commands for that:

   - =M-x tabify=
   - =M-x untabify=

2. Change ~indent-tabs-mode~ (nil = spaces, t = tabs) in =~/.doom.d/config.el=:

   #+BEGIN_SRC elisp
   ;; use tab indentation everywhere
   (setq-default indent-tabs-mode t)

   ;; or only in certain modes
   (setq-hook! 'sh-mode-hook indent-tabs-mode t) ; shell scripts
   (setq-hook! '(c-mode-hook c++-mode-hook) indent-tabs-mode t)  ; C/C++
   #+END_SRC

3. Use [[https://editorconfig.org/][editorconfig]] to configure code style on a per-project basis. If you
   enable Doom's =:tools editorconfig= module, Doom will recognize
   =.editorconfigrc= files.

4. Or trust in dtrt-indent; a plugin Doom uses to analyze and detect indentation
   when you open a file (that isn't in a project with an editorconfig file).
   This isn't foolproof, and won't work for files that have no content in them,
   but it can help in one-off scenarios.

** "clipetty--emit: Opening output file: Permission denied, /dev/pts/29" error
This applies to tmux users, in particular. See
https://github.com/spudlyo/clipetty/issues/15 for a solution.

** "The directory ~/.emacs.d/server is unsafe" error at startup
If you're getting this error you must reset the owner of
=C:\Users\USERNAME\.emacs.d= to your own account:

1. Right-click the =~/.emacs.d/server= directory in Windows Explorer,
2. Click Properties,
3. Select the "Security" tab,
4. Click the "Advanced" button,
5. Select the "Owner" tab
6. Change the owner to your account name

([[https://stackoverflow.com/questions/885793/emacs-error-when-calling-server-start][source]])

** My new keybinds don't work
Emacs has a complex and hierarchical keybinding system. If a global keybind
doesn't take effect, it's likely that another keymap is in effect with higher
priority than the global keymap. For example, non-evil users may have tried
something like this, to rebind =C-left= and =C-right=:
#+BEGIN_SRC elisp
(map! "<C-left>"  #'something
      "<C-right>" #'something)
#+END_SRC

Just to find that the rebinding had no effect (i.e. ~C-h k C-left~ reports that
it's still bound to ~sp-backward-slurp-sexp~). That's because these keys are
bound in ~smartparens-mode-map~. They need to be unbound for your global
keybinds to work:

#+BEGIN_SRC elisp
(map! :after smartparens
      :map smartparens-mode-map
      [C-right] nil
      [C-left] nil)
#+END_SRC

#+begin_quote
I use ~[C-left]~ because it is easier to type than ~"<C-left>"~, but are
equivalent; two different ways to refer to the same key.
#+end_quote
