summaryrefslogtreecommitdiff
path: root/README.org
blob: 8ba0344f79d3571cd82720f8322652cfcc4c62e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
#+TITLE: Evil Collection
#+STARTUP: noindent

[[https://github.com/emacs-evil/evil-collection/actions][file:https://github.com/emacs-evil/evil-collection/workflows/CI/badge.svg?branch=master]]
[[https://melpa.org/#/evil-collection][file:https://melpa.org/packages/evil-collection-badge.svg]]
[[https://stable.melpa.org/#/evil-collection][file:https://stable.melpa.org/packages/evil-collection-badge.svg]]

This is a collection of [[https://github.com/emacs-evil/evil][Evil]] bindings for /the parts of Emacs/ that Evil does
not cover properly by default, such as ~help-mode~, ~M-x calendar~, Eshell and
more.

*Warning:* Expect some default bindings to change in the future.

** Preliminaries

1. ~evil-overriding-maps~ is assumed as ~nil~ to reduce redundant ~w/W/l/f/t~
   etc evil bindings. See [[https://github.com/emacs-evil/evil-collection/pull/501][Fixup Info-mode]] for example.

** Goals

1. Reduce context switching: As soon as "moving around" gets hardwired
   to ~<hjkl>~, it becomes frustratingly inefficient not to have it everywhere.

2. 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.

3. 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.

** Installation

- Get the package, either from MELPA:

  : M-x package-install RET evil-collection RET

  Or clone / download this repository and modify your ~load-path~:

  : (add-to-list 'load-path (expand-file-name "/path/to/evil-collection/" user-emacs-directory))

- Register the bindings, either all at once with

  : (evil-collection-init)

  or mode-by-mode, for instance:

  : (with-eval-after-load 'calendar (evil-collection-calendar-setup))

  or by providing an argument to ~evil-collection-init~:

  : (evil-collection-init 'calendar)

  a list can also be provided to ~evil-collection-init~:

  : (evil-collection-init '(calendar dired calc ediff))

  The list of supported modes is configured by ~evil-collection-mode-list~.

~evil-collection~ assumes ~evil-want-keybinding~ is set to ~nil~ and
~evil-want-integration~ is set to ~t~ before loading ~evil~ and
~evil-collection~. Note some other packages may load evil (e.g. evil-leader) so
bear that in mind when determining when to set the variables.

See https://github.com/emacs-evil/evil-collection/issues/60 and https://github.com/emacs-evil/evil/pull/1087
for more details.

For example:

#+begin_src emacs-lisp :tangle yes
(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))
#+end_src

Here's another full TLDR ~use-package~ example.

#+begin_src emacs-lisp :tangle yes
(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))
#+end_src

NOTE: If you don't like surprises but still want to use ~evil-collection-init~, setting ~evil-collection-mode-list~ to nil
and adding each mode manually might be a better option.

** Configuration

Modify ~evil-collection-mode-list~ to disable or add any modes that should be evilified by ~evil-collection~.

| Variable                                   | Default | Description                                                       |
|--------------------------------------------+---------+-------------------------------------------------------------------|
| evil-collection-calendar-want-org-bindings | nil     | Set up Org functions in calendar keymap.                          |
| evil-collection-outline-bind-tab-p         | nil     | 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.                           |
| evil-collection-want-unimpaired-p          | t       | Set up unimpaired bindings globally.                              |
| evil-collection-want-find-usages-bindings  | t       | Bind -find references-, etc to various modes.                     |

For example, if you want to enable Evil in the minibuffer, you'll have to turn it on
explicitly by customizing ~evil-collection-setup-minibuffer~ to ~t~.
Some minibuffer-related packages such as Helm rely on this option.

~use-package~ example:

#+begin_src emacs-lisp :tangle yes
(use-package evil-collection
  :custom (evil-collection-setup-minibuffer t)
  :init (evil-collection-init))
#+end_src

** Guidelines

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.

1. Don't bind anything to ~:~ nor ~<escape>~.

2. Keep the movement keys when possible and sensible.

   - ~h~, ~j~, ~k~, ~l~
   - ~w~, ~W~, ~b~, ~B~, ~e~, ~E~, ~ge~, ~gE~
   - ~f~, ~F~, ~t~, ~T~, ~;~, =,=
   - ~gg~, ~G~
   - ~|~
   - ~(~, ~)~
   - ~{~, ~}~
   - ~%~
   - ~+~, ~-~, ~0~, ~^~, ~$~
   - ~C-i~, ~C-o~

3. Keep the yanking and register keys when possible and sensible.

   - ~y~, ~Y~
   - ="=

4. Keep the search keys when possible and sensible.

   - ~/~, ~?~
   - ~#~, ~*~

5. Keep the mark keys when possible and sensible.

   - ~m~
   - ='=, =~=

6. Keep the windowing keys when possible and sensible.

   - ~H~, ~L~, ~M~
   - ~C-e~, ~C-y~
   - ~C-f~, ~C-b~
   - ~C-d~, ~C-u~
   - ~C-w~-prefixed bindings.
   - Some ~z~-prefixed bindings (see below).

7. The following keys are free when insert state does not make sense in the
   current mode:

   - ~a~, ~A~, ~i~, ~I~
   - ~c~, ~C~, ~r~, ~R~, ~s~, ~S~
   - ~d~, ~D~, ~x~, ~X~
   - ~o~, ~O~
   - ~p~, ~P~
   - ~=~, ~<~, ~>~
   - ~J~
   - =~=

   Any of those keys can be set to be a prefix key.

8. Prefix keys: ~g~ and ~z~ are the ubiquitous prefix keys.

   - ~g~ generally stands for "go" and is best used for movements.
   - ~z~ is used for scrolling, folding, spell-checking and more.

9. Macro and action keys

   - ~@~, ~q~
   - ~.~

10. Ensure terminal compatibility without sacrificing GUI key bindings.
    - Tab key
      - Tab key is recognized as ~<tab>~ in GUI and ~TAB~ in terminal.
        ~TAB~ equals ~C-i~.
      - ~C-i~ is bound to jumping forward for vim compatibility.
        If Shift+Tab is not relevant, just bind ~g TAB~ to the function
        that Tab is bound to. If Shift+Tab is relevant, bind ~g]~ and
        ~g TAB~ to the function that Tab is bound to, and bind ~g[~ to
        the function that Shift+Tab is bound to for terminal compatibility.
    - Enter key
      - Enter key is recognized as ~<return>~ in GUI and ~RET~ in terminal.
        ~RET~ equals ~Ctrl+m~.
      - Bind only ~RET~ and ~M-RET~. Or, bind ~RET~ and ~M-RET~ to the same
        functions ~<return>~ and ~<M-return>~ are bound to.
      - ~S-RET~ is impossible on terminal. Bind ~<S-return>~ and a vacant key
        to the same function for terminal compatibility.

** Rationale

Many special modes share the same set of similar actions.  Those actions should
share the same bindings across all modes whenever feasible.

*** Motion (~[~, ~]~, ~{~, ~}~, ~(~, ~)~, ~gj~, ~gk~, ~C-j~, ~C-k~)

- ~[~ and ~]~: Use ~[-~ and ~]-~ 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 ~[~ and ~]~.

- ~gj~ and ~gk~: synonym for ~[~ and ~]~.  That's what [[evilmagit][evil-magit]] does.

  *Question:* Should ~gj~ / ~gk~ rather be synonyms for ~C-j~ / ~C-k~?  They cannot
  emulate the behaviour of ~[]~ or ~][~.

  - ~C-j~, ~C-k~: If there is granularity, i.e. subsections, use ~C-j~ and ~C-k~
    to browse them.  This reflects [[evilmagit][evil-magit]] and [[evilmu4e][evil-mu4e]] default
    bindings.

  - ~{~, ~}~: If there is no paragraph structure, ~{~ and ~}~ can be used for sub-sectioning.

  - ~(~, ~)~: If there is no sentence structure, ~(~ and ~)~ can be used for sub-sectioning.

  - ~HJKL~: ~hjkl~ can be used for atomic movements, but ~HJKL~ can usually not be used
    because ~H~, ~K~ and ~L~ are all universal (~J~ is ~evil-join~ and usually
    does not make sense in special modes).

  - ~C-h~ should not be remapped: Since we have ~C-j~ and ~C-k~ for vertical motion, it would
    make sense to use ~C-h~ and ~C-l~ for horizontal motion.  There are some
    shortcomings though:

    - In Vim, ~C-h~ works as backspace, but Evil does not follow that behaviour.

    - In Emacs, it is a prefix key for all help-related commands, and so is ~<f1>~.

    - Most importantly, ~C-h~ is too widespread and ubiquitous to be replaced.
      So we don't.

  - ~C-l~: As a consequence of the former point, ~C-l~ is available.

  - ~M-<hjkl>~: Those keys are usually free in Evil but still bound to their Emacs
    default (e.g. ~M-l~ is ~downcase-word~).  Besides, if ~C-j~ and ~C-k~ are
    already used, having ~M-j~ and ~M-k~ might add up to the confusion.

*** Quitting (~q~, ~ZQ~, ~ZZ~)

In Vim, ~q~ is for recording macros.  Vim quits with ~ZZ~ or ~ZQ~.  In most
Emacs special modes, it stands for quitting while macros are recorded/played
with ~<f3>~ and ~<f4>~.

A good rule of thumb would be:

- Always bind ~q~, ~ZZ~ and ~ZQ~ to the mode specific quitting functions. If there is none,
- Bind ~q~ and ~ZZ~ to ~quit-window~
- Bind ~ZQ~ to ~evil-quit~
- If macros don't make sense in current mode, then ~@~ is available.

*** Refreshing / Reverting (~gr~)

- ~gr~ is used for refreshing in [[evilmagit][evil-magit]], [[evilmu4e][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.

*** Marking

~m~ defaults to ~evil-set-marker~ which might not be very useful in special
modes.
='= 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 =~=
  by default.

- ~M~: Mark all, if available.  Otherwise use =U~=.

- ~*~: 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 ~x~.

If ~*~ is used for marking, then ~#~ is free.

Also note that Emacs inconsistently uses ~u~ and ~U~ to unmark.

*** Selecting / Filtering / Narrowing / Searching

- ~s~ and ~S~ seem to be used in some places like [[mu4e][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.

*** Sorting

- ~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:

  - ~package-menu~ uses ~S~.

  - ~M-x proced~ and Dired use ~s~.

  - ~profiler~ uses ~A~ and ~D~.

  - [[mu4e][mu4e]] uses ~O~.

  - [[http://www.nongnu.org/ranger/][ranger]] uses ~o~, inspired from [[http://mutt.org][Mutt]].

*** Go to definition (~gd~, ~gD~)

- ~gd~: [g]o to [d]efinition.  This is mostly for programming modes.
  If there's a corresponding 'pop' action, use ~C-t~.

*** Go to references, etc (~gr~, ~gA~)
When ~evil-collection-want-find-usages-bindings~ is set to t:

- ~gr~: [g] to [r]eferences. This binding is also used for refresh/reverting
  modes in non programming modes but is usually empty for programming modes.

- ~gA~: [g]o to [A]ssignments.

- Additional bindings:
  There may be additional binds under this category. Please file a Pull Request if so.

*** Go to current entity

- ~.~: go to current entity (day for calendar, playing track for [[EMMS][EMMS]]).
  Bind only if more relevant than ~evil-repeat~.

*** Open thing at point (~RET~, ~S-RET~, ~M-RET~, ~go~, ~gO~)

- ~RET~, ~S-RET~, ~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~, ~gO~: When available, same as ~S-RET~ and ~M-RET~ respectively.  This is
  useful in terminals where ~S-RET~ and ~M-RET~ might not work.

*** Emacs-style jumping (~J~)

- ~J~: [[mu4e][mu4e]] has ~j~ and [[evil-mu4e][evil-mu4e]] uses ~J~, so we use ~J~ too.

  Some special modes like [[mu4e][mu4e]] and ibuffer offer to "jump" to a different
  buffer.  This sometimes depends on the thing at point.

  This is not related to Evil jumps like ~C-i~ and ~C-o~, nor to "go to
  definition".

*** Browse URL (~gx~)

~gx~: go to URL.  This is a default Vim binding.

*** Help (~?~)

- ~g?~ : is the standard key for help related commands.
- ~?~ in places where backward search is not very useful.

*** History browsing (~C-n~, ~C-p~)

~C-n~ and ~C-p~ are standard bindings to browse the history elements.

*** Bookmarking

?

*** REPL (~gz~)

If the mode has a Go To REPL-type command, set it to ~gz~.

*** Zooming (~+~, ~-~, ~=~, ~0~)

- ~+~ and ~-~ have obvious meanings.
- ~0~ has a somewhat intuitive meaning, plus it is next to ~+~ and ~-~ on QWERTY.
- ~=~ is useful as a synonym for ~+~ because it is the unshifted key of ~+~ on QWERTY.

*** Debugging

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
- ~L~ : Locals
- ~t~ : Tracing
- ~q~ : Quit Debugging
- ~H~ : Continue until Point
- ~e~ : Evaluate Expression
- ~b~ : Set Breakpoint
- ~u~ : Unset Breakpoint
- ~>~ : Navigate to Next Frame
- ~<~ : Navigate to Previous Frame
- ~g?~ : Help
- ~J~ : Jump to debugger location
- ~R~ : Restart

For debugging outside of debugger being on (e.g. setting initial breakpoints),
we use similar keys to [[https://github.com/realgud/realgud][realgud]].

- ~f5~ Start/Continue/Resume Execution
- ~S-f5~ Continue Execution
- ~Mouse-1~ Toggle Breakpoint
- ~f9~ Toggle Breakpoint
- ~f10~ Step Over
- ~f11~ Step Into
- ~S-f11~ Step Out

*** Editable Buffers

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.

*** :q/:wq/etc

Modes with commands that can be bound to :q/:wq/etc will have those keys remapped.

** Key Translation

~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 ~states~ and ~keymaps~ to bind/look up the key(s) in followed
optionally by keyword arguments (currently only ~:destructive~) and
key/replacement pairs. ~states~ should be nil for non-evil keymaps, and both
~states~ and ~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 ~hjkl~
positions for directional movement in dired, the calendar, etc.

Here's an example for Colemak of making swaps in a single keymap:

#+begin_src emacs-lisp
(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")
#+end_src

Here's an example of using ~evil-collection-setup-hook~ to cycle the keys for
all modes in ~evil-collection-mode-list~:

#+begin_src emacs-lisp
(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)
#+end_src

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, ~SPC~,
~[~, and ~]~ are bound in some modes. If you use these keys as global prefix
keys that you never want to be overridden, you'll want to give them higher
priority than other evil keybindings (e.g. those made by ~(evil-define-key
'normal some-map ...)~). To do this, you can create an "intercept" map and bind
your prefix keys in it instead of in ~evil-normal-state-map~:

#+begin_src emacs-lisp
(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)
;; ...
#+end_src

You can then define replacement keys:

#+begin_src emacs-lisp
(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-translations)

(evil-collection-init)
#+end_src

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 ~map~, and ~: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 ~evil-collection-translate-key~, so
~:destructive t~ may be useful for interactive experimentation.

~evil-collection-swap-key~ is also provided as a wrapper around
~evil-collection-translate-key~ that allows swapping keys:

#+begin_src emacs-lisp
(evil-collection-swap-key nil 'evil-motion-state-map
  ";" ":")
;; is equivalent to
(evil-collection-translate-key nil 'evil-motion-state-map
  ";" ":"
  ":" ";")
#+end_src

In some cases, keys are bound through `evil-define-minor-mode-key` and may
need to be translated using ~evil-collection-translate-minor-mode-key~ and/or
~evil-collection-swap-minor-mode-key~.

#+begin_src emacs-lisp
(evil-collection-swap-minor-mode-key '(normal motion)
  '(evil-snipe-local-mode evil-snipe-override-local-mode)
  "k" "s"
  ;; Set this to t to make this swap the keys everytime
  ;; this expression is evaluated.
  :destructive nil)

(evil-collection-translate-minor-mode-key
 '(normal motion)
 '(evil-snipe-local-mode evil-snipe-override-local-mode)
 "k" "s"
 "s" "k"
 ;; Set this to t to make this swap the keys everytime
 ;; this expression is evaluated.
 :destructive nil)
#+end_src

** Third-party packages

Third-party packages are provided by several parties:

| Major mode | Evil bindings            |
|------------+--------------------------|
| ledger     | [[https://github.com/atheriel/evil-ledger][evil-ledger]]              |
| lispy      | [[https://github.com/noctuid/lispyville][lispyville]] or [[https://github.com/sp3ctum/evil-lispy][evil-lispy]] |
| org        | [[https://github.com/GuiltyDolphin/org-evil][org-evil]] or [[https://github.com/Somelauw/evil-org-mode][evil-org]]     |
| markdown   | [[https://github.com/Somelauw/evil-markdown][evil-markdown]]            |

Also ~evil-collection~ has minimal support (~TAB~, ~S-TAB~ and
sentence/paragraph forwarding) for ~markdown~ and ~org~ if you prefer less
packages installed.

Should you know any suitable package not mentioned in this list, let us know and
file an issue.

Other references:

- [[https://github.com/syl20bnr/spacemacs/blob/master/doc/CONVENTIONS.org#key-bindings-conventions][Spacemacs]]
- [[https://github.com/hlissner/doom-emacs/tree/develop/modules/editor/evil][Doom Emacs]]

** FAQ

*** Making SPC work similarly to [[https://github.com/syl20bnr/spacemacs][spacemacs]].

~evil-collection~ binds over SPC in many packages. To use SPC as a leader key
with the [[https://github.com/noctuid/general.el][general]] library:

#+begin_src emacs-lisp :tangle yes
(use-package general
  :ensure t
  :init
  (setq general-override-states '(insert
                                  emacs
                                  hybrid
                                  normal
                                  visual
                                  motion
                                  operator
                                  replace))
  :config
  (general-define-key
   :states '(normal visual motion)
   :keymaps 'override
   "SPC" 'hydra-space/body))
;; Replace 'hydra-space/body with your leader function.
#+end_src

See [[https://github.com/noctuid/evil-guide][noctuid's evil guide]] for other approaches.

- Unintialized mode maps in ~evil-collection-setup-hook~.
  ~evil-collection-setup-hook~ is ran with a list of keymaps passed into it.
  Some misconfigured modes may not have yet initialized their keymap at this
  time so the value of the variable may be nil. In that case, an alternative is
  to use a mode-hook to do any custom settings.

#+begin_src emacs-lisp :tangle yes
(add-hook 'evil-collection-setup-hook
          (lambda (_mode keymaps)
            (add-hook 'ediff-mode-hook
                      (lambda ()
                        (... keymaps ...)))))
#+end_src

View [[https://github.com/emacs-evil/evil-collection/issues/196][196]] for more info.

*** Modes left behind

Some modes might still remain unsupported by this package. Should you be missing
your ~<hjkl>~, please feel free to do a pull request.

*** Writing a new binding

This [[template][yasnippet template]] can be used to bootstrap a new binding.

For example, if we were to want to add ~evil-collection~ support to ~eldoc~.
(e.g.) There is a package that contains:

#+begin_src emacs-lisp :tangle yes
(provide 'eldoc)
#+end_src

Create a directory named eldoc under [[modes-directory][modes/]]. Create a file named
evil-collection-eldoc.el under the newly created eldoc directory. Then use the
above template as an example or, using [[yasnippet][yasnippet]], ~yas-expand~ the above
template which will result in something like below:

#+begin_src emacs-lisp :tangle yes
;;; evil-collection-eldoc.el --- Bindings for `eldoc'. -*- lexical-binding: t -*-

;; Copyright (C) 2022 James Nguyen

;; Author: James Nguyen <james@jojojames.com>
;; Maintainer: James Nguyen <james@jojojames.com>
;; URL: https://github.com/emacs-evil/evil-collection
;; Version: 0.0.2
;; Package-Requires: ((emacs "27.1"))
;; Keywords: evil, emacs, convenience, tools

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:
;;; Bindings for eldoc.

;;; Code:
(require 'evil-collection)
(require 'eldoc nil t)

(defvar eldoc-mode-map)
(defconst evil-collection-eldoc-maps '(eldoc-mode-map))

(defun evil-collection-eldoc-setup ()
  "Set up `evil' bindings for eldoc."
  (evil-collection-define-key 'normal 'eldoc-mode-map
    ))

(provide 'evil-collection-eldoc)
;;; evil-collection-eldoc.el ends here
#+end_src

Finally, add ~eldoc~ to ~evil-collection--supported-modes~.

#+begin_src emacs-lisp :tangle yes
(defvar evil-collection--supported-modes
  `(
    ;; ...
    eldoc
    ;; ...
    )
  "List of modes supported by evil-collection. Elements are
either target mode symbols or lists which `car' is the mode
symbol and `cdr' the packages to register.")
#+end_src
** Submitting Issues

When reproducing issues, you can use this emacs -Q recipe.

#+begin_src emacs-lisp :tangle yes
(setq user-emacs-directory "~/.emacs.1.d")
(setq package-user-dir
      (format "%selpa/%s/" user-emacs-directory emacs-major-version))

(setq package-enable-at-startup nil
      package-archives
      '(("melpa" . "https://melpa.org/packages/")
        ("gnu" . "http://elpa.gnu.org/packages/")))

(require 'package)
(package-initialize)
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))
(require 'use-package)
(setq use-package-always-ensure t)

(use-package evil
  :ensure t
  :init
  (setq evil-want-keybinding nil)
  :config
  (evil-mode 1))

(use-package evil-collection
  :after evil
  :ensure t
  :config
  (evil-collection-init))
#+end_src

** Contributing

We welcome any additional modes that are not already supported.

All bindings in ~evil-collection~ are open to change so if there's a better or
more consistent binding, please [[https://github.com/emacs-evil/evil-collection/issues][open an issue]] or [[https://github.com/emacs-evil/evil-collection/pulls][submit a pull request]].

Follow [[https://github.com/bbatsov/emacs-lisp-style-guide/][The Emacs Lisp Style Guide]] for coding conventions.

[[https://github.com/erlang/otp/wiki/writing-good-commit-messages][Erlang/OTP]] has a good read for helpful commit messages.

#+LINK: EMMS https://www.gnu.org/software/emms/
#+LINK: evilmagit https://github.com/emacs-evil/evil-magit
#+LINK: evilmu4e https://github.com/JorisE/evil-mu4e
#+LINK: mu4e https://www.djcbsoftware.nl/code/mu/mu4e.html
#+LINK: yasnippet https://github.com/joaotavora/yasnippet
#+LINK: template https://github.com/emacs-evil/evil-collection/blob/master/yasnippet_evil-collection
#+LINK: modes-directory https://github.com/emacs-evil/evil-collection/tree/master/modes