165 lines
6.4 KiB
EmacsLisp
Executable File
165 lines
6.4 KiB
EmacsLisp
Executable File
;;; 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-u-scroll 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-excluded-states '(normal visual multiedit emacs motion))
|
|
(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)
|
|
:defer t
|
|
: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))
|
|
:defer t)
|
|
|
|
;; 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))
|
|
:defer t
|
|
: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
|
|
:defer t
|
|
:bind (:map evil-visual-state-map
|
|
("*" . evil-visualstar/begin-search-forward)))
|
|
|
|
(provide 'syd-evil)
|