Professional Documents
Culture Documents
:ID: 5fa8967a-532f-4e0c-8ae8-25cd802bf9a9
:END:
#+title: Frequently Asked Questions
#+subtitle: Answers to common issues and questions
#+startup: nonum show2levels*
* General
:PROPERTIES:
:ID: 3c17177d-8ba9-4d1a-a279-b6dea21c8a9a
:END:
This section is for general questions about the Doom Emacs project and its
author.
- [[id:fba3642f-b01e-405b-80ac-2900df22e978][Why Emacs?]]
- [[id:e3172459-abcb-45cb-9135-9692f320a836][Why /not/ Emacs?]]
- [[id:46d2058d-249e-45a7-a7a2-58bade48df65][Why Doom?]]
- [[id:da317a3c-1672-40e2-85d5-b4246482af2c][Why /not/ Doom?]]
That's not to say I've taken no inspiration from them since. Doom's earliest
file structure was inspired by Prelude's, until it was replaced with a module
system. Other concepts (like [[kbd:][SPC]] as a leader key) came from Spacemacs or
were
PRed from migrating users, and were accepted because they seemed sensible.
More similarities (and differences) will no doubt emerge as our userbase grows
and more starter kits appear.
** Doom claims to be an Emacs framework, not a starter kit. What's the difference?
I don't claim to own these terms, but I use them to distinguish
[[https://git.doomemacs.org/core][Doom's core]] (a
framework) from [[https://git.doomemacs.org/modules][Doom's module library]] (a
starter kit).
My premise is: starter kits and Emacs frameworks have different goals. Where
starter kits help you avoid work by doing it for you, an Emacs framework helps
you /do/ that work yourself, but more effectively (by providing extra tools,
APIs, or organizational systems for writing/debugging). Of course, there will be
some crossover.
So "Doom Emacs" was what you got when you combined childhood, demon-carnage
nostalgia, [[https://www.youtube.com/user/n4sco][terrible]]
[[https://github.com/hlissner/emacs-solaire-mode][naming]]
[[https://github.com/hlissner/vim-forrestgump][sense]], and the sneaking suspicion
that Emacs is the
unwritten tenth circle Dante censored for humanity's protection.
- No disaster recovery ::
When things go wrong, we don't always have time to deal with it. Or we need to
wait for upstream to deploy a fix. While we wait, we still have work to do,
but now what? Emacs is broken! =package.el= doesn't give you any options to
roll back, so you /have/ to deal with it, and now. Or hope your old config was
backed up.
Though Doom doesn't have a 'doom rollback' command (yet), the ability to
quickly checkout an old commit of a problematic package (or Doom itself),
without the overhead of forking and/or maintaining a local copy, is priceless.
- Rolling release or bust ::
=package.el= installs the latest version of every package, or none at all.
There's no rollback, no pinning to a stable ref, and no git history to peek
into. It offers little reproducibility; wiping/losing/copying your config
becomes a gamble if you aren't constantly backing up your packages (then
recompiling them if you're up/downgrading Emacs).
=melpa-stable= was well intentioned, but it offers no guarantees or standards
on how/when maintainers tag their projects. I'd rather the user decide for
themselves, because they're the ones in the trenches.
- Can't install packages from superior sources ::
Often, a crucial fix sits in a pull request somewhere for too long, a package
becomes outdated through official channels, or a superior fork springs up
somewhere other than an ELPA. =package.el= cannot reach those sources.
- Slow at startup (by default) ::
Initializing =package.el= can be expensive, depending on the number (and
complexity) of installed packages -- especially for batch scripts.
~package-quickstart~ helps, up to a point, but Doom's package manager can do
better with the assumptions available to its monolithic ecosystem. All without
imposing =straight.el= or =package.el= on your runtime environments.
Granted, you /can/ get most of the above with a little Git know-how, but it
stops being convenient as you reach package 5 or 15, your tenacity permitting.
It's left to the user to know or care about optimal load paths, and to implement
them, but that's a lot to ask when the problem domain is so vast, esoteric, and
a moving target (with a high cost-to-benefit). Who has the time to inspect, much
less fix, all their packages? And maintain that effort across Emacs or package
updates? It's easier to use the daemon, so people do.
That said, there's no one to blame for that. I consider Doom's effort, the
daemon, even native compilation (though all excellent endeavors) stop-gap
measures for a deeper, underlying issue in Emacs that needs smarter people than
I to address.
Rather than startup time, runtime performance is a bigger priority, though the
two rarely stray far from each other.
* How do I...
:PROPERTIES:
:ID: 9c81ab2a-7da9-4b8e-9f90-d4ebff8bebbb
:END:
For common how-to and configuration questions from Doom users. You'll find more
[[https://discourse.doomemacs.org/tags/faq][on our Discourse]].
The installed version of Doom core is also displayed in the Doom dashboard's
mode-line.
** Turn (Doom) Emacs into a <insert language here> IDE with LSP?
:PROPERTIES:
:ID: 4cec77b2-bb1c-4b35-8ad1-d6dd9fcc1dbb
:END:
This is frequently asked: how to transform Doom Emacs into an IDE for some
programming language. In almost all cases, it's recommended that you enable
Doom's LSP support and install a supported LSP client.
#+begin_src elisp
;; Remember to replace MAJOR-MODE with the major mode that powers the language.
;; E.g. `ruby-mode-local-vars-hook' or `python-mode-local-vars-hook'
(add-hook 'MAJOR-MODE-local-vars-hook #'lsp! 'append)
2. Some languages have alternatives that are superior to the LSP offerings (such
as Cider for Clojure or Sly for Common Lisp).
** Change my fonts
Doom exposes a couple variables for setting fonts. They are:
For example:
#+begin_src emacs-lisp
;; in $DOOMDIR/config.el
(setq doom-font (font-spec :family "JetBrainsMono" :size 12 :weight 'light)
doom-variable-pitch-font (font-spec :family "DejaVu Sans" :size 13)
doom-unicode-font (font-spec :family "Symbola")
doom-big-font (font-spec :family "JetBrainsMono" :size 24))
#+end_src
#+begin_quote
🚧 If you or Emacs can't find your font, use ~M-x describe-font~ to look them
up, or run ~$ fc-list~ to see all the available fonts on your system. *Font
issues are /rarely/ Doom issues!*
#+end_quote
1. The correct way: by running ~$ doom upgrade~ in the shell and restarting
Emacs.
2. The manual way (if ~doom upgrade~ is broken for some reason):
#+begin_src bash
$ cd ~/.emacs.d
$ git pull # pull the latest version of Doom's source
$ doom sync -u # update Doom's packages and 'doom sync'
#+end_src
This may change in the future, so ~$ doom upgrade~ will always be the safest
option. That said, ~$ doom help upgrade~ will always document the correct
procedure for manual updates if you need it.
However, Doom provides a more general ~map!~ macro, to conveniently wrap up the
above four into a more succinct syntax. Comprehensive examples of ~map!~'s usage
can be found in its documentation (keyboard shortcut: [[kbd:][<help> f map\!]]).
For example:
#+begin_src emacs-lisp
;;; add to $DOOMDIR/config.el
(setq display-line-numbers-type 'relative)
#+end_src
E.g. ~normal -> relative -> visual -> disabled -> normal~
If anything is misbehaving, it's a good idea to run ~$ doom sync~ first, to rule
out any issues with missing packages or autoloads.
*Long answer:* packages can contain baked-in absolute paths and non-portable
byte-code. It is never a good idea to mirror it across multiple systems, unless
they are all the same (same OS, same version of Emacs, same paths). Most issues
should be solved by running ~$ doom sync && doom build~ on the other end, once
moved.
These keys were changed because they are redundant with [[kbd:][cl]] and [[kbd:]
[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 $DOOMDIR/config.el
(remove-hook 'doom-first-input-hook #'evil-snipe-mode)
#+end_src
* Common issues
:PROPERTIES:
:ID: 9adcf3a0-add2-4135-b918-e1d7f406c80d
:END:
For problems that come up especially often. You'll find more
[[https://discourse.doomemacs.org][on our Discourse]]
and [[https://github.com/doomemacs/doomemacs/issues][Github issue tracker]].
Consult [[id:14040b81-3dd3-422e-abce-245f4c03d1b4][our troubleshooting guide]] for
help debugging
issues.
** Doom and/or Emacs is slow
:PROPERTIES:
:ID: 643acc75-9717-4739-9c52-3947491e827e
:END:
The answer changes from version to version (of Emacs), and is often updated with
new information, so [[https://discourse.doomemacs.org/t/why-is-emacs-doom-slow/83]
[this is answered on Discourse]] instead.
If this isn't the case, run ~$ doom doctor~. It can detect a variety of common
issues and may offer you clues.
- An error occurred while starting up Doom. Use [[kbd:][C-h e]] to inspect Emacs'
log.
Search it for errors or warnings. If you find one, [[id:aa116c29-b7d5-488a-860f-
bdb22c1f4e8e][producing a backtrace]] from
the error can shed more light on it (and will be required if you ask the
community for help debugging it).
If you're still stuck, run ~$ doom doctor~. It can detect a variety of common
issues and may give you some clues as to what is wrong.
For issue #2, you'll need to investigate your launcher. There are too many
launchers write a walkthrough for, you'll have better luck asking about it on
[[https://doomemacs.org/discord][our Discord]] or
[[https://discourse.doomemacs.org][Discourse]].
#+begin_src emacs-lisp
(after! magit
(setq magit-repository-directories '(("~/projects" . 2))
magit-save-repository-buffers nil))
#+end_src
;; Don't defer setting variables whose documentation explicitly say they must
;; be set *before* the package is loaded. e.g.
(setq evil-respect-visual-line-mode t)
#+end_src
If none of these solve your issue, try ~$ doom doctor~. It will detect a variety
of common issues, and may give you some clues as to what is wrong. Otherwise,
consult [[id:2f277e96-654d-406f-8797-b9a7d2ccc218][the community]].
- Some fonts cause Emacs to crash when they lack support for a particular glyph
(typically symbols). Try changing your font by changing ~doom-font~ or
~doom-unicode-font~.
1. Fix your indentation! If it's highlighted, you have tabs when you should have
spaces (or spaces when you should be using tabs).
#+begin_src emacs-lisp
;; use tab indentation everywhere
(setq-default indent-tabs-mode t)
([[https://stackoverflow.com/questions/885793/emacs-error-when-calling-server-
start][source]])
Just to find that the rebinding had no effect (i.e. [[kbd:][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 emacs-lisp
(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 they are
equivalent; two different ways to refer to the same key.
#+end_quote
** Recursive load error on startup
If you see an error like:
#+begin_example
Error: error ("Recursive load"
"/Applications/Emacs.app/Contents/Resources/lisp/jka-compr.el.gz"
"/Applications/Emacs.app/Contents/Resources/lisp/jka-compr.el.gz"
"/Applications/Emacs.app/Contents/Resources/lisp/jka-compr.el.gz"
"/Applications/Emacs.app/Contents/Resources/lisp/jka-compr.el.gz"
"/Applications/Emacs.app/Contents/Resources/lisp/jka-compr.el.gz"
"/Applications/Emacs.app/Contents/Resources/lisp/obsolete/cl.el.gz")
#+end_example
#+begin_quote
🚧 *Warning macOS and *BSD distro users:* you likely have BSD variants of
=tar= and =gzip= installed by default. Emacs requires the GNU variants!
#+end_quote
- =tar= and/or =gzip= aren't in your =$PATH=, somehow. Once you've corrected
your shell config, run ~$ doom env~ to regenerate your envvar file (containing
the =$PATH= Doom will see), then restart Emacs.
- *(macOS users only)* You've installed Emacs from one of the sources I
recommend you avoid. For example, emacsformacosx.com. Our user manual outlines
where you should acquire Emacs from.
If none of the above help, then [[id:3f3ea085-dbba-4d28-a56f-852f386249c1][file a
bug report]].
* Contributors
:PROPERTIES:
:ID: 1afe59e5-0c67-4b70-a5b6-e7978ccf4220
:END:
For folks who want to report bugs and submit pull requests.
- Ensure there are no open PRs that tackle the same issue. If yours is intended
to replace an existing one, please mention it.
- Include an explanation: why the PR is necessary, what it fixes, any gotchas I
should be aware of, and issues it affects.
- Be acquainted with our [[id:46442b23-a7ae-44ba-afdb-b7ba8bb76b6e][git commit
conventions]]. Good commit etiquette is
required. Do not be afraid to rebase or force-push to tidy up your PR, once it
is ready for review.
- Adhere to our [[id:b3d85a53-a544-44e5-9353-06e413bd7f30][code]], [[id:9bb17259-
0b07-45a8-ae7a-fc5e0b16244e][documentation]], and [[id:cc55968b-f430-45e4-9e05-
4c6187871b9d][keybind]] conventions, where applicable.
- Ensure you've targeted the =master= branch.
- Keep your PR focused. It shouldn't do too much in too many places, if that can
be avoided.
- If your PR introduces new tools, dependencies, or packages, I'm going to test
them. It takes time to research them, acquire them, learn how to use them, and
finally test them in the context of your PR. You can speed this up by
including steps to set up an MVE with some mock inputs and expected results.
- Allow me to merge them when I have time to respond to regressions they may
cause.
- Give me a second chance to catch issues,
- Give the submitter extra time to correct mistakes,
- Give users a change to test it themselves,
If your PR was approved, you only have to wait for Henrik to get off his
glorious Canadian behind and merge it. If it's been a week or so with no
progress, feel free to ping him in-thread or [[https://doomemacs.org/discord][on
Discord]] (in the #contributing
channel).
Since Doom's "support team" only consists of one overworked maintainer and a
handful of busy volunteers, we have to be strict; we don't have the capacity to
chase issues that aren't *actionable*, *immediately reproducible*, or *cannot be
investigated within a reasonable amount of time* (which includes issues that are
poorly researched, vague, or open-ended).
Posts that fall into these categories will be immediately closed, tagged for
deletion, and given a brief explanation why, including instructions to overturn
or contest the ruling if I've made a mistake.
Some examples:
- Performance issues without a clear, verifiable, or reproducible cause.
- Behavior that can't be reproduced in [[id:04f91253-a92a-4125-a576-44de226582bb]
[vanilla Doom]].
- Behavior that can be reproduced in vanilla Emacs.
- An open-ended request to improve something without concrete goals.
- An issue that consists solely of "X doesn't work" and little else.
- An issue that omits important information, like steps to reproduce or system
information.
- A post asking how to configure or use Emacs to achieve some effect (our issue
tracker is for bug reports, not support; ask on [[https://doomemacs.org/discord]
[Discord]] or [[https://discourse.doomemacs.org][Discourse]] instead).
- A convoluted and unfocused issue that present multiple issues in one.
- A rude user that won't meet us half way and/or expects us to do all the work
for them.
* Sponsors
:PROPERTIES:
:ID: 739da458-feb0-42c3-abbc-11cbe3aaa273
:END:
For the generous folks who want to sponsor the project and its author.
If you do decide to sponsor me, thank you for your support! It is a big help,
and directly translates to more hours on my Doom, Emacs-related, or open-source
capers.
** Are there other ways to support the project or get sponsorship perks?
:PROPERTIES:
:ID: 29d9a145-8f2e-4d22-b4d0-de8a2c72698d
:END:
Yes! By becoming a module maintainer, community moderator, or regular you get
the same perks as sponsors [[https://github.com/sponsors/hlissner][on the 25/mo
tier]]. Here's what they do:
- *Module maintainers* look after one or more Doom modules. They become my
consultants for that module(s)' ecosystem, packages, and implementation, and
issues about them. Some Emacs Lisp expertise is helpful, but it's more
important that you are knowledgeable about your chosen module's ecosystem.
- *Moderators* look after our Github, Discord, and/or Discourse communities.
They keep our issue tracker, github projects, and repos organized, and they
keep the peace by warning/banning bad actors. They're held to a higher
standard, however, as they represent us.
- *Regulars* are pillars of our community; they're folks that frequent our
Discord and/or Discourse, are active, helpful, and friendly. This is the only
role you can't apply for, but we keep a eye out for folks to give it to!
If code, documentation, or bug reports are more your thing, visit [[id:eb67a668-
20ac-43ec-880b-883b6949ca76][our
contributing manual]] for ideas.
- Issues that get *first shake* get triaged and investigated before other
issues, and if it can be resolved in one sitting, I will.
- Issues that get *first priority* get entirely resolved before I move on to
anything else.
That said, the exception to these rules are issues that are extraordinarily
difficult, outside my expertise, or depend on other development efforts to
resolve.
Folks that depend on Doom for their work or businesses would benefit from
getting first priority, to ensure their issues are resolved ASAP. Or check out
[[https://github.com/sponsors/hlissner?frequency=one-time&sponsor=hlissner][my one-
time tiers]] to hire me for dedicated support.
I use it to indicate to the byte-compiler (or human readers) that a symbol will
be treated as a function rather than literal data.
- The way it applies its settings (through theme variables) defies conventional
load order, which is troublesome to support in middleware like Doom (or user
configuration) when lazy loading is involved.
- I don't see many instances in the wild where this load-order quirk is
accommodated. I think this is because those writing/offering that code are
Lisp programmers, who don't use =Customize= and may not be exposed to its
quirks, but for beginners this is frustration waiting to happen.
- =Customize= works flawlessly if it is the sole source of truth for your Emacs
configuration, but /all/ Emacs configs eventually take on Lisp. At this point
you acquire a second source of truth that =Customize= is happy to (quietly)
override.
#+begin_quote
📌 There are also text objects for xml tags ([[kbd:][x]]), C-style function
arguments
([[kbd:][a]]), angle brackets, and single/double quotes.
#+end_quote
;;; in $DOOMDIR/config.el
(map! :nv "C-=" #'er/contract-region
:nv "C-+" #'er/expand-region)
#+end_src
~$ 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.
;;; in $DOOMDIR/config.el
(require 'exec-path-from-shell)
(when (display-graphic-p)
(exec-path-from-shell-initialize))
#+end_src
Automated processes that mutate entire files (or worse, whole projects) should
be deliberately invoked, and by someone privvy to the consequences, rather than
automated. =ws-butler= achieves that balance by only cleaning whitespace on
lines that you have modified since opening the file.