complete-computing-environment/evil_mode.org

132 lines
5.0 KiB
Org Mode

:PROPERTIES:
:ID: cce/evil_mode
:ROAM_ALIASES: "Evil Mode"
:END:
#+TITLE: Evil Mode -- Vim in Emacs
#+filetags: :CCE:Emacs:Code:
#+PROPERTY: header-args :mkdirp yes :results none
#+PROPERTY: header-args:emacs-lisp :tangle evil-mode.el
#+ARCOLOGY_KEY: cce/evil-mode
#+ARCOLOGY_ALLOW_CRAWL: t
#+ARROYO_EMACS_MODULE: evil-mode
#+ARROYO_MODULE_WANTS: cce/diminish.org
#+ARROYO_MODULE_WANTS: cce/configure_packaging.org
#+begin_src emacs-lisp
(provide 'cce/evil-mode)
#+end_src
Evil-Mode is Vim keybindings and mode-switching, implemented in Emacs.
Context switching is unproductive. Modal editing is not. Those are at odds. Any interface modality introduced to a system should be understandable and it should be consistent so as to minimize the negative effects of context switching. I use Emacs with Evil-Mode to achieve this right now with a set of custom keybindings which build on top of the idioms of both Emacs and Vim where appropriate.
Vim modal commands are by no means perfect. It's not perfect in any respect, but it works well enough, and it's a set of portable idioms. The Evil project provides an additional set of libraries [[[https://github.com/emacs-evil/evil-collection][Evil Collection]]], which I use below:
#+begin_src emacs-lisp :noweb yes
(setq evil-want-keybinding nil)
(use-package evil
:init
<<evil-respect-visual-line>>
:config
(evil-mode 1))
(use-package evil-collection
:after evil
:config
(evil-collection-init))
#+end_src
#+begin_src emacs-lisp
(use-package evil-matchit
:config (global-evil-matchit-mode 1))
(use-package evil-surround
:config (global-evil-surround-mode 1))
#+end_src
Set up and configure a <leader> key; The idea here is to have a somewhat standard key to hang user-commands off of. I extend this idea maybe past its limit.
#+BEGIN_SRC emacs-lisp
(use-package evil-leader
:after evil
:demand
:config
(global-evil-leader-mode 1)
(evil-leader/set-leader "SPC"))
#+END_SRC
Syndicate is evil bindings and support for org-mode.
#+BEGIN_SRC emacs-lisp
(use-package evil-org
:ensure t
:after org
:diminish
:hook (org-mode . (lambda () (evil-org-mode)))
:init
(fset 'evil-redirect-digit-argument 'ignore)
:config
(evil-define-key 'normal 'org-mode-map (kbd "gc") #'org-cycle)
(require 'evil-org-agenda)
(evil-org-agenda-set-keys))
#+END_SRC
This construction iterates over a set of major modes, and tells Evil Mode what state buffers should start in when they're opened in that mode. This is useful for starting modes which do not support Evil Mode (or more correctly, evil-collection does not support the mode!) with Emacs controls, or starting =git commit= with insert mode.
#+BEGIN_SRC emacs-lisp
(cl-loop for (mode . state) in '((text-mode . normal)
(exwm-mode . emacs)
(sauron-mode . emacs)
(shell-mode . insert)
(git-commit-mode . insert)
(git-rebase-mode . emacs)
(magit-branch-manager-mode . emacs)
(mingus-playlist-mode . motion)
(mingus-browse-mode . motion)
(org-fc-review-flip-mode . motion)
(org-fc-review-rate-mode . motion)
(yari-mode . motion)
(mastodon-mode . emacs)
(mpc-mode . emacs)
(mpc-status-mode . emacs)
(mpc-tagbrowser-mode . emacs)
(mpc-tagbrowser-dir-mode . emacs)
(mpc-songs-mode . emacs)
(org-capture-mode . insert)
(org-fc-dashboard-mode . motion))
do (evil-set-initial-state mode state))
#+END_SRC
In my [[id:cce/text_editing_fundamental_opinions][Text Editing Fundamental Opinions]], I set up my system to use =visual-line-mode= to format my [[id:1fb8fb45-fac5-4449-a347-d55118bb377e][org-mode]] documents rather than do my own text wrapping. I prefer this a lot. This has to be set to true before evil-mode loads:
#+NAME: evil-respect-visual-line
#+begin_src emacs-lisp
(setq evil-respect-visual-line-mode t)
#+end_src
#+begin_src emacs-lisp
(use-package evil-args
:bind
(:map evil-normal-state-map
("L" . evil-forward-arg)
("H" . evil-backward-arg))
(:map evil-motion-state-map
("L" . evil-forward-arg)
("H" . evil-backward-arg))
(:map evil-inner-text-objects-map
("a" . evil-inner-arg))
(:map evil-inner-text-objects-map
("a" . evil-outer-arg)))
#+end_src
* visual line commands
#+begin_src emacs-lisp
(evil-define-key 'normal text-mode-map [remap evil-next-line] #'evil-next-visual-line)
(evil-define-key 'normal text-mode-map [remap evil-previous-line] #'evil-previous-visual-line)
(evil-define-key 'normal text-mode-map [remap evil-end-of-line] #'evil-end-of-visual-line)
#+end_src