Update & revise docs/faq.org

This commit is contained in:
Henrik Lissner 2020-01-26 04:19:39 -05:00
parent 827225e331
commit 6cdc060432
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395

View file

@ -37,7 +37,7 @@
- [[#can-vimevil-be-removed-for-a-more-vanilla-emacs-experience][Can Vim/Evil be removed for a more vanilla Emacs experience?]] - [[#can-vimevil-be-removed-for-a-more-vanilla-emacs-experience][Can Vim/Evil be removed for a more vanilla Emacs experience?]]
- [[#should-i-use-make-or-bindoom][Should I use ~make~ or ~bin/doom~?]] - [[#should-i-use-make-or-bindoom][Should I use ~make~ or ~bin/doom~?]]
- [[#when-should-and-shouldnt-i-use-bindoom][When should and shouldn't I use ~bin/doom~?]] - [[#when-should-and-shouldnt-i-use-bindoom][When should and shouldn't I use ~bin/doom~?]]
- [[#when-to-run-doom-refresh][When to run ~doom refresh~]] - [[#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]] - [[#how-to-suppress-confirmation-prompts-while-bindoom-is-running][How to suppress confirmation prompts while ~bin/doom~ is running]]
- [[#defaults][Defaults]] - [[#defaults][Defaults]]
- [[#why-ivy-over-helm][Why Ivy over Helm?]] - [[#why-ivy-over-helm][Why Ivy over Helm?]]
@ -134,15 +134,15 @@ Doom had +four+ *five* goals for its package management system:
are out-of-date through official channels, have changed hands, have a are out-of-date through official channels, have changed hands, have a
superior fork, or aren't available in ELPA repos. superior fork, or aren't available in ELPA repos.
3. *Performance:* lazy-loading the package management system is a tremendous 3. *Performance:* lazy-loading the package management system is a tremendous
boon to start up speed. Initializing package.el and quelpa (and/or checking boon to start up speed. Initializing package.el and straight (and/or checking
that your packages are installed) every time you start up is expensive. that your packages are installed) each time you start up is expensive.
4. *Organization:* an Emacs configuration grows so quickly, in complexity and 4. *Organization:* an Emacs configuration grows so quickly, in complexity and
size. A clear separation of concerns (configuration of packages from their size. A clear separation of concerns (configuration of packages from their
installation) is more organized. installation) is more organized.
5. *Reproducibility:* /This goal hasn't been implemented yet/, but all our work 5. *Reproducibility:* /This goal hasn't been implemented yet/, but all our work
up until now is aimed at this goal. Emacs is a tumultuous ecosystem; packages up until now is aimed at this goal. Emacs is a tumultuous ecosystem; packages
break left and right, and we rely on hundreds of them. Eventually, we want break left and right, and we rely on hundreds of them. Eventually, we want
package versions to be locked to versions of Doom so that Doom installs are package versions to be locked to Doom's releases so that Doom installs are
reproducible. reproducible.
** How does Doom start up so quickly? ** How does Doom start up so quickly?
@ -160,10 +160,10 @@ up ~gc-cons-threshold~ (and perhaps ~gc-cons-percentage~) temporarily:
;; ... your emacs config here ... ;; ... your emacs config here ...
#+END_SRC #+END_SRC
However, it is important to reset it eventually (as late as possible). Not doing However, it is important to reset it eventually. Not doing so will cause garbage
so will cause garbage collection freezes during long-term interactive use. collection freezes during long-term interactive use. Conversely, a
Conversely, a ~gc-cons-threshold~ that is too small will cause stuttering. We ~gc-cons-threshold~ that is too small will cause stuttering. We use 16mb as our
use 16mb as our default. default.
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(add-hook 'emacs-startup-hook (add-hook 'emacs-startup-hook
@ -190,14 +190,16 @@ helm and ivy). Here is how Doom does it:
(add-hook 'minibuffer-exit-hook #'doom-restore-garbage-collection-h) (add-hook 'minibuffer-exit-hook #'doom-restore-garbage-collection-h)
#+END_SRC #+END_SRC
Another alternative (which is [[https://github.com/hlissner/doom-emacs/blob/develop/core/core.el#L269-L274][what Doom uses]]) is to use the [[https://gitlab.com/koral/gcmh/][gcmh]] package to
stave off the GC until you are idle or unfocus the Emacs frame.
*** Unset ~file-name-handler-alist~ temporarily *** Unset ~file-name-handler-alist~ temporarily
Emacs consults this variable every time a file is read or library loaded, or 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 when certain functions in the file API are used (like ~expand-file-name~ or
~file-truename~). ~file-truename~).
They do so to check if a special handler is needed to read it, but none of these Emacs does to check if a special handler is needed to read that file, but none
handlers are necessary for the initialization work we do at startup, so it is of them are (typically) necessary at startup, so we disable them (temporarily!):
generally safe to disable it (temporarily!):
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(defvar doom--file-name-handler-alist file-name-handler-alist) (defvar doom--file-name-handler-alist file-name-handler-alist)
@ -214,60 +216,38 @@ generally safe to disable it (temporarily!):
(setq file-name-handler-alist doom--file-name-handler-alist))) (setq file-name-handler-alist doom--file-name-handler-alist)))
#+END_SRC #+END_SRC
It is important to restore this variable, otherwise you won't be able to use Don't forget to restore ~file-name-handler-alist~, otherwise TRAMP won't work
TRAMP and Emacs will be unable to read compressed/encrypted files. and compressed/encrypted files won't open.
*** Cut down on ~load-path~ lookups
Each ~load~ and ~require~ call (without an second argument) costs an O(n) lookup
on ~load-path~. The average Doom config has approximately 260 packages including
dependencies, and around 40 built-in packages. That means a minimum of 300
entries in ~load-path~ with a worst case of =n=300= for /each/ package load (but
realistically, =n= will be somewhere between =2= and =20=).
The cost isn't great, but it does add up. There isn't much to do about this,
except be mindful of it where we can:
+ Paths in Doom's autoloads file are replaced with absolute ones, thus incurring
no lookup cost to lazy load them.
+ The ~load!~ macro is used instead of ~require~ where possible. This builds
paths with string concatenation (which is baked in at compile time, removing
most of the associated cost).
+ ~load-path~ is let-bound to a subset of itself where possible (the
~doom--initial-load-path~ variable contains the value of ~load-path~ before it
was touched by Doom).
*** Concatenate package autoloads *** Concatenate package autoloads
When you install a package, a PACKAGE-autoloads.el file is generated. This file When you install a package, a PACKAGE-autoloads.el file is generated. This file
contains a map of autoloaded functions and snippets declared by the package contains a map of autoloaded functions and snippets declared by the package.
(that's what those ~;;;###autoload~ comments are for in packages). They tell They tell Emacs where to find them when they are eventually called. In your
Emacs where to find them, when they are eventually called. In your conventional conventional Emacs config, every one of these autoloads files are loaded
Emacs config, every single one of these autoloads files are loaded immediately immediately at startup (when ~package-initialize~ is called).
at startup.
Since you'll commonly have hundreds of packages, loading hundreds of autoloads Since you'll commonly have hundreds of packages, loading hundreds of autoloads
file can hurt startup times. We get around this by concatenating these autoloads file can hurt startup times, especially without an SSD. We get around this by
files into one giant one (in =~/.emacs.d/.local/autoloads.pkg.el=) when you run concatenating these files into one giant one when you run ~doom sync~.
~doom refresh~.
Emacs 27+ will introduce a ~package-quickstart~ feature that will do this for Emacs 27+ introduces a ~package-quickstart~ command does this for you, and
you -- the =straight= package manager does this for you too -- but Doom Emacs =straight=, 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
has its own specialized mechanism for doing this, and has tacked a number of own specialized mechanism]] for this, topped off with a few Doom-specific
Doom-specific optimizations on top of it. optimizations.
*** Lazy load package management system(s) *** Lazy load package management system(s)
Initializing package.el or straight.el at startup is expensive. We can save some 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 time by delaying that initialization until we actually need these libraries (and
only eagerly load them when we're doing package management, e.g. when we run load them only when we're doing package management, e.g. when we run ~doom
~doom refresh~). sync~).
Among other things, ~doom refresh~ does a lot for us. It generates concatenated Among other things, ~doom sync~ does a lot for us. It generates concatenated
autoloads files; caches expensive variables like caches ~load-path~, autoloads files; caches expensive variables like caches ~load-path~,
~Info-directory-list~ and ~auto-mode-alist~; and preforms all your package ~Info-directory-list~ and ~auto-mode-alist~; and preforms all your package
management activities there -- far away from your interactive sessions. management activities there -- far away from your interactive sessions.
How exactly Doom accomplishes all this is a little complex, so instead, here is How exactly Doom accomplishes all this is a long story, so here is a boiled-down
a boiled-down version you can use in your own configs (for package.el, not version you can use in your own configs (for package.el, not straight.el):
straight.el):
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(defvar cache-file "~/.emacs.d/cache/autoloads") (defvar cache-file "~/.emacs.d/cache/autoloads")
@ -278,26 +258,12 @@ straight.el):
(package-initialize) (package-initialize)
(with-temp-buffer (with-temp-buffer
(cl-pushnew doom-core-dir load-path :test #'string=) (cl-pushnew doom-core-dir load-path :test #'string=)
(dolist (spec package-alist) (dolist (desc (delq nil (mapcar #'cdr package-alist)))
(when-let (desc (cdr spec)) (let ((load-file-name (concat (package--autoloads-file-name desc) ".el")))
(let ((file (concat (package--autoloads-file-name desc) ".el"))) (when (file-readable-p load-file-name)
(when (file-readable-p file) (condition-case _
;; Ensure that the contents of this autoloads file believes they (while t (insert (read (current-buffer))))
;; haven't been moved: (end-of-file)))))
(insert "(let ((load-file-name " (prin1-to-string (abbreviate-file-name file)) "))\n")
(insert-file-contents file)
(save-excursion
;; Delete forms that modify `load-path' and `auto-mode-alist', we
;; will set them once, later.
(while (re-search-forward "^\\s-*\\((\\(?:add-to-list\\|\\(?:when\\|if\\) (boundp\\)\\s-+'\\(?:load-path\\|auto-mode-alist\\)\\)" nil t)
(goto-char (match-beginning 1))
(kill-sexp)))
;; Remove unnecessary comment lines and (provide ...) forms
(while (re-search-forward "^\\(?:;;\\(.*\n\\)\\|\n\\|(provide '[^\n]+\\)" nil t)
(unless (nth 8 (syntax-ppss))
(replace-match "" t t)))
(unless (bolp) (insert "\n"))
(insert ")\n")))))
(prin1 `(setq load-path ',load-path (prin1 `(setq load-path ',load-path
auto-mode-alist ',auto-mode-alist auto-mode-alist ',auto-mode-alist
Info-directory-list ',Info-directory-list) Info-directory-list ',Info-directory-list)
@ -309,10 +275,9 @@ straight.el):
#+END_SRC #+END_SRC
You'll need to delete ~cache-files~ any time you install, remove, or update a You'll need to delete ~cache-files~ any time you install, remove, or update a
new package, however. In that case you could advise ~package-install~ and new package. You could advise ~package-install~ and ~package-delete~ to call
~package-delete~ to call ~initialize~ when they succeed. Or, you could make ~initialize~ when they succeed, or make ~initialize~ interactive and call it
~initialize~ interactive and call it manually when you determine it's necessary. manually when necessary. Up to you!
Up to you!
Note: package.el is sneaky, and will initialize itself if you're not careful. Note: package.el is sneaky, and will initialize itself if you're not careful.
*Not on my watch, criminal scum!* *Not on my watch, criminal scum!*
@ -327,20 +292,21 @@ Note: package.el is sneaky, and will initialize itself if you're not careful.
*** Lazy load more than everything *** Lazy load more than everything
~use-package~ can defer your packages. Using it is a no-brainer, but Doom goes a ~use-package~ can defer your packages. Using it is a no-brainer, but Doom goes a
little further with lazy loading. There are some massive plugins out there. For little further with lazy loading. There are some massive plugins out there. For
many of them, ordinary lazy loading techniques simply don't work. To name a few: some of them, ordinary lazy loading techniques don't work. To name a few:
+ The =lang/org= module defers loading babel packages until their src blocks are + The =lang/org= module defers loading babel packages until their src blocks are
executed. You no longer need ~org-babel-do-load-languages~ in your config. executed or read. You no longer need ~org-babel-do-load-languages~ in your
config -- in fact, you shouldn't use it at all!
+ Company and yasnippet are loaded as late as possible (waiting until the user + 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)). opens a non-read-only, file-visiting buffer (that isn't in fundamental-mode)).
+ The =evil-easymotion= package has many keybinds. You'd need to load the + The =evil-easymotion= package binds many keys, none of which are available
package for them to all take effect, so instead, =gs= is bound to a command until you load the package. Instead of loading it at startup, =gs= is bound to
that loads the package and then invisibly populates =gs=, then simulates the a command that loads the package, populates =gs=, then simulates the =gs= key
=gs= keypress as though those new keys had always been there. press as though those new keys had always been there.
+ A number of packages are "incrementally" loaded. This is a Doom feature where, + Doom loads some packages "incrementally". i.e. after a few seconds of idle
after a few seconds of idle time post-startup, Doom will load packages time post-startup, Doom loads packages piecemeal (one dependency at a time)
piecemeal while Emacs. It will quickly abort if it detects input, as to make while Emacs. It aborts if it detects input, as to make the process as subtle
the process as subtle as possible. as possible.
For example, instead of loading =org= (a giant package), it will load these For example, instead of loading =org= (a giant package), it will load these
dependencies, one at a time, before finally loading =org=: dependencies, one at a time, before finally loading =org=:
@ -354,21 +320,6 @@ many of them, ordinary lazy loading techniques simply don't work. To name a few:
This ensures packages load as quickly as possible when you first load an org This ensures packages load as quickly as possible when you first load an org
file. file.
*** +Exploit byte-compilation!+
It used to be that byte-compilation bought a 40-60% improvement in startup
times, because expensive operations (like ~package-initialize~ or
~exec-path-from-shell~) were evaluated at compile time, but Doom has changed.
I've since adopted a pre-cache approach (when running ~doom refresh~), which
brings these startup benefits to uncompiled Emacs. This renders byte-compilation
significantly less beneficial for startup time.
That said, compilation will still benefit Doom's snappiness in general.
Run ~doom compile :core~ to only compile Doom's core files, or ~doom compile~ to
compile the /entire/ config (=~/.emacs.d= and =~/.doom.d=) -- which may take a
while.
*** Use [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html][lexical-binding]] everywhere *** 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 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 break code if you've written it to depend on undeclared dynamic variables, but
@ -381,32 +332,30 @@ find more about it in:
+ [[http://nullprogram.com/blog/2016/12/22/]["Some Performance Advantages of Lexical Scope."]] + [[http://nullprogram.com/blog/2016/12/22/]["Some Performance Advantages of Lexical Scope."]]
** Why is startup time important? Why not use the daemon? ** Why is startup time important? Why not use the daemon?
One of my motivations for a config that starts up fast (aside from the learning The central motivation for a config that starts up fast (aside from the learning
experience) was to shape Emacs into a viable alternative to vim for one-shot experience) was to have a viable alternative to vim for quick, one-shot editing
editing in the terminal (without ~-Q~). This also facilitates: in the terminal (without ~-Q~).
- Running multiple, independent instances of Emacs (e.g. on a per-project basis, or Besides that, it happens to facilitate:
for nix-shell users, or to isolate one instance for IRC from an instance for
writing code, etc). - 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 - Quicker restarting of Emacs, to reload package settings or recover from
disastrous errors which can leave Emacs in a broken state. 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 - Faster integration with "edit in Emacs" solutions (like [[https://github.com/alpha22jp/atomic-chrome][atomic-chrome]]), and
the potential to use them without a running daemon. without a daemon.
What's more, I don't like using more tools than I need. We should not need a What's more, I believe a daemon shouldn't be necessary to get a sane startup
second program just to make the first run comfortably. time out of Emacs.
** How do I use Doom alongside other Emacs configs? ** How do I use Doom alongside other Emacs configs?
I recommend [[https://github.com/plexus/chemacs][Chemacs]]. You can think of it as a bootloader for Emacs. You'll [[file:getting_started.org::*Alongside other Emacs configs (with Chemacs)][find I recommend [[https://github.com/plexus/chemacs][Chemacs]]. You can 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]]. instructions on how to use it with Doom in the user manual]].
If you only want to try it out without affecting your current config, it is safe
to install Doom anywhere you like. The ~bin/doom~ utility will only address the
config the script is located under.
You'll still need a separate folder for personal configuration (=~/.doom.d= or You'll still need a separate folder for personal configuration (=~/.doom.d= or
=~/.config/doom= by default), but the =-p PATH= flag (or ~DOOMDIR~ environment =~/.config/doom= by default), but the =--doomdir PATH= switch (or ~DOOMDIR~
variable) will allow you to use a different location: environment variable) will allow you to use a different location:
#+BEGIN_SRC bash #+BEGIN_SRC bash
# First install Doom somewhere # First install Doom somewhere
@ -479,80 +428,28 @@ first ran ~doom install~.
Check out the [[file:getting_started.org::Customize][Customize section]] in the [[file:getting_started.org][Getting Started]] guide for details. Check out the [[file:getting_started.org::Customize][Customize section]] in the [[file:getting_started.org][Getting Started]] guide for details.
** How do I enable or disable a Doom module? ** How do I enable or disable a Doom module?
You'll find your ~doom!~ block in =~/.doom.d/init.el=. This block contains a Comment or uncomment the module in your ~doom!~ block, found in
list of modules you want enabled and what order to load them in. Disable modules =$DOOMDIR/init.el=.
by commenting them out with semicolons. To enable them, remove those leading
semicolons:
#+BEGIN_SRC emacs-lisp Remember to run ~bin/doom sync~ afterwards, on the command line, to sync your
(doom! :lang
python ; this is enabled
;;ruby ; this is disabled
rust)
#+END_SRC
Remember to run ~bin/doom refresh~ afterwards, on the command line, to sync your
module list with Doom. module list with Doom.
You can find a comprehensive list of modules in the [[file:index.org::*Module list][Module Index]]. 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 install a package from ELPA? ** How do I install a package from ELPA?
Add a ~package!~ declaration to =~/.doom.d/packages.el= for each package you See the "[[file:getting_started.org::*Installing%20packages][Installing packages]]" section of the [[file:getting_started.org][Getting Started]] guide.
want installed.
#+BEGIN_SRC elisp
(package! winum)
#+END_SRC
Remember to run ~doom refresh~ afterwards to ensure the package is installed.
You'll find more information in the "[[file:getting_started.org::*Installing%20packages][Installing packages]]" section of the [[file:getting_started.org][Getting
Started]] guide.
** How do I install a package from github/another source? ** How do I install a package from github/another source?
The ~package!~ macro can be passed a MELPA style recipe, allowing you to install See the "[[file:getting_started.org::*Installing%20packages%20from%20external%20sources][Installing packages from external sources]]" section of the [[file:getting_started.org][Getting
packages from just about anywhere: Started]] guide.
#+BEGIN_SRC elisp
(package! evil :recipe (:host github :repo "hlissner/my-evil-fork"))
#+END_SRC
Remember to run ~doom refresh~ every time you modify you package list, to ensure
your packages are set up and installed.
You can find more information about the recipe format [[https://github.com/raxod502/straight.el#the-recipe-format][in the straight.el package
readme]].
#+begin_quote
If a MELPA recipe exists for the package you are writing a ~package!~
declaration for, you may omit keywords and Doom's package manager will fill them
in with values from its original recipe.
#+end_quote
You'll find more information in the "[[file:getting_started.org::*Installing%20packages%20from%20external%20sources][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? ** How do I change where an existing package is installed from?
~package!~ declarations in your private =packages.el= file have precedence over See the "[[file:getting_started.org::*Changing%20a%20built-in%20recipe%20for%20a%20package][Changing a built-in recipe for a package]]" section of the [[file:getting_started.org][Getting
modules (even your own). Simply add a new one for that package with the new Started]] guide.
recipe.
You'll find more information in the "[[file:getting_started.org::*Changing%20a%20built-in%20recipe%20for%20a%20package][Changing a built-in recipe for a package]]"
section of the [[file:getting_started.org][Getting Started]] guide.
** How do I disable a package completely? ** How do I disable a package completely?
With the ~package!~ macro's ~:disable~ property: See the "[[file:getting_started.org::*Disabling%20packages][disabling packages]]" section of the [[file:getting_started.org][Getting Started]] guide.
#+BEGIN_SRC elisp
;;; add to DOOMDIR/packages.el
(package! irony :disable t)
#+END_SRC
Remember to run ~doom refresh~ afterwards to ensure that the package is
uninstalled and disabled.
You'll find more information in the "[[file:getting_started.org::*Disabling%20packages][Disabling packages]]" section of the [[file:getting_started.org][Getting
Started]] guide.
** How do I reconfigure a package included in Doom? ** How do I reconfigure a package included in Doom?
~use-package!~ and ~after!~ (wrappers around ~use-package~ and ~use-package!~ and ~after!~ (wrappers around ~use-package~ and
@ -620,8 +517,8 @@ install it, then load it:
(setq doom-theme 'solarized-dark) (setq doom-theme 'solarized-dark)
#+END_SRC #+END_SRC
Don't forget to run ~doom refresh~ after adding that ~package!~ statement to Don't forget to run ~doom sync~ after adding that ~package!~ statement to ensure
ensure the package is installed. the package is installed.
** How do I change the fonts? ** How do I change the fonts?
Doom exposes five (optional) variables for controlling fonts in Doom, they are: Doom exposes five (optional) variables for controlling fonts in Doom, they are:
@ -632,8 +529,8 @@ Doom exposes five (optional) variables for controlling fonts in Doom, they are:
+ ~doom-unicode-font~ + ~doom-unicode-font~
+ ~doom-big-font~ (used for ~doom-big-font-mode~) + ~doom-big-font~ (used for ~doom-big-font-mode~)
Each of these will accept either a =font-spec=, font string (="Input Mono-12"=), They all accept either a =font-spec=, font string (="Input Mono-12"=), or [[https://wiki.archlinux.org/index.php/X_Logical_Font_Description][xlfd
or [[https://wiki.archlinux.org/index.php/X_Logical_Font_Description][xlfd font string]]. font string]].
e.g. e.g.
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
@ -760,6 +657,7 @@ rules.
You'll find more comprehensive documentation on ~set-popup-rule!~ in its 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). docstring (available through =SPC h f= -- or =C-h f= for non-evil users).
** How do I change the appearance a face (or faces)? ** How do I change the appearance a face (or faces)?
Doom provides the ~custom-set-faces!~ and ~custom-theme-set-faces!~ macros as a Doom provides the ~custom-set-faces!~ and ~custom-theme-set-faces!~ macros as a
convenience. convenience.
@ -785,15 +683,14 @@ tools for experienced Emacs users to skirt around it (most of the time):
- On-the-fly evaluation won't work for all changes. e.g. Changing your ~doom!~ - 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). block (i.e. the list of modules for Doom to enable).
But rather than running ~doom refresh~ and restarting Emacs, Doom provides But rather than running ~doom sync~ and restarting Emacs, Doom provides ~M-x
~M-x doom/reload~ for your convenience (bound to =SPC h r r= and =C-h r r=). doom/reload~ for your convenience (bound to =SPC h r r= and =C-h r r=). This
This runs ~doom refresh~, restarts the Doom initialization process and runs ~doom sync~, restarts the Doom initialization process and re-evaluates
re-evaluates your personal config. However, this won't clear pre-existing your personal config. However, this won't clear pre-existing state; Doom won't
state; Doom won't unload modules/packages that have already been loaded and it unload modules/packages that have already been loaded and it can't anticipate
can't anticipate complications arising from a private config that isn't complications arising from a private config that isn't idempotent.
idempotent. - Some ~bin/doom~ commands are available as elisp commands. e.g. ~doom/reload~
- Many ~bin/doom~ commands are available as elisp commands with the ~doom//*~ for ~doom sync~, ~doom/upgrade~ for ~doom upgrade~ ~doom//s~, ~doom//update~, etc. Feel free to use them, but
prefix. e.g. ~doom//refresh~, ~doom//update~, etc. Feel free to use them, but
consider them highly experimental and subject to change without notice. consider them highly experimental and subject to change without notice.
- You can quickly restart Emacs and restore the last session with - You can quickly restart Emacs and restore the last session with
~doom/restart-and-restore~ (bound to =SPC q r=). ~doom/restart-and-restore~ (bound to =SPC q r=).
@ -815,7 +712,7 @@ commands that you may find particularly useful:
+ ~doom doctor~ :: Diagnose common issues in your environment and list missing + ~doom doctor~ :: Diagnose common issues in your environment and list missing
external dependencies for your enabled modules. external dependencies for your enabled modules.
+ ~doom refresh~ :: Ensures that all missing packages are installed, orphaned + ~doom sync~ :: Ensures that all missing packages are installed, orphaned
packages are removed, and metadata properly generated. packages are removed, and metadata properly generated.
+ ~doom install~ :: Install any missing packages. + ~doom install~ :: Install any missing packages.
+ ~doom update~ :: Update all packages that Doom's (enabled) modules use. + ~doom update~ :: Update all packages that Doom's (enabled) modules use.
@ -829,12 +726,12 @@ commands that you may find particularly useful:
#+BEGIN_SRC bash #+BEGIN_SRC bash
git pull git pull
doom refresh doom sync
doom update doom update
#+END_SRC #+END_SRC
** When to run ~doom refresh~ ** When to run ~doom sync~
As a rule of thumb you should run ~doom refresh~ whenever you: As a rule of thumb you should run ~doom sync~ whenever you:
+ Update Doom with ~git pull~ instead of ~doom upgrade~, + Update Doom with ~git pull~ instead of ~doom upgrade~,
+ Change your ~doom!~ block in =$DOOMDIR/init.el=, + Change your ~doom!~ block in =$DOOMDIR/init.el=,
@ -843,8 +740,8 @@ As a rule of thumb you should run ~doom refresh~ whenever you:
+ Install an Emacs package or dependency outside of Emacs (i.e. through your OS + Install an Emacs package or dependency outside of Emacs (i.e. through your OS
package manager). package manager).
If anything is misbehaving, it's a good idea to run ~doom refresh~ first. ~doom If anything is misbehaving, it's a good idea to run ~doom sync~ first. ~doom
refresh~ is responsible for regenerating your autoloads file (which tells Doom sync~ is responsible for regenerating your autoloads file (which tells Doom
where to find lazy-loaded functions and libraries), installing missing packages, where to find lazy-loaded functions and libraries), installing missing packages,
and uninstall orphaned (unneeded) packages. and uninstall orphaned (unneeded) packages.
@ -860,7 +757,7 @@ YES=1 doom update
* Defaults * Defaults
** Why Ivy over Helm? ** Why Ivy over Helm?
Short answer: I chose ivy because it is the simpler of the two. Short answer: ivy is simpler to maintain.
Long answer: Features and performance appear to be the main talking points when 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 comparing the two, but as far as I'm concerned they are equal in both respects
@ -930,21 +827,20 @@ Otherwise, it is trivial to install expand-region and binds keys to it yourself:
#+END_SRC #+END_SRC
** Why not use exec-path-from-shell instead of ~doom env~? ** Why not use exec-path-from-shell instead of ~doom env~?
In a nutshell, the ~doom env~ approach is a faster and more robust solution. 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 1. ~exec-path-from-shell~ must spawn (at least) one process at startup to scrape
your shell environment. This can be arbitrarily slow depending on the user's your shell environment. This can be slow depending on the user's shell
shell configuration. A single program (like pyenv or nvm) or config framework configuration. A single program (like pyenv or nvm) or config framework (like
(like oh-my-zsh) could undo all of Doom's startup optimizations in one fell oh-my-zsh) could undo Doom's startup optimizations in one fell swoop.
swoop.
2. ~exec-path-from-shell~ only scrapes /some/ state from your shell. You have to 2. ~exec-path-from-shell~ takes a whitelist approach and captures only ~PATH~
be proactive in order to get it to capture all the envvars relevant to your and ~MANPATH~ by default. You must be proactive in order to capture all the
development environment. envvars relevant to your development environment and tools.
I'd rather it inherit your shell environment /correctly/ (and /completely/) ~doom env~ takes the blacklist approach and captures all of your shell
or not at all. It frontloads the debugging process rather than hiding it environment. This front loads the debugging process, which is nicer than dealing
until it you least want to deal with it. with it later, while you're getting work done.
That said, if you still want ~exec-path-from-shell~, it is trivial to install That said, if you still want ~exec-path-from-shell~, it is trivial to install
yourself: yourself:
@ -964,16 +860,16 @@ TL;DR: =ws-butler= is less imposing.
Don't be that guy who PRs 99 whitespace adjustments around his one-line Don't be that guy who PRs 99 whitespace adjustments around his one-line
contribution. Don't automate this aggressive behavior by attaching contribution. Don't automate this aggressive behavior by attaching
~delete-trailing-whitespace~ (or ~whitespace-cleanup~) to ~before-save-hook~. If ~delete-trailing-whitespace~ (or ~whitespace-cleanup~) to ~before-save-hook~. If
you have rambunctious colleagues peppering trailing whitespace into your project, you have rambunctious colleagues peppering trailing whitespace into your
you need to have a talk (with wiffle bats, preferably) rather than play this project, you need to have a talk (with wiffle bats, preferably) rather than play
passive-aggressive game of whack-a-mole. a passive-aggressive game of whack-a-mole.
Here at Doom Inc we believe that operations that mutate entire files should Here at Doom Inc we believe that operations that mutate entire files should not
never be automated. Rather, they should be invoked deliberately -- by someone be automated. Rather, they should be invoked deliberately, when and where it is
that is aware of the potential consequences. This is where =ws-butler= comes in. needed, by someone that is aware of the potential consequences. This is where
It only cleans up whitespace /on the lines you've touched/ *and* it leaves =ws-butler= comes in. It only cleans up whitespace /on the lines you've touched/
behind virtual whitespace (which is never written to the file, but remains there *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). 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 In any case, if you had used =ws-butler= from the beginning, trailing whitespace
and newlines would never be a problem! and newlines would never be a problem!
@ -1010,14 +906,14 @@ manually (e.g. by double-clicking each file in explorer).
** ~void-variable~ and ~void-function~ errors on startup ** ~void-variable~ and ~void-function~ errors on startup
The most common culprit for these types of errors are: The most common culprit for these types of errors are:
1. An out-of-date autoloads file. To regenerate it, run ~doom refresh~. 1. An out-of-date autoloads file. Run ~doom sync~ to regenerate them.
To avoid this issue, remember to run ~doom refresh~ whenever you modify your 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!~ 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 =~/.doom.d/packages.el=. Or if you modify =~/.emacs.d/.local= by hand, for
whatever reason. whatever reason.
See ~doom help refresh~ for details on what this command does and when you See ~doom help sync~ for details on what this command does and when you
should use it. should use it.
2. Emacs byte-code isn't forward compatible. If you've recently switched to a 2. Emacs byte-code isn't forward compatible. If you've recently switched to a
@ -1075,8 +971,8 @@ If you still want to restore the old behavior, simply disable evil-snipe-mode:
1. Make sure you don't have both =~/.doom.d= and =~/.config/doom= directories. 1. Make sure you don't have both =~/.doom.d= and =~/.config/doom= directories.
Doom will ignore the former if the latter exists. Doom will ignore the former if the latter exists.
2. Remember to run ~doom refresh~ when it is necessary. To get to know when, 2. Remember to run ~doom sync~ when it is necessary. To get to know when,
exactly, you should run this command, run ~doom help refresh~. 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 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. variety of common issues, and may give you some clues as to what is wrong.
@ -1138,7 +1034,7 @@ Emacs will search for this file in ~custom-theme-load-path~ and
~doom-theme~ to ~'third-party-theme~, it will search for ~doom-theme~ to ~'third-party-theme~, it will search for
~third-party-theme-theme.el~. This is rarely intentional. Omit the ~-theme~ ~third-party-theme-theme.el~. This is rarely intentional. Omit the ~-theme~
suffix. suffix.
3. Did you run ~doom refresh~ after adding your third party theme plugin's 3. Did you run ~doom sync~ after adding your third party theme plugin's
~package!~ declaration to =~/.doom.d/packages.el=? ~package!~ declaration to =~/.doom.d/packages.el=?
** TRAMP connections hang forever when connecting ** TRAMP connections hang forever when connecting
You'll find solutions [[https://www.emacswiki.org/emacs/TrampMode#toc7][on the emacswiki]]. You'll find solutions [[https://www.emacswiki.org/emacs/TrampMode#toc7][on the emacswiki]].
@ -1148,21 +1044,30 @@ upstream, you can't run ~doom update~ to get the latest fixes due to evaluation
errors. errors.
In those cases, you need to delete the broken local copy before you can install In those cases, you need to delete the broken local copy before you can install
the new one, which is achieved thus: 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. 1. Comment out the broken module/package.
2. Run ~doom refresh -p~. 2. Run ~doom sync~.
3. Uncomment the module/package. 3. Uncomment the module/package.
4. Run ~doom refresh~. 4. Run ~doom sync~.
** Why do I see ugly indentation highlights for tabs? ** 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 [[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. Doom uses space indentation for most the indent style you've set for that file. Spaces are Doom's default style for
languages by default (excluding languages where tabs are the norm, like Go). most languages (excluding languages where tabs are the norm, like Go).
There are a couple ways to address this: There are a couple ways to address this:
1. Change ~indent-tabs-mode~ (nil = spaces, t = tabs). 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 #+BEGIN_SRC elisp
;; use tab indentation everywhere ;; use tab indentation everywhere
@ -1173,13 +1078,13 @@ There are a couple ways to address this:
(setq-hook! '(c-mode-hook c++-mode-hook) indent-tabs-mode t) ; C/C++ (setq-hook! '(c-mode-hook c++-mode-hook) indent-tabs-mode t) ; C/C++
#+END_SRC #+END_SRC
2. Use [[https://editorconfig.org/][editorconfig]] to configure code style on a per-project basis. If you 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 enable Doom's =:tools editorconfig= module, Doom will recognize
=.editorconfigrc= files. =.editorconfigrc= files.
3. Or trust in dtrt-indent; a plugin Doom uses to analyze and detect 4. Or trust in dtrt-indent; a plugin Doom uses to analyze and detect indentation
indentation when you open a file (that isn't in a project with an when you open a file (that isn't in a project with an editorconfig file).
editorconfig file). This isn't foolproof, and won't work for files that have This isn't foolproof, and won't work for files that have no content in them,
no content in them, but it can help in one-off scenarios. but it can help in one-off scenarios.
* TODO Contributing * TODO Contributing