Doom’s FAQs have moved to Discourse. This file will be removed soon.
bin/doom?bin/doom is runningvoid-function errors on startups and S keys don’t behave like they do in vim/evil (#1307)unable to find theme file for X errorsIt’s an homage to idsoftware’s classic game, whose 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.
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.
It does, but there are caveats:
That said, Doom does have happy Windows users (using WSL or scoop/chocolatey). 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!
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 removing evil-mode section in the :editor evil module’s documentation.
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 if you ask – but expect a hefty commitment and a bumpy journey. Don’t pass up on the Documentation: it’ll work you through setting Doom up and includes links to external resources created by myself or the community.
To paraphrase (and expand upon) a reddit answer to this question by @gilbertw1:
bin/doom script
allows you to script package management, manage your config, or utilize elisp
functionality externally, like org tangling or batch processing.Doom had four five goals for its package management system:
Doom employs a number of techniques to cut down startup time. Here are its most effective techniques:
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:
(setq gc-cons-threshold most-positive-fixnum ; 2^61 bytes
gc-cons-percentage 0.6)
;; ... your emacs config here ...
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.
(add-hook 'emacs-startup-hook
(lambda ()
(setq gc-cons-threshold 16777216 ; 16mb
gc-cons-percentage 0.1)))
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:
(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)
Another alternative (which is what Doom uses) is the gcmh package; which staves off the GC until you are idle. Doom also triggers GC when you unfocus the Emacs frame.
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 Doom
Emacs has its own specialized mechanism for this, topped off with a few
Doom-specific optimizations.
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):
(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)
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!
;; 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)
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:
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.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:
(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)
This ensures packages load as quickly as possible when you first load an org file.
file-name-handler-alist temporarilyEmacs 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!):
(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)))
Don’t forget to restore file-name-handler-alist, otherwise TRAMP won’t work
and compressed/encrypted files won’t open.
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:
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:
-Q).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?
I recommend Chemacs. Think of it as a bootloader for Emacs. You’ll 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:
# 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
Warning: the way
bin/doom runstarts Doom bypasses many of its startup optimizations. Treat it as a convenience for testing rather than a permanent entry point.
Two reasons:
It also integrates with command line workflows, so automate to your heart’s content!
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.
You’ll find an overview of Doom’s code conventions in the contributing guide.
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.
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 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.
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?
:ui tabs, :ui indent-guides, :ui ligatures, :editor word-wrap and :ui
vc-gutter.(setq display-line-numbers-type nil). It’s known to
slow down scrolling, in particular.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:
(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))
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.:ui modeline module with :ui (modeline +light). There
are aspects of the default modeline that can be unpredictably slow.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 (/).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 Customize section in the Getting Started guide for details.
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.
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 ”Configuration modules” section of the Getting Started guide for more information.
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.
;;; add to ~/.doom.d/config.el
(setq doom-theme 'doom-tomorrow-night)
;; or
(load-theme 'doom-tomorrow-night t)
At the moment, the only difference between the two is that
doom-themeis loaded when Emacs has finished initializing at startup andload-themeloads the theme immediately. Which you choose depends on your needs, but I recommend settingdoom-themebecause, if I later discover a better way to load themes, I can easily change how Doom usesdoom-theme, but I can’t (easily) control how you use theload-themefunction.
To install a theme from a third party plugin, say, solarized, you need only install it, then load it:
;;; add to ~/.doom.d/packages.el
(package! solarized-theme)
;;; add to ~/.doom.d/config.el
(setq doom-theme 'solarized-dark)
Don’t forget to run doom sync after adding that package! statement to ensure
the package is installed.
Doom exposes five (optional) variables for controlling fonts in Doom, they are:
doom-fontdoom-variable-pitch-fontdoom-serif-fontdoom-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 xlfd
font string.
e.g.
;;; 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))
There are many options. Emacs provides a number of keybind functions:
define-key KEYMAP KEY DEFglobal-set-key KEY DEFlocal-set-key KEY DEFevil-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 in
docs/api).
There are also live examples map!’s usage in config/default/+evil-bindings.el.
(This explanation comes from 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:
(modify-syntax-entry ?_ "w")
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.:
;; 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"))
These variables control what key to use for leader and localleader keys:
doom-leader-key (default: SPC)doom-localleader-key (default: SPC m)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.
;;; add to ~/.doom.d/config.el
(setq doom-leader-key ","
doom-localleader-key "\\")
Doom uses the display-line-numbers package, which is built into Emacs 26+.
;;; 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)
To change the style of line numbers, change the value of the
display-line-numbers-type variable. It accepts the following values:
t normal line numbers 'relative relative line numbers 'visual relative line numbers in screen space nil no line numbers
For example:
;;; add to ~/.doom.d/config.el
(setq display-line-numbers-type 'relative)
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).
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.
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 :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).
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.
Other sources may recommend
M-x customize,M-x customize-themesorM-x customize-face. Do not use these commands. Doom does not support them and their settings could break any time.
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:
;; add to ~/.doom.d/config.el
(setq doom-theme 'XYZ)
;; or
(load-theme 'XYZ t)
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):
+eval/region (bound to the gr
operator for evil users) or eval-last-sexp (bound to C-x C-e). Changes
take effect immediately.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.
doom/restart-and-restore (bound to SPC q r).Yes! See the Removing evil-mode section in :editor evil’s documentation.
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 doctordoom syncdoom installdoom updatedoom envdoom purge -gdoom upgrade
git pull
doom sync
doom update
doom sync
As a rule of thumb you should run doom sync whenever you:
git pull instead of doom upgrade,doom! block in $DOOMDIR/init.el,$DOOMDIR),$DOOMDIR).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.
bin/doom is runningThe -y and --yes flags (or the YES environment variable) will force
bin/doom to auto-accept confirmation prompts:
doom -y update
doom --yes update
YES=1 doom update
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 the :term
vterm module’s documentation.For a terminal in Emacs, eshell and vterm are generally the best options.
Doom supports LSP, but it is not enabled by default. To enable it, you must:
:tools lsp module,+lsp flag for the appropriate modules you want LSP support for
(e.g. :lang (python +lsp) or :lang (rust +lsp)),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:
(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
Some outdated sources may tell you to do this, but it is no longer correct:
(after! smartparens
(smartparens-global-mode -1))
Instead, use the following:
(remove-hook 'doom-first-buffer-hook #'smartparens-global-mode)
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.
(add-to-list 'initial-frame-alist '(fullscreen . maximized))
Some window managers may not understand/work with maximized (or may not
produce the desired effect), in that case try fullboth or fullscreen.
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.
See the ”Installing packages” section of the Getting Started guide.
See the ”Installing packages from external sources” section of the Getting Started guide.
See the ”Changing a recipe for a included package” section of the Getting Started guide.
See the ”disabling packages” section of the Getting Started guide.
See the ”configuring packages” section of the Getting Started guide.
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.
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.
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.
expand-region is redundant with and less precise than evil’s text objects and
motions.
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.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.
There are also text objects for xml tags (
x), C-style function arguments (a), angle brackets, and single/double quotes.
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:
;;; 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)
doom env?The doom env approach is a faster and more reliable solution.
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.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:
;;; 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))
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!
#'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.
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.
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.
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 startupThe most common culprit for these types of errors are:
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.
doom build,~/.emacs.d/.local/straight then running doom install (this
will take a while).PATH
The two most common causes for PATH issues in Doom are:
PATH correctly. If which
<PROGRAM> doesn’t emit the path you expect on the command line then this is
likely the case.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. Our Discord is a good place to ask about it.
Check your font rendering settings. Changing the RGBA order to “rgba” will often fix this issue. See #956 for details.
s and S keys don’t behave like they do in vim/evil (#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:
;; in ~/.doom.d/config.el
(remove-hook 'doom-first-input-hook #'evil-snipe-mode)
~/.doom.d and ~/.config/doom directories.
Doom will ignore the former if the latter exists.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.
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:
+childframe flag on the modules that
support it),emacs-mac homebrew formula.Here are a few common causes for random crashes:
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:
(after! org
(setq org-startup-indented nil))
Or disable the :ui doom-dashboard & :tools magit modules (see #1170).
unable to find theme file for X errorsThis 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:
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:
(require 'third-party-theme)
(setq doom-theme 'third-party)
-theme to the end of your theme’s name.
(setq doom-theme 'third-party-theme)
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.
doom sync after adding your third party theme plugin’s
package! declaration to ~/.doom.d/packages.el?You’ll find solutions on the emacswiki.
Sometimes, if you’ve installed a 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:
doom sync.doom sync.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:
Two easy commands for that:
M-x tabifyM-x untabifyindent-tabs-mode (nil = spaces, t = tabs) in ~/.doom.d/config.el:
;; 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++
:tools editorconfig module, Doom will recognize
.editorconfigrc files.This applies to tmux users, in particular. See https://github.com/spudlyo/clipetty/issues/15 for a solution.
If you’re getting this error you must reset the owner of
C:\Users\USERNAME\.emacs.d to your own account:
~/.emacs.d/server directory in Windows Explorer,(source)
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:
(map! "<C-left>" #'something
"<C-right>" #'something)
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:
(map! :after smartparens
:map smartparens-mode-map
[C-right] nil
[C-left] nil)
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.
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。