Difference between revisions of "Evil"
(→Plug-ins: evil-goggles) |
|||
(39 intermediate revisions by 9 users not shown) | |||
Line 1: | Line 1: | ||
'''Evil''' is an '''e'''xtensible '''vi''' '''l'''ayer for Emacs. It provides Vim features like Visual selection and text objects, and is the successor to the now defunct vimpulse and vim-mode. | '''Evil''' is an '''e'''xtensible '''vi''' '''l'''ayer for Emacs. It provides Vim features like Visual selection and text objects, and is the successor to the now defunct vimpulse and vim-mode. | ||
− | + | There’s a [http://youtu.be/Uz_0i27wYbg 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. | |
− | + | = Installation = | |
− | |||
− | == | + | Evil can be downloaded and installed using [[el-get]] with: {{Command|el-get-install RET evil RET}}, or using [[Melpa]] with {{Command|package-install RET evil RET}}. |
+ | |||
+ | == Manual install == | ||
Alternatively, Evil lives in a Git repository. To download Evil, do: | Alternatively, Evil lives in a Git repository. To download Evil, do: | ||
− | + | git clone https://github.com/emacs-evil/evil/ | |
− | |||
− | + | If you installed it manually, move Evil to {{Filename|~/.emacs.d/evil}} (or somewhere else in your load-path). | |
− | |||
− | If you installed it manually, move Evil to ~/.emacs.d/evil (or somewhere else in your | ||
In any case, add the following lines to ~/.emacs: | In any case, add the following lines to ~/.emacs: | ||
Line 23: | Line 21: | ||
(evil-mode 1) | (evil-mode 1) | ||
+ | Evil requires [[UndoTree]] in the load-path for linear undo and undo branches. Otherwise, Evil uses regular Emacs undo. | ||
+ | |||
+ | = Documentation = | ||
+ | |||
+ | A brief [https://bytebucket.org/lyro/evil/raw/default/doc/evil.pdf PDF manual] is available in the /doc subdirectory. | ||
+ | |||
+ | = Usage = | ||
+ | |||
+ | For those not familiar with vim, here's a quick summary of useful commands. | ||
+ | |||
+ | |||
+ | '''Tip:''': to see a full list of commands available in the current mode, install ''help-fns+'' with [[ELPA]], require it (see its doc). Now you can type '''C-h M-k'''. | ||
+ | |||
+ | |||
+ | To enter '''insert''' state: try out '''i a o''' and the upper-case ones; | ||
+ | |||
+ | To delete chars, words and lines use '''x''', the usual '''d''' followed by a word or a movement ('''$''' is end of line, '''^''' the beginning), '''dd''' and '''D''', or replace an object with '''c''' ; Want to delete a whole line and enter insert mode ? '''S''' or '''cc'''. | ||
+ | |||
+ | Copy and paste: '''y Y p P''' ; | ||
+ | |||
+ | To navigate around the buffer, in normal mode, use '''e E w W b B t T f F ( ) { }''' and '''j k h l - + <RET> <backspace> <space>'''; | ||
+ | Go to beginning and end of buffer with '''gg''' and '''G'''; | ||
+ | |||
+ | Cycle between cursor position: double backquotes, '''C-i''' and '''C-o'''; | ||
+ | |||
+ | To navigate around the screen, use '''H L M''' to go to the Highest/Lowest/Middle line of the screen; | ||
+ | |||
+ | Search forward and backward with '''/''' and '''?''', use '''n''' and '''N''' to go to the next and previous occurence; | ||
+ | |||
+ | Go to the next or previous occurence of token under point with '''*''' or '''#''' ; | ||
+ | |||
+ | Select a region with '''v''' or '''V''', use '''vi''' and '''"''', '''(''' or '''[''' to select what's inside them and re-select the last region selected with '''gv'''. Again with text objects, type '''ci(''' when you are inside brackets to replace all that is inside them. | ||
+ | |||
+ | Go to the '''definition of the symbol''' under point with '''gd''' ; | ||
+ | |||
+ | Indent the line or region with '''<''' and '''>''' ; | ||
+ | |||
+ | |||
+ | Operate on text objects: '''diw''' will delete a word, replace the '''w''' with a '''p''' to act on the paragraph; | ||
+ | |||
+ | |||
+ | Some more: | ||
+ | |||
+ | Join lines with '''J''' | ||
+ | |||
+ | Set a mark with '''m<char>''', go to a mark with backquote + <char> | ||
+ | |||
+ | Move the current line at the center, bottom and top of screen: '''zz''', '''zb''' and '''zt''' (C-l with emacs). | ||
+ | |||
+ | == Code folding == | ||
+ | |||
+ | '''Code folding''' with '''za''' (toggle), '''zc''' (close), '''zm''' and '''zr''' (close and open all). They are an interface to other folding packages, most notably hideshow. The value of the variable <code>evil-fold-list</code> determines which backend is used for which major or minor modes, and what functions are available for those backends. | ||
+ | |||
+ | The [https://github.com/mrkkrp/vimish-fold vimish-fold] package (in MELPA) features: | ||
+ | |||
+ | * folding of active regions; | ||
+ | |||
+ | * good visual feedback: it's obvious which part of text is folded; | ||
+ | |||
+ | * persistence by default: when you kill a buffer your folds don't disappear; | ||
+ | |||
+ | * persistence scales well, you can work on hundreds of files with lots of folds without adverse effects; | ||
+ | |||
+ | * it does not break indentation; | ||
+ | |||
+ | * folds can be toggled from folded state to unfolded and back very easily; | ||
+ | |||
+ | * quick navigation between existing folds; | ||
+ | |||
+ | * you can use mouse to unfold folds (good for beginners and not only for them); | ||
+ | |||
+ | * for fans of the avy package: you can use avy to fold text with minimal number of key strokes! | ||
+ | |||
+ | See also [[Folding]]. | ||
+ | |||
+ | = Configuration = | ||
+ | |||
+ | One thing I would recommend to any ex vimmer is to make escape to quit actually pretty much anything (like pending prompts in the minibuffer): | ||
+ | |||
+ | ;;; esc quits | ||
+ | (define-key evil-normal-state-map [escape] 'keyboard-quit) | ||
+ | (define-key evil-visual-state-map [escape] 'keyboard-quit) | ||
+ | (define-key minibuffer-local-map [escape] 'minibuffer-keyboard-quit) | ||
+ | (define-key minibuffer-local-ns-map [escape] 'minibuffer-keyboard-quit) | ||
+ | (define-key minibuffer-local-completion-map [escape] 'minibuffer-keyboard-quit) | ||
+ | (define-key minibuffer-local-must-match-map [escape] 'minibuffer-keyboard-quit) | ||
+ | (define-key minibuffer-local-isearch-map [escape] 'minibuffer-keyboard-quit) | ||
+ | |||
+ | The following makes you lose vim commands, but gives you back basic emacs commands, like C-y to paste in insert mode or C-r to search backward: | ||
+ | |||
+ | (define-key evil-normal-state-map "\C-y" 'yank) | ||
+ | (define-key evil-insert-state-map "\C-y" 'yank) | ||
+ | (define-key evil-visual-state-map "\C-y" 'yank) | ||
+ | (define-key evil-insert-state-map "\C-e" 'end-of-line) | ||
+ | (define-key evil-normal-state-map "\C-w" 'evil-delete) | ||
+ | (define-key evil-insert-state-map "\C-w" 'evil-delete) | ||
+ | (define-key evil-insert-state-map "\C-r" 'search-backward) | ||
+ | (define-key evil-visual-state-map "\C-w" 'evil-delete) | ||
+ | |||
+ | == Use fine grain undo == | ||
+ | |||
+ | In insert mode, Evil uses linear undo. If you want fine grain undo: | ||
+ | |||
+ | (setq evil-want-fine-undo t) | ||
+ | |||
+ | but remember, we shouldn't stay long in insert mode. | ||
+ | |||
+ | == Use keychords to go back to normal mode == | ||
+ | |||
+ | If you'd like to type jj or jk in insert mode to go back to normal mode, you may use [[key-chord]]: | ||
+ | |||
+ | (key-chord-define evil-insert-state-map "jj" 'evil-normal-state) | ||
+ | |||
+ | Or you can use [https://melpa.org/#/evil-escape evil-escape], which is installed by default in [[spacemacs]]: | ||
+ | |||
+ | (setq-default evil-escape-key-sequence "jj") | ||
+ | |||
+ | == Load config only when we call evil-mode == | ||
+ | |||
+ | I still load evil with M-x, I didn't set (evil-mode 1), so in order to tweak keybindings I had to enclose them in a hook, so that my config is called when evil is called and not at startup: | ||
+ | |||
+ | (add-hook 'evil-after-load-hook | ||
+ | (lambda () | ||
+ | ;; config | ||
+ | )) | ||
+ | |||
+ | == Hooks == | ||
+ | |||
+ | There are some hooks that allow to do things when we enter or exit a mode (see the pdf manual). | ||
+ | |||
+ | For example, to save the buffer when we exit the insert mode: | ||
+ | |||
+ | (defun my-save-if-bufferfilename () | ||
+ | (if (buffer-file-name) | ||
+ | (progn | ||
+ | (save-buffer) | ||
+ | ) | ||
+ | (message "no file is associated to this buffer: do nothing") | ||
+ | ) | ||
+ | ) | ||
+ | |||
+ | (add-hook 'evil-insert-state-exit-hook 'my-save-if-bufferfilename) | ||
+ | |||
+ | == Enter an emacs mode in a given state == | ||
+ | |||
+ | There are some situations where you don't want to be in normal mode by default. For example, it's more useful to be in insert mode when we enter a magit commit buffer, or maybe you prefer to be in emacs mode in a dired buffer. | ||
+ | |||
+ | For that purpose, evil provides the '''evil-set-initial-state''' command (see part 2.2 of the pdf documentation) that we can use like that: | ||
+ | |||
+ | <source lang="lisp"> | ||
+ | (evil-set-initial-state 'git-commit-mode 'insert) ;; enter insert mode to edit a commit message | ||
+ | </source> | ||
− | + | Here is a handy loop to define more at once: | |
− | = | + | <source lang="lisp"> |
+ | (loop for (mode . state) in '((inferior-emacs-lisp-mode . emacs) | ||
+ | (nrepl-mode . insert) | ||
+ | (pylookup-mode . emacs) | ||
+ | (comint-mode . normal) | ||
+ | (shell-mode . insert) | ||
+ | (git-commit-mode . insert) | ||
+ | (git-rebase-mode . emacs) | ||
+ | (term-mode . emacs) | ||
+ | (help-mode . emacs) | ||
+ | (helm-grep-mode . emacs) | ||
+ | (grep-mode . emacs) | ||
+ | (bc-menu-mode . emacs) | ||
+ | (magit-branch-manager-mode . emacs) | ||
+ | (rdictcc-buffer-mode . emacs) | ||
+ | (dired-mode . emacs) | ||
+ | (wdired-mode . normal)) | ||
+ | do (evil-set-initial-state mode state)) | ||
+ | </source> | ||
− | + | = See also = | |
− | + | == Articles == | |
* [http://dnquark.com/blog/2012/02/emacs-evil-ecumenicalism/ Emacs Evil Ecumenicalism] | * [http://dnquark.com/blog/2012/02/emacs-evil-ecumenicalism/ Emacs Evil Ecumenicalism] | ||
− | + | == Plug-ins == | |
+ | |||
+ | * [[ace-jump]]: Port of Vim's Easy-motion: jump to any character in the buffer with 3 keystrokes. | ||
* [https://github.com/timcharper/evil-surround evil-surround]: Port of Vim's surround script. | * [https://github.com/timcharper/evil-surround evil-surround]: Port of Vim's surround script. | ||
Line 42: | Line 212: | ||
* [https://github.com/cofi/evil-leader evil-leader]: Port of Vim's mapleader. | * [https://github.com/cofi/evil-leader evil-leader]: Port of Vim's mapleader. | ||
− | * [[ | + | * [https://github.com/edwtjo/evil-org-mode evil-org-mode]: Supplemental evil-mode key-bindings to Emacs org-mode. |
+ | |||
+ | * [https://github.com/krisajenkins/evil-tabs evil-tabs]: for when you type <code>:tabnew</code> and nothing happens. | ||
+ | |||
+ | * [https://github.com/raugturi/powerline-evil powerline-evil]: Utilities for better Evil support for Powerline. | ||
+ | |||
+ | * [https://github.com/Dewdrops/evil-exchange evil-exchange]: a port of vim-exchange | ||
+ | |||
+ | * [https://github.com/gridaphobe/evil-god-state evil-god-state]: an evil-mode state for using god-mode. | ||
+ | |||
+ | * [https://github.com/cofi/evil-leader evil-leader]: <leader> key for evil | ||
+ | |||
+ | * [https://github.com/noctuid/general.el general.el]: allows defining multiple keys at once, implicitly wrapping key strings with (kbd ...), having named prefix key sequences (like the leader key in vim), and more. For evil and non-evil users. | ||
+ | |||
+ | * [https://github.com/roman/evil-paredit evil-paredit]: integration to paredit | ||
+ | |||
+ | * [http://melpa.milkbox.net/#/evil-visualstar evil-visualstar]: make a visual selection and search it. | ||
+ | |||
+ | * [https://github.com/gabesoft/evil-mc evil-mc]: easy multiple cursors | ||
+ | |||
+ | * [http://melpa.org/#/evil-jumper evil-jumper]: jump accross buffer boundaries | ||
+ | |||
+ | * [https://github.com/hlissner/evil-snipe evil-snipe]: a port of [https://github.com/justinmk/vim-sneak vim-sneak]/[https://github.com/goldfeld/vim-seek vim-seek]; 2-char searching | ||
+ | |||
+ | search for all plugins in [http://melpa.milkbox.net/#/ the melpa page]. | ||
+ | |||
+ | === Visual feedbak === | ||
+ | |||
+ | With [https://github.com/edkolev/evil-goggles evil-goggles], we get visual feedback of evil's selections. | ||
− | + | == Bug tracker == | |
− | The | + | The bugtracker can be found on [https://github.com/emacs-evil/evil/issues GitHub]. |
[[Category:Vi User]] [[Category:Vim User]] | [[Category:Vi User]] [[Category:Vim User]] | ||
+ | [[Category:Text_Editing]] |
Latest revision as of 21:43, 5 September 2017
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 defunct vimpulse and vim-mode.
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.
Installation
Evil can be downloaded and installed using el-get with: M-x el-get-install RET evil RET, or using Melpa with M-x package-install RET evil RET.
Manual install
Alternatively, Evil lives in a Git repository. To download Evil, do:
git clone https://github.com/emacs-evil/evil/
If you installed it manually, move Evil to ~/.emacs.d/evil (or somewhere else in your load-path).
In any case, add the following lines to ~/.emacs:
(add-to-list 'load-path "~/.emacs.d/evil") ;;no need with 24 (require 'evil) (evil-mode 1)
Evil requires UndoTree 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.
Usage
For those not familiar with vim, here's a quick summary of useful commands.
Tip:: to see a full list of commands available in the current mode, install help-fns+ with ELPA, require it (see its doc). Now you can type C-h M-k.
To enter insert state: try out i a o and the upper-case ones;
To delete chars, words and lines use x, the usual d followed by a word or a movement ($ is end of line, ^ the beginning), dd and D, or replace an object with c ; Want to delete a whole line and enter insert mode ? S or cc.
Copy and paste: y Y p P ;
To navigate around the buffer, in normal mode, use e E w W b B t T f F ( ) { } and j k h l - + <RET> <backspace> <space>; Go to beginning and end of buffer with gg and G;
Cycle between cursor position: double backquotes, C-i and C-o;
To navigate around the screen, use H L M to go to the Highest/Lowest/Middle line of the screen;
Search forward and backward with / and ?, use n and N to go to the next and previous occurence;
Go to the next or previous occurence of token under point with * or # ;
Select a region with v or V, use vi and ", ( or [ to select what's inside them and re-select the last region selected with gv. Again with text objects, type ci( when you are inside brackets to replace all that is inside them.
Go to the definition of the symbol under point with gd ;
Indent the line or region with < and > ;
Operate on text objects: diw will delete a word, replace the w with a p to act on the paragraph;
Some more:
Join lines with J
Set a mark with m<char>, go to a mark with backquote + <char>
Move the current line at the center, bottom and top of screen: zz, zb and zt (C-l with emacs).
Code folding
Code folding with za (toggle), zc (close), zm and zr (close and open all). They are an interface to other folding packages, most notably hideshow. The value of the variable evil-fold-list
determines which backend is used for which major or minor modes, and what functions are available for those backends.
The vimish-fold package (in MELPA) features:
- folding of active regions;
- good visual feedback: it's obvious which part of text is folded;
- persistence by default: when you kill a buffer your folds don't disappear;
- persistence scales well, you can work on hundreds of files with lots of folds without adverse effects;
- it does not break indentation;
- folds can be toggled from folded state to unfolded and back very easily;
- quick navigation between existing folds;
- you can use mouse to unfold folds (good for beginners and not only for them);
- for fans of the avy package: you can use avy to fold text with minimal number of key strokes!
See also Folding.
Configuration
One thing I would recommend to any ex vimmer is to make escape to quit actually pretty much anything (like pending prompts in the minibuffer):
;;; esc quits (define-key evil-normal-state-map [escape] 'keyboard-quit) (define-key evil-visual-state-map [escape] 'keyboard-quit) (define-key minibuffer-local-map [escape] 'minibuffer-keyboard-quit) (define-key minibuffer-local-ns-map [escape] 'minibuffer-keyboard-quit) (define-key minibuffer-local-completion-map [escape] 'minibuffer-keyboard-quit) (define-key minibuffer-local-must-match-map [escape] 'minibuffer-keyboard-quit) (define-key minibuffer-local-isearch-map [escape] 'minibuffer-keyboard-quit)
The following makes you lose vim commands, but gives you back basic emacs commands, like C-y to paste in insert mode or C-r to search backward:
(define-key evil-normal-state-map "\C-y" 'yank) (define-key evil-insert-state-map "\C-y" 'yank) (define-key evil-visual-state-map "\C-y" 'yank) (define-key evil-insert-state-map "\C-e" 'end-of-line) (define-key evil-normal-state-map "\C-w" 'evil-delete) (define-key evil-insert-state-map "\C-w" 'evil-delete) (define-key evil-insert-state-map "\C-r" 'search-backward) (define-key evil-visual-state-map "\C-w" 'evil-delete)
Use fine grain undo
In insert mode, Evil uses linear undo. If you want fine grain undo:
(setq evil-want-fine-undo t)
but remember, we shouldn't stay long in insert mode.
Use keychords to go back to normal mode
If you'd like to type jj or jk in insert mode to go back to normal mode, you may use key-chord:
(key-chord-define evil-insert-state-map "jj" 'evil-normal-state)
Or you can use evil-escape, which is installed by default in spacemacs:
(setq-default evil-escape-key-sequence "jj")
Load config only when we call evil-mode
I still load evil with M-x, I didn't set (evil-mode 1), so in order to tweak keybindings I had to enclose them in a hook, so that my config is called when evil is called and not at startup:
(add-hook 'evil-after-load-hook (lambda () ;; config ))
Hooks
There are some hooks that allow to do things when we enter or exit a mode (see the pdf manual).
For example, to save the buffer when we exit the insert mode:
(defun my-save-if-bufferfilename () (if (buffer-file-name) (progn (save-buffer) ) (message "no file is associated to this buffer: do nothing") ) )
(add-hook 'evil-insert-state-exit-hook 'my-save-if-bufferfilename)
Enter an emacs mode in a given state
There are some situations where you don't want to be in normal mode by default. For example, it's more useful to be in insert mode when we enter a magit commit buffer, or maybe you prefer to be in emacs mode in a dired buffer.
For that purpose, evil provides the evil-set-initial-state command (see part 2.2 of the pdf documentation) that we can use like that:
(evil-set-initial-state 'git-commit-mode 'insert) ;; enter insert mode to edit a commit message
Here is a handy loop to define more at once:
(loop for (mode . state) in '((inferior-emacs-lisp-mode . emacs)
(nrepl-mode . insert)
(pylookup-mode . emacs)
(comint-mode . normal)
(shell-mode . insert)
(git-commit-mode . insert)
(git-rebase-mode . emacs)
(term-mode . emacs)
(help-mode . emacs)
(helm-grep-mode . emacs)
(grep-mode . emacs)
(bc-menu-mode . emacs)
(magit-branch-manager-mode . emacs)
(rdictcc-buffer-mode . emacs)
(dired-mode . emacs)
(wdired-mode . normal))
do (evil-set-initial-state mode state))
See also
Articles
Plug-ins
- ace-jump: Port of Vim's Easy-motion: jump to any character in the buffer with 3 keystrokes.
- evil-surround: Port of Vim's surround script.
- evil-numbers: Vim-like increment and decrement.
- evil-leader: Port of Vim's mapleader.
- evil-org-mode: Supplemental evil-mode key-bindings to Emacs org-mode.
- evil-tabs: for when you type
:tabnew
and nothing happens.
- powerline-evil: Utilities for better Evil support for Powerline.
- evil-exchange: a port of vim-exchange
- evil-god-state: an evil-mode state for using god-mode.
- evil-leader: <leader> key for evil
- general.el: allows defining multiple keys at once, implicitly wrapping key strings with (kbd ...), having named prefix key sequences (like the leader key in vim), and more. For evil and non-evil users.
- evil-paredit: integration to paredit
- evil-visualstar: make a visual selection and search it.
- evil-mc: easy multiple cursors
- evil-jumper: jump accross buffer boundaries
- evil-snipe: a port of vim-sneak/vim-seek; 2-char searching
search for all plugins in the melpa page.
Visual feedbak
With evil-goggles, we get visual feedback of evil's selections.
Bug tracker
The bugtracker can be found on GitHub.