用Evil Collection,在emacs和evil按键存在冲突时,只能迁就一个,不能两全。典型的场景是magit中jk是evil的操作,hl是emacs的操作。这太别扭了。
我想到一种解决思路,同时保留两套按键。evil像是悬浮在emacs上面,所有按键都是evil的操作。然后定义一个前缀键(define-prefix-command),按下前缀键之后可以穿透evil,继续按键就是emacs的操作。
具体实现如下:
(use-package evil :ensure t
:init
(setq evil-disable-insert-state-bindings t) ;; insert state保留emacs键绑定。
(setq evil-want-keybinding nil) ;; 不要执行evil-keybindings.el,evil-keybindings.el的作用和Evil Collection类似。
(setq evil-want-C-i-jump nil) ;; 把TAB键释放出来。
:config
(setq evil-emacs-state-modes '(ediff-mode color-rg-mode)) ;; ediff-mode和color-rg-mode不需要evil。
(add-hook 'with-editor-mode-hook 'evil-insert-state) ;; 可编辑模式默认insert state。
(evil-mode))
;; 使用define-prefix-command实现类似spacemacs键绑定
(define-prefix-command 'space-leader-map)
(keymap-set evil-motion-state-map "SPC" 'space-leader-map)
(keymap-set evil-normal-state-map "SPC" 'space-leader-map)
(evil-define-key nil space-leader-map
(kbd "SPC") 'execute-extended-command
(kbd "RET") 'consult-bookmark
"0" 'treemacs-select-window
;; buffer
"bb" 'consult-buffer
"bi" 'ibuffer
"bd" 'evil-delete-buffer
"bl" 'evil-switch-to-windows-last-buffer
"bx" #'(lambda () (interactive) (switch-to-buffer "*scratch*"))
;; 省略更多键绑定
;; quit
"qr" 'restart-emacs
"qq" '("Quit" . save-buffers-kill-terminal))
;; 最关键一步。在normal模式下按 SPC + m 会进入当前mode的major-mode-map,继续按键就是emacs的操作了。
(add-hook 'buffer-list-update-hook #'(lambda () (interactive) (keymap-set space-leader-map "m" (symbol-value (intern-soft (format "%s-map" major-mode))))))
;; 之前已经把TAB键释放出来,再把RET和q释放出来。
(define-key evil-motion-state-map (kbd "RET") nil)
(evil-define-key 'normal text-mode-map (kbd "RET") #'embark-dwim) ;; embark-dwim相当于vscode中 Ctrl + 鼠标左键。
(evil-define-key 'normal prog-mode-map (kbd "RET") #'embark-dwim)
(evil-define-key 'normal special-mode-map "q" #'quit-window)
这套模式我已经用了一段时间了,很舒服。比如在magit中,hjkl就是evil的方向键。然后按 SPC + m + s 进行stage。多个文件需要state话,移动到对应文件,按 .(evil-repeat)。按 SPC + m + c + c 进行提交。
总结一下,默认所有按键都是evil操作,需要emacs操作时,先按 SPC + m ,再按emacs中对应的键绑定。
配合which key,按下 SPC + m,会呈现出当前major mode的快捷键提示。
我的完整配置看这里: .emacs.d/lisp/key.el at main · ltylty/.emacs.d · GitHub