feature/evil: refactor

This commit is contained in:
Henrik Lissner 2017-05-15 13:52:22 +02:00
parent 04c270d76b
commit 5fb028b49d
4 changed files with 197 additions and 199 deletions

View file

@ -23,9 +23,6 @@
mouse-yank-at-point t ; middle-click paste at point, not at click mouse-yank-at-point t ; middle-click paste at point, not at click
resize-mini-windows 'grow-only ; Minibuffer resizing resize-mini-windows 'grow-only ; Minibuffer resizing
show-help-function nil ; hide :help-echo text show-help-function nil ; hide :help-echo text
show-paren-delay 0.075
show-paren-highlight-openparen t
show-paren-when-point-inside-paren t
split-width-threshold nil ; favor horizontal splits split-width-threshold nil ; favor horizontal splits
uniquify-buffer-name-style 'forward uniquify-buffer-name-style 'forward
use-dialog-box nil ; always avoid GUI use-dialog-box nil ; always avoid GUI
@ -89,6 +86,12 @@ local value, whether or not it's permanent-local. Therefore, we cycle
(require 'winner) (require 'winner)
(add-hook 'window-setup-hook #'winner-mode) (add-hook 'window-setup-hook #'winner-mode)
;; highlight matching delimiters
(setq show-paren-delay 0.2
show-paren-highlight-openparen t
show-paren-when-point-inside-paren t)
(show-paren-mode +1)
;; ;;
;; Bootstrap ;; Bootstrap

View file

@ -99,10 +99,114 @@ flags. See http://vimdoc.sourceforge.net/htmldoc/cmdline.html#filename-modifiers
path file-name t t 1)))) path file-name t t 1))))
(setq file-name (replace-regexp-in-string regexp "\\1" file-name t)))) (setq file-name (replace-regexp-in-string regexp "\\1" file-name t))))
(defun +evil--window-swap (direction)
"Move current window to the next window in DIRECTION. If there are no windows
there and there is only one window, split in that direction and place this
window there. If there are no windows and this isn't the only window, use
evil-window-move-* (e.g. `evil-window-move-far-left')"
(let* ((this-window (get-buffer-window))
(this-buffer (current-buffer))
(that-window (windmove-find-other-window direction nil this-window))
(that-buffer (window-buffer that-window)))
(when (or (minibufferp that-buffer)
(doom-popup-p that-window))
(setq that-buffer nil that-window nil))
(if (not (or that-window (one-window-p t)))
(funcall (case direction
('left 'evil-window-move-far-left)
('right 'evil-window-move-far-right)
('up 'evil-window-move-very-top)
('down 'evil-window-move-very-bottom)))
(unless that-window
(setq that-window
(split-window this-window nil (cond ((eq direction 'up) 'above)
((eq direction 'down) 'below)
(t direction))))
(with-selected-window that-window
(switch-to-buffer doom-buffer))
(setq that-buffer (window-buffer that-window)))
(with-selected-window this-window
(switch-to-buffer that-buffer))
(with-selected-window that-window
(switch-to-buffer this-buffer))
(select-window that-window))))
;; ;;;###autoload
;; Custom argument handlers (defun +evil/window-move-left () "`+evil--window-swap'" (interactive) (+evil--window-swap 'left))
;; ;;;###autoload
(defun +evil/window-move-right () "`+evil--window-swap'" (interactive) (+evil--window-swap 'right))
;;;###autoload
(defun +evil/window-move-up () "`+evil--window-swap'" (interactive) (+evil--window-swap 'up))
;;;###autoload
(defun +evil/window-move-down () "`+evil--window-swap'" (interactive) (+evil--window-swap 'down))
;;;###autoload (autoload '+evil:macro-on-all-lines "feature/evil/autoload/evil" nil t)
(evil-define-operator +evil:macro-on-all-lines (beg end &optional macro)
"Apply macro to each line."
:motion nil
:move-point nil
(interactive "<r><a>")
(unless (and beg end)
(setq beg (region-beginning)
end (region-end)))
(evil-ex-normal beg end
(concat "@"
(single-key-description
(or macro (read-char "@-"))))))
;;;###autoload (autoload '+evil:retab "feature/evil/autoload/evil" nil t)
(evil-define-operator +evil:retab (&optional beg end)
"Wrapper around `doom/retab'."
:motion nil :move-point nil :type line
(interactive "<r>")
(doom/retab beg end))
;;;###autoload (autoload '+evil:narrow-buffer "feature/evil/autoload/evil" nil t)
(evil-define-command +evil:narrow-buffer (beg end &optional bang)
"Wrapper around `doom-narrow-buffer'."
:move-point nil
(interactive "<r><!>")
(doom-narrow-buffer beg end bang))
;; --- code folding -----------------------
;; I wrote these for two reasons:
;; 1. To facilitate lazy-loading of hideshow.el (otherwise, evil wouldn't know what mode to use)
;; 2. To allow level-based folding (parity with vim), e.g. 2zr will open all
;; folds up to 2nd level folds.
;;;###autoload (autoload '+evil:open-folds-recursively "feature/evil/autoload/evil" nil t)
(evil-define-command +evil:open-folds-recursively (level)
"Opens all folds recursively, up to LEVEL."
(interactive "<c>")
(unless (bound-and-true-p hs-minor-mode)
(hs-minor-mode 1))
(if level (hs-hide-level level) (evil-open-folds)))
;;;###autoload (autoload '+evil:close-folds-recursively "feature/evil/autoload/evil" nil t)
(evil-define-command +evil:close-folds-recursively (level)
"Closes all folds recursively, up to LEVEL."
(interactive "<c>")
(unless (bound-and-true-p hs-minor-mode)
(hs-minor-mode 1))
(if level (hs-hide-level level) (evil-close-folds)))
;;;###autoload
(defun +evil/matchit-or-toggle-fold ()
"Do what I mean. If on a fold-able element, toggle the fold with
`hs-toggle-hiding'. Otherwise, if on a delimiter, jump to the matching one with
`evilmi-jump-items'. If in a magit-status buffer, use `magit-section-toggle'."
(interactive)
(cond ((eq major-mode 'magit-status-mode)
(call-interactively 'magit-section-toggle))
((ignore-errors (hs-already-hidden-p))
(hs-toggle-hiding))
(t
(call-interactively 'evilmi-jump-items))))
;; --- custom arg handlers ----------------
(defvar +evil--buffer-match-global evil-ex-substitute-global "") (defvar +evil--buffer-match-global evil-ex-substitute-global "")
@ -155,101 +259,3 @@ flags. See http://vimdoc.sourceforge.net/htmldoc/cmdline.html#filename-modifiers
(+evil--ex-match-init hl-name) (+evil--ex-match-init hl-name)
(let ((result (car-safe (evil-ex-parse-global arg)))) (let ((result (car-safe (evil-ex-parse-global arg))))
(+evil--ex-buffer-match result hl-name nil (point-min) (point-max)))))) (+evil--ex-buffer-match result hl-name nil (point-min) (point-max))))))
;;;###autoload
(defun +evil-window-move (direction)
"Move current window to the next window in DIRECTION. If there are no windows
there and there is only one window, split in that direction and place this
window there. If there are no windows and this isn't the only window, use
evil-window-move-* (e.g. `evil-window-move-far-left')"
(let* ((this-window (get-buffer-window))
(this-buffer (current-buffer))
(that-window (windmove-find-other-window direction nil this-window))
(that-buffer (window-buffer that-window)))
(when (or (minibufferp that-buffer)
(doom-popup-p that-window))
(setq that-buffer nil that-window nil))
(if (not (or that-window (one-window-p t)))
(funcall (case direction
('left 'evil-window-move-far-left)
('right 'evil-window-move-far-right)
('up 'evil-window-move-very-top)
('down 'evil-window-move-very-bottom)))
(unless that-window
(setq that-window
(split-window this-window nil (cond ((eq direction 'up) 'above)
((eq direction 'down) 'below)
(t direction))))
(with-selected-window that-window
(switch-to-buffer doom-buffer))
(setq that-buffer (window-buffer that-window)))
(with-selected-window this-window
(switch-to-buffer that-buffer))
(with-selected-window that-window
(switch-to-buffer this-buffer))
(select-window that-window))))
;;;###autoload
(defun +evil/window-move-left () "`+evil-window-move'" (interactive) (+evil-window-move 'left))
;;;###autoload
(defun +evil/window-move-right () "`+evil-window-move'" (interactive) (+evil-window-move 'right))
;;;###autoload
(defun +evil/window-move-up () "`+evil-window-move'" (interactive) (+evil-window-move 'up))
;;;###autoload
(defun +evil/window-move-down () "`+evil-window-move'" (interactive) (+evil-window-move 'down))
;;;###autoload
(defun +evil/matchit-or-toggle-fold ()
"If on a fold-able element, toggle the fold (`hs-toggle-hiding'). Otherwise,
if on a delimiter, jump to the matching one (`evilmi-jump-items')."
(interactive)
(cond ((eq major-mode 'magit-status-mode)
(call-interactively 'magit-section-toggle))
((ignore-errors (hs-already-hidden-p))
(hs-toggle-hiding))
(t
(call-interactively 'evilmi-jump-items))))
;;;###autoload (autoload '+evil:macro-on-all-lines "feature/evil/autoload/evil" nil t)
(evil-define-operator +evil:macro-on-all-lines (beg end &optional macro)
"Apply macro to each line."
:motion nil
:move-point nil
(interactive "<r><a>")
(unless (and beg end)
(setq beg (region-beginning)
end (region-end)))
(evil-ex-normal beg end
(concat "@"
(single-key-description
(or macro (read-char "@-"))))))
;;;###autoload (autoload '+evil:open-folds-recursively "feature/evil/autoload/evil" nil t)
(evil-define-command +evil:open-folds-recursively (level)
"Opens all folds recursively, up to LEVEL."
(interactive "<c>")
(unless (bound-and-true-p hs-minor-mode)
(hs-minor-mode 1))
(if level (hs-hide-level level) (evil-open-folds)))
;;;###autoload (autoload '+evil:close-folds-recursively "feature/evil/autoload/evil" nil t)
(evil-define-command +evil:close-folds-recursively (level)
"Closes all folds recursively, up to LEVEL."
(interactive "<c>")
(unless (bound-and-true-p hs-minor-mode)
(hs-minor-mode 1))
(if level (hs-hide-level level) (evil-close-folds)))
;;;###autoload (autoload '+evil:retab "feature/evil/autoload/evil" nil t)
(evil-define-operator +evil:retab (&optional beg end)
"Wrapper around `doom/retab'."
:motion nil :move-point nil :type line
(interactive "<r>")
(doom/retab beg end))
;;;###autoload (autoload '+evil:narrow-buffer "feature/evil/autoload/evil" nil t)
(evil-define-command +evil:narrow-buffer (beg end &optional bang)
"Wrapper around `doom-narrow-buffer'."
:move-point nil
(interactive "<r><!>")
(doom-narrow-buffer beg end bang))

View file

@ -26,9 +26,7 @@
:init :init
(setq evil-want-C-u-scroll t (setq evil-want-C-u-scroll t
evil-want-visual-char-semi-exclusive t evil-want-visual-char-semi-exclusive t
evil-want-fine-undo nil
evil-want-Y-yank-to-eol t evil-want-Y-yank-to-eol t
evil-ex-interactive-search-highlight 'selected-window
evil-magic t evil-magic t
evil-echo-state t evil-echo-state t
evil-indent-convert-tabs t evil-indent-convert-tabs t
@ -36,7 +34,12 @@
evil-ex-substitute-global t evil-ex-substitute-global t
evil-ex-visual-char-range t ; column range for ex commands evil-ex-visual-char-range t ; column range for ex commands
evil-insert-skip-empty-lines t evil-insert-skip-empty-lines t
evil-mode-line-format 'nil
;; Move to new split
evil-split-window-below t
evil-vsplit-window-right t
;; more vim-like behavior
evil-symbol-word-search t
;; don't activate mark on shift-click ;; don't activate mark on shift-click
shift-select-mode nil) shift-select-mode nil)
@ -51,7 +54,7 @@
;; Don't interfere with localleader key ;; Don't interfere with localleader key
(define-key evil-motion-state-map "\\" nil) (define-key evil-motion-state-map "\\" nil)
;; Set cursor colors later, presumably once theme is loaded ;; Set cursor colors later, once theme is loaded
(defun +evil*init-cursors (&rest _) (defun +evil*init-cursors (&rest _)
(setq evil-default-cursor (face-background 'cursor nil t) (setq evil-default-cursor (face-background 'cursor nil t)
evil-normal-state-cursor 'box evil-normal-state-cursor 'box
@ -60,23 +63,10 @@
evil-visual-state-cursor 'hollow)) evil-visual-state-cursor 'hollow))
(advice-add #'load-theme :after #'+evil*init-cursors) (advice-add #'load-theme :after #'+evil*init-cursors)
;; highlight matching delimiters where it's important ;; default modes
(defun +evil|show-paren-mode-off () (show-paren-mode -1))
(defun +evil|show-paren-mode-on ()
(unless (bound-and-true-p org-indent-mode) ; interferes with org-indent
(show-paren-mode +1)))
(add-hook 'evil-insert-state-entry-hook #'+evil|show-paren-mode-on)
(add-hook 'evil-insert-state-exit-hook #'+evil|show-paren-mode-off)
(add-hook 'evil-visual-state-entry-hook #'+evil|show-paren-mode-on)
(add-hook 'evil-visual-state-exit-hook #'+evil|show-paren-mode-off)
(add-hook 'evil-operator-state-entry-hook #'+evil|show-paren-mode-on)
(add-hook 'evil-operator-state-exit-hook #'+evil|show-paren-mode-off)
(add-hook 'evil-normal-state-entry-hook #'+evil|show-paren-mode-off)
(dolist (mode '(tabulated-list-mode view-mode comint-mode term-mode calendar-mode Man-mode grep-mode)) (dolist (mode '(tabulated-list-mode view-mode comint-mode term-mode calendar-mode Man-mode grep-mode))
(evil-set-initial-state mode 'emacs)) (evil-set-initial-state mode 'emacs))
(dolist (mode '(help-mode)) (dolist (mode '(help-mode debugger-mode))
(evil-set-initial-state mode 'normal)) (evil-set-initial-state mode 'normal))
;; make `try-expand-dabbrev' from `hippie-expand' work in mini-buffer ;; make `try-expand-dabbrev' from `hippie-expand' work in mini-buffer
@ -85,81 +75,82 @@
(set-syntax-table (let* ((table (make-syntax-table))) (set-syntax-table (let* ((table (make-syntax-table)))
(modify-syntax-entry ?/ "." table) (modify-syntax-entry ?/ "." table)
table))) table)))
(add-hook 'minibuffer-inactive-mode-hook #'minibuffer-inactive-mode-hook-setup)) (add-hook 'minibuffer-inactive-mode-hook #'minibuffer-inactive-mode-hook-setup)
(defsubst +evil--textobj (key inner-fn &optional outer-fn) (defsubst +evil--textobj (key inner-fn &optional outer-fn)
"Define a text object." "Define a text object."
(declare (indent defun))
(define-key evil-inner-text-objects-map key inner-fn) (define-key evil-inner-text-objects-map key inner-fn)
(define-key evil-outer-text-objects-map key (or outer-fn inner-fn))) (define-key evil-outer-text-objects-map key (or outer-fn inner-fn)))
;; ;; --- keybind fixes ----------------------
;; evil hacks (map! :n "zr" #'+evil:open-folds-recursively
;; :n "zm" #'+evil:close-folds-recursively
(defvar +evil-esc-hook nil ;; undo/redo for regions
:v "u" #'undo-tree-undo
:v "C-r" #'undo-tree-redo)
;; --- evil hacks -------------------------
(defvar +evil-esc-hook nil
"A hook run after ESC is pressed in normal mode (invoked by "A hook run after ESC is pressed in normal mode (invoked by
`evil-force-normal-state').") `evil-force-normal-state').")
(defun +evil*attach-escape-hook () (defun +evil*attach-escape-hook ()
"Run the `+evil-esc-hook'." "Run the `+evil-esc-hook'."
(run-hooks '+evil-esc-hook)) (run-hooks '+evil-esc-hook))
(advice-add #'evil-force-normal-state :after #'+evil*attach-escape-hook) (advice-add #'evil-force-normal-state :after #'+evil*attach-escape-hook)
(defun +evil|escape-minibuffer () (defun +evil|escape-minibuffer ()
"Quit the minibuffer if open." "Quit the minibuffer if open."
(when (minibuffer-window-active-p (minibuffer-window)) (when (minibuffer-window-active-p (minibuffer-window))
(abort-recursive-edit))) (abort-recursive-edit)))
(defun +evil|escape-highlights () (defun +evil|escape-highlights ()
"Disable ex search buffer highlights." "Disable ex search buffer highlights."
(when (evil-ex-hl-active-p 'evil-ex-search) (when (evil-ex-hl-active-p 'evil-ex-search)
(evil-ex-nohighlight))) (evil-ex-nohighlight)))
(add-hook! '+evil-esc-hook '(+evil|escape-minibuffer +evil|escape-highlights)) (add-hook! '+evil-esc-hook '(+evil|escape-minibuffer +evil|escape-highlights))
(defun +evil*restore-normal-state-on-windmove (orig-fn &rest args) (defun +evil*restore-normal-state-on-windmove (orig-fn &rest args)
"If in anything but normal or motion mode when moving to another window, "If in anything but normal or motion mode when moving to another window,
restore normal mode. This prevents insert state from bleeding into other modes restore normal mode. This prevents insert state from bleeding into other modes
across windows." across windows."
(unless (memq evil-state '(normal motion)) (unless (memq evil-state '(normal motion))
(evil-normal-state +1)) (evil-normal-state +1))
(apply orig-fn args)) (apply orig-fn args))
(advice-add #'windmove-do-window-select :around #'+evil*restore-normal-state-on-windmove) (advice-add #'windmove-do-window-select :around #'+evil*restore-normal-state-on-windmove)
(defun +evil*static-reindent (orig-fn &rest args) (defun +evil*static-reindent (orig-fn &rest args)
"Don't move cursor on indent." "Don't move cursor on indent."
(save-excursion (apply orig-fn args))) (save-excursion (apply orig-fn args)))
(advice-add #'evil-indent :around #'+evil*static-reindent) (advice-add #'evil-indent :around #'+evil*static-reindent)
;; Move to new split ;; monkey patch `evil-ex-replace-special-filenames' to add more ex
(defun +evil*window-follow (&rest _) (evil-window-down 1)) ;; substitution flags to evil-mode
(defun +evil*window-vfollow (&rest _) (evil-window-right 1)) (advice-add #'evil-ex-replace-special-filenames
(advice-add #'evil-window-split :after #'+evil*window-follow)
(advice-add #'evil-window-vsplit :after #'+evil*window-vfollow)
;; monkey patch `evil-ex-replace-special-filenames' to add more ex
;; substitution flags to evil-mode
(advice-add #'evil-ex-replace-special-filenames
:override #'+evil*ex-replace-special-filenames) :override #'+evil*ex-replace-special-filenames)
;; Add extra argument types that highlight matches in the current buffer. ;; Add extra argument types that highlight matches in the current buffer.
;; TODO Must be simpler way to do this ;; TODO Must be simpler way to do this
(evil-ex-define-argument-type buffer-match :runner +evil-ex-buffer-match) (evil-ex-define-argument-type buffer-match :runner +evil-ex-buffer-match)
(evil-ex-define-argument-type global-match :runner +evil-ex-global-match) (evil-ex-define-argument-type global-match :runner +evil-ex-global-match)
(evil-define-interactive-code "<//>" (evil-define-interactive-code "<//>"
:ex-arg buffer-match (list (when (evil-ex-p) evil-ex-argument))) :ex-arg buffer-match (list (when (evil-ex-p) evil-ex-argument)))
(evil-define-interactive-code "<g//>" (evil-define-interactive-code "<g//>"
:ex-arg global-match (when (evil-ex-p) (evil-ex-parse-global evil-ex-argument))) :ex-arg global-match (when (evil-ex-p) (evil-ex-parse-global evil-ex-argument)))
(evil-define-operator +evil:global (beg end pattern command &optional invert) (evil-define-operator +evil:global (beg end pattern command &optional invert)
"Rewritten :g[lobal] that will highlight buffer matches. Takes the same arguments." "Rewritten :g[lobal] that will highlight buffer matches. Takes the same arguments."
:motion mark-whole-buffer :move-point nil :motion mark-whole-buffer :move-point nil
(interactive "<r><g//><!>") (interactive "<r><g//><!>")
(evil-ex-global beg end pattern command invert)) (evil-ex-global beg end pattern command invert))
(evil-define-operator +evil:align (&optional beg end bang pattern) (evil-define-operator +evil:align (&optional beg end bang pattern)
"Ex interface to `align-regexp'. Accepts vim-style regexps." "Ex interface to `align-regexp'. Accepts vim-style regexps."
(interactive "<r><!><//>") (interactive "<r><!><//>")
(align-regexp (align-regexp
@ -170,8 +161,8 @@ across windows."
(evil-transform-vim-style-regexp pattern))) (evil-transform-vim-style-regexp pattern)))
1 1)) 1 1))
(evil-ex-define-cmd "g[lobal]" #'+evil:global) (evil-ex-define-cmd "g[lobal]" #'+evil:global)
(evil-ex-define-cmd "al[ign]" #'+evil:align) (evil-ex-define-cmd "al[ign]" #'+evil:align))
;; ;;
@ -383,7 +374,6 @@ the new algorithm is confusing, like in python or ruby."
(?\; "[;:]"))) (?\; "[;:]")))
:config :config
;; (evil-snipe-mode +1)
(evil-snipe-override-mode +1) (evil-snipe-override-mode +1)
;; Switch to evil-easymotion/avy after a snipe ;; Switch to evil-easymotion/avy after a snipe
(map! :map evil-snipe-parent-transient-map (map! :map evil-snipe-parent-transient-map
@ -434,6 +424,8 @@ the new algorithm is confusing, like in python or ruby."
neo-show-updir-line nil neo-show-updir-line nil
neo-theme 'nerd ; fallback neo-theme 'nerd ; fallback
neo-banner-message nil neo-banner-message nil
neo-confirm-create-file #'off-p
neo-confirm-create-directory #'off-p
neo-show-hidden-files nil neo-show-hidden-files nil
neo-hidden-regexp-list neo-hidden-regexp-list
'(;; vcs folders '(;; vcs folders
@ -447,16 +439,10 @@ the new algorithm is confusing, like in python or ruby."
"~$" "~$"
"^#.*#$")) "^#.*#$"))
(set! :evil-state 'neotree-mode 'motion) (evil-set-initial-state 'neotree-mode 'motion)
(push neo-buffer-name winner-boring-buffers) (push neo-buffer-name winner-boring-buffers)
(defun +evil*neotree-create-node (orig-fun &rest args)
"Don't ask for confirmation when creating files"
(cl-letf (((symbol-function 'yes-or-no-p) (lambda (&rest _) t)))
(apply orig-fun args)))
(advice-add #'neotree-create-node :around #'+evil*neotree-create-node)
;; `neotree-mode-map' are overridden when the neotree buffer is created. So we ;; `neotree-mode-map' are overridden when the neotree buffer is created. So we
;; bind them in a hook. ;; bind them in a hook.
(add-hook 'neo-after-create-hook #'+evil|neotree-init-keymap) (add-hook 'neo-after-create-hook #'+evil|neotree-init-keymap)

View file

@ -46,6 +46,9 @@
"Run everytime `org-mode' is enabled." "Run everytime `org-mode' is enabled."
(setq line-spacing 1) (setq line-spacing 1)
;; show-paren-mode causes problems for org-indent-mode
(show-paren-mode -1)
(visual-line-mode +1) (visual-line-mode +1)
(when (and (featurep 'evil) evil-mode) (when (and (featurep 'evil) evil-mode)
(evil-org-mode +1)) (evil-org-mode +1))