5 Minutes Vim: Copying, Cutting, Pasting, Registers, and How to Tame Them

vintharas

Jaime González García

Posted on February 1, 2020

5 Minutes Vim: Copying, Cutting, Pasting, Registers, and How to Tame Them

This article was originally posted in barbarianmeetscoding.com. Sorry for the long 5 minutes-ish. 😊

In this 5 minutes of Vim goodness we'll learn how to effectively copy, cut and paste things in Vim by taking advantage of Vim registers and a cool plugin. Here we go!

Copy and paste. Doesn't sound like much excitement, does it? You are probably accustomed to use your mouse to perform some text selection, copy or cut it and then paste it somewhere else. And that is it. Not so much to be excited about.

Vim spices up copying, cutting and pasting in a couple of ways:

  1. It gives you new shiny operators and commands you can use in combination with all the motions you've learn thus far
  2. It provides a handful of registers where you can save stuff for later pasting which can enable interesting workflows

The two main commands for copying and pasting are y and p. Why y and not c for **copy, you may wonder? Well, if you are familiar with Vim you may know that c is already taken, it is the change command. And thus, the vi engineers had to come up with a suitable way to describe copying and settled on the colourful name of yank (because engineers are far more playful than one would think at first sight). So in Vim you don't copy stuff, you yank it (great naming... So visceral). p stands for put and therefore in Vim you yank some text from somwhere and put it some place else. If you're accustomed to think of p in terms of pasting then feel free to use whichever mnemonic makes you happy.

From now on, instead of copy I'll say yank so you get accustomed to it and can easily connect it in your brain and muscle memory to the letter y. Yank! Yank! Yank!

y is an operator. You can combine it with any of the motions and text-objects we've learned to yank stuff to your heart's content:

  • yl yanks a letter,
  • yaw yanks a word,
  • yas yanks a sentence
  • yi( yanks everything within ( and so on...

If you double y as in yy you get a linewise operator like dd and cc and yank a whole line. The Y command also yanks a complete line.

In order to paste things you use the p command and its variants:

  • p pastes something after the cursor
  • P pastes something before the cursor
  • gp same as p but puts the cursor after the pasted selection
  • gP same as P and puts the cursor after the pasted selection

Pasting in Vim is kind of special and the behavior of p and P depend on whether you've yanked characters or lines. If you've yanked characters then pasting will put those characters after or before the cursor (no surprises there). If you've yanked lines, however, pasting will put those lines after or before the line where the cursor is resting on. This behavior may sound weird at first but it makes a lot of sense in practice.

Imagine that you are contemplating this powerful extract from an ancient text:

Hither came Conan, the Cimmerian, black-haired, sullen-eyed, sword in hand, a thief, a reaver, a slayer, with gigantic melancholies and gigantic mirth, to tread the jeweled thrones of the Earth under his sandaled feet.
Enter fullscreen mode Exit fullscreen mode

And you want to add more intensity to this passage you may decide to yank the the particle and sprinkle it here and there:

v
Hither came Conan, the Cimmerian, black-haired, sullen-eyed, ...
Enter fullscreen mode Exit fullscreen mode

Start by jumping to the the particle with f,w:

       v                  v
f,w    Hither came Conan, the Cimmerian, black-haired, ...
Enter fullscreen mode Exit fullscreen mode

Then yank the word with yaw, jump to the next location were to put the with ;w and paste with P:

                         v                 v
;w    Hither came Conan, the Cimmerian, the black-haired, ...
Enter fullscreen mode Exit fullscreen mode

The jump to the next location again with ;w and type . to repeat the last change:

Hither came Conan, the Cimmerian, the black-haired, the sullen-eyed, ...
Enter fullscreen mode Exit fullscreen mode

Want to duplicate a line instead? It is as easy as typing yyp. Imagine that you have an array literal in JavaScript and it's filled with magical items of wonder:

const chest = [
  {name: 'sword', weight: 2.1, state: 'well kept'},
  {name: 'rusty dagger', weight: 0.4, state: 'worn out'},
];
Enter fullscreen mode Exit fullscreen mode

And now you want to add some more items to this chest. You can use any of the existing items as a template and type yyp to duplicate it:

const chest = [
  {name: 'sword', weight: 2.1, state: 'well kept'},
  {name: 'rusty dagger', weight: 0.4, state: 'worn out'},
  {name: 'rusty dagger', weight: 0.4, state: 'worn out'},
];
Enter fullscreen mode Exit fullscreen mode

Then type ci' to change its name to something else:

const chest = [
  {name: 'sword', weight: 2.1, state: 'well kept'},
  {name: 'rusty dagger', weight: 0.4, state: 'worn out'},
  {name: 'scepter of fire', weight: 0.4, state: 'worn out'},
];
Enter fullscreen mode Exit fullscreen mode

Want to n-plicate a line? (Yes, I'm pretty sure that's a real word) It is as simple as typing yy{count}p. Yes! Counts also work with yank and pasting because they're just commands! Let's retry the example above but this time type yy5p:

const chest = [
  {name: 'sword', weight: 2.1, state: 'well kept'},
  {name: 'rusty dagger', weight: 0.4, state: 'worn out'},
  {name: 'rusty dagger', weight: 0.4, state: 'worn out'},
  {name: 'rusty dagger', weight: 0.4, state: 'worn out'},
  {name: 'rusty dagger', weight: 0.4, state: 'worn out'},
  {name: 'rusty dagger', weight: 0.4, state: 'worn out'},
  {name: 'rusty dagger', weight: 0.4, state: 'worn out'},
];
Enter fullscreen mode Exit fullscreen mode

Wow! Impressive, isn't it?

Ok. So if y, the yank command, copies stuff... How do you cut things in Vim? Aha! Here comes a surprise!

Cutting Stuff In Vim

You may be familiar with the d (delete) and c (change) commands in Vim? As their name indicates they let you delete and change text in Vim. A lesser know fact is that, in addition to deleting and changing text, they also cut it.

Imagine that in addition to the chest we had earlier we now have a brave adventurer ready to explore the world and confront its perils. Sadly, our adventurer has little and lacks many of the tools of the adventuring trade she'll need to survive:

const chest = [
  {name: 'sword', weight: 2.1, state: 'well kept'},
  {name: 'rusty dagger', weight: 0.4, state: 'worn out'},
  {name: 'rusty dagger', weight: 0.4, state: 'worn out'},
];

const sonja = {
  name: 'Sonja',
  inventory: [
  ],
};
Enter fullscreen mode Exit fullscreen mode

Let's give her some help and move the well kept sword from the chest into her inventory:

v
const chest = [
  {name: 'sword', weight: 2.1, state: 'well kept'},
  {name: 'rusty dagger', weight: 0.4, state: 'worn out'},
  {name: 'rusty dagger', weight: 0.4, state: 'worn out'},
];
Enter fullscreen mode Exit fullscreen mode

We type 2jdd to jump two lines down and delete (and cut) our sword:

const chest = [
  v
  {name: 'rusty dagger', weight: 0.4, state: 'worn out'},
  {name: 'rusty dagger', weight: 0.4, state: 'worn out'},
];
Enter fullscreen mode Exit fullscreen mode

Then /in<ENTER> to move our cursor on to of the in in inventory:

const sonja = {
  name: 'Sonja',
  v
  inventory: [
  ],
};
Enter fullscreen mode Exit fullscreen mode

And now we type p and we're ready for adventure:

const sonja = {
  name: 'Sonja',
  inventory: [
  v
  {name: 'sword', weight: 2.1, state: 'well kept'},
  ],
};
Enter fullscreen mode Exit fullscreen mode

Now you can save the file and if you have an autoformatter setup it'll fix your indentation or you can type == to manually format that line.

What more can you do with cutting and pasting in Vim? Have you ever made a typo and need to swap two characters? Type dlp (or xp). Want to swap couple of lines? Type ddp. Want to swap a couple of paragraphs? Type dapp.

Excellent! So now you've boosted your knowledge with yanking, cutting and pasting in Vim. But there's yet one crucial element left that we haven't even touched on yet: The mighty registers.

A wonderful way to illustrate the impact of registers is swapping two values within Vim. I do some variant of this task incredibly often.

Imagine that you have a couple of CSS variables that represent a couple of colors in a color theme of a beautiful website you've just designed:

:root {
  --red: #0F0;
  --green: #F00;
}
Enter fullscreen mode Exit fullscreen mode

You quickly notice the colors are wrong. You've mixed them. The red is the green and the green is the red. Oh no! What to do!?

So you try swapping them using what we've just learned. You type /#<Enter> and put the cursor on top of the hexadecimal value:

  --red: #0F0;
         ^
Enter fullscreen mode Exit fullscreen mode

You cut it with daW:

  --red:
       ^
Enter fullscreen mode Exit fullscreen mode

Type n to move to the next hex value, delete it with daW and try to paste the red with p, but...

:root {
  --red:
  --green: #F00;
}
Enter fullscreen mode Exit fullscreen mode

What!? That is so not what I expected to happen. What did I do wrong?

You may have noticed the issue with this swap as you were following the example but if you haven't I will tell you: The problem is that delete also cuts. When we deleted the hexadecimal value for the green color in the last step we literally overwrote the red hexadecimal value. That's why when we typed p at the end the pasted characters where #F00 and not #0F0 as we initially expected.

But what did we overwrite exactly? Most systems have the concept of a clipboard, which is a place where you put the stuff that you copy and cut. Well Vim doesn't have a clipboard, Vim has registers.

Vim Registers

Vim registers are the equivalent of a clipboard, but since you have lots of them, they're that much powerful.

When we use commands like y, d, c and p we're interacting with Vim's unnamed register. You aren't limited to that one though, you have 26 named registers, one for each letter of the alphabet, that you are free to use as you see fit.

The way that you explicitly access a given register is by prefixing a command with "[a-z]. So:

  • "ayy yanks a line into the a register
  • "add cuts a line into the a register
  • "ap pastes from the a register

Using the same pattern we can access the mysterious unnamed register which does have a name after all. Its name is " and you could replace y for ""y if you had a fancy for writing more than you need to. But we won't do that.

Using the lowercase name of a named register overwrites its contents, whereas if we use the capitalized version of that name we will append whatever we yank or cut into the register (this can be really useful when we want to collect text into a register for later pasting).

Using named registers offers one way to solve the problem that ailed us earlier when we were swapping colors. Instead of using the unnamed register alone we could've used it in combination with the a register:

  1. /#<Enter> to move the cursor to the first hex value
  2. daW to cut the green color value in the unnamed register
  3. n to move to the second hex value
  4. "adaW to cut it into the a named register
  5. p pastes the first hex value in the write place
  6. k to go up
  7. "ap which now pastes from the a register and we're done

Excellent! If you ever lose track about which register you have put stuff in, you can rely on the :registers (or :reg) command. :registers will print the value of all registers into a buffer. If you're only interested in the contents of a particular register you can also specify it as an argument. For instance, typing :reg a after the previous example would result in the following:

--- Registers ---
"a    #F00;
Enter fullscreen mode Exit fullscreen mode

Another useful way to interact with named registers is by taking advantage of the fact that capitalized named registers append to the register instead of replacing its contents. For instance, we could build an outline of a markdown document by continously appending headers to the a register:

  • /^#.*<ENTER> to jump to the next header
  • "ayy to copy the header into the a register
  • n to jump to the next header
  • "Ayy to append the header to the contents of the a register
  • then n and "Ayy until you've gathered all the headers you want
  • "ap to paste the outline of the mardown document

In addition to the named and unnamed registers there are more registers that will be useful from time to time: The yank register (0), the delete registers (1-9) and the black hole register (_).

The yank register 0 holds the last bit of text you yanked. That is, it only stores text you have yanked with the y command and lives completely unperturbed by whatever happens with cutting operations like d or c. This can be really useful if you want to rename a variable or other pieces of text. Using the yank register offers yet another alternative way to swap values.

The delete registers 1-9 are nine registers that contain the last 9 pieces of text you cut or deleted. They work as a queue where every time you cut something it gets stuck in the queue at position 1, whatever was in 1 is pushed to 2 and so on. The delete register can be really useful when you happen to delete something in the past and you want to bring it back (in fact, it just saved me from losing a beautifully written parapraph). Just like the named and yank registers, you can take advantage of delete registers as an alternative way to swap values.

The black hole register has a fitting name because it truly allows you to delete text into oblivion. A nice way to avoid overwriting the unnamed register is to prefix the delete operator with the black hole register: For instance, type "_daw to blast a word into oblivion for ever and ever.

For a list of all registers available in Vim and how you can use them take a look at :h registers.

Copy and Pasting In and Outside Of Vim

Everything we've discussed thus far only applies to the world of Vim. All the commands and registers that we've seen allow you to yank, cut and paste text only within the confines of Vim. What happens when you want to copy to or paste from outside of Vim? For instance, when you find a wonderful piece of code on StackOverflow and want to try it in a program?

There's two registers that work as an interface between Vim and the outside world: The + and the * registers.

  • You can use the + register to interact with the system clipboard in Windows, Mac and Linux
  • You can use the * register to interact with the primary clipboard in Linux, and also the system clipboard in Windows and Mac (since these two only have the single clipboard)

One thing that I find super convenient and that I'd advise you to do is to have your system clipboard use the unnamed register. That way you can seamlessly copy and paste between Vim and the rest of your computer, taking advantage of the fastest commands d, c, y and p, and avoiding the need to specify the + and * registers.

If you are using Neovim you can enable this behavior in your vimrc like so:

set clipboard+=unnamedplus " use system clipboard
Enter fullscreen mode Exit fullscreen mode

Likewise in traditional Vim:

set clipboard=unnamed " use system clipboard
Enter fullscreen mode Exit fullscreen mode

Take a look at :h clipboard for more information.

Pasting in Insert mode

All of this article has focused on how you can copy and paste things from within Normal mode. Sometimes however, it can be helpful to paste things within Insert mode. Earlier you learned how you can paste using the p command but that won't do in Insert mode (it would just insert the letter p). What to do? Well, in some instances (f.i. gvim and mvim) you may be able to use your system copy/paste key bindings, but you can always rely on <C-R>{register} to paste text from any given register:

  • <C-R>a pastes the contents of the a register
  • <C-R>" pastes the contents of the unnamed register
  • <C-R>0 pastes the contents of the yank register.

And yes, you've guessed it right, the R stands for Register. Use that as a mnemnonic and you'll never forget how to paste things in Insert mode.

A Really Cool Plugin To Simplify Working With Registers in Vim

Before we part here is a really cool plugin that helps you work with register in Vim: vim-peekaboo. This plugin extends " and @ in normal mode and <CTRL-R> in insert mode so you can see the contents of the registers as you are about to perform a copying, cutting or pasting operation:

A Vim user takes advantage of the peekaboo plugin to inspect what's inside their registers before pasting

Cool right?

And that's all for today! Take care and have a wonderful day!

💖 💪 🙅 🚩
vintharas
Jaime González García

Posted on February 1, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related