All Projects → emacs-evil → Evil Collection

emacs-evil / Evil Collection

Licence: gpl-3.0
A set of keybindings for evil-mode

Projects that are alternatives of or similar to Evil Collection

Evil Org Mode
Supplemental evil-mode keybindings to emacs org-mode
Stars: ✭ 241 (-64.61%)
Mutual labels:  evil, emacs
Doom Emacs
An Emacs framework for the stubborn martian hacker
Stars: ✭ 12,774 (+1775.77%)
Mutual labels:  evil, emacs
Org Evil
Evil extensions for Org-mode.
Stars: ✭ 51 (-92.51%)
Mutual labels:  evil, emacs
Evil
The extensible vi layer for Emacs.
Stars: ✭ 2,265 (+232.6%)
Mutual labels:  evil, emacs
Evil Multiedit
Multiple cursors for evil-mode, based on iedit
Stars: ✭ 200 (-70.63%)
Mutual labels:  evil, emacs
Evil Snipe
2-char searching ala vim-sneak & vim-seek, for evil-mode
Stars: ✭ 196 (-71.22%)
Mutual labels:  evil, emacs
Emacs Smart Input Source
Less manual switch for native or OS input source (input method).
Stars: ✭ 130 (-80.91%)
Mutual labels:  evil, emacs
Dotfiles
Ninrod's sharpened dotfiles for emacs, vim, zsh, tmux. Since '15.
Stars: ✭ 208 (-69.46%)
Mutual labels:  evil, emacs
Evil Mc
Multiple cursors implementation for evil-mode
Stars: ✭ 308 (-54.77%)
Mutual labels:  evil, emacs
Ox Hugo
A carefully crafted Org exporter back-end for Hugo
Stars: ✭ 591 (-13.22%)
Mutual labels:  emacs
Vue Threejs
Vue bindings for Three.js
Stars: ✭ 620 (-8.96%)
Mutual labels:  bindings
Meghanada Emacs
A Better Java Development Environment for Emacs
Stars: ✭ 582 (-14.54%)
Mutual labels:  emacs
Magithub
**This project is being (mostly) migrated into Forge!** -- Magit-based interfaces to GitHub
Stars: ✭ 592 (-13.07%)
Mutual labels:  emacs
Markdown Mode
Emacs Markdown Mode
Stars: ✭ 634 (-6.9%)
Mutual labels:  emacs
Nyan Mode
Nyan Cat for Emacs! Nyanyanyanyanyanyanyanyanyan!
Stars: ✭ 590 (-13.36%)
Mutual labels:  emacs
Cmake Ide
Use Emacs as a C/C++ IDE
Stars: ✭ 661 (-2.94%)
Mutual labels:  emacs
Editorconfig Emacs
EditorConfig plugin for Emacs
Stars: ✭ 577 (-15.27%)
Mutual labels:  emacs
God Mode
Minor mode for God-like command entering
Stars: ✭ 570 (-16.3%)
Mutual labels:  emacs
Sx.el
Stack Exchange for Emacs
Stars: ✭ 667 (-2.06%)
Mutual labels:  emacs
Solarized Emacs
The Solarized colour theme, ported to Emacs.
Stars: ✭ 640 (-6.02%)
Mutual labels:  emacs

#+TITLE: Evil Collection

[[https://github.com/emacs-evil/evil-collection/actions][file:https://github.com/emacs-evil/evil-collection/workflows/build/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.

** Goals

  1. Reduce context switching: As soon as "moving around" gets hardwired to , 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)

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-company-use-tng | t | Set up autocompletion to be similar to Vim's YouCompleteMe. | | evil-collection-calendar-want-org-bindings | nil | Set up Org functions in calendar keymap. | | evil-collection-outline-bind-tab-p | nil | Enable -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 .

  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 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 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 and are bound to.
      • S-RET is impossible on terminal. Bind 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 [email protected]~ 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

** Third-party packages

Third-party packages are provided by several parties:

| Major mode | Evil bindings | |------------+--------------------------| | 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]] | | ledger | [[https://github.com/atheriel/evil-ledger][evil-ledger]] |

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 , please feel free to do a pull request.

** 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

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].