Advanced Vim registers

Registers in Vim are best thought of as scratch spaces for text, some of which are automatically filled by the editor in response to certain actions. Learning how to use registers fluently has a lot of subtle benefits, although it takes some getting used to because the syntax for using them is a little awkward.

If you’re reasonably fluent with Vim by now, it’s likely you’re already familiar with the basic usage of the 26 named registers, corresponding to the letters of the alphabet. These are commonly used for recording macros; for example, to record a series of keystrokes into register a, you might start recording with qa, and finish with q; your keystrokes could then be executed with @a.

Similarly, we can store text from the buffer itself rather than commands in these registers, by prepending "a to any command which uses a register, such as the c, d, and y commands:

  • "ayy — Read current line into register a.
  • "bP — Paste contents of register b above current line.
  • "cc3w — Change three words, putting the previous three words into register c.

Like many things in Vim, there’s a great deal more functionality to registers for those willing to explore.

Note that here I’ll be specifically ignoring the *, +, and ~ registers; that’s another post about the generally unpleasant business of making Vim play nice with system clipboards. Instead, I’ll be focussing on stuff that only applies within a Vim session. All of this is documented in :help registers.

Capital registers

Yanking and deleting text into registers normally replaces the previous contents of that register. In some cases it would be preferable to append to a register, for example while cherry-picking different lines from the file to be pasted elsewhere. This can be done by simply capitalizing the name of the register as it’s referenced:

  • "ayyReplace the contents of register a with the current line.
  • "AyyAppend the current line to register a.

This works for any context in which an alphabetical register can be used. Similarly, to append to a macro already recorded in register a, we can start recording with qA to add more keystrokes to it.

Viewing register contents

A good way to start getting a feel for how all the other registers work is to view a list of them with their contents during an editing session with :registers. This will show the contents of any register used in the editing session. It might look something like this, a little inscrutable at first:

--- Registers ---
""   Note that much of it includes
"0   execut
"1   ^J^J
"2   16 Oct (2 days ago)^J^Jto Jeff, Alan ^JHi Jeff (cc Alan);^J^JPlease 
"3   <?php^Jheader("Content-Type: text/plain; charset=utf-8");^J?>^J.^J
"4   ^J
"5   Business-+InternationalTrade-TelegraphicTransfers-ReceivingInternati
"6   ../^J
"7       diff = auto^J    status = auto^J    branch = auto^J    interacti
"8   ^J[color]^J    ui = auto^J    diff = auto^J    status = auto^J    br
"9       ui = true^J
"a    escrow
"b   03wdei^R=2012-^R"^M^[0j
"c   a
"e   dui{<80>kb^[^[
"g   ^[gqqJgqqjkV>JgqqJV>^[Gkkkjo^[I[4]: ^[k
"h   ^[^Wh:w^Mgg:w^M^L:w^Mjk/src^Mllhh
"j   jjjkkkA Goo<80>kb<80>kb<80>kbThis one is good pio<80>kbped through a
"-   Note that much of it includes
".    OIt<80>kb<80>kb<80>kbIt might looks <80>kb<80>kb something like thi
":   register
"%   advanced-vim-registers.markdown
"/   Frij

The first column contains the name of the register, and the second its contents. The contents of any of these registers can be pasted into the buffer with "ap, where a is the name of any of them. Note that there are considerably more registers than just the named alphabetical ones mentioned above.

Unnamed register

The unnamed register is special in that it’s always written to in operations, no matter whether you specified another register or not. Thus if you delete a line with dd, the line’s contents are put into the unnamed register; if you delete it with "add, the line’s contents are put into both the unnamed register and into register a.

If you need to explicitly reference the contents of this register, you can use ", meaning you’d reference it by tapping " twice: "". One handy application for this is that you can yank text into the unnamed register and execute it directly as a macro with @".

Man, and you thought Perl looked like line noise.

Black hole register

Another simple register worth mentioning is the black hole register, referenced with "_. This register is special in that everything written to it is discarded. It’s the /dev/null of the Vim world; you can put your all into it, and it’ll never give anything back. A pretty toxic relationship.

This may not seem immediately useful, but it does come in handy when running an operation that you don’t want to clobber the existing contents of the unnamed register. For example, if you deleted three lines into the unnamed register with 3dd with the intent of pasting them elsewhere with p, but you wanted to delete another line before doing so, you could do that with "_dd; line gone, and no harm done.

Numbered registers

The read-only registers 0 through 9 are your “historical record” registers. The register 0 will always contain the most recently yanked text, but never deleted text; this is handy for performing a yank operation, at least one delete operation, and then pasting the text originally yanked with "0p.

The registers 1 through 9 are for deleted text, with "1 referencing the most recently deleted text, "2 the text deleted before that, and so on up to "9.

The small delete register

This read-only register, referenced by "-, stores any text that you deleted or changed that was less than one line in length, unless you specifically did so into some other named register. So if you just deleted three characters with 3x, you’ll find it in here.

Last inserted text register

The read-only register ". contains the text that you last inserted. Don’t make the mistake of using this to repeat an insert operation, though; just tap . for that after you leave insert mode, or have the foresight to prepend a number to your insert operation; for example, 6i.

Filename registers

The read-only register "% contains the name of the current buffer’s file. Similarly, the "# register contains the name of the alternate buffer’s file.

Command registers

The read-only register ": contains the most recently executed : command, such as :w or :help. This is likely only of interest to you if you’re wanting to paste your most recent command into your Vim buffer. For everything else, such as repeating or editing previous commands, you will almost certainly want to use the command window.

Search registers

The read-only register / contains the most recent search pattern; this can be handy for inserting the search pattern on the command line, by pressing Ctrl-R and then / — very useful for performing substitutions using the last search pattern.

Expression register

Here’s the black sheep of the bunch. The expression register = is used to treat the results of arbitrary expressions in register context. What that means in actual real words is that you can use it as a calculator, and the result is returned from the register.

Whenever the expression register is referenced, the cursor is put on the command line to input an expression, such as 2+2, which is ended with a carriage return.

This means in normal mode you can type "=2+2<Enter>p, and 4 will be placed after the cursor; in insert or command mode you can use Ctrl-R then =2+2<Enter> for the same result. If you don’t find this syntax as impossibly awkward as I do, then this may well suit you for quick inline calculations … personally, I’d drop to a shell and bust out bc for this.

Knowing your registers well isn’t as profound a productivity boost as squelching a few of the other Vim anti-patterns, but it can certainly save you some of the annoyance of lost text.