hlissner/evil-multiedit
{ "createdAt": "2016-02-20T19:58:51Z", "defaultBranch": "master", "description": "Multiple cursors for evil-mode, based on iedit", "fullName": "hlissner/evil-multiedit", "homepage": "", "language": "Emacs Lisp", "name": "evil-multiedit", "pushedAt": "2022-08-29T20:08:04Z", "stargazersCount": 357, "topics": [ "emacs", "emacs-packages", "evil", "melpa" ], "updatedAt": "2025-11-18T07:19:50Z", "url": "https://github.com/hlissner/evil-multiedit"}evil-multiedit
Section titled “evil-multiedit”This plugin was an answer to the lack of proper multiple cursor support in
Emacs+evil. It allows you to select and edit matches interactively, integrating
iedit-mode into evil-mode with an attempt at sensible defaults.
Since then, [evil-mc] has matured, and now that I use both I’ve found they can coexist, filling different niches, complimenting evil’s built-in column/line-wise editing operations.
![evil-multiedit]!(../screenshots/main.gif?raw=true)
Thanks to [syl20bnr] for his [evil-iedit-state] plugin, which this plugin was heavily inspired by.
Installation
Section titled “Installation”The package is available on MELPA.
M-x package-install RET evil-multiedit
Then load it up with the default keybinds:
(require 'evil-multiedit)(evil-multiedit-default-keybinds)Doom Emacs
Section titled “Doom Emacs”This package comes pre-configured with [Doom Emacs], in its :editor multiple-cursors module. Enable this
module
and you’re good to go!
Evil-multiedit does not automatically bind any keys. Call
(evil-multiedit-default-keybinds) to bind my recommended configuration:
;; Highlights all matches of the selection in the buffer.(define-key evil-visual-state-map "R" 'evil-multiedit-match-all)
;; Match the word under cursor (i.e. make it an edit region). Consecutive presses will;; incrementally add the next unmatched match.(define-key evil-normal-state-map (kbd "M-d") 'evil-multiedit-match-and-next);; Match selected region.(define-key evil-visual-state-map (kbd "M-d") 'evil-multiedit-match-and-next);; Insert marker at point(define-key evil-insert-state-map (kbd "M-d") 'evil-multiedit-toggle-marker-here)
;; Same as M-d but in reverse.(define-key evil-normal-state-map (kbd "M-D") 'evil-multiedit-match-and-prev)(define-key evil-visual-state-map (kbd "M-D") 'evil-multiedit-match-and-prev)
;; OPTIONAL: If you prefer to grab symbols rather than words, use;; `evil-multiedit-match-symbol-and-next` (or prev).
;; Restore the last group of multiedit regions.(define-key evil-visual-state-map (kbd "C-M-D") 'evil-multiedit-restore)
;; RET will toggle the region under the cursor(define-key evil-multiedit-state-map (kbd "RET") 'evil-multiedit-toggle-or-restrict-region)
;; ...and in visual mode, RET will disable all fields outside the selected region(define-key evil-motion-state-map (kbd "RET") 'evil-multiedit-toggle-or-restrict-region)
;; For moving between edit regions(define-key evil-multiedit-state-map (kbd "C-n") 'evil-multiedit-next)(define-key evil-multiedit-state-map (kbd "C-p") 'evil-multiedit-prev)(define-key evil-multiedit-insert-state-map (kbd "C-n") 'evil-multiedit-next)(define-key evil-multiedit-insert-state-map (kbd "C-p") 'evil-multiedit-prev)
;; Ex command that allows you to invoke evil-multiedit with a regular expression, e.g.(evil-ex-define-cmd "ie[dit]" 'evil-multiedit-ex-match)Once regions are highlighted, changes are mirrored across them all.
Many evil-mode motions/operators will have slightly different behavior while evil-multiedit is active or the cursor is in an iedit region:
D: clear the regionC: clear to end-of-region and go into insert modeA: go into insert mode at end-of-regionI: go into insert mode at start-of-regionV: select the regionP: replace the iedit region with the contents of the clipboard$: go to end-of-region0/^: go to start-of-regiongg/G: go to the first/last region
To disable these, set evil-multiedit-dwim-motion-keys to nil before loading
evil-multiedit.
NOTE: No need to bind a key for evil-multiedit-abort, pressing ESC
in normal mode will invoke it.
Ex Command
Section titled “Ex Command”:iedit [REGEXP] is available for invoking multiedit from the ex command line.
Commands
Section titled “Commands”evil-multiedit-restore: Restore the last evil-multiedit session.evil-multiedit-match-all: Create iedit regions of all matches of the current selection (or symbol at point) as multiedit regions.evil-multiedit-match-and-next:evil-multiedit-match-and-prevevil-multiedit-match-symbol-and-nextevil-multiedit-match-symbol-and-prevevil-multiedit-toggle-marker-hereevil-multiedit-toggle-or-restrict-regionevil-multiedit-nextevil-multiedit-prevevil-multiedit-abortevil-multiedit-ex-match
Options
Section titled “Options”evil-multiedit-dwim-motion-keys(default:t): If non-nil, evil’s motion keys behave differently when the point is inside a multiedit region. Must be set before evil-multiedit is loaded.evil-multiedit-ignore-indent-and-trailing(default:t): If non-nil, skip over indentation and trailing whitespace in iedit matches.evil-multiedit-scope(defaultnil): How far evil-multiedit should look for incremental matches (doesn’t affectevil-multiedit-match-allorevil-multiedit-ex-match). Accepts anything thatbounds-of-thing-at-pointaccepts, such as'defun,'sexp,'emailor the default,'buffer.evil-multiedit-smart-match-boundaries(defaultt): If non-nil, multiedit will treat matches as atoms when invoked from normal mode. E.g.evil-multiedit-matchwill not matchevil-multiedit-match-alliwill only matchiand not every individual i inignition.- NOTE: If evil-multiedit is invoked from visual mode, this is ignored.
evil-multiedit-store-in-search-history(defaultnil): If non-nil, highlighted occurrences are stored inregexp-search-ring, so that after exiting ieditevil-search-nextandevil-search-previous(usually n and N) use the last occurrence as if it were the last string in the search history.evil-multiedit-follow-matches(defaultnil): If non-nil, the cursor will jump to each additional match, rather than remain in its original position.
Co-existing with evil-mc
Section titled “Co-existing with evil-mc”How the two plugins mingle is entirely personal preference. I often reach for evil-mc for more complex operations and evil-multiedit for simpler ones.
My strategy is to bind evil-multiedit to M-d/M-D, and evil-mc to a bunch of keys prefixed with gz:
;; evil-multiedit(evil-define-key 'normal 'global (kbd "M-d") #'evil-multiedit-match-symbol-and-next (kbd "M-D") #'evil-multiedit-match-symbol-and-prev)(evil-define-key 'visual 'global "R" #'evil-multiedit-match-all (kbd "M-d") #'evil-multiedit-match-and-next (kbd "M-D") #'evil-multiedit-match-and-prev)(evil-define-key '(visual normal) 'global (kbd "C-M-d") #'evil-multiedit-restore)
(with-eval-after-load 'evil-mutliedit (evil-define-key 'multiedit 'global (kbd "M-d") #'evil-multiedit-match-and-next (kbd "M-S-d") #'evil-multiedit-match-and-prev (kbd "RET") #'evil-multiedit-toggle-or-restrict-region) (evil-define-key '(multiedit multiedit-insert) 'global (kbd "C-n") #'evil-multiedit-next (kbd "C-p") #'evil-multiedit-prev))
;; evil-mc(evil-define-key '(normal visual) 'global "gzm" #'evil-mc-make-all-cursors "gzu" #'evil-mc-undo-all-cursors "gzz" #'+evil/mc-toggle-cursors "gzc" #'+evil/mc-make-cursor-here "gzn" #'evil-mc-make-and-goto-next-cursor "gzp" #'evil-mc-make-and-goto-prev-cursor "gzN" #'evil-mc-make-and-goto-last-cursor "gzP" #'evil-mc-make-and-goto-first-cursor)(with-eval-after-load 'evil-mc (evil-define-key '(normal visual) evil-mc-key-map (kbd "C-n") #'evil-mc-make-and-goto-next-cursor (kbd "C-N") #'evil-mc-make-and-goto-last-cursor (kbd "C-p") #'evil-mc-make-and-goto-prev-cursor (kbd "C-P") #'evil-mc-make-and-goto-first-cursor))NOTE: These are the default keybindings on [Doom Emacs]. Doom users don’t need to bind these.
[Doom Emacs] !: https://github.com/hlissner/doom-emacs [evil-iedit-state] !: https://github.com/syl20bnr/evil-iedit-state [evil-mc] !: https://github.com/gabesoft/evil-mc [evil-mode] !: https://bitbucket.org/lyro/evil/wiki/Home [syl20bnr] !: https://github.com/syl20bnr [vim-multiedit] !: https://github.com/hlissner/vim-multiedit
