Archived
85 lines
2.6 KiB
EmacsLisp
Executable File
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
|