Introduction to Zed Multi-Cursor Editing
Zed is a high-performance code editor built in Rust by the creators of Atom. One of its standout features is the robust multi-cursor editing system, which allows developers to place multiple cursors throughout a document and edit text at all locations simultaneously. This capability dramatically accelerates repetitive editing tasks and is a cornerstone of efficient text manipulation in modern editors.
Whether you are refactoring variable names across a file, transforming data structures, or applying consistent formatting, multi-cursor editing in Zed provides a fast, keyboard-driven workflow that keeps your hands on the keys and your focus on the code.
What Is Multi-Cursor Editing?
Multi-cursor editing is the ability to have more than one active cursor in a single document at the same time. When you type, delete, or apply commands, those actions are mirrored across every cursor position. Each cursor can also have its own selection range, enabling simultaneous edits to different spans of text.
In Zed, multi-cursor support is deeply integrated into the editor's core rather than bolted on as a plugin. This means operations like find and replace, indentation, and even language-aware features work seamlessly across all active cursors.
Key Concepts
- Cursor: A single insertion point in the document.
- Selection: A highlighted range of text associated with a cursor.
- Column selection: A rectangular block of cursors spanning multiple lines and columns.
- Selection stack: Zed's mechanism for managing and cycling through multiple selections.
Why Multi-Cursor Editing Matters
Multi-cursor editing matters because it eliminates the need for complex regular expressions or brittle find-and-replace patterns when the changes you need are visual and contextual. Instead of crafting a regex that might match unintended text, you can simply select the exact occurrences you want and edit them directly.
This approach offers several advantages:
- Speed: Repetitive edits that would take dozens of keystrokes become a single action.
- Precision: You see exactly which locations will be modified before you type.
- Flexibility: Cursors can be added incrementally, allowing you to build up complex selections organically.
- Reduced cognitive load: No need to mentally simulate regex matching behavior.
For developers working in large codebases, these benefits compound. Refactoring a function signature, updating API calls, or reformatting data literals can all be accomplished in seconds rather than minutes.
How to Use Multi-Cursor Editing in Zed
Zed provides a rich set of keyboard shortcuts for creating and manipulating multiple cursors. The exact bindings depend on your platform, but the following examples use the default macOS keymap. On Linux and Windows, substitute Cmd with Ctrl in most cases.
Adding Cursors Manually
The simplest way to create multiple cursors is to add them one at a time at specific locations.
Cmd + Click— Add a cursor at the click location.Cmd + D— Select the next occurrence of the current word or selection.Cmd + Shift + L— Select all occurrences of the current word or selection.Cmd + Alt + Down— Add a cursor on the line below.Cmd + Alt + Up— Add a cursor on the line above.
Column Selection
Column selection creates a rectangular block of cursors, which is useful for editing tabular data or aligned code blocks.
Cmd + Alt + Drag— Drag to create a column selection with the mouse.Cmd + Alt + Shift + Down/Up— Extend column selection down or up line by line.
Practical Example: Renaming a Variable Across a Function
Suppose you have the following JavaScript function and you want to rename the variable user to account only within this function.
function getUserInfo(user) {
const name = user.name;
const email = user.email;
const role = user.role;
return {
name,
email,
role,
id: user.id,
};
}
Follow these steps:
- Place your cursor on the word
userin the function parameter. - Press
Cmd + Drepeatedly to select each subsequent occurrence ofuser. - Once all desired occurrences are selected, type
account. - Press
Escapeto collapse back to a single cursor.
The result will look like this:
function getUserInfo(account) {
const name = account.name;
const email = account.email;
const role = account.role;
return {
name,
email,
role,
id: account.id,
};
}
Practical Example: Editing Aligned Data
Column selection shines when working with aligned data. Consider this list of configuration entries:
const config = {
host: "localhost",
port: "8080",
user: "admin",
pass: "secret",
debug: "true",
};
If you want to change all the string values to template literals, you can use column selection:
- Position your cursor at the first quotation mark before
localhost. - Press
Cmd + Alt + Shift + Downfour times to create cursors on each line. - Type a backtick to replace the opening quote.
- Move right with the arrow key to the closing quote.
- Type a backtick again.
The result:
const config = {
host: `localhost`,
port: `8080`,
user: `admin`,
pass: `secret`,
debug: `true`,
};
Using Select All Occurrences
When you need to change every instance of a word in the entire file, Cmd + Shift + L is your fastest option. For example, given this Python code:
def calculate_total(items):
total = 0
for item in items:
total += item.price
return total
def print_total(items):
total = calculate_total(items)
print(f"Total: {total}")
If you place your cursor on total and press Cmd + Shift + L, every occurrence of total in the file will be selected. You can then type a new name, such as sum_value, and all instances update simultaneously.
Combining Multi-Cursor with Find and Replace
Zed's find and replace panel integrates with multi-cursor editing. After performing a search, you can select all matches and convert them into cursors for direct editing.
Cmd + F— Open the find panel.- Type your search query.
Alt + Enter— Select all matches as multi-cursors.
This is particularly powerful when combined with regular expressions. For example, to wrap all numbers in a file with a function call, you could search for the regex \d+ and then use Alt + Enter to place a cursor at each match.
// Before
const values = [10, 20, 30, 40];
const more = [100, 200, 300];
// After wrapping each number with Number()
const values = [Number(10), Number(20), Number(30), Number(40)];
const more = [Number(100), Number(200), Number(300)];
To achieve this, after selecting all matches with Alt + Enter, you can use the End key to move all cursors to the end of each number, type ), then jump back to the start of each number with Home or Cmd + Left, and type Number(.
Managing and Navigating Selections
Once you have multiple cursors, Zed provides tools to manage them efficiently.
Escape— Collapse all cursors into a single cursor (the last active one).Cmd + U— Undo the last selection change, removing the most recently added cursor.Cmd + K, Cmd + U— Skip the current occurrence when usingCmd + Dto select the next one.- Arrow keys — Move all cursors simultaneously in any direction.
Cmd + Left / Right— Move all cursors to the start or end of their respective lines.
Practical Example: Adding a Prefix to Multiple Lines
Imagine you have a list of imports and want to comment out several of them:
import fs from 'fs';
import path from 'path';
import os from 'os';
import http from 'http';
import url from 'url';
To comment out the middle three lines:
- Click at the start of the
pathline. - Press
Cmd + Alt + Shift + Downtwice to add cursors on the next two lines. - Type
//to comment all three lines at once.
import fs from 'fs';
// import path from 'path';
// import os from 'os';
// import http from 'http';
import url from 'url';
Best Practices for Multi-Cursor Editing
Start Small and Build Up
When learning multi-cursor editing, begin with two or three cursors and gradually work up to more complex selections. This helps you understand how edits propagate and reduces the chance of accidentally modifying unintended locations.
Use Cmd + U to Undo Selections
If you accidentally select one too many occurrences with Cmd + D, do not reach for Escape and start over. Instead, press Cmd + U to undo just the last selection addition. This keeps your workflow smooth and preserves the selections you already built.
Leverage Skip When Selecting Occurrences
When using Cmd + D to select occurrences one by one, you may encounter a match you do not want to change. Use the skip command (Cmd + K, Cmd + U) to move past that occurrence without selecting it, then continue selecting with Cmd + D.
Combine with Snippets
Zed supports snippets, and they work with multi-cursor editing. You can place multiple cursors and then expand a snippet at each location. This is useful for generating repetitive boilerplate code such as test cases or interface definitions.
// Place a cursor on each empty line, then type a snippet trigger
test("should ", () => {
});
test("should ", () => {
});
test("should ", () => {
});
Know When to Use Find and Replace Instead
Multi-cursor editing is excellent for visual, contextual changes, but it is not always the right tool. For truly global replacements across many files, Zed's project-wide find and replace is more appropriate. Reserve multi-cursor editing for changes within a single file where you need fine-grained control over which occurrences to modify.
Save Before Complex Edits
Before performing a large multi-cursor edit, save your file or commit your current changes. If the edit goes wrong, you can quickly revert without losing work. Zed's undo history will also help, but having a clean save point provides peace of mind.
Practice Common Patterns
Certain multi-cursor patterns appear frequently in real-world editing. Practicing these will make you faster over time:
- Wrapping values in function calls or quotes.
- Adding or removing trailing commas in lists and objects.
- Converting between different quoting styles.
- Adding prefixes or suffixes to multiple lines.
- Extracting or inlining variables across a block of code.
Advanced Techniques
Selection Stack
Zed maintains a selection stack that lets you push and pop selections. This is useful when you want to temporarily work on a different part of the document without losing your current multi-cursor selection. You can push your current selection, make edits elsewhere, and then pop back to your previous selection state.
Multi-Cursor with Language-Aware Features
Because Zed's multi-cursor system is integrated with its language servers, features like autocomplete and code actions work at each cursor independently. This means you can type a partial identifier at multiple cursors and accept autocomplete suggestions at each location, potentially with different completions.
// Cursors placed before each property name
const user = {
na: "", // autocomplete suggests "name"
em: "", // autocomplete suggests "email"
ag: "", // autocomplete suggests "age"
};
Transforming Data with Multi-Cursor and Regex
One of the most powerful workflows combines regex search with multi-cursor selection. For example, converting a list of key-value pairs from one format to another:
// Original format
name: John
email: john@example.com
role: admin
active: true
Using a regex search for (\w+): (.+) with capture groups, you can select all matches and then use multi-cursor editing to reformat them into JSON syntax:
{
"name": "John",
"email": "john@example.com",
"role": "admin",
"active": "true"
}
The key insight is that after selecting all matches with Alt + Enter, you can navigate each cursor independently within its match to insert quotes, commas, and braces as needed.
Conclusion
Multi-cursor editing in Zed is a transformative feature that turns tedious, repetitive text manipulation into a fast and intuitive process. By mastering the core commands for adding cursors, selecting occurrences, and managing selections, you can dramatically reduce the time spent on refactoring and formatting tasks. The key to proficiency is practice: start with simple two-cursor edits, gradually incorporate column selection and regex integration, and soon multi-cursor editing will become a natural extension of your thinking. Combined with Zed's speed and language-aware features, it makes the editor a powerful tool for developers who value efficiency and precision in their daily workflow.