What is Multi-Cursor Editing in Emacs?
Multi-cursor editing allows you to create multiple simultaneous cursors (also called "multiple cursors" or "mc") at different locations in a buffer. Any text you type appears at all cursor positions at once. This is similar to the multi-selection editing found in modern editors like Sublime Text, VS Code, or IntelliJ IDEA, but Emacs implements it with its own unique flavor and extensibility.
In Emacs, multi-cursor support comes primarily through the multiple-cursors package. The package transforms Emacs's single-cursor paradigm into a multi-cursor powerhouse, letting you edit many locations simultaneously without resorting to macros or repetitive commands.
Core Concepts
When you activate multiple cursors, Emacs maintains:
- Primary cursor — the original cursor position that drives the editing
- Secondary cursors — additional fake cursors rendered at specified locations
- Simulated key events — keystrokes are captured and replayed at every cursor position
The package works by intercepting your input, running the commands at each cursor location in sequence, and updating all positions accordingly. It handles complex scenarios like overlapping edits, undo behavior, and region-specific operations remarkably well.
Why Multi-Cursor Editing Matters
🚀 Deploy your AI agent in 10 minutes
Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.
Try it free →Multi-cursor editing dramatically accelerates repetitive editing tasks. Consider these common scenarios:
- Renaming variables across a function — change all occurrences in one go
- Adding prefixes or suffixes to multiple lines simultaneously
- Wrapping multiple items in quotes, parentheses, or HTML tags at once
- Aligning columns by inserting spaces across several lines
- Converting formats — transform a list of values from one format to another in parallel
Without multi-cursors, you'd typically reach for:
- Keyboard macros (F3/F4) — powerful but require careful recording and aren't interactive
- query-replace — good for simple substitutions but limited for structural edits
- Rectangle commands — useful for columnar edits but restricted to rectangular regions
- Manual repetition — slow and error-prone
Multi-cursors give you visual, interactive, simultaneous editing — you see exactly what changes are happening and can adjust on the fly. This immediacy reduces cognitive overhead and catches errors before they propagate.
Installation and Setup
Installing the Multiple-Cursors Package
The canonical package is multiple-cursors by Magnar Sveen, available on MELPA. Add this to your Emacs configuration:
;; Add MELPA if you haven't already
(require 'package)
(add-to-list 'package-archives
'("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
;; Install multiple-cursors
(unless (package-installed-p 'multiple-cursors)
(package-refresh-contents)
(package-install 'multiple-cursors))
;; Enable the package
(require 'multiple-cursors)
Basic Keybindings
The package provides sensible default bindings. Here's a recommended setup that doesn't conflict with common Emacs workflows:
(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
(global-set-key (kbd "C->") 'mc/mark-next-like-this)
(global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
(global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
(global-set-key (kbd "C-S-d") 'mc/mark-all-like-this-dwim)
(global-set-key (kbd "C-S-m") 'mc/mark-more-like-this-extended)
;; For Emacs 28+ with repeat-mode, consider:
(global-set-key (kbd "C-.") 'mc/mark-next-like-this)
(global-set-key (kbd "C-,") 'mc/mark-previous-like-this)
If you use use-package, here's a clean configuration block:
(use-package multiple-cursors
:ensure t
:bind (("C-S-c C-S-c" . mc/edit-lines)
("C->" . mc/mark-next-like-this)
("C-<" . mc/mark-previous-like-this)
("C-c C-<" . mc/mark-all-like-this)
("C-S-d" . mc/mark-all-like-this-dwim))
:config
(setq mc/always-run-for-all-cursors t
mc/always-focus-minibuffer t))
How to Use Multiple Cursors
Adding Cursors One by One
The most common workflow: place your cursor on a symbol, then press C-> to mark the next occurrence and create a new cursor there. Repeat to add more cursors. Use C-< to skip back and remove the most recent cursor.
Example — given this code:
function updateUser(userId, userName) {
console.log(userId);
return fetchUser(userId, userName);
}
Place the cursor on userId, press C-> twice to mark the other two occurrences. Now type accountId — all three instances change simultaneously.
Marking All Occurrences at Once
To select every occurrence of the symbol at point, use C-c C-< (mc/mark-all-like-this). This is faster than stepping through occurrences when you want to edit them all.
;; Before — cursor on 'status'
status = computeStatus(data);
if (status == 0) {
logStatus(status);
}
;; Press C-c C-< then type 'result'
result = computeResult(data);
if (result == 0) {
logResult(result);
}
DWIM (Do What I Mean) Marking
The mc/mark-all-like-this-dwim command (bound to C-S-d) intelligently decides whether to mark all occurrences in the whole buffer or just within the current defun/scope. If a region is active, it limits searching to that region. This is the most versatile marking command for programming.
Editing Multiple Lines
The mc/edit-lines command (C-S-c C-S-c) places a cursor at the beginning of each line in the active region. This is perfect for columnar editing:
;; Select these three lines with a region, then C-S-c C-S-c:
apple
banana
cherry
;; Type: " - fruit" at each cursor
apple - fruit
banana - fruit
cherry - fruit
You can also use mc/edit-lines without a region — it operates on consecutive lines starting from the current line, placing cursors at the beginning of each. Use a numeric prefix argument (e.g., C-u 10 C-S-c C-S-c) to specify how many lines to cover.
Matching Complex Patterns
The command mc/mark-more-like-this-extended (bound to C-S-m) prompts you for a regular expression and marks all matches with cursors. This is invaluable for pattern-based edits:
;; Buffer contains:
;; error: connection refused on port 8080
;; error: timeout on port 3000
;; error: invalid token on port 5432
;; Press C-S-m, enter regex: port \d+
;; All port numbers are now selected with cursors
;; Type: 9090 — all ports change at once
Using Rectangle Mark Mode with Multi-Cursors
You can combine rectangle selections with multi-cursors. Use C-x SPC to enter rectangle-mark-mode, select a rectangle, then use mc/edit-lines — cursors appear at each line within the rectangle, at the column of the rectangle's edge.
Practical Code Examples
Example 1: Converting a List of Constants to Enums
Given a plain list of constants that need enum wrapping:
STATUS_ACTIVE = 1
STATUS_PENDING = 2
STATUS_CLOSED = 3
Workflow:
- Place cursor on
STATUS_ACTIVE - Press
C-S-m, enter regex:STATUS_\w+to mark all three lines - Type:
case(appears before each constant) - Press
C-eto move each cursor to end of its line - Type:
: return ", thenC-eagain, then type:"; break;
Result:
case STATUS_ACTIVE: return "STATUS_ACTIVE"; break;
case STATUS_PENDING: return "STATUS_PENDING"; break;
case STATUS_CLOSED: return "STATUS_CLOSED"; break;
Example 2: Adding Type Annotations to Function Parameters
Starting with untyped Python parameters:
def process_data(name, age, location, status):
pass
Workflow:
- Place cursor on
name - Press
C->three times to markage,location,status - Press
C-s ,to search forward for comma, thenRETto exit search — now each cursor is after its parameter - Type:
: str(or appropriate types)
Result:
def process_data(name: str, age: str, location: str, status: str):
pass
Note: For different types, you'd manually adjust individual cursors or use a macro instead.
Example 3: HTML List Transformation
Transform a bullet list into HTML list items:
* Introduction
* Getting Started
* Advanced Topics
* Conclusion
Workflow:
- Select all four lines as a region
- Press
C-S-c C-S-c(mc/edit-lines) - Type:
<li>at the start of each line - Press
C-eto move to end of each line - Type:
</li>
Result:
<li>Introduction</li>
<li>Getting Started</li>
<li>Advanced Topics</li>
<li>Conclusion</li>
Example 4: Inserting Commas at Line Ends
Given a JSON-like list missing commas:
{"name": "Alice"}
{"name": "Bob"}
{"name": "Carol"}
{"name": "Dave"}
Workflow:
- Select the region covering all lines
C-S-c C-S-cto place cursors at line startsC-eto move all cursors to line ends- Type:
,
Result:
{"name": "Alice"},
{"name": "Bob"},
{"name": "Carol"},
{"name": "Dave"},
Advanced Techniques
Navigating with Multiple Cursors
When you have multiple cursors active, standard motion commands work but behave slightly differently. Here are key navigation patterns:
C-n/C-p— move each cursor down/up independently. If cursors are on different columns, each moves relative to its own column.C-e/C-a— move each cursor to the end/start of its own line.M-f/M-b— move each cursor forward/backward by word.C-s— isearch works across all cursors; the search happens from the primary cursor's position, but all cursors jump to matching positions.
Be careful with line-based movement when cursors are on different lines — each cursor maintains its own column position independently.
Undo Behavior with Multiple Cursors
Undo (C-/ or C-x u) with multiple cursors undoes the entire batch of simultaneous edits as a single undo step. This is a major advantage over macros, where undo replays the entire macro in reverse. With multi-cursors, one undo reverts all changes from the last multi-cursor edit atomically.
Exiting Multi-Cursor Mode
Press C-g (keyboard-quit) to exit multi-cursor mode and return to a single cursor. Alternatively, RET or SPC in the special mc/keymap context also exits gracefully. If you accidentally enter multi-cursor mode, C-g is your escape hatch.
Using Marks and Regions
With multiple cursors, each cursor has its own mark. You can set marks with C-SPC and then perform region-based operations. The primary cursor's region determines the behavior for commands that aren't cursor-aware. For predictable results, stick to simple insertions and deletions when using regions across multiple cursors.
Customizing Cursor Appearance
You can customize how fake cursors look:
(setq mc/cursor-color "red") ;; Color of fake cursors
(setq mc/cursor-bar-color "orange") ;; Bar cursor color (if using bar cursor)
(setq mc/use-blink-cursor t) ;; Blink fake cursors
(setq mc/use-falling-bomb-cursor t) ;; Fun animation (try it!)
Built-in Emacs Alternatives
While multiple-cursors is the most popular package, Emacs has several built-in approaches worth knowing:
Iedit Mode
Built into Emacs (since 24.x), iedit lets you edit all occurrences of a symbol in a buffer or region. It's more limited than multiple-cursors but requires no external package:
;; Place cursor on a symbol, then:
;; M-x iedit-mode (or bind to a key)
;; All occurrences are highlighted and editable
;; Type your changes — they appear everywhere
;; Press C-g to exit iedit mode
Iedit shines for quick symbol renaming without the visual overhead of multiple cursors. It's essentially "edit all occurrences inline."
Query-Replace with Zero-Length Replacements
A creative built-in approach: use query-replace-regexp with capture groups and zero-length assertions to simulate multi-cursor insertion:
;; To insert "DEBUG: " before every line starting with "log"
;; M-x query-replace-regexp
;; Search: ^\(log.*\)
;; Replace: DEBUG: \1
This is powerful but lacks the interactive visual feedback of multi-cursors.
Keyboard Macros
For truly complex, non-uniform edits across multiple locations, keyboard macros remain the gold standard:
;; Record a macro (F3)
;; Perform the edit on one occurrence
;; Stop recording (F4)
;; Execute macro with prefix: C-u 0 F4 (runs until error)
;; Or: C-x e e e e ... for manual step-through
Macros complement multi-cursors — use macros for sequential, pattern-based edits and multi-cursors for simultaneous, uniform edits.
Best Practices
1. Start Simple, Add Cursors Incrementally
Don't immediately mark all occurrences. Start with C-> to add cursors one at a time. This builds spatial awareness of where each cursor is and prevents accidentally editing locations you didn't intend to touch.
2. Use DWIM for Scoped Edits
Prefer mc/mark-all-like-this-dwim over mc/mark-all-like-this. The DWIM variant respects function boundaries and active regions, reducing the chance of editing code outside your current context.
3. Combine with Isearch for Precision
After activating multiple cursors, use C-s (isearch) to navigate all cursors to specific positions. For example, if you want to insert text after the first comma on each line, place cursors at line starts, then C-s , to jump all cursors to their respective commas.
4. Limit Cursor Count on Large Files
With hundreds of cursors, Emacs can slow down noticeably. If you're marking all occurrences of a common symbol (like i or tmp) in a large file, consider narrowing the buffer first with C-x n n (narrow-to-region) to limit the scope.
5. Use Rectangle Mode for Columnar Data
For CSV files, log files, or tabular data, combine rectangle-mark-mode with mc/edit-lines. Select a rectangle over the column you want to edit, then activate multi-cursors within that rectangle.
6. Master the Escape Hatch
Train yourself to hit C-g immediately if multi-cursor behavior goes wrong. It's fast, non-destructive, and gets you back to a single cursor instantly. Don't try to "fix" a bad multi-cursor state — escape and start fresh.
7. Pair with Multiple-Cursors for Symmetrical Edits
When editing HTML/JSX with matching tags, or parentheses-balanced expressions, use multi-cursors together with smartparens or paredit for structural editing across multiple locations simultaneously.
8. Customize the mc/keymap for Efficiency
During multi-cursor editing, a special keymap (mc/keymap) is active. You can bind keys specifically for use during multi-cursor sessions:
(define-key mc/keymap (kbd "C-j") 'mc/insert-newline)
(define-key mc/keymap (kbd "C-d") 'mc/delete-forward)
;; This ensures predictable behavior across all cursors
9. Use Prefix Arguments for edit-lines
Instead of selecting a region for mc/edit-lines, use a prefix argument: C-u 20 C-S-c C-S-c places cursors on the next 20 lines. This is often faster than mouse-selecting a region.
10. Combine Macros and Multi-Cursors
For edits that require different types of changes at each cursor, record a keyboard macro that handles the variation, then apply it with multi-cursors. The macro executes at each cursor position sequentially, giving you the best of both worlds.
Troubleshooting Common Issues
Cursors Disappear or Flicker
If fake cursors flicker or disappear, check your theme. Some themes don't handle the cursor overlay well. Try setting mc/cursor-color explicitly to a contrasting color. Also, disable mc/use-falling-bomb-cursor if it causes visual glitches.
Commands Don't Work with Multiple Cursors
Not all Emacs commands are multi-cursor-aware. Commands that rely on buffer-wide state (like undo, complex query-replace, or commands that manipulate windows) may behave unpredictably. Stick to insertion, deletion, and simple motion commands for reliable results.
Performance Degradation
With more than ~50 cursors on a large buffer, you may notice lag. Solutions:
- Narrow the buffer with
C-x n nbefore marking cursors - Use
iedit-modeinstead for very large-scale symbol editing - Increase
gc-cons-thresholdtemporarily during multi-cursor operations
Accidental Activation
If you find yourself accidentally triggering multi-cursors (especially with easy-to-reach bindings like C->), consider using a less sensitive binding or enabling a confirmation prompt:
(setq mc/always-confirm t) ;; Prompt before activating multiple cursors
Comparison with Other Editors
Emacs multi-cursor editing differs from implementations in other editors in notable ways:
- VS Code / Sublime Text — multi-cursors are native and deeply integrated. Emacs's implementation is package-based but equally capable.
- Vim — uses "blockwise visual mode" and
:normcommands rather than true multi-cursors. Emacs's approach is more visually interactive. - IntelliJ — multi-cursors are called "multiple carets" and work similarly. Emacs's package offers more customizable cursor appearance and behavior.
The key advantage in Emacs: multi-cursors compose with every other Emacs feature — registers, macros, rectangle commands, isearch, and custom functions. This composability is uniquely Emacs.
Conclusion
Multi-cursor editing transforms Emacs from a single-point editor into a parallel editing machine. The multiple-cursors package provides an intuitive, visual way to apply simultaneous edits across many locations, filling the gap between simple query-replace and complex keyboard macros. By mastering the incremental marking commands, the DWIM variant, and the line-editing mode, you can handle the vast majority of repetitive editing tasks with fluid, interactive precision.
Start with C-> to mark occurrences one by one, graduate to C-S-d for scoped DWIM marking, and combine with C-S-c C-S-c for line-based edits. Keep C-g ready as your escape, and remember that multi-cursors complement rather than replace macros and query-replace — each tool has its sweet spot. With practice, multi-cursor editing becomes an indispensable part of your Emacs muscle memory, turning tedious repetition into a satisfying, instantaneous transformation.