Registers and Macros: 26 Clipboards and a Record Button

What a Register Is

A register is a named container that holds a chunk of text. Vim has many. Every yank, delete, and change writes to at least one register. You can name a register explicitly when you yank or put, which lets you keep multiple independent clipboards.

To view what's in your registers:

:reg                    show all registers
:reg a b c              show just a, b, c

The Default Registers

""    the unnamed register. Holds your last yank or delete
"0    the yank register. Holds your last yank only
"1    to "9    the delete history. Shifts on each delete
"-    the small delete register. Single-line deletes under a line long
"/    the last search pattern
":    the last ex command
"%    the current file name
"#    the alternate file name
".    the last inserted text
"+    the system clipboard
"*    the selection clipboard (X11) or the system clipboard (mac/win)
"_    the black hole register. Writes go nowhere

You do not need to memorise this. You need to know a few patterns, below.

Yank Without Overwriting: Use "0 or Named Registers

The default Vim gotcha: yw then dw then p pastes what you just deleted, not what you yanked. Every delete overwrites the unnamed register.

Two fixes:

"0p    paste the last yank specifically, ignoring any delete between

The "0 register only holds yanks, never deletes. So it survives a later delete.

Or use named registers:

"ayw    yank a word into register a
"ap     paste register a

The double-quote syntax is "target the next command at this register". It applies to any yank, delete, or put.

The System Clipboard

Your operating system's clipboard is "+ (and on X11, "* is the selection). To copy a line into the system clipboard:

"+yy    yank the line into the system clipboard
"+p     paste from the system clipboard

Works from visual mode too: select, then "+y.

Making the system clipboard the default

Add to your .vimrc:

set clipboard=unnamedplus

Now every yank and put automatically uses "+. yy yanks into both the unnamed register and the system clipboard. p pastes from wherever you most recently copied.

If yanks still don't go to the system clipboard, your Vim may be built without clipboard support:

vim --version | grep clipboard

You want +clipboard, not -clipboard. If negative, install a version with clipboard support (vim-gtk3 on Debian, Homebrew Vim on macOS, or just use Neovim).

Named Registers: a through z

The 26 lowercase letters are general-purpose registers you can write to and read from:

"ayy      yank this line into register a
"byy      yank this line into register b
"ap       paste register a
"bp       paste register b

Capital letters append to the matching lowercase register:

"ayy      yank line 1 into a (overwrites a)
"Ayy      yank line 2, append to a

This is useful for collecting lines from around the file into a single register.

A realistic use

You're refactoring. You need to move a function from one file to another.

Va{                select the function block
"fd                delete into register f
:b other-file
G                  go to end of other file
"fp                paste from register f

Register f survived buffer switches and edits in between. That is the advantage over the unnamed register.

The Black Hole: "_

Sometimes you want to delete text without touching any register. Use the black hole:

"_dd       delete the line without overwriting the unnamed register
"_d$       delete to end of line, keep the unnamed register intact

Pair with yanks: yank a word, then "_diw to delete the word you're over, then P to paste your yank in its place.

A common mapping in .vimrc:

nnoremap x "_x
nnoremap d "_d

This makes d never clobber your clipboard. Some people love it, some hate it. Try both if the default annoys you.

Reading Registers in Insert or Command Mode

<C-r> in insert or command-line mode pastes a register:

<C-r>0      paste yank register
<C-r>"      paste unnamed register
<C-r>a      paste register a
<C-r>/      paste the last search pattern
<C-r>:      paste the last command
<C-r>%      paste the current file name

Incredibly useful at the : prompt. If you just searched for a pattern and want to build a substitute off it:

:%s/<C-r>//new/g

<C-r>/ fills in your last search. Now you don't have to retype it.

Macros

A macro is a recorded sequence of keystrokes stored in a register. To record:

q{a-z}      start recording into register {a-z}
...         perform any normal-mode commands
q           stop recording

To play back:

@{a-z}      replay the macro
@@          replay the last macro
{n}@a       replay macro a n times

You record into any lowercase register. I default to q: qq to start recording, the keys, q to stop, @q to play.

A worked example

You have a file with lines like Alice,30 and you want each line to become Alice is 30 years old..

qq                     start recording into register q
^                      jump to start of line
f,                     jump to the comma
c$                     change to end of line
 is <C-r>" years old.  type the template, pasting the age back
<Esc>                  leave insert mode
0                      back to start
j                      next line
q                      stop recording

Ignore the messy middle. It worked; now run it on every remaining line:

100@q       apply macro q up to 100 times (stops early if it fails)

Macros stop silently when they fail, which is usually fine. If a line doesn't match your pattern, f, beeps, the macro aborts, and subsequent macros don't run. Put the most-likely-to-fail motion first and you get a natural stop condition.

Editing a macro

Macros are just text in a register. View and edit them like any text:

:let @q='0j'        overwrite register q with "0j"
:put q              dump register q into the buffer so you can edit it

A common workflow: put the macro, edit it, yank it back into the register:

"qp            put register q below current line
# edit
"qdd           delete that line back into register q (with linefeed)

This is also how you save a useful macro into your .vimrc: put it, copy the text out, and paste it into a let @q = '...' line.

Recursive macros

A macro can call itself by referencing its own register:

qqqq            clear register q (record nothing into it, then stop)
qq              start recording q
{actions}
@q              call register q at the end of the macro
q               stop recording

Now @q runs itself over and over until it fails. No need to pass a count.

Most of the time a count (100@q) is simpler. Recursive macros shine when the iteration count is unknown and you want to run until failure.

Registers and Macros Together

Macros are stored in registers, so you can inspect them:

:reg q        show what's in register q

You can also yank normal text into q and execute it:

# type this on a line: 0j
yy             yank the line
"qy$           yank it into register q (sort of)
@q             runs "0j" as a command: down one line, to column 0

This means any Vim script you can write can be stored in a register and run as a macro. It is weird and powerful, and you probably won't need it for the first year.

Common Pitfalls

"My macro stopped halfway." That is usually correct. It means a motion failed. Add safer motions (0 instead of h, gg instead of {n}k) or wrap your workflow so the failure is the stop condition.

"@@ did the wrong thing." @@ repeats the last macro you played, not the last one recorded. If you played @a, then @@ replays a.

"I wrote a macro in register q and now @q does nothing." Make sure you didn't accidentally record an empty macro by pressing q twice. qq q clears register q.

"I want to move text and not just copy it." d moves, y copies. "_d moves without saving anywhere. Pair these with p and P.

"set clipboard=unnamedplus doesn't work." Check vim --version | grep clipboard. You need +clipboard. If you're on SSH, X forwarding can make clipboard work too, but it is usually easier to install an OSC52-capable terminal or use tmux with its clipboard integration.

Next Steps

Continue to 09-configuration.md to start shaping Vim to your hands.