:editor evil

Come to the dark side, we have cookies

1. Description

A holy module that brings the best vim emulation you’ll find in any editor and, sometimes, even vim itself.

1.2. Module flags

+everywhere
Enable evilified keybinds everywhere possible. Uses evil-collection as a foundation.

1.4. Hacks

  • The o/O keys will respect and continue commented lines (can be disabled by setting +evil-want-o/O-to-continue-comments to nil).
  • In visual mode, * and # will search for the current selection instead of the word-at-point.
  • The :g[lobal] ex command has been modified to highlight matches.
  • More of vim’s filename modifiers are supported in ex commands (like :p, :p:h or :t) than vanilla evil-mode offers.
  • A custom filename modifier is available in Doom: :P, which expands to the project root (throws an error if not in a project).

2. Prerequisites

This module has no external prerequisites.

3. Usage

3.1. Ported vim plugins

The following vim plugins have been ported to evil:

Vim Plugin Emacs Plugin Keybind(s)
vim-commentary evil-nerd-commenter omap gc
vim-easymotion evil-easymotion omap gs
vim-lion evil-lion omap gl/gL
vim-seek or vim-sneak evil-snipe mmap s/S, omap z/Z & x/X
vim-surround evil-embrace and evil-surround vmap S, omap ys
vim-unimpaired (provided by Doom) See the list

This module has also ported vim-unimpaired keybinds to Emacs.

In other modules:

3.2. Custom Text Objects

This module provides a couple extra text objects, along with the built-in ones. For posterity, here are the built-in ones:

  • w W words
  • s sentences
  • p paragraphs
  • b parenthesized blocks
  • b ( ) { } [ ] < > braces, parentheses and brackets
  • ' " ` quotes
  • t tags
  • o symbols

And these are text objects added by this module:

  • a C-style function arguments (provided by evil-args)
  • B any block delimited by braces, parentheses or brackets (provided by evil-textobj-anyblock)
  • c Comments
  • f For functions (but relies on the major mode to have sane definitions for beginning-of-defun-function and end-of-defun-function)
  • g The entire buffer
  • i j k by indentation (k includes one line above; j includes one line above and below) (provided by evil-indent-plus)
  • q For quotes (any kind)
  • u For URLs
  • x XML attributes (provided by exato)

3.3. Custom Ex Commands

Ex Command Description
:@ Apply macro on selected lines
:al[ign][!] REGEXP Align text to the first match of REGEXP. If BANG, align all matches on each line
:cp[!] NEWPATH Copy the current file to NEWPATH
:dash QUERY Look up QUERY (or the symbol at point) in dash docsets
:dehtml [INPUT] HTML decode selected text / inserts result if INPUT is given
:enhtml [INPUT] HTML encode selected text / inserts result if INPUT is given
:iedit REGEXP Invoke iedit on all matches for REGEXP
:k[ill]all[!] Kill all buffers (if BANG, affect buffer across workspaces)
:k[ill]b Kill all buried buffers
:k[ill]m[!] REGEXP Kill buffers whose name matches REGEXP (if BANG, affect buffers across workspaces)
:k[ill]o Kill all other buffers besides the selected one
:k[ill] Kill the current buffer
:lo[okup] QUERY Look up QUERY on an online search engine
:mc REGEXP Invoke multiple cursors on all matches for REGEXP
:mv[!] NEWPATH Move the current file to NEWPATH
:na[rrow] Narrow the buffer to the selection
:pad Open a scratch pad for running code quickly
:ral[ign][!] REGEXP Right-Align text that matches REGEXP. If BANG, align all matches on each line
:repl Open a REPL and/or copy the current selection to it
:retab Convert indentation to the default within the selection
:rev[erse] Reverse the selected lines
:rm[!] [PATH] Delete the current buffer’s file and buffer
:tcd[!] Send cd X to tmux. X = the project root if BANG, X = default-directory otherwise

4. Configuration

4.1. Removing evil-mode

You must do two things to remove Evil:

  1. Remove :editor evil from $DOOMDIR/init.el,
  2. Run $ doom sync to clean up lingering dependencies and regenerate your autoloads files.

Once evil is disabled, you may want to assign new values to doom-leader-alt-key and doom-localleader-alt-key. These are bound to C-c and C-c l by default.

Also, ignore doom-leader-key and doom-localleader-key; they aren’t used in non-evil setups.

Evil-specific configuration and keybindings (defined with map!) will be ignored without :editor evil present (and omitted when byte-compiling).

Afterwards, I suggest studying config/default/+emacs-bindings.el to see what keybinds are available for non-evil users. Otherwise, you may find inspiration on the example Doom configurations page.

4.2. Restoring old substitution behavior on s/S

Doom replaces the s and S keys with the evil-snipe package (a port of vim-seek/vim-sneak for 2-character versions of f/F/t/T).

To disable evil-snipe on s/S, you can either:

  1. Disable evil-snipe-mode by adding (remove-hook 'doom-first-input-hook #'evil-snipe-mode) to $DOOMDIR/config.el,
  2. Or disable the evil-snipe package with (package! evil-snipe :disable t) added to $DOOMDIR/packages.el, but this will also disable incremental highlighting for the f/F/t/T motions keys.
  3. Or use cl and cc, respectively; they do the same thing.

4.3. Restoring old Y behavior (yank the whole line)

Doom changes the behavior of the Y key in normal mode to yank-to-EOL (equivalent to y$). This was to make it consistent with the C and D capital operators, and because it was redundant with yy, which is easier to type than y$.

If you prefer the old behavior, it can be reversed with:

;; add to $DOOMDIR/config.el
(setq! evil-want-Y-yank-to-eol nil)

4.4. Disabling cursor movement when exiting insert mode

Vim (and evil) move the cursor one character back when exiting insert mode. If you prefer that it didn’t, set:

;; add to $DOOMDIR/config.el
(setq evil-move-cursor-back nil)

4.5. Increment/decrement number at point

Vimmers may notice that C-a and C-x do not increment and decrement numbers like they do in vim.

Because C-x is a pivotal Emacs keybind, it was decided that Doom would bind these keys elsewhere:

  • g -
  • g =
  • g +

If you want these on C-x and C-a you can forcibly bind them yourself:

(map! :n  "C-a"   #'evil-numbers/inc-at-pt
      :v  "C-a"   #'evil-numbers/inc-at-pt-incremental
      :v  "C-S-a" #'evil-numbers/inc-at-pt
      :n  "C-x"   #'evil-numbers/dec-at-pt
      :v  "C-x"   #'evil-numbers/dec-at-pt-incremental)

5. TODO Appendix

This module has no appendix yet. Write one?