diff --git a/modules/feature/evil/autoload/evil-mc.el b/modules/feature/evil/autoload/evil-mc.el new file mode 100644 index 000000000..b000d69ef --- /dev/null +++ b/modules/feature/evil/autoload/evil-mc.el @@ -0,0 +1,67 @@ +;;; feature/evil/autoload/evil-mc.el + +;;;###autoload +(defun +evil/mc-toggle-cursors () + "Toggle frozen state of evil-mc cursors." + (interactive) + (setq evil-mc-frozen (not (and (evil-mc-has-cursors-p) + evil-mc-frozen))) + (if evil-mc-frozen + (message "evil-mc paused") + (message "evil-mc resumed"))) + +;;;###autoload (autoload '+evil/mc-make-cursor-here "feature/evil/autoload/evil-mc" nil nil) +(evil-define-command +evil/mc-make-cursor-here () + "Create a cursor at point. If in visual block or line mode, then create +cursors in column beneath+above the point on each line. Otherwise pauses +cursors." + :repeat nil + :keep-visual nil + :evil-mc t + (interactive) + (cond ((memq evil-this-type '(block line)) + (let ((col (evil-column)) + (line-at-pt (line-number-at-pos)) + (beg evil-visual-beginning) + (end evil-visual-end)) + ;; Fix off-by-one error + (when (= evil-visual-direction 1) + (cl-decf col) + (backward-char)) + (save-excursion + (evil-apply-on-block + (lambda (ibeg _) + (unless (= line-at-pt (line-number-at-pos ibeg)) + (goto-char ibeg) + (move-to-column col) + (when (= (current-column) col) + (evil-mc-make-cursor-here)))) + beg + (if (eq evil-this-type 'line) (1- evil-visual-end) evil-visual-end) + nil) + (evil-exit-visual-state)))) + (t + (evil-mc-pause-cursors) + ;; I assume I don't want the cursors to move yet + (evil-mc-make-cursor-here)))) + +;;;###autoload (autoload '+evil:mc "feature/evil/autoload/evil-mc" nil nil) +(evil-define-command +evil:mc (beg end type pattern &optional bang) + "Create mc cursors at each match of PATTERN within BEG and END, and leave the +cursor at the final match. If BANG, then surround PATTERN with whole-word +boundaries." + :move-point nil + :evil-mc t + (interactive "") + (setq evil-mc-pattern (cons (evil-mc-make-pattern pattern bang) + (list beg end type))) + (save-excursion + (evil-with-restriction beg end + (evil-mc-make-cursors-for-all) + (evil-mc-print-cursors-info "Created"))) + (evil-exit-visual-state) + (evil-mc-goto-cursor + (if (= (evil-visual-direction) 1) + (evil-mc-find-last-cursor) + (evil-mc-find-first-cursor)) + nil)) diff --git a/modules/feature/evil/config.el b/modules/feature/evil/config.el index 6ddd1900e..cf90409fd 100644 --- a/modules/feature/evil/config.el +++ b/modules/feature/evil/config.el @@ -323,51 +323,47 @@ the new algorithm is confusing, like in python or ruby." (def-package! evil-mc - :commands evil-mc-make-cursor-here - :init (defvar evil-mc-key-map (make-sparse-keymap)) + :commands (evil-mc-make-cursor-here evil-mc-make-all-cursors + evil-mc-undo-all-cursors evil-mc-pause-cursors + evil-mc-resume-cursors evil-mc-make-and-goto-first-cursor + evil-mc-make-and-goto-last-cursor evil-mc-make-cursor-here + evil-mc-make-cursor-move-next-line + evil-mc-make-cursor-move-prev-line + evil-mc-make-cursor-at-pos + evil-mc-make-and-goto-next-cursor evil-mc-skip-and-goto-next-cursor + evil-mc-make-and-goto-prev-cursor evil-mc-skip-and-goto-prev-cursor + evil-mc-make-and-goto-next-match evil-mc-skip-and-goto-next-match + evil-mc-skip-and-goto-next-match evil-mc-make-and-goto-prev-match + evil-mc-skip-and-goto-prev-match) + :init + (defvar evil-mc-key-map (make-sparse-keymap)) :config - ;; Start evil-mc in paused mode. - (add-hook 'evil-mc-mode-hook #'evil-mc-pause-cursors) - (add-hook 'evil-mc-before-cursors-created #'evil-mc-pause-cursors) + (global-evil-mc-mode +1) - (global-evil-mc-mode 1) - (setq evil-mc-custom-known-commands - '((doom/deflate-space-maybe . ((:default . evil-mc-execute-default-call))))) + ;; Add custom commands to whitelisted commands + (dolist (fn '(doom/deflate-space-maybe doom/inflate-space-maybe + doom/backward-to-bol-or-indent doom/forward-to-last-non-comment-or-eol + doom/backward-kill-to-bol-and-indent)) + (push (cons fn '((:default . evil-mc-execute-default-call))) evil-mc-custom-known-commands)) - ;; My workflow is to place the cursors, get into position, then enable evil-mc - ;; by invoking `+evil/mc-toggle-cursors' - (defun +evil/mc-toggle-cursors () - "Toggle frozen state of evil-mc cursors." - (interactive) - (setq evil-mc-frozen (not (and (evil-mc-has-cursors-p) - evil-mc-frozen)))) - ;; ...or going into insert mode - (add-hook 'evil-insert-state-entry-hook #'evil-mc-resume-cursors) + ;; if I'm in insert mode, chances are I want cursors to resume + (add-hook! 'evil-mc-before-cursors-created + (add-hook 'evil-insert-state-entry-hook #'evil-mc-resume-cursors nil t)) + (add-hook! 'evil-mc-after-cursors-deleted + (remove-hook 'evil-insert-state-entry-hook #'evil-mc-resume-cursors t)) (defun +evil|escape-multiple-cursors () - "Undo cursors and freeze them again (for next time)." + "Clear evil-mc cursors and restore state." (when (evil-mc-has-cursors-p) (evil-mc-undo-all-cursors) + (evil-mc-resume-cursors) t)) (add-hook '+evil-esc-hook #'+evil|escape-multiple-cursors) - ;; disable evil-escape in evil-mc + ;; disable evil-escape in evil-mc; causes unwanted text on invocation (push 'evil-escape-mode evil-mc-incompatible-minor-modes)) -(def-package! evil-multiedit - :commands (evil-multiedit-match-all - evil-multiedit-match-and-next - evil-multiedit-match-and-prev - evil-multiedit-match-symbol-and-next - evil-multiedit-match-symbol-and-prev - evil-multiedit-toggle-or-restrict-region - evil-multiedit-next - evil-multiedit-prev - evil-multiedit-abort - evil-multiedit-ex-match)) - - (def-package! evil-textobj-anyblock :init (+evil--textobj "B" diff --git a/modules/feature/evil/packages.el b/modules/feature/evil/packages.el index 95528f74e..45ae692d5 100644 --- a/modules/feature/evil/packages.el +++ b/modules/feature/evil/packages.el @@ -10,7 +10,6 @@ (package! evil-exchange) (package! evil-indent-plus) (package! evil-matchit) -(package! evil-multiedit) (package! evil-mc) (package! evil-numbers) (package! evil-textobj-anyblock) diff --git a/modules/private/hlissner/+bindings.el b/modules/private/hlissner/+bindings.el index 21783002f..dbea2c372 100644 --- a/modules/private/hlissner/+bindings.el +++ b/modules/private/hlissner/+bindings.el @@ -278,23 +278,24 @@ (call-interactively 'company-dabbrev-code) (company-select-previous-or-abort)))) ;; evil-mc - :n "M-d" #'evil-mc-make-cursor-here + :v "R" #'evil-mc-make-all-cursors + :nv "M-d" #'evil-mc-make-and-goto-next-match + :nv "M-D" #'evil-mc-make-and-goto-prev-match + (:prefix "gz" + :nv "m" #'evil-mc-make-all-cursors + :nv "u" #'evil-mc-undo-all-cursors + :nv "z" #'+evil/mc-toggle-cursors + :nv "c" #'+evil/mc-make-cursor-here + :nv "n" #'evil-mc-make-and-goto-next-cursor + :nv "p" #'evil-mc-make-and-goto-prev-cursor + :nv "N" #'evil-mc-make-and-goto-last-cursor + :nv "P" #'evil-mc-make-and-goto-first-cursor) (:after evil-mc :map evil-mc-key-map - :n "M-D" #'+evil/mc-toggle-cursors) - ;; evil-multiedit - :v "M-d" #'evil-multiedit-match-and-next - :v "M-D" #'evil-multiedit-match-and-prev - :v "C-M-d" #'evil-multiedit-restore - :v "R" #'evil-multiedit-match-all - (:after evil-multiedit - (:map evil-multiedit-state-map - "M-d" #'evil-multiedit-match-and-next - "M-D" #'evil-multiedit-match-and-prev - "RET" #'evil-multiedit-toggle-or-restrict-region) - (:map (evil-multiedit-state-map evil-multiedit-insert-state-map) - "C-n" #'evil-multiedit-next - "C-p" #'evil-multiedit-prev)) + :nv "C-n" #'evil-mc-make-and-goto-next-cursor + :nv "C-N" #'evil-mc-make-and-goto-last-cursor + :nv "C-p" #'evil-mc-make-and-goto-prev-cursor + :nv "C-P" #'evil-mc-make-and-goto-first-cursor) ;; evil-surround :v "S" #'evil-surround-region :o "s" #'evil-surround-edit diff --git a/modules/private/hlissner/+commands.el b/modules/private/hlissner/+commands.el index 6483c0881..43c97b59d 100644 --- a/modules/private/hlissner/+commands.el +++ b/modules/private/hlissner/+commands.el @@ -14,7 +14,7 @@ (ex! "@" #'+evil:macro-on-all-lines) ; TODO Test me (ex! "enhtml" #'+web:encode-html-entities) (ex! "dehtml" #'+web:decode-html-entities) -(ex! "ie[dit]" #'evil-multiedit-ex-match) +(ex! "mc" #'+evil:mc) (ex! "na[rrow]" #'+evil:narrow-buffer) (ex! "retab" #'+evil:retab)