2017-10-08 20:36:28 +02:00
|
|
|
;;; Evil
|
2017-05-22 23:57:52 +02:00
|
|
|
|
2017-10-27 10:55:34 +02:00
|
|
|
;;; TODO: helm-show-kill-ring behaves like Emacs when pasting whole lines, not like Vim.
|
2017-05-27 16:36:01 +02:00
|
|
|
|
2017-10-08 20:36:28 +02:00
|
|
|
;;; TODO: Make Evil commands react more dynamically with read-only text, like eshell, wdired.
|
|
|
|
;;; Add support for I, C, D, S, s, c*, d*, R, r.
|
|
|
|
;;; See https://github.com/emacs-evil/evil/issues/852.
|
2017-07-19 17:58:33 +02:00
|
|
|
|
2017-10-08 20:36:28 +02:00
|
|
|
;;; REVIEW: 'cw' fails on the last character of the line when \n does not terminate it.
|
|
|
|
;;; See https://github.com/emacs-evil/evil/issues/863.
|
2017-08-01 20:55:50 +02:00
|
|
|
|
2017-05-22 23:57:52 +02:00
|
|
|
(evil-mode 1)
|
2019-02-04 19:10:57 +01:00
|
|
|
;; Enable search history:
|
|
|
|
(evil-select-search-module 'evil-search-module 'evil-search)
|
|
|
|
|
2017-06-26 18:14:04 +02:00
|
|
|
(remove-hook 'evil-insert-state-exit-hook 'expand-abbrev)
|
|
|
|
;; (setq evil-want-abbrev-expand-on-insert-exit nil)
|
2017-06-29 21:40:42 +02:00
|
|
|
(setq undo-tree-mode-lighter "")
|
2017-05-22 23:57:52 +02:00
|
|
|
|
2017-07-29 14:00:24 +02:00
|
|
|
(setq evil-cross-lines t
|
|
|
|
evil-move-beyond-eol t ; Especially useful for Edebug.
|
2017-08-04 18:49:59 +02:00
|
|
|
evil-move-cursor-back nil
|
2017-10-27 11:02:23 +02:00
|
|
|
evil-want-fine-undo t)
|
|
|
|
|
|
|
|
(setq-default evil-symbol-word-search t)
|
2017-07-29 14:00:24 +02:00
|
|
|
|
2017-10-08 20:36:28 +02:00
|
|
|
;;; Commenting.
|
|
|
|
;;; M-; comments next line in VISUAL. This is because of a different newline
|
|
|
|
;;; definition between Emacs and Vim.
|
|
|
|
;;; https://github.com/redguardtoo/evil-nerd-commenter: does not work well with
|
|
|
|
;;; motions and text objects, e.g. it cannot comment up without M--.
|
|
|
|
;;; `evil-commentary' is the way to go. We don't need an additional minor-mode though.
|
2017-07-02 19:53:20 +02:00
|
|
|
(when (require 'evil-commentary nil t)
|
|
|
|
(evil-global-set-key 'normal "gc" 'evil-commentary)
|
|
|
|
(evil-global-set-key 'normal "gy" 'evil-commentary-yank))
|
2017-06-24 11:04:05 +02:00
|
|
|
|
2017-06-25 13:12:56 +02:00
|
|
|
;;; Term mode should be in emacs state. It confuses 'vi' otherwise.
|
|
|
|
;;; Upstream will not change this:
|
|
|
|
;;; https://github.com/emacs-evil/evil/issues/854#issuecomment-309085267
|
|
|
|
(evil-set-initial-state 'term-mode 'emacs)
|
|
|
|
|
2017-10-08 20:36:28 +02:00
|
|
|
;;; For git commit, web edits and others.
|
|
|
|
;;; Since `with-editor-mode' is not a major mode, `evil-set-initial-state' cannot
|
|
|
|
;;; be used.
|
2017-10-27 10:55:34 +02:00
|
|
|
;;; This requires Eshell, shells and more.
|
2017-05-22 23:57:52 +02:00
|
|
|
(when (require 'with-editor nil t)
|
|
|
|
(add-hook 'with-editor-mode-hook 'evil-insert-state))
|
|
|
|
|
2017-10-08 20:36:28 +02:00
|
|
|
;;; Go-to-definition.
|
|
|
|
;;; From https://emacs.stackexchange.com/questions/608/evil-map-keybindings-the-vim-way.
|
2017-05-22 23:57:52 +02:00
|
|
|
(evil-global-set-key
|
|
|
|
'normal "gd"
|
|
|
|
(lambda () (interactive)
|
|
|
|
(evil-execute-in-emacs-state)
|
|
|
|
(call-interactively (key-binding (kbd "M-.")))))
|
|
|
|
|
2018-02-15 19:32:13 +01:00
|
|
|
;;; Multiedit
|
|
|
|
(when (require 'evil-multiedit nil t)
|
2018-03-19 11:44:38 +01:00
|
|
|
;; iedit exits as soon as an Evil operator is pressed.
|
|
|
|
;; Replace iedit's default binding with multiedit to avoid confusions.
|
|
|
|
(global-set-key (kbd "C-;") 'evil-multiedit-match-all)
|
2018-02-15 19:32:13 +01:00
|
|
|
;; REVIEW: Some bindings are missing:
|
|
|
|
;; See https://github.com/hlissner/evil-multiedit/issues/20.
|
|
|
|
(evil-multiedit-default-keybinds))
|
2017-05-22 23:57:52 +02:00
|
|
|
|
2017-10-08 20:36:28 +02:00
|
|
|
;;; Change mode-line color by Evil state.
|
2017-07-13 18:00:12 +02:00
|
|
|
(setq evil-default-modeline-color (cons (face-background 'mode-line) (or (face-foreground 'mode-line) "black")))
|
2018-02-15 13:28:49 +01:00
|
|
|
(defun ambrevar/evil-color-modeline ()
|
2017-07-13 18:00:12 +02:00
|
|
|
(let ((color (cond ((minibufferp) evil-default-modeline-color)
|
|
|
|
((evil-insert-state-p) '("#006fa0" . "#ffffff")) ; 00bb00
|
|
|
|
((evil-emacs-state-p) '("#444488" . "#ffffff"))
|
|
|
|
(t evil-default-modeline-color))))
|
|
|
|
(set-face-background 'mode-line (car color))
|
|
|
|
(set-face-foreground 'mode-line (cdr color))))
|
2018-02-15 13:28:49 +01:00
|
|
|
(add-hook 'post-command-hook 'ambrevar/evil-color-modeline)
|
2017-07-13 18:00:12 +02:00
|
|
|
(setq evil-mode-line-format nil)
|
2017-07-15 19:24:21 +02:00
|
|
|
|
2017-10-08 20:36:28 +02:00
|
|
|
;;; Add defun text-object. TODO: Does not work for "around".
|
|
|
|
;;; https://github.com/emacs-evil/evil/issues/874
|
2018-02-15 15:55:30 +01:00
|
|
|
;;; See Evil-cleverparens?
|
2017-07-17 18:16:43 +02:00
|
|
|
(evil-define-text-object evil-a-defun (count &optional beg end type)
|
|
|
|
"Select a defun."
|
|
|
|
(evil-select-an-object 'evil-defun beg end type count))
|
|
|
|
(evil-define-text-object evil-inner-defun (count &optional beg end type)
|
|
|
|
"Select inner defun."
|
|
|
|
(evil-select-inner-object 'evil-defun beg end type count))
|
|
|
|
(define-key evil-outer-text-objects-map "d" 'evil-a-defun)
|
|
|
|
(define-key evil-inner-text-objects-map "d" 'evil-inner-defun)
|
|
|
|
|
2017-10-08 20:36:28 +02:00
|
|
|
;;; Without the hook, the Edebug keys (f, n, i, etc.) would get mixed up on initialization.
|
2017-07-27 17:31:17 +02:00
|
|
|
(add-hook 'edebug-mode-hook 'evil-normalize-keymaps)
|
|
|
|
|
2017-10-08 20:36:28 +02:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;; Mode specific bindings.
|
2017-07-19 17:58:33 +02:00
|
|
|
|
2017-12-25 12:37:28 +01:00
|
|
|
;; Note: Config must be done before `require'-ing evil-collection.
|
|
|
|
(setq evil-collection-setup-minibuffer t
|
2020-10-26 09:42:57 +01:00
|
|
|
evil-collection-term-sync-state-and-mode-p t
|
|
|
|
evil-collection-want-unimpaired-p nil)
|
2017-11-06 18:05:14 +01:00
|
|
|
(when (require 'evil-collection nil t)
|
2017-12-23 11:23:06 +01:00
|
|
|
(evil-collection-init))
|
2017-10-16 19:21:24 +02:00
|
|
|
|
2017-11-06 18:05:14 +01:00
|
|
|
(with-eval-after-load 'elfeed
|
|
|
|
;; Custom
|
2018-03-03 18:04:15 +01:00
|
|
|
(evil-define-key 'normal elfeed-search-mode-map
|
2018-06-12 11:51:37 +02:00
|
|
|
(kbd "S-<return>") 'elfeed-search-show-entry
|
|
|
|
(kbd "<return>") 'ambrevar/elfeed-visit-maybe-external)
|
|
|
|
;; (evil-define-key 'normal elfeed-show-mode-map
|
|
|
|
;; (kbd "S-<return>") 'ambrevar/elfeed-visit-maybe-external)
|
2018-03-03 18:04:15 +01:00
|
|
|
(evil-define-key 'normal elfeed-show-mode-map
|
2018-02-15 23:40:15 +01:00
|
|
|
(kbd "q") 'ambrevar/elfeed-kill-entry))
|
2017-11-06 18:05:14 +01:00
|
|
|
|
2017-12-07 11:42:04 +01:00
|
|
|
;; Custom Helm
|
2017-12-08 17:28:40 +01:00
|
|
|
(with-eval-after-load 'helm
|
2019-03-03 10:06:36 +01:00
|
|
|
(define-key evil-motion-state-map "'" 'helm-all-mark-rings)
|
2017-12-08 17:28:40 +01:00
|
|
|
(global-set-key (kbd "M-y") 'helm-show-kill-ring)
|
2020-06-16 09:11:35 +02:00
|
|
|
;; Since Helm 3.6.* M-SPC is bound to helm-toggle-visible-mark-backward by default.
|
|
|
|
(define-key helm-map (kbd "M-SPC") 'helm-toggle-visible-mark)
|
|
|
|
(define-key helm-map (kbd "M-S-SPC") 'helm-toggle-visible-mark-backward)
|
2017-12-08 17:28:40 +01:00
|
|
|
(dolist (map (list helm-find-files-map helm-read-file-map))
|
2018-02-13 13:42:11 +01:00
|
|
|
(ambrevar/define-keys map
|
|
|
|
"M-." 'helm-end-of-buffer
|
|
|
|
"M-," 'helm-beginning-of-buffer))
|
2017-12-08 17:28:40 +01:00
|
|
|
;; `helm-mark-or-exchange-rect' is not needed with Evil.
|
|
|
|
(global-set-key (kbd "C-x C-x") 'helm-all-mark-rings))
|
2017-11-06 18:05:14 +01:00
|
|
|
|
2017-10-16 19:21:24 +02:00
|
|
|
;;; nXML
|
2017-11-07 12:18:47 +01:00
|
|
|
;;; TODO: Add to evil-collection?
|
2017-10-16 19:21:24 +02:00
|
|
|
(evil-define-key 'normal nxml-mode-map
|
2017-10-17 00:52:50 +02:00
|
|
|
(kbd "C-j") 'nxml-forward-element
|
|
|
|
(kbd "C-k") 'nxml-backward-element
|
|
|
|
(kbd "M-j") 'nxml-forward-element ; Custom
|
|
|
|
(kbd "M-k") 'nxml-backward-element ; Custom
|
2017-10-16 19:21:24 +02:00
|
|
|
">" 'nxml-down-element
|
|
|
|
"<" 'nxml-backward-up-element)
|
|
|
|
(evil-define-key 'visual nxml-mode-map
|
2017-10-17 00:52:50 +02:00
|
|
|
(kbd "C-j") 'nxml-forward-element
|
|
|
|
(kbd "C-k") 'nxml-backward-element
|
|
|
|
(kbd "M-j") 'nxml-forward-element ; Custom
|
|
|
|
(kbd "M-k") 'nxml-backward-element ; Custom
|
2017-10-16 19:21:24 +02:00
|
|
|
">" 'nxml-down-element
|
|
|
|
"<" 'nxml-backward-up-element)
|
2017-07-24 16:25:45 +02:00
|
|
|
|
2018-06-16 19:25:19 +02:00
|
|
|
|
|
|
|
(defun ambrevar/evil-mu4e (mode _mode-keymaps &rest _rest)
|
|
|
|
(when (eq mode 'mu4e)
|
|
|
|
(evil-define-key 'normal mu4e-main-mode-map
|
|
|
|
"s" 'helm-mu)
|
|
|
|
(evil-define-key 'normal mu4e-headers-mode-map
|
|
|
|
;; "r" 'mu4e-compose-reply
|
|
|
|
"s" 'helm-mu
|
|
|
|
;; Custom
|
|
|
|
"x" 'ambrevar/mu4e-mark-execute-all-no-confirm
|
|
|
|
"d" 'ambrevar/mu4e-headers-move-to-trash)
|
|
|
|
(evil-define-key 'visual mu4e-headers-mode-map
|
|
|
|
"s" 'helm-mu
|
|
|
|
;; Custom
|
|
|
|
"x" 'ambrevar/mu4e-mark-execute-all-no-confirm
|
|
|
|
"d" 'ambrevar/mu4e-headers-move-to-trash)
|
|
|
|
(evil-define-key 'normal mu4e-view-mode-map
|
|
|
|
;; "r" 'mu4e-compose-reply
|
|
|
|
"s" 'helm-mu
|
|
|
|
;; Custom
|
|
|
|
"d" 'ambrevar/mu4e-view-move-to-trash
|
2019-03-03 14:07:18 +01:00
|
|
|
"x" 'ambrevar/mu4e-mark-execute-all-no-confirm)))
|
2018-06-16 19:25:19 +02:00
|
|
|
(add-hook 'evil-collection-setup-hook 'ambrevar/evil-mu4e)
|
2017-07-19 17:17:24 +02:00
|
|
|
|
2019-03-17 09:27:18 +01:00
|
|
|
(defun ambrevar/evil-notmuch (mode _mode-keymaps &rest _rest)
|
|
|
|
(when (eq mode 'notmuch)
|
|
|
|
(evil-define-key 'normal notmuch-hello-mode-map
|
|
|
|
"s" 'helm-notmuch)
|
|
|
|
(evil-define-key 'normal notmuch-search-mode-map
|
|
|
|
"s" 'helm-notmuch)
|
2019-03-18 18:51:25 +01:00
|
|
|
(evil-define-key 'normal notmuch-tree-mode-map
|
2019-03-17 09:27:18 +01:00
|
|
|
"s" 'helm-notmuch)
|
|
|
|
(evil-define-key 'normal notmuch-show-mode-map
|
|
|
|
"s" 'helm-notmuch)))
|
|
|
|
(add-hook 'evil-collection-setup-hook 'ambrevar/evil-notmuch)
|
|
|
|
|
2017-07-19 17:58:33 +02:00
|
|
|
(with-eval-after-load 'magit
|
|
|
|
(when (require 'evil-magit nil t)
|
|
|
|
(evil-magit-define-key evil-magit-state 'magit-mode-map "<" 'magit-section-up)
|
|
|
|
;; C-j/k is the default, M-j/k is more consistent with our customization for Helm.
|
|
|
|
(evil-magit-define-key evil-magit-state 'magit-mode-map "M-j" 'magit-section-forward)
|
|
|
|
(evil-magit-define-key evil-magit-state 'magit-mode-map "M-k" 'magit-section-backward)))
|
|
|
|
|
2017-12-22 18:31:53 +01:00
|
|
|
(with-eval-after-load 'org
|
|
|
|
;; Don't require evil-org before org is loaded.
|
|
|
|
;; Elfeed-link is loaded after org.
|
|
|
|
(when (require 'evil-org nil t)
|
2018-01-17 10:13:28 +01:00
|
|
|
;; org-evil is not as polished as of May 2017.
|
|
|
|
;; See https://github.com/Somelauw/evil-org-mode/blob/master/doc/keythemes.org for inspiration.
|
|
|
|
(add-hook 'org-mode-hook 'evil-org-mode)
|
2018-03-24 15:10:08 +01:00
|
|
|
;; No need for 'insert, 'todo 'heading.
|
2018-01-17 10:13:28 +01:00
|
|
|
(evil-org-set-key-theme '(navigation textobjects additional shift))
|
2018-02-15 13:28:49 +01:00
|
|
|
(defun ambrevar/evil-org-meta-return ()
|
2018-01-17 10:13:28 +01:00
|
|
|
"Like `org-meta-return' but switch to insert mode."
|
|
|
|
(interactive)
|
|
|
|
(evil-insert 1)
|
|
|
|
(org-meta-return))
|
|
|
|
(evil-define-key 'normal evil-org-mode-map
|
|
|
|
"^" 'org-up-element ; Evil-Magit-inspired. TODO: Suggest upstream.
|
|
|
|
"<" 'org-up-element ; Custom
|
|
|
|
">" 'org-down-element ; Custom
|
2018-02-15 13:28:49 +01:00
|
|
|
(kbd "M-<return>") 'ambrevar/evil-org-meta-return)
|
2017-12-22 18:31:53 +01:00
|
|
|
(with-eval-after-load 'org-agenda
|
|
|
|
(require 'evil-org-agenda)
|
2019-08-05 11:46:46 +02:00
|
|
|
(evil-org-agenda-set-keys))
|
|
|
|
|
|
|
|
;; REVIEW: Fix shift-tab in Evil org.
|
|
|
|
;; See https://github.com/emacs-evil/evil-collection/issues/53.
|
2019-08-14 17:26:32 +02:00
|
|
|
(setq evil-collection-outline-bind-tab-p nil)
|
2019-08-05 11:46:46 +02:00
|
|
|
(evil-define-key '(normal visual) evil-org-mode-map
|
|
|
|
(kbd "<backtab>") 'org-shifttab)))
|
2017-07-19 17:58:33 +02:00
|
|
|
|
2018-03-24 15:33:40 +01:00
|
|
|
;; EWW
|
|
|
|
(defun ambrevar/evil-eww (mode _mode-keymaps &rest _rest)
|
|
|
|
(when (eq mode 'eww)
|
2018-04-15 15:08:04 +02:00
|
|
|
(evil-define-key 'operator eww-mode-map
|
|
|
|
"t" '(menu-item
|
|
|
|
""
|
|
|
|
nil
|
|
|
|
:filter (lambda (&optional _)
|
|
|
|
(when (memq evil-this-operator
|
|
|
|
evil-collection-yank-operators)
|
|
|
|
(setq evil-inhibit-operator t)
|
|
|
|
#'ambrevar/eww-copy-page-title))))
|
2018-04-14 09:10:23 +02:00
|
|
|
(evil-define-key 'normal eww-mode-map "O" 'ambrevar/eww-open-in-new-buffer)
|
2018-03-24 15:33:40 +01:00
|
|
|
(evil-define-key 'normal eww-mode-map "[" 'ambrevar/eww-previous-url)
|
|
|
|
(evil-define-key 'normal eww-mode-map "]" 'ambrevar/eww-next-url)))
|
|
|
|
(add-hook 'evil-collection-setup-hook 'ambrevar/evil-eww)
|
|
|
|
|
2018-04-26 09:30:04 +02:00
|
|
|
(with-eval-after-load 'helm-eww
|
|
|
|
(evil-define-key '(insert normal) helm-eww-buffers-map (kbd "S-<return>") 'helm-buffer-switch-other-window)
|
|
|
|
(evil-define-key '(insert normal) helm-eww-bookmarks-map (kbd "S-<return>") 'helm-buffer-switch-other-window))
|
|
|
|
|
2018-07-29 11:22:46 +02:00
|
|
|
;; Elfeed
|
2018-08-06 11:05:32 +02:00
|
|
|
(with-eval-after-load 'elfeed
|
|
|
|
(dolist (map (list elfeed-search-mode-map elfeed-show-mode-map))
|
|
|
|
(evil-define-key 'normal map "m" 'ambrevar/elfeed-add-bookmark)))
|
2018-07-29 11:22:46 +02:00
|
|
|
|
2019-05-25 19:47:55 +02:00
|
|
|
(with-eval-after-load 'notmuch
|
|
|
|
(defun ambrevar/notmuch-mark-unread-and-bury ()
|
|
|
|
(interactive)
|
|
|
|
(notmuch-show-add-tag '("+unread"))
|
|
|
|
(notmuch-bury-or-kill-this-buffer))
|
|
|
|
(evil-define-key 'normal notmuch-show-mode-map "Q" 'ambrevar/notmuch-mark-unread-and-bury))
|
|
|
|
|
2019-02-04 19:12:48 +01:00
|
|
|
;; Eshell
|
2019-02-11 19:40:49 +01:00
|
|
|
(defun ambrevar/evil-eshell ()
|
2020-06-26 17:41:47 +02:00
|
|
|
(evil-define-key 'visual eshell-mode-map (kbd "<return>") 'ambrevar/eshell-append-region-to-command-line)
|
|
|
|
(evil-define-key 'visual shell-mode-map (kbd "<return>") 'ambrevar/eshell-append-region-to-command-line))
|
2019-02-11 19:40:49 +01:00
|
|
|
(with-eval-after-load 'init-eshell
|
|
|
|
;; Eshell bindings must be initializeed in the mode hook.
|
|
|
|
(add-hook 'eshell-mode-hook 'ambrevar/evil-eshell))
|
2019-02-04 19:12:48 +01:00
|
|
|
|
2019-06-01 13:47:05 +02:00
|
|
|
(with-eval-after-load 'guix
|
|
|
|
(evil-define-key 'normal guix-generation-list-mode-map "=" 'ambrevar/guix-generations-list-diff-this))
|
|
|
|
|
2017-06-18 18:50:31 +02:00
|
|
|
(provide 'init-evil)
|