vim - replace a word with yanked text multiple times
It is often useful to copy, let’s say new_name, to clipboard and then replace one or more occurrences of old_name with it.
We can use :%s/new_name/old_name/g for that, but sometimes it is more convenient to go over the text and do replacements “manually”.
A possible way to do that in vim is:
- Yank inner word:
yiw(thenew_nameis now in the default register"") - Move cursor to another word (the
old_name) - Select it and paste over:
viwp(viw- visual inner word,p- paste)
What happens next might be unexpected in this scenario: when we pasted over the old_name, it was deleted and put into the default Vim register instead of new_name, so next time we use p, it will paste the old_name (tldr: the xnoremap p pgvy mapping helps fix this).
This behavior is nice when we actually deleted something, for example, if we did dw to delete old_name, we expect to be able to paste it with p, but this is less expected in the case the deletion was implicit, as in the case of the pasting over slection.
At this point, we have a couple of choices to continue pasting new_name:
- Option 1:
gvy(gv- reselect last selection,y- copy) to reselectnew_nameand copy it again and then doviwpon another word - Option 2: use
viw"0pon another word; here"0pwill paste from0register (the default register now containsold_nameand"0register contains the previouslyyankednew_name)
In more detail, what happens during this process is:
- Deleting, changing and yanking text copies the affected text to the unnamed register (
""). - Yanking text also copies the text to register 0 (
"0). - We yank inner word:
yiw(thenew_name), it is now in""and"0 - We move cursor to another word (the
old_name) - We select the
old_nameand paste over:viwp, the deletedold_nameis in""and thenew_nameis still in"0p - Next time we use
p, it pastesold_namesincepuses""register by default (but we can instructpto use the"0register with"0p)
Solution
The solution that works quite well for me is the following mapping
xnoremap p pgvy
As mentioned above, the default Vim behavior is counter-intuitive when we paste over the selection: most of the time we do not need the text we pasted over (so do not want it to get into the default "" register), but the same behavior is useful when we explicitely delete something (dw a word and the paste it somewhere else).
The mapping above only redefines the first case:
xnoremap- map only in visual mode, when we have something selectedp- redefinepbehaviorpgvy-ppast,gvreselect what we’ve just pasted,ycopy back what we’ve just pasted
With this mapping, we can still use Vim’s standard behavior if needed by using gp instead of p (gp is almost the same as p, with cursor left after the pasted text instead of the last char of it).
Another solution that seems simple is to have a xnoremap p "0p that would always use the "0p register when pasting in visual mode (in the example above, we saw that new_name stays in "0p during the whole process). But there is a negative side-effect: when we delete something explicitely, it gets into "", but not into "0p, so we can not then paste it in visual mode. For example, select and copy irrelevant_name with yiw, delete new_name with dw, select old_name and paste with yiwp - the irrelevant_name will be pasted (whie new_name is expected).
One more solution is to use named registeres:
- Yank the
new_nameinto a specific register, for example, thearegister:"ayiw - Move the cursor to the
old_name, select it withviw - Paste the contents of the
aregister over the selected text:"ap
This works, but I need to remember to use the named register before I start the operation and it also requires typing the "a prefix, which is not very convenient.
I recommend the xnoremap p pgvy, it works well and I did not find any drawbacks while using it.
Links
vim.wikia.com Stackoverflow: Paste multiple times

