gabesoft/evil-mc

Multiple cursors implementation for evil-mode

Emacs Lisp

428

331 commits

updated Oct 25, 2024

See the code

README

: ▓█████ ██▒   █▓ ██▓ ██▓        ███▄ ▄███▓ ▄████▄  
: ▓█   ▀▓██░   █▒▓██▒▓██▒       ▓██▒▀█▀ ██▒▒██▀ ▀█  
: ▒███   ▓██  █▒░▒██▒▒██░       ▓██    ▓██░▒▓█    ▄ 
: ▒▓█  ▄  ▒██ █░░░██░▒██░       ▒██    ▒██ ▒▓▓▄ ▄██▒
: ░▒████▒  ▒▀█░  ░██░░██████▒   ▒██▒   ░██▒▒ ▓███▀ ░
: ░░ ▒░ ░  ░ ▐░  ░▓  ░ ▒░▓  ░   ░ ▒░   ░  ░░ ░▒ ▒  ░
:  ░ ░  ░  ░ ░░   ▒ ░░ ░ ▒  ░   ░  ░      ░  ░  ▒   
:    ░       ░░   ▒ ░  ░ ░      ░      ░   ░        
:    ░  ░     ░   ░      ░  ░          ░   ░ ░      
:            ░                             ░        

 [[https://travis-ci.org/gabesoft/evil-mc][https://travis-ci.org/gabesoft/evil-mc.svg?branch=master]] [[http://melpa.org/#/evil-mc][file:http://melpa.org/packages/evil-mc-badge.svg?style=flat-square]] [[http://melpa.org/#/evil-mc][file:http://stable.melpa.org/packages/evil-mc-badge.svg?style=flat-square]]

** Multiple cursors implementation for evil-mode
*** Synopsis
*evil-mc* provides multiple cursors functionality for Emacs when used with *evil-mode* 
*** Usage
Start with:
#+BEGIN_SRC emacs-lisp
 (require 'evil-mc)
#+END_SRC
**** Local Setup
To enable or disable *evil-mc* mode for a single buffer use:\\
#+BEGIN_SRC emacs-lisp
(evil-mc-mode  1) ;; enable
(evil-mc-mode -1) ;; disable
#+END_SRC
**** Global Setup
To enable or disable *evil-mc* mode for all buffers use:\\
#+BEGIN_SRC emacs-lisp
(global-evil-mc-mode  1) ;; enable
(global-evil-mc-mode -1) ;; disable
#+END_SRC
**** Basic Usage
The main commands used to create or delete cursors are:

#+BEGIN_SRC emacs-lisp
(evil-mc-make-all-cursors)
;; Create cursors for all strings that match the selected 
;; region or the symbol under cursor.

(evil-mc-undo-all-cursors)
;; Remove all cursors.

(evil-mc-make-and-goto-next-match)
;; Make a cursor at point and go to the next match of the 
;; selected region or the symbol under cursor.

(evil-mc-skip-and-goto-next-match)
;; Go to the next match of the selected region or the symbol under 
;; cursor without creating a cursor at point.
#+END_SRC

The above commands as well as others, detailed below, are setup with key bindings
when the *evil-mc* mode is enabled. The keys are defined in ~evil-mc-key-map~. You can 
take a look at that variable declaration in [[https://github.com/gabesoft/evil-mc/blob/master/evil-mc.el][evil-mc.el]] to see all key bindings. But,
in short, ~C-n~ / ~C-p~ are used for creating cursors, and ~M-n~ / ~M-p~
are used for cycling through cursors. The commands that create cursors wrap around; but, 
the ones that cycle them do not. 
To skip creating a cursor forward use ~C-t~ or ~grn~ and backward ~grp~. 
Finally use ~gru~ to "undo" the last added cursor, and ~grq~ to remove all cursors.

Optionally set up visual mode keybindings for ~I~ and ~A~ to create cursors at the
beginning or end of every visually selected line.

#+BEGIN_SRC emacs-lisp
(evil-define-key 'visual evil-mc-key-map
  "A" #'evil-mc-make-cursor-in-visual-selection-end
  "I" #'evil-mc-make-cursor-in-visual-selection-beg)
#+END_SRC

For an example of setting up *evil-mc* see this [[https://github.com/gabesoft/evil-mc/blob/master/evil-mc-setup.el][setup file]]
**** Commands
Here's a detailed list of all commands used to create, navigate through, or delete cursors:\\
/All the commands below assume that there is a real cursor and possibly some fake cursors./

#+BEGIN_SRC emacs-lisp
(evil-mc-make-all-cursors)
;; Make a cursor for every match of the selected region or the symbol at point.

(evil-mc-undo-all-cursors)
;; Remove all cursors.

(evil-mc-undo-last-added-cursor)
;; Remove the last added cursor and move point to its position.

(evil-mc-make-and-goto-next-match)
;; Make a cursor at point, and go to the next match of the 
;; selected region or the symbol at point.

(evil-mc-make-and-goto-prev-match)
;; Make a cursor at point, and go to the previous match of the 
;; selected region or the symbol at point.

(evil-mc-skip-and-goto-next-match)
;; Go to the next match of the selected region or symbol at point
;; without making a cursor at point. This command can be used to
;; remove unwanted cursors.

(evil-mc-skip-and-goto-prev-match)
;; Go to the previous match of the selected region or symbol at point
;; without making a cursor at point. This command can be used to
;; remove unwanted cursors.

(evil-mc-make-and-goto-prev-cursor)
;; Make a cursor at point and move point to the cursor
;; closest to it when searching backwards.

(evil-mc-make-and-goto-next-cursor)
;; Make a cursor at point and move point to the cursor
;; closest to it when searching forwards.

(evil-mc-skip-and-goto-prev-cursor)
;; Move point to the cursor closest to it when searching backwards
;; without making a cursor at point. This command can be used to
;; remove unwanted cursors.

(evil-mc-skip-and-goto-next-cursor)
;; Move point to the cursor closest to it when searching forwards
;; without making a cursor at point. This command can be used to
;; remove unwanted cursors.

(evil-mc-make-and-goto-first-cursor)
;; Make a cursor at point and move point to the cursor at the first position.

(evil-mc-make-and-goto-last-cursor)
;; Make a cursor at point and move point to the cursor at the last position.

(evil-mc-make-cursor-here)
;; Create a cursor at point. This command should be used with `evil-mc-pause-cursors'.

(evil-mc-pause-cursors)
;; Pause all fake cursors. This can be used with `evil-mc-make-cursor-here'

(evil-mc-resume-cursors)
;; Call to resume paused cursors.

(evil-mc-make-cursor-in-visual-selection-beg)
;; Create cursors at the beginning of every visually selected line.

(evil-mc-make-cursor-in-visual-selection-end)
;; Create cursors at the end of every visually selected line.
#+END_SRC

**** Customization
*evil-mc* can be customized in several ways:

- Every known command is executed using a command handler defined in a variable
  called ~evil-mc-known-commands~ in [[https://github.com/gabesoft/evil-mc/blob/master/evil-mc-known-commands.el][evil-mc-known-commands.el]]. Those can be overridden by 
  defining the ~evil-mc-custom-known-commands~ variable. See the documentation of 
  that variable in [[https://github.com/gabesoft/evil-mc/blob/master/evil-mc.el][evil-mc.el]] for more info.
- Some minor modes are incompatible with *evil-mc*. Those modes are defined in 
  ~evil-mc-incompatible-minor-modes~ and can be overridden by defining that variable.
- In addition there are two hooks that can be used to temporarily disable or enable 
  additional functionality while there are multiple cursors active
  #+BEGIN_SRC emacs-lisp
  evil-mc-before-cursors-created
  ;; this hook runs just before the first cursor is created

  evil-mc-after-cursors-created
  ;; this hook runs just after the last cursor is deleted
  #+END_SRC

*** Mode line text and colors
There are 4 variables, that can change the mode lines text, and its color.

**** Only one cursor
The ~emc~ text can be hidden, by setting this variable to ~nil~.
(default: ~t~)
#+BEGIN_SRC
(setq evil-mc-one-cursor-show-mode-line-text t)
#+END_SRC

**** Two or more cursors, resumed (unpaused)
The resumed mode line text, can have two different colors:
- The cursors color, when this variable is ~t~.
- The default colors, when this variable is ~nil~.
(default: ~t~)
#+BEGIN_SRC
(setq evil-mc-mode-line-text-cursor-color t)
#+END_SRC

**** Two or more cursors, paused
The ~(paused)~ text can be hidden, by setting this variable to ~nil~.
(default: ~t~)
#+BEGIN_SRC
(setq evil-mc-mode-line-text-paused t)
#+END_SRC

The paused mode line text can have three different colors:
- Inverse colors, when the inverse colors variable is ~t~.
- Cursors color, when the inverse colors variable is ~nil~, and the cursor color variable is ~t~.
- Default colors, when both the inverse and cursor color variables are ~nil~.
(default: ~t~, for both the inverse and cursor variables)
#+BEGIN_SRC
(setq evil-mc-mode-line-text-inverse-colors t)
(setq evil-mc-mode-line-text-cursor-color t)
#+END_SRC

*** Notes
- Most evil motions and operators are supported but not every single command will work. 
- If the cursors don't seem to work during a command, either the command is
  not known (see ~evil-mc-known-commands~ in [[https://github.com/gabesoft/evil-mc/blob/master/evil-mc-known-commands.el][evil-mc-known-commands.el]]) or some minor modes
  could be interfering with the evil-mc operations. 
- Issues and pull requests are welcome. 

**** Debugging
- When a command does not work, and you want to get more information,
  you can enable (or disable) debugging by running any of the commands 
  below interactively.
  #+BEGIN_SRC emacs-lisp
  (evil-mc-executing-debug-on)
  ;; Turn debug on while executing a command.

  (evil-mc-executing-debug-off)
  ;; Turn debug off while executing a command.

  (evil-mc-recording-debug-on)
  ;; Turn debug on while recording a command.

  (evil-mc-recording-debug-off)
  ;; Turn debug off while recording a command.

  (evil-mc-all-debug-on)
  ;; Turn all debug on.

  (evil-mc-all-debug-off)
  ;; Turn all debug off.
  #+END_SRC

**** Limitations
- After an undo command the cursors will return to their original positions
  if [[http://www.emacswiki.org/emacs/UndoTree][undo-tree]] mode is enabled and ~evil-repeat~ has not been used.
- Redo may cause the real cursor to get out of sync with the others.
  This can be worked around by setting a mark and returning to it after a redo.
- Jumps work if [[https://github.com/bling/evil-jumper][evil-jumper]] mode is enabled
- Search commands such as ~evil-search-forward~, ~evil-search-backward~, and ~evil-search-next~ are not supported

**** Known issues
- Only named commands can be executed by the fake cursors.
- There could be a performance penalty when there are too many cursors (30+).
- Paste will not work when [[https://github.com/syl20bnr/spacemacs][spacemacs]]' paste micro state is enabled.
  This is due to the fact that ~evil-paste-pop~ and ~evil-paste-pop-next~ 
  commands are not supported.
- ~evil-repeat~ works only for some commands. 
  In particular it doesn't work for delete. It will also interfere with the 
  cursor positions during an undo or redo operation.



* 
: .__                                            .___.__  __  .__                
: |  |__ _____  ______ ______ ___.__.   ____   __| _/|__|/  |_|__| ____    ____  
: |  |  \\__  \ \____ \\____ <   |  | _/ __ \ / __ | |  \   __\  |/    \  / ___\ 
: |   Y  \/ __ \|  |_> >  |_> >___  | \  ___// /_/ | |  ||  | |  |   |  \/ /_/  >
: |___|  (____  /   __/|   __// ____|  \___  >____ | |__||__| |__|___|  /\___  / 
:      \/     \/|__|   |__|   \/           \/     \/                  \//_____/  

Not written in Markdown, so it's shown here as plain text — view it formatted on GitHub.

emacs
evil
multiple-cursors
vim

Contributors

gabesoft

294 commits

Dickby

6 commits

syohex

3 commits

duianto

3 commits

gabesoft/evil-mc

Multiple cursors implementation for evil-mode

Emacs Lisp

428

331 commits

updated Oct 25, 2024

See the code

README

: ▓█████ ██▒   █▓ ██▓ ██▓        ███▄ ▄███▓ ▄████▄  
: ▓█   ▀▓██░   █▒▓██▒▓██▒       ▓██▒▀█▀ ██▒▒██▀ ▀█  
: ▒███   ▓██  █▒░▒██▒▒██░       ▓██    ▓██░▒▓█    ▄ 
: ▒▓█  ▄  ▒██ █░░░██░▒██░       ▒██    ▒██ ▒▓▓▄ ▄██▒
: ░▒████▒  ▒▀█░  ░██░░██████▒   ▒██▒   ░██▒▒ ▓███▀ ░
: ░░ ▒░ ░  ░ ▐░  ░▓  ░ ▒░▓  ░   ░ ▒░   ░  ░░ ░▒ ▒  ░
:  ░ ░  ░  ░ ░░   ▒ ░░ ░ ▒  ░   ░  ░      ░  ░  ▒   
:    ░       ░░   ▒ ░  ░ ░      ░      ░   ░        
:    ░  ░     ░   ░      ░  ░          ░   ░ ░      
:            ░                             ░        

 [[https://travis-ci.org/gabesoft/evil-mc][https://travis-ci.org/gabesoft/evil-mc.svg?branch=master]] [[http://melpa.org/#/evil-mc][file:http://melpa.org/packages/evil-mc-badge.svg?style=flat-square]] [[http://melpa.org/#/evil-mc][file:http://stable.melpa.org/packages/evil-mc-badge.svg?style=flat-square]]

** Multiple cursors implementation for evil-mode
*** Synopsis
*evil-mc* provides multiple cursors functionality for Emacs when used with *evil-mode* 
*** Usage
Start with:
#+BEGIN_SRC emacs-lisp
 (require 'evil-mc)
#+END_SRC
**** Local Setup
To enable or disable *evil-mc* mode for a single buffer use:\\
#+BEGIN_SRC emacs-lisp
(evil-mc-mode  1) ;; enable
(evil-mc-mode -1) ;; disable
#+END_SRC
**** Global Setup
To enable or disable *evil-mc* mode for all buffers use:\\
#+BEGIN_SRC emacs-lisp
(global-evil-mc-mode  1) ;; enable
(global-evil-mc-mode -1) ;; disable
#+END_SRC
**** Basic Usage
The main commands used to create or delete cursors are:

#+BEGIN_SRC emacs-lisp
(evil-mc-make-all-cursors)
;; Create cursors for all strings that match the selected 
;; region or the symbol under cursor.

(evil-mc-undo-all-cursors)
;; Remove all cursors.

(evil-mc-make-and-goto-next-match)
;; Make a cursor at point and go to the next match of the 
;; selected region or the symbol under cursor.

(evil-mc-skip-and-goto-next-match)
;; Go to the next match of the selected region or the symbol under 
;; cursor without creating a cursor at point.
#+END_SRC

The above commands as well as others, detailed below, are setup with key bindings
when the *evil-mc* mode is enabled. The keys are defined in ~evil-mc-key-map~. You can 
take a look at that variable declaration in [[https://github.com/gabesoft/evil-mc/blob/master/evil-mc.el][evil-mc.el]] to see all key bindings. But,
in short, ~C-n~ / ~C-p~ are used for creating cursors, and ~M-n~ / ~M-p~
are used for cycling through cursors. The commands that create cursors wrap around; but, 
the ones that cycle them do not. 
To skip creating a cursor forward use ~C-t~ or ~grn~ and backward ~grp~. 
Finally use ~gru~ to "undo" the last added cursor, and ~grq~ to remove all cursors.

Optionally set up visual mode keybindings for ~I~ and ~A~ to create cursors at the
beginning or end of every visually selected line.

#+BEGIN_SRC emacs-lisp
(evil-define-key 'visual evil-mc-key-map
  "A" #'evil-mc-make-cursor-in-visual-selection-end
  "I" #'evil-mc-make-cursor-in-visual-selection-beg)
#+END_SRC

For an example of setting up *evil-mc* see this [[https://github.com/gabesoft/evil-mc/blob/master/evil-mc-setup.el][setup file]]
**** Commands
Here's a detailed list of all commands used to create, navigate through, or delete cursors:\\
/All the commands below assume that there is a real cursor and possibly some fake cursors./

#+BEGIN_SRC emacs-lisp
(evil-mc-make-all-cursors)
;; Make a cursor for every match of the selected region or the symbol at point.

(evil-mc-undo-all-cursors)
;; Remove all cursors.

(evil-mc-undo-last-added-cursor)
;; Remove the last added cursor and move point to its position.

(evil-mc-make-and-goto-next-match)
;; Make a cursor at point, and go to the next match of the 
;; selected region or the symbol at point.

(evil-mc-make-and-goto-prev-match)
;; Make a cursor at point, and go to the previous match of the 
;; selected region or the symbol at point.

(evil-mc-skip-and-goto-next-match)
;; Go to the next match of the selected region or symbol at point
;; without making a cursor at point. This command can be used to
;; remove unwanted cursors.

(evil-mc-skip-and-goto-prev-match)
;; Go to the previous match of the selected region or symbol at point
;; without making a cursor at point. This command can be used to
;; remove unwanted cursors.

(evil-mc-make-and-goto-prev-cursor)
;; Make a cursor at point and move point to the cursor
;; closest to it when searching backwards.

(evil-mc-make-and-goto-next-cursor)
;; Make a cursor at point and move point to the cursor
;; closest to it when searching forwards.

(evil-mc-skip-and-goto-prev-cursor)
;; Move point to the cursor closest to it when searching backwards
;; without making a cursor at point. This command can be used to
;; remove unwanted cursors.

(evil-mc-skip-and-goto-next-cursor)
;; Move point to the cursor closest to it when searching forwards
;; without making a cursor at point. This command can be used to
;; remove unwanted cursors.

(evil-mc-make-and-goto-first-cursor)
;; Make a cursor at point and move point to the cursor at the first position.

(evil-mc-make-and-goto-last-cursor)
;; Make a cursor at point and move point to the cursor at the last position.

(evil-mc-make-cursor-here)
;; Create a cursor at point. This command should be used with `evil-mc-pause-cursors'.

(evil-mc-pause-cursors)
;; Pause all fake cursors. This can be used with `evil-mc-make-cursor-here'

(evil-mc-resume-cursors)
;; Call to resume paused cursors.

(evil-mc-make-cursor-in-visual-selection-beg)
;; Create cursors at the beginning of every visually selected line.

(evil-mc-make-cursor-in-visual-selection-end)
;; Create cursors at the end of every visually selected line.
#+END_SRC

**** Customization
*evil-mc* can be customized in several ways:

- Every known command is executed using a command handler defined in a variable
  called ~evil-mc-known-commands~ in [[https://github.com/gabesoft/evil-mc/blob/master/evil-mc-known-commands.el][evil-mc-known-commands.el]]. Those can be overridden by 
  defining the ~evil-mc-custom-known-commands~ variable. See the documentation of 
  that variable in [[https://github.com/gabesoft/evil-mc/blob/master/evil-mc.el][evil-mc.el]] for more info.
- Some minor modes are incompatible with *evil-mc*. Those modes are defined in 
  ~evil-mc-incompatible-minor-modes~ and can be overridden by defining that variable.
- In addition there are two hooks that can be used to temporarily disable or enable 
  additional functionality while there are multiple cursors active
  #+BEGIN_SRC emacs-lisp
  evil-mc-before-cursors-created
  ;; this hook runs just before the first cursor is created

  evil-mc-after-cursors-created
  ;; this hook runs just after the last cursor is deleted
  #+END_SRC

*** Mode line text and colors
There are 4 variables, that can change the mode lines text, and its color.

**** Only one cursor
The ~emc~ text can be hidden, by setting this variable to ~nil~.
(default: ~t~)
#+BEGIN_SRC
(setq evil-mc-one-cursor-show-mode-line-text t)
#+END_SRC

**** Two or more cursors, resumed (unpaused)
The resumed mode line text, can have two different colors:
- The cursors color, when this variable is ~t~.
- The default colors, when this variable is ~nil~.
(default: ~t~)
#+BEGIN_SRC
(setq evil-mc-mode-line-text-cursor-color t)
#+END_SRC

**** Two or more cursors, paused
The ~(paused)~ text can be hidden, by setting this variable to ~nil~.
(default: ~t~)
#+BEGIN_SRC
(setq evil-mc-mode-line-text-paused t)
#+END_SRC

The paused mode line text can have three different colors:
- Inverse colors, when the inverse colors variable is ~t~.
- Cursors color, when the inverse colors variable is ~nil~, and the cursor color variable is ~t~.
- Default colors, when both the inverse and cursor color variables are ~nil~.
(default: ~t~, for both the inverse and cursor variables)
#+BEGIN_SRC
(setq evil-mc-mode-line-text-inverse-colors t)
(setq evil-mc-mode-line-text-cursor-color t)
#+END_SRC

*** Notes
- Most evil motions and operators are supported but not every single command will work. 
- If the cursors don't seem to work during a command, either the command is
  not known (see ~evil-mc-known-commands~ in [[https://github.com/gabesoft/evil-mc/blob/master/evil-mc-known-commands.el][evil-mc-known-commands.el]]) or some minor modes
  could be interfering with the evil-mc operations. 
- Issues and pull requests are welcome. 

**** Debugging
- When a command does not work, and you want to get more information,
  you can enable (or disable) debugging by running any of the commands 
  below interactively.
  #+BEGIN_SRC emacs-lisp
  (evil-mc-executing-debug-on)
  ;; Turn debug on while executing a command.

  (evil-mc-executing-debug-off)
  ;; Turn debug off while executing a command.

  (evil-mc-recording-debug-on)
  ;; Turn debug on while recording a command.

  (evil-mc-recording-debug-off)
  ;; Turn debug off while recording a command.

  (evil-mc-all-debug-on)
  ;; Turn all debug on.

  (evil-mc-all-debug-off)
  ;; Turn all debug off.
  #+END_SRC

**** Limitations
- After an undo command the cursors will return to their original positions
  if [[http://www.emacswiki.org/emacs/UndoTree][undo-tree]] mode is enabled and ~evil-repeat~ has not been used.
- Redo may cause the real cursor to get out of sync with the others.
  This can be worked around by setting a mark and returning to it after a redo.
- Jumps work if [[https://github.com/bling/evil-jumper][evil-jumper]] mode is enabled
- Search commands such as ~evil-search-forward~, ~evil-search-backward~, and ~evil-search-next~ are not supported

**** Known issues
- Only named commands can be executed by the fake cursors.
- There could be a performance penalty when there are too many cursors (30+).
- Paste will not work when [[https://github.com/syl20bnr/spacemacs][spacemacs]]' paste micro state is enabled.
  This is due to the fact that ~evil-paste-pop~ and ~evil-paste-pop-next~ 
  commands are not supported.
- ~evil-repeat~ works only for some commands. 
  In particular it doesn't work for delete. It will also interfere with the 
  cursor positions during an undo or redo operation.



* 
: .__                                            .___.__  __  .__                
: |  |__ _____  ______ ______ ___.__.   ____   __| _/|__|/  |_|__| ____    ____  
: |  |  \\__  \ \____ \\____ <   |  | _/ __ \ / __ | |  \   __\  |/    \  / ___\ 
: |   Y  \/ __ \|  |_> >  |_> >___  | \  ___// /_/ | |  ||  | |  |   |  \/ /_/  >
: |___|  (____  /   __/|   __// ____|  \___  >____ | |__||__| |__|___|  /\___  / 
:      \/     \/|__|   |__|   \/           \/     \/                  \//_____/  

Not written in Markdown, so it's shown here as plain text — view it formatted on GitHub.

emacs
evil
multiple-cursors
vim

Contributors

gabesoft

294 commits

Dickby

6 commits

syohex

3 commits

duianto

3 commits

Languages

Emacs Lisp

78.8%

Gherkin

20.9%