emacs-lisp source: :tangle ~/nix/lisp/evil-mode.el(provide 'cce/evil-mode)
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 Evil Collection] which I use below:
emacs-lisp source: :tangle ~/nix/lisp/evil-mode.el :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))
emacs-lisp source: :tangle ~/nix/lisp/evil-mode.el(use-package evil-matchit :config (global-evil-matchit-mode 1)) (use-package evil-surround :config (global-evil-surround-mode 1))
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.
emacs-lisp source: :tangle ~/nix/lisp/evil-mode.el(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 :tangle ~/nix/lisp/evil-mode.el (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 :tangle ~/nix/lisp/evil-mode.el (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 :tangle ~/nix/lisp/evil-mode.el (setq evil-respect-visual-line-mode t)
emacs-lisp source: :tangle ~/nix/lisp/evil-mode.el(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)))
visual line commands
emacs-lisp source: :tangle ~/nix/lisp/evil-mode.el(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)