;;; syd-evil.el -*- lexical-binding: t; -*- ;; Vim emulation. (use-package evil :init (setq evil-want-minibuffer t) (setq evil-move-beyond-eol t) (setq evil-vsplit-window-right t) ;; 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) (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 :ensure t :config (global-evil-surround-mode 1) ;; 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 :config (setq-default evil-escape-key-sequence "jk" evil-escape-delay 0.15) (evil-escape-mode 1)) ;; `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 :config (define-key evil-normal-state-map "#" #'evilnc-comment-operator) (define-key evil-visual-state-map "#" #'evilnc-comment-operator) (define-key evil-inner-text-objects-map "c" 'evilnc-inner-commenter) (define-key evil-outer-text-objects-map "c" 'evilnc-outer-commenter)) ;; Enhance `evil-surround' with integration with `embrace'. (use-package evil-embrace :disabled :after evil-surround :config (evil-embrace-enable-evil-surround-integration)) ;; Provides a command to swap two regions of text. (use-package evil-exchange :config (define-key evil-normal-state-map "gX" 'evil-exchange) (define-key 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 :config ;; 'g=' is a bit more comfortable than 'g+', whilst preserving the analogy. ;; ('=' is '+' modulo shift) (define-key evil-normal-state-map "g=" 'evil-numbers/inc-at-pt) (define-key evil-normal-state-map "g-" 'evil-numbers/dec-at-pt)) ;; Tree-sitter queries → Evil text objects. (use-package evil-textobj-tree-sitter) ;; Visually "flash" the region acted upon by Evil-mode operations. (use-package evil-goggles ;; 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) :config (evil-goggles-mode 1)) ;; Change cursor shape and color by evil state in terminal. (use-package evil-terminal-cursor-changer :if (not (display-graphic-p)) :config (setq evil-motion-state-cursor 'box) (setq evil-visual-state-cursor 'box) (setq evil-normal-state-cursor 'box) (setq evil-insert-state-cursor 'bar) (setq evil-emacs-state-cursor 'hbar) (evil-terminal-cursor-changer-activate)) ;; Automatic alignment in region, by regexp. (use-package evil-lion :config (evil-lion-mode 1)) ;; Provides the 'g' text object which selects the entire buffer. (use-package evil-textobj-entire) ;; 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) :hook (on-first-input . evil-snipe-mode) :init (setq evil-snipe-smart-case t evil-snipe-scope 'visible evil-snipe-repeat-scope 'visible evil-snipe-char-fold t)) ;; Extend the set of delimiters recognised by '%'. (use-package evil-matchit :config (global-evil-matchit-mode 1)) (provide 'syd-evil)