(macros)
Editing

Editing commands

Beyond raw motion, Macros provides the core Emacs editing commands — region-aware where Emacs is, and each command's edits coalesce into a single undo group so they undo as a unit.

The region and the kill ring

Set the mark with C-Space, then move point; the text between mark and point is the region. Commands that say "region" act on it (or fall back sensibly when there's no active region).

Key Command Action
C-Space set-mark Start a selection
C-w kill-region Cut the region to the kill ring
M-w kill-ring-save Copy the region
C-y yank Paste the latest kill
M-y yank-pop Cycle through earlier kills (after a yank)
C-x C-x exchange-point-and-mark Swap point and mark
C-x C-h / cmd-a mark-whole-buffer Select all

The kill ring and the system clipboard are kept in sync by the clipboard commands (cmd-c/x/v), so copying in Macros and pasting in another app just works.

Killing & transposing

Key Command
C-k kill-line
M-d / M-Backspace kill-word / backward-kill-word
M-z zap-to-char
C-t transpose-chars
C-x C-t transpose-lines
M-^ join-line
C-o open-line

Incremental search, Emacs-style:

Key Command
C-s isearch-forward
C-r isearch-backward

Type to extend the match; C-s / C-r again to jump to the next/previous hit; C-g to cancel and return to where you started.

Replace

Key Command
M-% query-replace — ask at each match of a literal string
C-M-% query-replace-regexp — same, for a regexp
M-x replace-string / replace-regexp replace every match without asking
C-c p r / C-c p % projectile-replace / projectile-replace-regexp — across the project

All of them run from point to the end of the buffer, or inside the active region (an evil Visual selection counts). An empty search string reuses the previous pair. An all-lower-case search matches any case, and a lower-case replacement then follows the match's case (FOO → BAR, Foo → Bar). In the regexp versions \1…\9 insert capture groups, \& the whole match, \n / \t a newline / tab.

At each match of a query session:

Key Action
y / SPC replace and go on
n / DEL skip
! replace all remaining
. replace this one and stop
, replace, but stay to look at the result
u / U undo the last / every replacement
^ back to the previous match
E edit the replacement string
q / RET stop (any other key stops too)
? help

The whole session is a single undo step. The keys work the same under evil and helix (M-% falls through the modal keymaps).

The project versions find the files with ripgrep (gitignore-aware), then run a query session through each file in turn: ! finishes the current file, Y replaces everything in all remaining files, N skips to the next file. At the end you're asked whether to save the files that changed. With evil, bind them on your leader, e.g. (evil-leader-set "n R" 'projectile-replace).

Occur

C-c o (occur) prompts for a regexp (an all-lower-case one ignores case) and opens an *occur* window listing every matching line with its line number, matches highlighted. n / p move between hits; Enter, o or a click jumps to the match in the source; q closes.

Editing results (occur-edit / wgrep)

In *occur* and in the project grep buffer (C-c p G), press e or C-c C-p (i under evil/helix) to make the results editable. Only the text after each file:line: prefix can change — the prefixes are read-only. Then:

  • C-c C-c applies every changed line. Sources open in a buffer are edited in that buffer and left modified for you to review and save; files that aren't open are patched directly on disk. A line that changed since the search is skipped and reported.
  • C-c C-k throws the edits away.

Comment toggling

M-; (comment-dwim) toggles a line comment on the current line (or region). The comment prefix is a buffer-local string set per mode (comment-string), defaulting to // ; modes like steel-mode set their own.

Sorting & case

These act on the region, or the whole buffer when there's no region:

  • sort-lines — sort the lines.
  • upcase-region / downcase-region / capitalize-region — case conversion.

Run them by name with M-x, or bind them in your init.scm.

Undo & redo

Key Command Action
C-/ undo Undo the last change
C-? redo Redo

Undo is branching (Emacs undo-tree): undoing and then making a new edit starts a branch rather than discarding the redone edits, so no work is ever lost. M-x vundo opens a read-only view of the undo tree (g refreshes, q closes); navigate the history itself with C-/ and C-?.

Expanding the selection

Grow the region outward along tree-sitter syntax boundaries — word, then expression, statement, block (Emacs expand-region). It works in any buffer with a tree-sitter grammar, no language server needed.

Key Command Action
C-= er/expand Widen the selection to the enclosing node
M-= er/contract Step back to the previous, narrower selection

In evil visual state, + and - do the same.

Multiple cursors

Edit in many places at once (Emacs mc.el). Add secondary cursors, then typed text, Enter, and Backspace are replicated at every cursor.

Key Command Action
C-c C-n mc-add-cursor-below Add a cursor on the next line
C-c C-p mc-add-cursor-above Add a cursor on the previous line
C-c C-d mc-mark-next-like-this Add a cursor at the next occurrence of the word at point
C-g mc-clear Collapse back to a single cursor

Plain motions move only the primary cursor — add the cursors first, then type or delete.

Jumping to a character

Jump anywhere on screen in a couple of keystrokes (Emacs avy / ace-jump).

Key Command Action
C-c j avy-goto-char Type a character; every visible occurrence is tagged with a hint letter — press the letter to jump

In evil normal state this is g s. C-g cancels the jump.

The buffer list

C-x C-b (ibuffer) opens a buffer manager (Emacs ibuffer) listing every open buffer. Enter switches to the buffer on the line, d or x kills it, g refreshes. (To pick a buffer through Helm instead, use C-x b.)