Files
sydnix/users/crumb/programs/emacs/modules/syd-evil.el
Madeleine Sydney d3fbc8442b feat: Various completion additions
- Add `vertico-mode` keybindings.
- Unmap `C-k` in insert state.
2025-01-17 16:28:45 -07:00

159 lines
6.3 KiB
EmacsLisp

;;; syd-evil.el -*- lexical-binding: t; -*-
;; Vim emulation.
(use-package evil
:preface
(setq evil-want-minibuffer t
evil-move-beyond-eol t
evil-vsplit-window-right t
evil-ex-search-vim-style-regexp t
evil-want-Y-yank-to-eol t
evil-want-C-w-in-emacs-state t
;; - If nil: When using ex commands on a visual selection, pass the
;; precise region selected to the command.
;; - If non-nil: Pass the region of /lines/ spanned by the visual
;; selection.
evil-ex-visual-char-range nil
;; Don't display the state in the mode line.
evil-mode-line-format nil
evil-normal-state-cursor 'box
evil-emacs-state-cursor 'hbar
evil-operator-state-cursor 'evil-half-cursor
evil-insert-state-cursor 'bar
evil-visual-state-cursor 'hollow
;; Only do highlighting in selected window so that Emacs has less work
;; to do highlighting them all.
evil-ex-interactive-search-highlight 'selected-window
;; It's infuriating that innocuous "beginning of line" or "end of line"
;; errors will abort macros, so suppress them:
evil-kbd-macro-suppress-motion-error t
evil-undo-system (cond ((featurep 'undo-tree) 'undo-tree)
((featurep 'undo-fu) 'undo-fu)))
;; These two are required for evil-collection.
(setq evil-want-keybinding nil
evil-want-integration t)
:config
;; 'M-:' starts off in insert mode, yet initialises with the normal mode
;; cursor. Quick fix! }:P
(add-hook 'minibuffer-setup-hook
#'evil-refresh-cursor)
;; Unbind 'C-k'. Normally, it inserts digraphs; I have a compose key. It
;; often gets in the way of buffers with navigation, e.g. scrolling through
;; shell/REPL history, navigating Vertico completions, etc.
(keymap-set evil-insert-state-map "C-k" nil)
(evil-mode 1))
;; A large, community-sourced collection of preconfigured Evil-mode
;; integrations.
(use-package evil-collection
:after evil
:custom (evil-collection-setup-minibuffer t)
:config
(evil-collection-init))
;; Tim Pope's famous `surround.vim' for Evil.
(use-package evil-surround
:commands (global-evil-surround-mode
evil-surround-edit
evil-Surround-edit
evil-surround-region)
:hook (on-first-input . global-evil-surround-mode)
:config
;; In `emacs-lisp-mode', `' is a much more common pair than ``.
(add-hook 'emacs-lisp-mode-hook
(lambda ()
(push '(?` . ("`" . "'")) evil-surround-pairs-alist))))
;; TODO: I'd like JK to escape visual state. evil-escape only allows defining a
;; single key sequence. Perhaps key-chord is capable of this?
(use-package evil-escape
:hook (on-first-input . evil-escape-mode)
:custom ((evil-escape-key-sequence "jk")
(evil-escape-delay 0.15)))
;; `evil-nerd-commenter' has a bunch of cool functions[1]. Here, only the Evil
;; operator is used. }:3
;; [1]: https://github.com/redguardtoo/evil-nerd-commenter?tab=readme-ov-file#commands-and-hotkeys
(use-package evil-nerd-commenter
:commands (evilnc-comment-operator
evilnc-inner-comment
evilnc-outer-commenter)
:bind (:map evil-normal-state-map ("#" . evilnc-comment-operator)
:map evil-visual-state-map ("#" . evilnc-comment-operator)
:map evil-inner-text-objects-map ("c" . evilnc-inner-comment)
:map evil-outer-text-objects-map ("c" . evilnc-outer-comment)))
;; Enhance `evil-surround' with integration with `embrace'.
(use-package evil-embrace
:disabled
:after evil-surround
:config
(evil-embrace-enable-evil-surround-integration))
;; Provides an Evil operator to swap two spans of text.
(use-package evil-exchange
:bind (:map evil-normal-state-map ("gX" . evil-exchange)
:map evil-visual-state-map ("gX" . evil-exchange)))
;; Evil doesn't ship with support for Vim's 'g-'/'g+'. `evil-numbers'
;; implements this.
(use-package evil-numbers
;; 'g=' is a bit more comfortable than 'g+', whilst preserving the analogy.
;; ('=' is '+' modulo shift)
:bind (:map evil-normal-state-map ("g=" . 'evil-numbers/inc-at-pt)
:map evil-normal-state-map ("g-" . 'evil-numbers/dec-at-pt)))
;; Tree-sitter queries → Evil text objects.
(use-package evil-textobj-tree-sitter
:defer t)
;; Visually "flash" the region acted upon by Evil-mode operations.
(use-package evil-goggles
:hook (on-first-input . evil-goggles-mode)
;; The flash animation will delay actions, which can be very annoying for some
;; operations. Disable `evil-goggles' for those ones.
:custom
((evil-goggles-enable-delete nil)
(evil-goggles-enable-change nil)
(evil-goggles-duration 0.1)))
;; Change cursor shape and color by evil state in terminal.
(use-package evil-terminal-cursor-changer
;; This package is only useful in the terminal.
:if (not (display-graphic-p))
:hook (on-first-input . evil-terminal-cursor-changer-activate))
;; Automatic alignment in region, by regexp.
(use-package evil-lion
:hook (on-first-input . evil-lion-mode))
;; 'g' text object selecting the entire buffer.
(with-eval-after-load 'evil
(evil-define-text-object
evil-entire-buffer (count &optional beg end type)
"Select entire buffer"
(evil-range (point-min) (point-max) type))
(define-key evil-inner-text-objects-map "g" #'evil-entire-buffer)
(define-key evil-outer-text-objects-map "g" #'evil-entire-buffer))
;; 2-character search.
(use-package evil-snipe
:commands (evil-snipe-local-mode evil-snipe-override-local-mode)
:hook ((on-first-input . evil-snipe-override-mode)
(on-first-input . evil-snipe-mode))
:custom ((evil-snipe-smart-case t)
(evil-snipe-scope 'visible)
(evil-snipe-repeat-scope 'visible)
(evil-snipe-char-fold t)))
;; Evil's default behaviour for '#'/'*' in visual state will remain in visual
;; mode, and jump to the next occurence of the symbol under point. That is, the
;; movement is exactly the same as it is in normal state; if the region is over
;; the text `two words`, but the point is over `two`, Evil will search for
;; `two`. `evil-visualstar' will instead search for `two words`.
(use-package evil-visualstar
:bind (:map evil-visual-state-map
("*" . evil-visualstar/begin-search-forward)))
(provide 'syd-evil)