This is a collection of Evil bindings for the parts of Emacs that Evil does
not cover properly by default, such as
M-x calendar, Eshell and
Warning: Expect some default bindings to change in the future.
- Reduce context switching: As soon as “moving around” gets hardwired
<hjkl>, it becomes frustratingly inefficient not to have it everywhere.
- Community work: setting up bindings is tremendous work and joining force can only save hours for all of Evil users out there. While not everyone may agree on the chosen bindings, it helps to have something to start with rather than nothing at all. In the end, users are free to override a subset of the proposed bindings to best fit their needs.
- Consistency: Having all bindings defined in one place allows for enforcing consistency across special modes and coordinating the community work to define a reference implementation.
- Get the package, either from MELPA:
M-x package-install RET evil-collection RET
Or clone / download this repository and modify your
(add-to-list 'load-path (expand-file-name "/path/to/evil-collection/" user-emacs-directory))
- Register the bindings, either all at once with
or mode-by-mode, for instance:
(with-eval-after-load 'calendar (require 'evil-collection-calendar) (evil-collection-calendar-setup))
or by providing an argument to
The list of supported modes is configured by ~~evil-collection-mode-list~~.
evil-want-keybinding is set to nil
evil-want-integration is set to t before loading
See https://github.com/emacs-evil/evil-collection/issues/60 and https://github.com/emacs-evil/evil/pull/1087 for more details.
(setq evil-want-integration t) ;; This is optional since it's already set to t by default. (setq evil-want-keybinding nil) (require 'evil) (when (require 'evil-collection nil t) (evil-collection-init))
Here’s another full TLDR
(use-package evil :ensure t :init (setq evil-want-integration t) ;; This is optional since it's already set to t by default. (setq evil-want-keybinding nil) :config (evil-mode 1)) (use-package evil-collection :after evil :ensure t :config (evil-collection-init))
NOTE: If you don’t like surprises but still want to use
evil-collection-mode-list to nil
and adding each mode manually might be a better option.
evil-collection-mode-list to disable or add any modes that should be evilified by
|evil-collection-company-use-tng||t||Set up autocompletion to be similar to Vim’s YouCompleteMe.|
|evil-collection-outline-bind-tab-p||t||Enable <tab>-based bindings in Outline mode.|
|evil-collection-term-sync-state-and-mode-p||t||Synchronize insert/normal state with char/line-mode in term-mode.|
|evil-collection-setup-minibuffer||nil||Set up Vim style bindings in the minibuffer.|
|evil-collection-setup-debugger-keys||t||Set up debugger keys for certain modes.|
For example, if you want to enable Evil in the minibuffer, you’ll have to turn it on
explicitly by customizing
Some minibuffer-related packages such as Helm rely on this option.
(use-package evil-collection :custom (evil-collection-setup-minibuffer t) :init (evil-collection-init))
The following rules serve as guiding principles to define the set of standard Evil bindings for various modes. Since special modes are by definition structurally incomparable, those rules cannot be expected to be applied universally.
The rules are more-or-less sorted by priority.
- Don’t bind anything to
- Keep the movement keys when possible and sensible.
- Keep the yanking and register keys when possible and sensible.
- Keep the search keys when possible and sensible.
- Keep the mark keys when possible and sensible.
- Keep the windowing keys when possible and sensible.
z-prefixed bindings (see below).
- The following keys are free when insert state does not make sense in the
Any of those keys can be set to be a prefix key.
- Prefix keys:
zare the ubiquitous prefix keys.
ggenerally stands for “go” and is best used for movements.
zis used for scrolling, folding, spell-checking and more.
- Macro and action keys
Many special modes share the same set of similar actions. Those actions should share the same bindings across all modes whenever feasible.
]-prefixed keys for navigation between sections.
If the mode makes no difference between the end of a section and the beginning of the next, use
gk: synonym for
]. That’s what evil-magit does.
gk rather be synonyms for
C-k? They cannot
emulate the behaviour of
C-k: If there is granularity, i.e. subsections, use
C-kto browse them. This reflects evil-magit and evil-mu4e default bindings.
}: If there is no paragraph structure,
}can be used for sub-sectioning.
): If there is no sentence structure,
)can be used for sub-sectioning.
hjklcan be used for atomic movements, but
HJKLcan usually not be used because
Lare all universal (
evil-joinand usually does not make sense in special modes).
C-hshould not be remapped: Since we have
C-kfor vertical motion, it would make sense to use
C-lfor horizontal motion. There are some shortcomings though:
- In Vim,
C-hworks as backspace, but Evil does not follow that behaviour.
- In Emacs, it is a prefix key for all help-related commands, and so is
- Most importantly,
C-his too widespread and ubiquitous to be replaced. So we don’t.
- In Vim,
C-l: As a consequence of the former point,
M-<hjkl>: Those keys are usually free in Evil but still bound to their Emacs default (e.g.
downcase-word). Besides, if
C-kare already used, having
M-kmight add up to the confusion.
q is for recording macros. Vim quits with
ZQ. In most
Emacs special modes, it stands for quitting while macros are recorded/played
A good rule of thumb would be:
- Always bind
ZQto the quitting function(s),
evil-quitif nothing else makes sense.
evil-quitif macros don’t make sense in current mode.
- If macros don’t make sense in current mode, then
Refreshing / Reverting (
gris used for refreshing in evil-magit, evil-mu4e, and some Spacemacs configurations (org-agenda and neotree among others).
C-l is traditionally used to refresh the terminal screen. Since there does
not seem to be any existing use of it, we leave the binding free for other uses.
m defaults to
evil-set-marker which might not be very useful in special
=’= can still be used as it can jump to other buffers.
m: Mark or toggle mark, depending on what the mode offers. In visual mode, always mark. With a numeric argument, toggle mark on that many following lines.
u: Unmark current selection.
U: Unmark all.
~: Toggle all marks. This mirrors the “invert-char” Vim command bound to
M: Mark all, if available. Otherwise use
*: Mark-prefix or mark all if current mode has no prefix.
*is traditionally a wildcard.
%: Mark regexp.
x: Execute action on marks. This mirrors Dired’s binding of
* is used for marking, then
# is free.
Also note that Emacs inconsistently uses
U to unmark.
Selecting / Filtering / Narrowing / Searching
Sseem to be used in some places like mu4e.
s: [s]elect/[s]earch/filter candidates according to a pattern.
S: Remove filter and select all.
=is usually free and its significance is obvious. It’s taken for zooming though.
|is not free but the pipe symbolic is very tantalizing.
o: Change the sort [o]rder.
O: Sort in reverse order.
There is no real consensus around which key to bind to sorting. What others do by default:
M-x procedand Dired use
- mu4e uses
- ranger uses
o, inspired from Mutt.
Go to definition (
gd: [g]o to [d]efinition. This is mostly for programming modes. If there’s a corresponding ‘pop’ action, use
Go to current entity
.: go to current entity (day for calendar, playing track for EMMS). Bind only if more relevant than
Open thing at point (
M-RET: Open thing at point in current window, open in other window and display in other window respectively. The latter is like the former with the focus remaining on the current window.
gO: When available, same as
M-RETrespectively. This is useful in terminals where
M-RETmight not work.
Emacs-style jumping (
Some special modes like mu4e and ibuffer offer to to “jump” to a different buffer. This sometimes depends on the thing at point.
This is not related to Evil jumps like
C-o, nor to “go to
Browse URL (
gx: go to URL. This is a default Vim binding.
g?: is the standard key for help related commands.
?in places where backward search is not very useful.
History browsing (
C-p are standard bindings to browse the history elements.
If the mode has a Go To REPL-type command, set it to
-have obvious meanings.
0has a somewhat intuitive meaning, plus it is next to
=is useful as a synonym for
+because it is the unshifted key of
When debugging is on, debugger keys takes the most precedence.
These keys will be set when there’s an available command for them.
n: Step Over
i: Step Into
o: Step Out
c: Continue/Resume Execution
q: Quit Debugging
H: Continue until Point
e: Evaluate Expression
b: Set Breakpoint
u: Unset Breakpoint
>: Navigate to Next Frame
<: Navigate to Previous Frame
J: Jump to debugger location
For debugging outside of debugger being on (e.g. setting initial breakpoints), we use similar keys to realgud.
For buffers where insert-state doesn’t make sense but buffer can be edited,
(e.g. wdired or wgrep), pressing
i will change into editable state.
When this editable state is turned on,
ZQ will abort and clear any changes.
ZZ will finish and save any changes.
ESC will exit editable state.
evil-collection-translate-key allows binding a key to the definition of
another key in the same keymap (comparable to how Vim’s keybindings work). Its
arguments are the
keymaps to bind/look up the key(s) in followed
optionally by keyword arguments (currently only
states should be nil for non-evil keymaps, and both
keymaps can be a single symbol or a list of symbols.
This function can be useful for making key swaps/cycles en masse. For example,
someone who uses an alternate keyboard layout may want to retain the
positions for directional movement in dired, the calendar, etc.
Here’s an example for Colemak of making swaps in a single keymap:
(evil-collection-translate-key nil 'evil-motion-state-map ;; colemak hnei is qwerty hjkl "n" "j" "e" "k" "i" "l" ;; add back nei "j" "e" "k" "n" "l" "i")
Here’s an example of using
evil-collection-setup-hook to cycle the keys for
all modes in
(defun my-hjkl-rotation (_mode mode-keymaps &rest _rest) (evil-collection-translate-key 'normal mode-keymaps "n" "j" "e" "k" "i" "l" "j" "e" "k" "n" "l" "i")) ;; called after evil-collection makes its keybindings (add-hook 'evil-collection-setup-hook #'my-hjkl-rotation) (evil-collection-init)
A more common use case of
evil-collection-translate-key would be for keeping
the functionality of some keys that users may bind globally. For example,
] are bound in some modes. If you use these keys as global prefix
keys that you never want to be overriden, you’ll want to give them higher
priority than other evil keybindings (e.g. those made by
'normal some-map ...)). To do this, you can create an “intercept” map and bind
your prefix keys in it instead of in
(defvar my-intercept-mode-map (make-sparse-keymap) "High precedence keymap.") (define-minor-mode my-intercept-mode "Global minor mode for higher precedence evil keybindings." :global t) (my-intercept-mode) (dolist (state '(normal visual insert)) (evil-make-intercept-map ;; NOTE: This requires an evil version from 2018-03-20 or later (evil-get-auxiliary-keymap my-intercept-mode-map state t t) state)) (evil-define-key 'normal my-intercept-mode-map (kbd "SPC f") 'find-file) ;; ...
You can then define replacement keys:
(defun my-prefix-translations (_mode mode-keymaps &rest _rest) (evil-collection-translate-key 'normal mode-keymaps "C-SPC" "SPC" ;; these need to be unbound first; this needs to be in same statement "[" nil "]" nil "[[" "[" "]]" "]")) (add-hook 'evil-collection-setup-hook #'my-prefix-translation) (evil-collection-init)
By default, the first invocation of
evil-collection-translate-key will make a
backup of the keymap. Each subsequent invocation will look up keys in the backup
instead of the original. This means that a call to
evil-collection-translate-key will always have the same behavior even if
evaluated multiple times. When
:destructive t is specified, keys are looked up
in the keymap as it is currently. This means that a call to
evil-collection-translate-key that swapped two keys would continue to
swap/unswap them with each call. Therefore when
:destructive t is used, all
cycles/swaps must be done within a single call to
evil-collection-translate-key. To make a comparison to Vim keybindings,
:destructive t is comparable to Vim’s
:destructive nil is
comparable to Vim’s
noremap (where the “original” keybindings are those that
existed in the keymap when
evil-collection-translate-key was first called).
You’ll almost always want to use the default behavior (especially in your init
file). The limitation of
:destructive nil is that you can’t translate a key to
another key that was defined after the first
:destructive t may be useful for interactive experimentation.
evil-collection-swap-key is also provided as a wrapper around
evil-colletion-translate-key that allows swapping keys:
(evil-collection-swap-key nil 'evil-motion-state-map ";" ":") ;; is equivalent to (evil-collection-translate-key nil 'evil-motion-state-map ";" ":" ":" ";")
Modes left behind
Some modes might still remain unsupported by this package. Should you be
<hjkl>, feel free to file an issue or even a pull request.
Third-party packages are provided by several parties:
- Lispy: lispyville or evil-lispy
- Org-mode: https://github.com/GuiltyDolphin/org-evil or https://github.com/Somelauw/evil-org-mode
Should you know any suitable package not mentioned in this list, let us know and file an issue.
- Making SPC work similarly to spacemacs.
evil-collectionbinds over SPC in many packages. To use SPC as a leader key with the general library:
(use-package general :ensure t :config (setq general-override-states '(insert emacs hybrid normal visual motion operator replace)) (general-override-mode) (general-define-key :states '(normal visual motion) :keymaps 'override "SPC" 'hydra-space/body))
See noctuid’s evil guide for other approaches.
This should also be accomplishable using key translation from general.
We welcome any additional modes that are not already supported.
Follow The Emacs Lisp Style Guide for coding conventions.
Erlang/OTP has a good read for helpful commit messages.