This repository has been archived on 2026-10-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files

85 lines
2.6 KiB
EmacsLisp
Executable File

;;; init-evil.el --- Evil, scoped to buffer editing -*- lexical-binding: t; -*-
;;; Commentary:
;; Evil is deliberately narrow: modal editing in text buffers only, no
;; evil-collection. Dired/Magit/etc. keep native bindings on purpose.
;; The nav keys below use `my/project-or': project-scoped command inside a
;; project, consult fallback everywhere else.
;;; Code:
(require 'project)
(defmacro my/project-or (project-cmd fallback-cmd)
"Call PROJECT-CMD inside a known project, else FALLBACK-CMD.
Both are unquoted command symbols."
`(lambda ()
(interactive)
(call-interactively
(if (project-current)
#',project-cmd
#',fallback-cmd))))
(defun my/insert-tab ()
"Insert a literal tab.
Bound to both TAB and <tab> to override major-mode indent in insert state;
`self-insert-command' can't handle the <tab> event (its arg is the symbol
`tab', not a character)."
(interactive)
(insert "\t"))
(use-package evil
:init
(setq evil-want-keybinding nil)
:config
(evil-mode 1)
;; Vim commands
(evil-ex-define-cmd "w" #'save-buffer)
(evil-ex-define-cmd "q" #'kill-current-buffer)
(evil-ex-define-cmd "wq" #'save-buffers-kill-terminal)
;; Half-page movement
(define-key evil-normal-state-map (kbd "C-d") #'evil-scroll-down)
(define-key evil-normal-state-map (kbd "C-u") #'evil-scroll-up)
;; Editor shortcuts
(dolist (map '(evil-normal-state-map
evil-motion-state-map))
(define-key (symbol-value map)
(kbd "C-e")
(my/project-or project-dired dired-jump))
(define-key (symbol-value map)
(kbd "C-s")
#'consult-line)
;; C-m is \r (= RET). Bind [return] to evil-ret so GUI Enter never falls
;; back to this C-m binding, leaving C-m free as its own key (GUI only).
(define-key (symbol-value map)
(kbd "C-m")
(my/project-or project-switch-to-buffer consult-buffer))
(define-key (symbol-value map)
[return]
#'evil-ret)
;; consult-ripgrep everywhere: it already scopes to the project root when
;; there is one, and shows hits in the posframe (RET jumps) like the other
;; finders — unlike project-find-regexp's separate xref pane.
(define-key (symbol-value map)
(kbd "C-f")
#'consult-ripgrep)
(define-key (symbol-value map)
(kbd "C-p")
(my/project-or project-find-file consult-fd))))
;; Literal tab on TAB/<tab> in insert state, overriding major-mode indent.
(with-eval-after-load 'evil
(evil-define-key 'insert 'global (kbd "TAB") #'my/insert-tab)
(evil-define-key 'insert 'global [tab] #'my/insert-tab))
(provide 'init-evil)
;;; init-evil.el ends here