Evil

EvilLogo

Evil is an extensible vi layer for Emacs. It provides Vim features like Visual selection and text objects, and is the successor to the now-obsolete Vimpulse and vim-mode. You can find its GitHub repository, here.

Current stable version: 1.14.0

There’s a four-minute Evil demo on YouTube, created by Bailey Ling. The captions in the corner of the frame show the keystrokes which Bailey is entering.

Quick install

Install using the latest version of Emacs and its builtin package system. Start with this in your .emacs:

  (require 'package)
  (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
  (package-initialize)

Then:

  M-x package-refresh-contents
  M-x package-install RET evil

The current development version is available from MELPA. The stable version is listed on MELPA Stable but cannot be installed due to an unavailable dependency. Use the packaging system UI to install either of these by:

Moving cursor over package name.

  i
  x

i - mark for installation, x - to execute

See How to Install Packages Using ELPA, MELPA, Marmalade for more installation options.

After install, add to your .emacs:

  (require 'evil)
  (evil-mode 1)

Install via el-get

Evil can be alternatively downloaded and installed with:

    M-x el-get-install RET evil RET

Install via QUELPA

    M-x quelpa RET evil RET

Install from source

Evil lives in a Git repository. To download Evil, do:

    git clone https://github.com/emacs-evil/evil.git

If you don’t have Git, follow this link to download snapshot of master (extract with tar -xzf master.tar.gz).

Move Evil to ~/.emacs.d/evil (or somewhere else in your load-path). Then add the following lines to ~/.emacs:

    (add-to-list 'load-path "~/.emacs.d/evil")
    (require 'evil)
    (evil-mode 1)

If your .emacs file has a custom-set-variables section, you should place it after Evil.

Evil requires undo-tree.el in the load-path for linear undo and undo branches. Otherwise, Evil uses regular Emacs undo.

Documentation

A brief PDF manual is available in the /doc subdirectory.

There is also a guide on Github made by Noctuid evil-guide.

Plug-ins

Bug tracker

If you have bug reports or suggestions, please submit them at the Bug tracker (open for all).

Managing keymaps

If you want to use the full power of Emacs in Vim-like ways (ie using short key sequences near home row instead of Control-Shift-Nonsense), this section provides some guidance. This guide assumes you’ve read the Evil manual sections “Modes and states” and “Keymaps”.

Overriding and intercept keymaps

There are Emacs modes that provide their own single letter key bindings, independent of Evil. BufferMenu, Ediff, and Edebug are a few examples. By default, Evil allows these modes’ keymaps to override Evil’s. To change this behavior, customize the evil-overriding-maps and evil-intercept-maps variables. If you set these two to nil, then the active Evil keymaps have precedence over other active keymaps. For example, without customization, inputting n in the Buffer Menu will call a Buffer Menu command to move down a line. If Buffer-menu-mode-map is removed from evil-overriding-maps, then n will invoke Evil’s command to go to the next search term.

With these customizations made, there are still some familiar Evil key bindings that are unavailable in Buffer Menu. These pertain to commands that edit raw text – disabled because raw text editing doesn’t make much sense in the Buffer Menu. This is realized by the Buffer-menu-mode entry in the evil-motion-state-maps variable. Because the evil-normal-state-map is inactive in motion state, Buffer Menu commands like x and d are directly available.

Temporary execution in Emacs state

You may still wish to use a mode’s key bindings, if you decided to remove its keymap from evil-overriding-maps or evil-intercept-maps. Evil defines the \ command to temporarily interpret the subsequent Key Sequence in the Emacs state. If you wish to use Buffer Menu’s b command, you can do so with two key strokes: \b . This is pretty reasonable in most cases, but if you want to have a one letter key binding you can add it specifically with the evil-define-key function.

Modes' initial state

While Buffer Menu comes up in motion state, other modes such as Ediff come up in Emacs state where all Evil keymaps are inactive. You may change a mode’s initial state by customizing the evil-*-state-modes variables. The Minibuffer is an exception: it is always in Emacs state regardless of these variables. To move all elements of evil-emacs-state-modes to evil-motion-state-modes:

   (setq evil-motion-state-modes (append evil-emacs-state-modes evil-motion-state-modes))
   (setq evil-emacs-state-modes nil)

Making the most of RET and SPC

It is common for Emacs modes like Buffer Menu, Ediff, and others to define key bindings for RET and SPC. Since these are motion commands, Evil places its key bindings for these in evil-motion-state-map. However, these commands are fairly worthless to a seasoned Vim user, since they do the same thing as j and l commands. Thus it is useful to remove them from evil-motion-state-map so as when modes define them, RET and SPC bindings are available directly.

   (defun my-move-key (keymap-from keymap-to key)
     "Moves key binding from one keymap to another, deleting from the old location. "
     (define-key keymap-to key (lookup-key keymap-from key))
     (define-key keymap-from key nil))
   (my-move-key evil-motion-state-map evil-normal-state-map (kbd "RET"))
   (my-move-key evil-motion-state-map evil-normal-state-map " ")

Key Translations (simple)

Key Translations are another useful Emacs feature which allows one Key Sequence to translate to another prior to Emacs’ process of Key Lookup in the active keymaps. One limitation is an Evil bug that prevents Key Translations taking effect in the operator state.

An example of defining a Key Translation: You could translate ch to C-h and cx to C-x. To do this, make c a Prefix Key so as Key Lookup does not end on the c input alone.

   (define-key evil-normal-state-map "c" nil)
   (define-key evil-motion-state-map "cu" 'universal-argument)

The second line automatically made c a Prefix Key, and its binding was somewhat arbitrary. Now we define the Key Translations:

   (define-key key-translation-map (kbd "ch") (kbd "C-h"))
   (define-key key-translation-map (kbd "cx") (kbd "C-x"))

Note that this won’t interfere with insert state because c is bound to self-insert-command, and the evil-motion-state-map defining c as a Prefix Key is inactive.

Key Translations (better)

The approach above to Key Translations has a couple of disadvantages: it won’t allow single letter Key Translations, and if a mode offers its own binding for ch or cx, it is unavailable to you (not even via \). To resolve these issues, you’ll need to use the Emacs pretest 24.2.90 release which will become Emacs 24.3 .

In addition to updating your Emacs version, you’ll have to enable lexical binding. Doing so might render other Elisp in your init file inoperable if it relies on dynamic binding. Put this on the very first line of your init file:

   ;; -*- lexical-binding: t -*-

C-x is a common Prefix Key and it is extremely convenient to bind to a single letter near home row. Let’s translate ch to C-h and g to C-x as follows:

   ;; Note: lexical-binding must be t in order for this to work correctly.
   (defun make-conditional-key-translation (key-from key-to translate-keys-p)
     "Make a Key Translation such that if the translate-keys-p function returns true,
   key-from translates to key-to, else key-from translates to itself.  translate-keys-p
   takes key-from as an argument. "
     (define-key key-translation-map key-from
       (lambda (prompt)
         (if (funcall translate-keys-p key-from) key-to key-from))))
   (defun my-translate-keys-p (key-from)
     "Returns whether conditional key translations should be active.  See make-conditional-key-translation function. "
     (and
       ;; Only allow a non identity translation if we're beginning a Key Sequence.
       (equal key-from (this-command-keys))
       (or (evil-motion-state-p) (evil-normal-state-p) (evil-visual-state-p))))
   (define-key evil-normal-state-map "c" nil)
   (define-key evil-motion-state-map "cu" 'universal-argument)
   (make-conditional-key-translation (kbd "ch") (kbd "C-h") 'my-translate-keys-p)
   (make-conditional-key-translation (kbd "g") (kbd "C-x") 'my-translate-keys-p)

If another keymap defines a binding for “ch”, you can access it with \ch , because my-translate-keys-p returns false in the Emacs state, resulting in a Key Translation of “ch” to itself.

In non insert state, you can now type “g3” to split-window-right, “go” to move to the other window, etc. This code is written to only translate the key when it is the first of a Key Sequence, so as a binding like “sg” won’t translate into “s C-x”.

If there are Evil g commands you miss, just redefine them for C-x:

   (define-key evil-motion-state-map "\C-x\C-]" 'find-tag)

See evil-maps.el to find all of the Evil g commands.

To continue the pattern of translating “c<char>” to “C-<char>”:

  (when (fboundp 'cl-loop)
        ;; cl-loop iterates from ASCII '!' to ASCII '~'.
        (cl-loop for ascii-code-i from 33 to 126 by 1 do
                 (make-conditional-key-translation (kbd (format "c%c" ascii-code-i))
                                                   (kbd (format "C-%c" ascii-code-i))
                                                   'my-translate-keys-p)))

Create new text objects

See Gordon Gustafson’s answer at http://stackoverflow.com/questions/18102004/emacs-evil-mode-how-to-create-a-new-text-object-to-select-words-with-any-non-sp

Please note there are two ways to define the text objects.

The latest/updated way is for DEV version.

The old/original way is for STABLE version 1.0.9-

Defining your own escape

You can define any key sequence you like for escaping from Evil insert state back to normal state. C-c is one of the options available in Vim by default, but Evil cannot define C-c this way because Emacs coding standards require packages to reserve C-c for the user.

The following Elisp shows how to define C-c as an escape key, using a Key Translation.

   ;;; C-c as general purpose escape key sequence.
   ;;;
   (defun my-esc (prompt)
     "Functionality for escaping generally.  Includes exiting Evil insert state and C-g binding. "
     (cond
      ;; If we're in one of the Evil states that defines [escape] key, return [escape] so as
      ;; Key Lookup will use it.
      ((or (evil-insert-state-p) (evil-normal-state-p) (evil-replace-state-p) (evil-visual-state-p)) [escape])
      ;; This is the best way I could infer for now to have C-c work during evil-read-key.
      ;; Note: As long as I return [escape] in normal-state, I don't need this.
      ;;((eq overriding-terminal-local-map evil-read-key-map) (keyboard-quit) (kbd ""))
      (t (kbd "C-g"))))
   (define-key key-translation-map (kbd "C-c") 'my-esc)
   ;; Works around the fact that Evil uses read-event directly when in operator state, which
   ;; doesn't use the key-translation-map.
   (define-key evil-operator-state-map (kbd "C-c") 'keyboard-quit)
   ;; Not sure what behavior this changes, but might as well set it, seeing the Elisp manual's
   ;; documentation of it.
   (set-quit-char "C-c")

In Emacs, C-g is somewhat analogous to what C-c was in Vim. And since C-c is more ergonomic than C-g, I decided it’s useful and intuitive to translate C-c to C-g if I’m already escaped out of insert state.

Emacs defines C-c as a useful global prefix key. In order to use it, you may define a Key Translation as described in the Key Translation section. Emacs does not apply Key Translation twice so if you define a Key Translation from cc to C-c, cc will not escape but access the global prefix key for C-c as desired.

Another way is to use keychords.el as a basis for an escape key sequence. For example, this Elisp defines ,, as an escape key (very convenient for bépo layout, rather not for qwerty…):

   (key-chord-define evil-normal-state-map ",," 'evil-force-normal-state)
   (key-chord-define evil-visual-state-map ",," 'evil-change-to-previous-state)
   (key-chord-define evil-insert-state-map ",," 'evil-normal-state)
   (key-chord-define evil-replace-state-map ",," 'evil-normal-state)

If you use org-mode or other packages that define C-c prefixes a lot, you may want to remap C-c in all modes except normal mode. This way, you can exit out of insert/visual/replace modes, but then still use C-c keybindings in normal mode.

   (defun my-esc (prompt)
     "Functionality for escaping from Evil insert/visual/replace state using C-c but otherwise leaving C-c intact."
     (cond
      ((or (evil-insert-state-p) (evil-replace-state-p) (evil-visual-state-p)) [escape])
      (t (kbd "C-c"))))
   (define-key key-translation-map (kbd "C-c") 'my-esc)
   (define-key evil-operator-state-map (kbd "C-c") 'keyboard-quit)
   (set-quit-char "C-c")

CapsLock as both Control and Escape

A lot of emacs users remap their CapsLock key to Control. A number of vim users remap their CapsLock to Escape. In Evil mode, it can be useful to do both at once. When in insert mode, you hit CapsLock and get dropped back to command mode. If you do C-x C-; you’ll toggle commenting on the current line. It’s the best of both worlds.

There are a number of ways to accomplish this feat, depending on your operating environment. There is a guide for Linux/Mac/Windows folks. On Linux, xmodmap and xcape appear to be the easiest path.

AceJump Integration

See this gist.

https://gist.github.com/4963125

Changing the mode-line color by state

In Vim I like to have the status line change color when in insert mode and when the buffer is dirty (needs saving). It’s much easier to do in Evil than it is in Vim itself.

   ;; change mode-line color by evil state
   (lexical-let ((default-color (cons (face-background 'mode-line)
                                      (face-foreground 'mode-line))))
     (add-hook 'post-command-hook
       (lambda ()
         (let ((color (cond ((minibufferp) default-color)
                            ((evil-insert-state-p) '("#e80000" . "#ffffff"))
                            ((evil-emacs-state-p)  '("#444488" . "#ffffff"))
                            ((buffer-modified-p)   '("#006fa0" . "#ffffff"))
                            (t default-color))))
           (set-face-background 'mode-line (car color))
           (set-face-foreground 'mode-line (cdr color))))))

Make the most out of search and replace

The ‘cgn’ command is “change next search object”, which is perfect for search and replace. I’ve read an article called (I guess) “Why Vim doesn’t need multiple cursors”, which mentioned that ‘cgn’ + rectangle selection can cover 90% what multiple cursors can do.

Back to the topic, the default evil searching with ‘/’ is:

  1. Hit ‘/’
  2. Insert regex
  3. Hit enter and search
  4. Hit “N” if you jump to the next match
  5. Hit ‘cgn’ to start replacing

This workflow has two downsides:

  1. You need to insert the text again
  2. If you are on the text you want to replace and you start the search, evil automatically jumps to the next match, ew.

How about this:

  1. Go to visual mode and select what you want to replace
  2. Hit `.’
  3. hit ‘cgn’ and replace

Here is the code:

  ;; . in visual mode
  (defun moon/make-region-search-history ()
    "Make region a histroy so I can use cgn."
    (interactive)
    (let ((region (strip-text-properties (funcall region-extract-function nil))))
      (push region evil-ex-search-history)
      (setq evil-ex-search-pattern (evil-ex-make-search-pattern region))
      (evil-ex-search-activate-highlight evil-ex-search-pattern)
      (deactivate-mark)))

Bind this command to `.’ in visual mode and you are set!

Here are some advice functions that can insert the selected text for you in evil search:

  ;; / in visual mode will start search immediately
  (defun moon-evil-ex-start-search-with-region-string ()
    (let ((selection (with-current-buffer (other-buffer (current-buffer) 1)
                       (when (evil-visual-state-p)
                         (let ((selection (buffer-substring-no-properties (region-beginning)
                                                                          (1+ (region-end)))))
                           (evil-normal-state)
                           selection)))))
      (when selection
        (evil-ex-remove-default)
        (insert selection)
        (evil-ex-search-activate-highlight (list selection
                                                 evil-ex-search-count
                                                 evil-ex-search-direction)))))
  (advice-add #'evil-ex-search-setup :after #'moon-evil-ex-start-search-with-region-string)
  ;; # in visual mode
  (defun moon-evil-ex-search-word-backward-advice (old-func count &optional symbol)
    (if (evil-visual-state-p)
        (let ((region (buffer-substring-no-properties
                       (region-beginning) (1+ (region-end)))))
          (setq evil-ex-search-pattern region)
          (deactivate-mark)
          (evil-ex-search-full-pattern region count 'backward))
      (apply old-func count symbol)))
  ;; * in visual mode
  (defun moon-evil-ex-search-word-forward-advice (old-func count &optional symbol)
    (if (evil-visual-state-p)
        (let ((region (buffer-substring-no-properties
                       (region-beginning) (1+ (region-end)))))
          (setq evil-ex-search-pattern region)
          (deactivate-mark)
          (evil-ex-search-full-pattern region count 'forward))
      (apply old-func count symbol)))
  (advice-add #'evil-ex-search-word-backward :around #'moon-evil-ex-search-word-backward-advice)
  (advice-add #'evil-ex-search-word-forward :around #'moon-evil-ex-search-word-forward-advice))

Powerline Integration

Here is a powerline fork tuned for Evil user.

counsel-yank-pop (or yank-pop) integration in visual mode

‘counsel-yank-pop’ in visual mode does not replace the region, instead it just inserts the text. To fix this behavior, I simply advise ‘counsel-yank-pop’ with a function that kills the region.

    (defun moon-override-yank-pop (&optional arg)
          "Delete the region before inserting poped string."
          (when (and evil-mode (eq 'visual evil-state))
            (kill-region (region-beginning) (region-end))))
    (advice-add 'counsel-yank-pop :before #'moon-override-yank-pop)

Discussion

(Evil is also discussed at the gmane.emacs.vim-emulation mailing list and in our IRC channel #evil-mode on irc.freenode.net.)

It would be nice with a brief overview over the objectives and difference to Viper.

The main difference is that while Viper emulates classical vi, Evil emulates Vim. It therefore sports additional features like Visual selection and text objects. Evil also attempts to integrate with Emacs: for example, repetition is implemented in terms of keyboard macros. At the most basic level, Evil is just a collection of key bindings that can be extended and adapted to any Emacs mode.

Vim tabs

The first thing I missed of Vim were the tabs. With elscreen.el and its dependencies installed, the following code emulates part of the Vim behaviour:

    (load "elscreen" "ElScreen" t)
    (elscreen-start)
    (define-key evil-normal-state-map (kbd "C-w t") 'elscreen-create) ;create tab
    (define-key evil-normal-state-map (kbd "C-w x") 'elscreen-kill) ;kill tab
    (define-key evil-normal-state-map "gT" 'elscreen-previous) ;previous tab
    (define-key evil-normal-state-map "gt" 'elscreen-next) ;next tab

Toggle input method

Add below code into ~/.emacs:

    (defun evil-toggle-input-method ()
      "when toggle on input method, switch to evil-insert-state if possible.
    when toggle off input method, switch to evil-normal-state if current state is evil-insert-state"
      (interactive)
      (if (not current-input-method)
          (if (not (string= evil-state "insert"))
              (evil-insert-state))
        (if (string= evil-state "insert")
            (evil-normal-state)
            ))
      (toggle-input-method))
    
    (global-set-key (kbd "C-\\") 'evil-toggle-input-method)

ESC key under GNU Screen

You may find that the ESC key does not work as expected when running “emacs -nw” under GNU Screen. I.e. pressing ESC does not get you out of insert mode if you press quickly. The fix is to put this in your .screenrc

    maptimeout 5

See details here

ESC key under tmux

Like GNU Screen above, the ESC key may not work as expected when running emacs within tmux. This can be alleviated by setting the option ‘escape-time’ to 0. You can perform the following in runtime, or add it to your tmux configuration file:

    set -s escape-time 0

This fix was found on this page

Setting this to 0 causes issues with tmux keybindings beginning with alt. This fixed it for me (same timeout as the screen timeout above):

    set -s escape-time 5

Cursor shape and color when running in terminal mode

In a terminal emulator, the shape and color of the cursor is controlled by the emulator. The default setting will give the same cursor for all states, and it is confusing that the normal state and the insert state have the same cursor. To change the cursor in a terminal emulator, we can send a control sequence to the terminal by the following code:

  (defun my/set-cursor-in-terminal ()
    (unless (display-graphic-p)
      (cond
       ((evil-insert-state-p)
	;; Green bar cursor for insert mode
	(send-string-to-terminal "\033[5 q")  ; bar shape
	(send-string-to-terminal "\033]12;green\007"))  ; green color
       ((evil-normal-state-p)
	;; White block cursor for normal mode
	(send-string-to-terminal "\033[2 q")  ; block shape
	(send-string-to-terminal "\033]12;white\007"))  ; white color
       ((evil-replace-state-p)
	;; Red underline cursor for replace mode
	(send-string-to-terminal "\033[3 q")  ; underline shape
	(send-string-to-terminal "\033]12;red\007"))  ; red color
       )
      ))
  (add-hook 'post-command-hook #'my/set-cursor-in-terminal)

Note that the final effect like the color depends on the terminal used.


CategoryKeys CategoryEmulation CategoryModalEditing