Editing Columns, Not Lines: Emacs Rectangles in Practice
Emacs rectangles let you kill, yank, clear, and overwrite columnar blocks of text independent of line structure. A practical guide to string-rectangle, rectangle-mark-mode, and the tab-related sharp edges.
01 Oct 2026, 06:07 UTC

You've got forty lines of code where every line needs the same change in the same column — a prefix added, a column of a table swapped out, a block of assignments re-indented by exactly twelve spaces. Your instinct is a macro or a regex replace, and both work. But Emacs has a simpler tool built for exactly this shape of problem: rectangles, which let you cut, copy, blank out, and overwrite a columnar block of text that ignores line structure entirely.
The thesis is simple: whenever an edit is defined by "these columns on these lines" rather than "this pattern," rectangles beat regexes. You see what you're about to change, and the change is one command instead of a substitution you have to debug.
What a rectangle actually is
A rectangle is the region between the column of the mark and the column of point, extended across every line in between. Lines shorter than that column are treated as if padded with spaces. That last detail matters: rectangles don't fail on ragged text, they just include virtual whitespace.
The core commands all live under the C-x r prefix:
C-x r k— kill the rectangle (cut it into a special rectangle register, not the normal kill ring).C-x r y— yank the last killed rectangle with its upper-left corner at point.C-x r c— clear the rectangle, replacing it with spaces (text to the right stays put).C-x r o— open the rectangle, inserting blank space and pushing text to the right.C-x r t— string-rectangle: replace every line of the rectangle with a string you type.
Note that C-x r o does not open anything in a new buffer — it shifts text rightward, which is handy for carving out space before pasting a column.
A worked example: commenting out a column of code
Say you have a block of aligned assignments and you want to comment out just the middle ones, or prepend a prefix like legacy_ to a column of identifiers:
alpha = compute_alpha(x)
beta = compute_beta(x)
gamma = compute_gamma(x)
delta = compute_delta(x)Put point at the start of alpha (line 1, column 0), set the mark with C-SPC, then move point to the start of delta on the last line — same column, four lines down. The rectangle is now zero columns wide and four lines tall. Run C-x r t (string-rectangle) and type # at the prompt. Every line gets # inserted at that column:
# alpha = compute_alpha(x)
# beta = compute_beta(x)
# gamma = compute_gamma(x)
# delta = compute_delta(x)Zero-width rectangles are the trick most people miss: because the rectangle can be empty, string-rectangle becomes a pure insert the same text on every line at this column operation. To verify the result, just look — but a quick programmatic check is M-x occur with pattern ^# , which should report exactly four matches.
For moving a column instead of annotating one: mark the rectangle over the column, C-x r k, move point to where the column's upper-left corner should land, and C-x r y. The yanked rectangle overwrites whatever occupies that space, so use C-x r o first if you need to make room.
Rectangle mark mode: see before you cut
The classic complaint about rectangles is that the region highlighting doesn't show the rectangle — it shows the ordinary linear region, so you can't tell which columns you're about to kill. Since Emacs 24.4, C-x SPC (rectangle-mark-mode) fixes this: it activates a rectangular region with true columnar highlighting, and normal commands like C-w, M-w, and even string-rectangle operate on the rectangle. If you do column edits more than occasionally, this is the mode to reach for first, because the visual feedback prevents the classic mistake of being off by one column.
Trade-offs and sharp edges
- Killed rectangles don't live in the normal kill ring. There's one rectangle register; a second
C-x r koverwrites the first. If you need to keep one around, save it withC-x r r(copy rectangle to a named register) and restore withC-x r i. - Yank overwrites, it doesn't insert. Pasting a rectangle on top of existing text replaces those columns. When in doubt,
C-x r ofirst. - Tabs are treacherous. Rectangles count display columns, and a tab is one character but many columns. In files with mixed tabs and spaces, run
M-x untabifyon the region first, or expect ragged results. - Accidents are easy to abort. If you realize mid-command that the mark is in the wrong place,
C-gcancels; if you already killed, a plainC-x r yat the same spot followed byundo(C-/) gets you back.
Rectangles also don't replace regexes for pattern-shaped problems — "every line containing TODO" is still an occur/replace job. The decision rule: if you can describe the target by pointing at two corners, use a rectangle; if you describe it by matching text, use a regex.
Try it in the next five minutes
Open any file with aligned text — a .env file, a table in a README, a block of struct fields. Press C-x SPC, drag out a column with the arrow keys, and hit C-x r t to insert a prefix. Then C-/ to undo. That thirty-second exercise covers eighty percent of what rectangles do, and the next time you catch yourself writing a regex to hit "column 17 on lines 40 through 58," you'll have a faster option.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.