Multi-Cursor and Column Selection for Bulk Changes in PhpStorm
AI generated
IDE
{ }
PhpStorm · Editor · Productivity
Multi-Cursor and Column Selection
for fast bulk changes across your code

Typing the same change ten times by hand wastes time that PhpStorm's multi-cursor editing and column selection handle in seconds. Together, both techniques cover nearly every repetitive text change in the editor.

13 min read Multi-cursor Column selection Select All Occurrences

1. Why manual bulk changes are a time and error risk

Repetitive changes like renaming ten similar array keys, adding a prefix to a list of constants, or adjusting twenty nearly identical lines in a configuration file come up constantly in day-to-day PHP work. Editing line by line by hand not only costs time but also raises the risk of missing a line or introducing a typo somewhere that only surfaces at the next test run.

PhpStorm offers two complementary tools for this: multi-cursor editing places several independent carets that all react to keyboard input in parallel, while column selection allows a rectangular text selection across multiple lines, independent of the actual line content. Anyone who masters both techniques can handle changes that would be too coarse for a regex find-and-replace and too slow for manual editing, all in a single fluid step.

2. Placing cursors manually at arbitrary positions

The most direct way to get multiple cursors is Alt+Shift+Click, or Option+Shift+Click on macOS, at every position where an additional cursor should appear. Each cursor placed this way behaves completely independently: typing text inserts it at every active cursor position simultaneously, and key combinations like deleting a word or jumping to the end of a line also act on all cursors in parallel.

This is especially useful for structurally similar but not identical lines, for example when a parameter needs to be added at different positions across several method calls. Alt+J additionally adds the next occurrence of the current selection to the existing cursor set, allowing a smooth transition between manually placed cursors and automatic occurrence search, all without touching the mouse.


// Before: three separate log calls without a context prefix
$this->logger->info('Order created');
$this->logger->info('Payment captured');
$this->logger->info('Shipment sent');

// With three manually placed cursors (Alt+Shift+Click) right
// after each info(' , insert: 'Checkout: ' before every string

$this->logger->info('Checkout: Order created');
$this->logger->info('Checkout: Payment captured');
$this->logger->info('Checkout: Shipment sent');

3. Select All Occurrences: every match at once

Instead of placing cursors manually, Ctrl+Shift+Alt+J, or Cmd+Ctrl+G on macOS, instantly selects every occurrence of the currently selected text in the visible area or across the whole file and places its own cursor at each spot. This is the fastest way to, for example, consistently rename a repeated string key in an array without launching a project-wide find-and-replace that would also catch unwanted hits in other files.

The difference from Alt+J matters: Alt+J adds occurrences step by step and lets you deliberately skip individual hits, while Select All Occurrences marks every hit at once immediately. For a controlled, selective change, Alt+J is the better fit, while for a change that must apply to absolutely every occurrence without exception, Select All Occurrences is the faster and safer choice.

4. Column selection: a rectangular selection independent of line content

Column selection is activated via Alt+Shift plus dragging with the mouse, or alternatively via the shortcut that toggles column selection mode, and produces a rectangular selection based purely on visual columns rather than actual text. This is the key difference from Select All Occurrences: column selection does not care what is in the column, only where it sits.

That makes column selection ideal for situations where something needs to be inserted, deleted, or replaced at the same horizontal position across multiple lines, regardless of the actual content, for example adding a uniform prefix in front of a list of variable names of varying length, or stripping a comment character at the start of several consecutive lines column by column.

5. Practical example: reformatting arrays quickly

A classic use case in Magento modules is reformatting an array of short single-line entries into a multi-line array with consistent indentation, for example when transferring a list of constants from an external source. Column selection lets you insert a uniform indentation prefix in front of every line in one go, and Select All Occurrences can then replace every trailing comma with a uniform separator afterward, all without regex.

The benefit becomes even clearer when converting short notation into more verbose PHP array syntax, for example turning a list of store view codes from a CSV file into an associative PHP array. Column selection places the cursor at the end of every copied line, a single keystroke adds the closing quote and comma everywhere, and the entire reformatting job is done in a few seconds instead of several minutes of manual editing.


// Before: raw list, one ID per line
DE
AT
CH

// After, with column selection inserted before every line ('    ) => ')
// and Select All Occurrences appended at the end of every line (', )
$allowedStoreViewCodes = [
    'DE' => 'default',
    'AT' => 'austria',
    'CH' => 'switzerland',
];

6. Combining with Live Templates and structural navigation

Multi-cursor editing often reaches its full potential only in combination with other editor features. After placing multiple cursors, Live Templates can still be triggered normally, expanding a code snippet at several positions at once, for example a uniform PHPDoc block across several methods. Auto-completion also reacts independently at each cursor position, allowing very precise completions on structurally similar but not identical code.

Another often overlooked trick is combining this with Ctrl+D to duplicate a line or selection, followed by multi-cursor edits on the duplicates. This makes it possible to quickly generate a series of nearly identical test cases that differ only in a single parameter, without copying and adjusting every line by hand.

7. Limits and common pitfalls

Multi-cursor editing runs into trouble as soon as the structure of the affected lines differs too much, for example when some lines have an extra parameter and others don't. In such cases, blindly typing in parallel easily produces subtly wrong code that looks correct at first glance. A quick look at all affected lines before typing, ideally with soft wrap enabled, reliably prevents such silent mistakes.

A second common pitfall is accidentally leaving multi-cursor mode with a plain mouse click, which instantly collapses all extra cursors back down to a single one. Escape ends the mode in a controlled way, while a click into the editor without a held modifier key ends it uncontrolled. Anyone who accidentally clicks in the middle of a longer multi-cursor session loses all placed positions and has to rebuild the selection.

8. The most important shortcuts at a glance

For daily use, a small but well-practiced set of shortcuts is enough: Alt+Shift+Click for manual cursors, Alt+J to add the next occurrence step by step, Alt+Shift+J to remove the most recently added occurrence from the selection, Ctrl+Shift+Alt+J for all occurrences at once, and Alt+Shift plus mouse drag for column mode. In practice, these five combinations cover the vast majority of all bulk changes.

Once these shortcuts become muscle memory, they get reached for automatically at every repetitive change, instead of reaching for a regex find-and-replace that often takes longer to formulate than the actual change would take. For one-off, project-specific tweaks in particular, multi-cursor and column selection are usually noticeably faster than any regex, since no time is spent testing the pattern.

9. When a regex replacement is still the better choice

Multi-cursor techniques excel at visually or structurally clear patterns, but reach their limits when the change depends on a complex condition, for example only affecting certain numeric values above a threshold, or when hundreds of occurrences need changing across many files. In such cases, project-wide find-and-replace with regular expressions is the more robust choice, since it can be described programmatically and checked in a preview before being applied.

The rule of thumb in practice: up to a few dozen occurrences within one or a handful of files with a recognizable visual pattern belong to multi-cursor and column selection, while larger, logically more complex, or project-wide changes are better handled with regex find-and-replace including a preview. Using both tools situationally, rather than sticking to just one, saves the most time overall.

Action Shortcut (Win/Linux) Shortcut (macOS) Typical use
Place a manual cursor Alt+Shift+Click Option+Shift+Click Punctual changes at several spots
Add next occurrence Alt+J Ctrl+G Selective, controlled multi-selection
Select all occurrences Ctrl+Shift+Alt+J Cmd+Ctrl+G Consistently renaming every match
Enable column selection Alt+Shift+Drag Option+Shift+Drag Column-wise insert/delete
Duplicate line Ctrl+D Cmd+D Create a base for similar follow-up lines

Mironsoft

PhpStorm setup, Docker integration, and team productivity

PhpStorm that actually runs optimally for Magento and PHP projects?

We review existing PhpStorm setups for slow indexing, unused Docker integration, and missing team conventions, then set up a configuration that is productive from the first second.

Setup Review

Optimizing indexing, interpreter, and memory settings for large Magento projects.

Docker Integration

Cleanly connecting Xdebug, PHPUnit, and database tools to the Docker setup.

Team Conventions

Standardizing inspection profiles, code style, and live templates project-wide.

10. Summary

Multi-Cursor and Column Selection: The Essentials at a Glance

Two tools

Multi-cursor editing for content-based matches, column selection for purely position-based selection.

Select All Occurrences

Ctrl+Shift+Alt+J marks every occurrence instantly, Alt+J adds them one at a time under control.

Combinable

Live Templates, auto-completion and line duplication all keep working at every cursor position.

Know the limits

For structurally inconsistent lines or project-wide changes, regex find-and-replace is safer.

11. FAQ: Multi-Cursor and Column Selection: The Essentials at a Glance

1What is the difference between multi-cursor editing and column selection?
Multi-cursor editing places several independent carets that react to keyboard input, regardless of text structure. Column selection creates a rectangular selection along visual columns, regardless of the actual content of each line.
2How do I add every occurrence of a word to the selection at once?
Ctrl+Shift+Alt+J on Windows and Linux, or Cmd+Ctrl+G on macOS, instantly marks every occurrence of the currently selected text and places its own cursor at each one.
3How does Alt+J differ from Select All Occurrences?
Alt+J adds occurrences one at a time and lets you deliberately skip individual hits. Select All Occurrences instead marks every hit simultaneously, with no intermediate steps.
4How do I activate column selection mode?
Hold Alt+Shift and drag with the mouse button held down to create a rectangular selection across multiple lines. Alternatively, the mode can also be toggled persistently via a dedicated shortcut.
5Can I use Live Templates with multiple active cursors?
Yes, Live Templates can be triggered independently at every active cursor position, for example inserting a uniform PHPDoc block across several methods at once.
6What happens if I accidentally click during a multi-cursor session?
A plain mouse click without a held modifier key instantly collapses all active cursors back down to a single one. Escape should be used instead to end the mode in a controlled way.
7Is multi-cursor editing suitable for project-wide changes across many files?
No, multi-cursor editing works within one open file, or the visible area of it. For changes across many files, project-wide find-and-replace with regex is the better choice.
8How can I remove an occurrence from an existing multi-cursor selection?
Alt+Shift+J removes the most recently added occurrence (added via Alt+J) from the current selection, without affecting the remaining cursors.
9Why is column selection especially useful for array reformatting?
Because it lets you insert characters like quotes, commas, or indentation at the same column position across many lines at once, regardless of the differing length of the values on each line.
10When is a regex find-and-replace preferable to multi-cursor editing?
When the change depends on a complex condition, or when hundreds of occurrences across many files are affected. Multi-cursor works better for a few dozen matches with a clearly recognizable visual pattern.