Vim’s multiple cursors feature lets you edit text in multiple locations simultaneously, which sounds like magic but is fundamentally about clever state management and efficient command application.
Let’s see it in action. Imagine you have this file:
apple pie
banana bread
cherry tart
date cake
elderberry jam
You want to add "delicious " before each fruit.
- Place your cursor on the
ainapple. - Press
Ctrl-vto enter visual block mode. - Move your cursor down to the
binbanana, thencincherry,dindate, andeinelderberry. You’ll see a block selection highlighting the first letter of each line. - Press
I(uppercase i) to enter insert mode before the block. - Type
delicious. - Press
<Esc>to exit insert mode.
The file now looks like this:
delicious apple pie
delicious banana bread
delicious cherry tart
delicious date cake
delicious elderberry jam
This works by creating multiple "virtual" cursors. When you enter insert mode in visual block mode, Vim essentially remembers the column you started in and the lines you’ve selected. Any characters you type are inserted at that column position across all selected lines. Exiting insert mode then applies the change to all those locations.
The core problem this solves is repetitive editing. Think about renaming a variable across several files, or adding a prefix/suffix to many lines. Doing this manually with . (repeat last command) or n and N to find occurrences is tedious and error-prone. Multiple cursors streamline this dramatically.
Internally, Vim doesn’t actually create separate cursor objects for each location in the way you might imagine. Instead, when you use commands like Ctrl-v followed by movement, it builds a selection region. When you enter insert mode (I or A), Vim enters a special mode where it buffers the characters you type. Upon exiting insert mode (<Esc>), it iterates through the selected lines and inserts the buffered characters at the appropriate column for each. For other commands, like a substitution that spans multiple cursors, it applies the command sequentially to each cursor’s position.
The "multiple cursors" functionality is largely provided by plugins like "vim-multiple-cursors." The core Vim functionality that enables this relies on its powerful visual selection modes (block, line, character) and its ability to repeat complex operations. Plugins leverage these by providing commands to:
- Add new cursors at visually selected locations.
- Add cursors to lines matching a pattern.
- Add cursors to specific column positions.
- Move cursors independently or in sync.
- Perform actions (insert, delete, replace, run commands) across all cursors.
Let’s dive deeper into a common scenario: adding a suffix. Suppose you have a list of variable names and want to add _old to each:
var1
var2
var3
- Place your cursor on
1invar1. - Press
Ctrl-v. - Move down to the
3invar3. You have a block selection. - Press
A(uppercase a) to enter insert mode after the block. - Type
_old. - Press
<Esc>.
The result:
var1_old
var2_old
var3_old
The A command is crucial here. Unlike I, which inserts before the visual selection’s start column on each line, A inserts after the visual selection’s end column on each line. This distinction is vital for correctly appending text.
Another powerful technique is adding cursors based on search. If you want to add a prefix to all lines containing "important":
This is a normal line.
This is an important message.
Another line.
This is another important item.
- Press
Ctrl-n(orCtrl-x Ctrl-ndepending on your plugin setup) to add a new cursor below the current one. - Press
/importantand then<Enter>to search for "important". The cursor moves to the start of "important". - Press
Ctrl-nagain. This adds another cursor, but now it’s focused on finding the next instance of "important". - Press
Ctrl-pto add a cursor above the current one, searching upwards for the previous "important". - You now have multiple cursors on the word "important". To add text before these, press
i(lowercase i) to enter normal insert mode. - Type
VERY_. - Press
<Esc>.
The file becomes:
This is a normal line.
This is an VERY_important message.
Another line.
This is an VERY_important item.
This demonstrates how you can combine visual selection, search, and specific cursor-adding commands to precisely target where you want your edits to occur. The key is understanding that each cursor is an independent editing point, but commands are broadcast to them in a synchronized fashion.
The most surprising thing about how multiple cursors work is that for many operations, the plugin doesn’t need to perform complex AST (Abstract Syntax Tree) analysis of your code. It often relies on Vim’s fundamental text manipulation capabilities and its robust undo/redo system. When you issue a command like "delete character" across multiple cursors, the plugin effectively tells Vim, "delete the character at cursor A, then delete the character at cursor B, then delete…" and Vim handles the state transitions and undo history for each operation, coalescing them into a single logical undo step.
After fixing a common issue like the ^M (carriage return) characters showing up when editing files from Windows on Linux/macOS, the next problem you’ll likely encounter is accidentally deleting your entire file if you press Ctrl-c instead of <Esc> while in insert mode with multiple cursors active.