Multi-Cursor
Multi-cursor lets you edit at many positions at once. Hold Alt + click to drop cursors; use shortcuts to add cursors by selection, line, or word match. Once mastered, the single biggest editor productivity boost.
Drop, line up/down, find all, snippets
EXAMPLE
// 1) Manual placement
// Alt + Click → drop a cursor where you click
// Hold Alt + drag → drop a column of cursors
// Cmd / Ctrl + click → goto definition (NOT multi-cursor)
// 2) Add cursor above / below current
// Cmd + Alt + Up / Down (macOS)
// Ctrl + Alt + Up / Down (Windows / Linux)
// Useful when you want to type the same prefix on multiple lines
// import { foo } from './foo';
// import { bar } from './bar';
// import { baz } from './baz';
// Place cursor at 'import' → add cursor above/below → type prefix in all
// 3) Add cursor at every occurrence of selection
// Cmd + D (macOS) / Ctrl + D (Windows/Linux)
// First press: select word under cursor
// Each subsequent press: select next occurrence
// Continue pressing to multi-edit
function example() {
const user = getUser();
const userName = user.name;
const userEmail = user.email;
user.greeting(); // rename 'user' → 'person' by Cmd+D-ing 4 times
}
// 4) Add cursor at ALL occurrences
// Cmd + Shift + L (macOS) / Ctrl + Shift + L (Windows/Linux)
// Selects ALL occurrences of the current word in the file
// 5) Skip occurrence
// Cmd + K + Cmd + D (macOS) — skip the current and select the next
// Useful when you Cmd+D'd one you didn't want
// 6) Column / box selection
// Alt + Shift + drag → rectangular selection
// Cmd + Alt + Shift + arrow keys (macOS) — expand selection box
//
// Useful for table-like edits, log alignment, CSV editing
// 7) Multi-line cursor in find/replace
// Cmd + F (find), type query → Alt + Enter
// Drops a cursor at EVERY match in the file
// Then you can edit each match simultaneously
// 8) Selecting whole lines
// Cmd + L (macOS) / Ctrl + L (Windows/Linux)
// First press: select current line
// Multiple presses: extend selection by line
// 9) Useful editing patterns
// Pattern A — rename variable inline (single file)
// 1. Cursor on the variable
// 2. Cmd + Shift + L (all occurrences)
// 3. Type the new name
// 4. (Use F2 for proper rename refactor across files)
// Pattern B — convert object to array of values
// const data = {
// a: 1,
// b: 2,
// c: 3,
// };
// Goal: make it [1, 2, 3]
// 1. Multi-cursor at each value (Cmd+D or column select)
// 2. Wrap each in something or remove keys
// Pattern C — change function param names
// function foo(userId, postId, commentId) {
// db.find({ userId, postId, commentId });
// }
// Rename userId to uid everywhere in the function:
// 1. Click userId
// 2. Cmd + Shift + L (selects all 3 occurrences in scope of selection)
// Or use F2 (rename symbol) for safe cross-file rename
// Pattern D — generate boilerplate
// import { useState } from 'react';
// const [count, setCount] = useState(0);
//
// Want: const [name, setName] / [age, setAge] / [email, setEmail]
// 1. Drop cursors on each line
// 2. Type `const [`, `, set`, `] = useState(...)`
// 3. Type the variable name first, then capitalise via custom
// 10) Combine with snippets
// Define a snippet that uses multiple tab stops at the same position:
// "React component": {
// "prefix": "rfc",
// "body": [
// "export function ${1:Name}() {",
// " return <${2:div}>${3:content}</${2:div}>;",
// "}"
// ]
// }
// $2 appears in TWO places — typing once edits both. Multi-cursor in a snippet!
// 11) Multi-cursor with regex find/replace
// Cmd + Shift + H — find & replace in files
// Or Cmd + F → toggle 'Use Regular Expression' icon
// Find: /(\w+)Id\b/
// Replace: $1_id
// All matches transform; with 'Replace all in selected text' for scoped change
// 12) Useful 'Selection' menu commands
// Selection → Expand Selection — grow selection to enclosing syntax
// Selection → Shrink Selection — opposite
// Selection → Copy Line Up / Down — duplicate current line
// Selection → Move Line Up / Down — shuffle lines
// Selection → Add Cursor to All Occurrences
// Selection → Add Cursors to Line Ends — drop cursor at end of every selected line
// 13) Macros — multi-edit one column
// Select column with Alt + Shift + drag
// Type — all selected positions get same input
// Press End — every cursor jumps to end of its line
// Type ; — adds semicolon to every line
// 14) Real-world examples
// Convert single quotes to double quotes (when ESLint says you should)
// Cmd + F → 'Replace All' with regex /'/g → ' "' '
// Or use multi-cursor at each quote — typing once changes all
// Add type annotations to many JS variables
// const a = 1
// const b = 2
// const c = 3
// Drop multi-cursor at each 'a', 'b', 'c'
// Type ': number' before the =
// Convert CSV lines to objects
// Ada,32,Sydney
// Bo,28,Sydney
// Cy,41,Melbourne
// Use Alt+Shift+drag to column-select
// Replace commas with ', '
// Wrap each line: 'name'/ age / city /...
// 15) Settings to enable / improve multi-cursor
{
"editor.multiCursorModifier": "alt", // 'alt' (default) or 'ctrlCmd'
"editor.multiCursorPaste": "spread", // paste from clipboard per cursor
"editor.smartSelect.selectLeadingAndTrailingWhitespace": false,
"editor.wordWrap": "off" // multi-cursor easier without wrap
}
// 16) Common shortcuts (cross-platform)
// Add cursor above / below : Cmd/Ctrl + Alt + Up/Down
// Select word at cursor : Cmd/Ctrl + D
// Select all occurrences : Cmd/Ctrl + Shift + L
// Skip current occurrence : Cmd + K + Cmd + D
// Column / box selection : Alt + Shift + drag (or Shift + arrow with Alt held)
// Drop in find: Alt + Enter
// Add cursors at line ends : Selection → Add Cursors to Line Ends
// Toggle column selection mode : Alt + Shift + ' (or settings)
// Expand / shrink selection : Shift + Alt + Right/Left
// 17) Multi-cursor with diff / merge
// Works in VS Code's merge editor too — drop cursors across both versions
// Useful for batch-resolving conflicts of the same pattern
// 18) When NOT to use multi-cursor
// • Cross-file rename → use F2 (Rename Symbol) — refactor-aware
// • Find & Replace with logic → use regex replace with capture groups
// • Renaming variables — F2 understands scope, multi-cursor doesn't
// • Reformatting code → use Format Document (Shift + Alt + F)
// 19) Practice patterns
// Try these on your codebase:
// 1. Rename a parameter in 5 places at once (Cmd+D × 5)
// 2. Convert 10 var to const using Cmd+Shift+L
// 3. Add console.log() to 5 places using Alt+click
// 4. Add JSDoc comment to multiple functions using line-end cursors
// 5. Convert hex codes to RGB using regex Find→Alt+Enter
// 20) Tips
// • Escape exits multi-cursor (down to single cursor)
// • Cursor positions persist while you scroll — useful for long files
// • Combined with snippets — supercharged code generation
// • Practice with Find→Alt+Enter for any 'edit all matches' task
// • Pair with column selection for tabular data + log alignment
Why it matters
Multi-cursor + selection commands is the single biggest VS Code productivity boost. Cmd+D (next occurrence) and Cmd+Shift+L (all occurrences) cover 80% of cases; combine with column selection (Alt+Shift+drag) for tabular edits.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
// Ctrl + D next match // Ctrl + Shift + L all matches at once // Alt + Click add cursor at click // Ctrl + Alt + ↑ / ↓ column cursorsTry it Yourself »
Exercise
Add the next match to multi-cursor.
Ctrl +
One letter.
Discussion
Loading…