In Vim is there a way to delete without putting text in the register?

Viewed 84532

Using Vim I often want to replace a block of code with a block that I just yanked.

But when I delete the block of code that is to be replaced, that block itself goes into the register which erases the block I just yanked. So I've got in the habit of yanking, then inserting, then deleting what I didn't want, but with large blocks of code this gets messy trying to keep the inserted block and the block to delete separate.

So what is the slickest and quickest way to replace text in Vim?

  • is there a way to delete text without putting it into the register?
  • is there a way to say e.g. "replace next word" or "replace up to next paragraph"
  • or is the best way to somehow use the multi-register feature?
29 Answers

To delete something without saving it in a register, you can use the "black hole register":

"_d

Of course you could also use any of the other registers that don't hold anything you are interested in.

Yep. It's slightly more convoluted than deleting the "old" text first, but:

I start off with..

line1
line2
line3
line4

old1
old2
old3
old4

I shift+v select the line1, line 2, 3 and 4, and delete them with the d command

Then I delete the old 1-4 lines the same way.

Then, do

"2p

That'll paste the second-last yanked lines (line 1-4). "3p will do the third-from-last, and so on..

So I end up with

line1
line2
line3
line4

Reference: Vim documentation on numbered register

VIM docs: Numbered register 0 contains the text from the most recent yank command, unless the command specified another register with ["x].

E.g. we yank "foo" and delete "bar" - the registry 0 still contains "foo"! Hence "foo" can be pasted using "0p

It's handy to have an easy mapping which lets you replace the current selection with buffer.

For example when you put this in your .vimrc

" it's a capital 'p' at the end
vmap r "_dP

then, after copying something into register (i.e. with 'y'), you can just select the text which you want to be replaced, and simply hit 'r' on your keyboard. The selection will be substituted with your current register.

Explanation:

vmap - mapping for visual mode
"_d - delete current selection into "black hole register"
P - paste

For the specific example that you gave, if I understand the question then this might work:

*Highlight what you want to put somewhere else
*delete (d)
*Highlight the code that you want it to replace
*paste (p)

If you're using Vim then you'll have the visual mode, which is like selecting, but with the separating modes thing that's the basis of vi/vim.

What you want to do is use visual mode to select the source, then yank, then use visual mode again to select the scope of the destination, and then paste to text from the default buffer.

Example:

In a text file with:

1| qwer
2| asdf
3| zxcv
4| poiu

with the following sequence: ggVjyGVkp you'll end with:

1| qwer
2| asdf
3| qewr
4| asdf

Explained:

  • gg: go to first line
  • V: start visual mode with whole lines
  • j: go down one line (with the selection started on the previous lines this grows the selection one line down)
  • y: yank to the default buffer (the two selected lines, and it automatically exits you from visual mode)
  • G: go to the last line
  • V: start visual mode (same as before)
  • k: go up one line (as before, with the visual mode enabled, this grows the selection one line up)
  • p: paste (with the selection on the two last lines, it will replace those lines with whatever there is in the buffer -- the 2 first lines in this case)

This has the little inconvenient that puts the last block on the buffer, so it's somehow not desired for repeated pastings of the same thing, so you'll want to save the source to a named buffer with something like "ay (to a buffer called "a") and paste with something like "ap (but then if you're programming, you probably don't want to paste several times but to create a function and call it, right? RIGHT?).

If you are only using vi, then youll have to use invisible marks instead the visual mode, :he mark for more on this, I'm sorry but I'm not very good with this invisible marks thing, I'm pretty contaminated with visual mode.

For 'replace word', try cw in normal mode.

For 'replace paragraph', try cap in normal mode.

Well, first do this command:

:h d

Then you will realize that you can delete into a specific register. That way you won't alter what is in your default register.

My situation: in Normal mode, when I delete characters using the x keypress, those deletions overwrite my latest register -- complicating edits where I want to delete characters using x and paste something I have in my most recent register (e.g. pasting the same text at two or more places).

I tried the suggestion in the accepted answer ("_d), but it did not work.

However, from the accepted answer/comments at https://vi.stackexchange.com/questions/122/performing-certain-operations-without-clearing-register, I added this to my ~/.vimrc, which works (you may have to restart Vim):

nnoremap x "_x

That is, I can now do my normal yank (y), delete (d), and paste (p) commands -- and characters I delete using x no longer populate the most recent registers.

Vim's occasional preference for complexity over practicality burdens the user with applying registers to copy/delete actions -- when more often than not, one just wants paste what was copied and "forget" what was deleted.

However, instead of fighting vim's complicated registers, make them more convenient: choose a "default" register to store your latest delete. For example, send deletes to the d register (leaving a-c open for ad-hoc usage; d is a nice mnemonic):

nnoremap d "dd           "send latest delete to d register
nnoremap D "dD           "send latest delete to d register 
nnoremap dd "ddd         "send latest delete to d register
nnoremap x "_x           "send char deletes to black hole, not worth saving
nnoremap <leader>p "dp   "paste what was deleted
nnoremap <leader>P "dP   "paste what was deleted

This approach prevents deletes from clobbering yanks BUT doesn't forfeit registering the delete -- one can paste (back) what was deleted instead of losing it in a black hole (as in the accepted answer). In the example above, this recalling is done with two leader p mappings. A benefit of this approach, is that it gives you the ability to choose what to paste: (a) what was just yanked, or (b) what was just deleted.

Text deleted, while in insert mode, doesn't go into default register.

In the windows version (probably in Linux also), you can yank into the system's copy/paste buffer using "*y (i.e. preceding your yank command with double-quotes and asterisk).

You can then delete the replaceable lines normally and paste the copied text using "*p.

For emacs-evil users, the function (evil-paste-pop) can be triggered after pasting, and cycles through previous entries in the kill-ring. Assuming you bound it to <C-p> (default in Spacemacs), you would hit p followed by as many <C-p> as needed.

The following vscode setting should allow e.g. dd and dw to become "_dd and "_dw, which work correctly now with our remapper.

{
     "vim.normalModeKeyBindingsNonRecursive": [
        {
            "before": ["d"],
            "after": [ "\"", "_", "d" ]
        }
    ]
}

For those of you who are primary interested of not overwriting the unnamed register when you replace a text via virtual selection and paste.

You could use the following solution which is easy and works best for me:

xnoremap <expr> p 'pgv"'.v:register.'y'

It's from the answers (and comments) here: How to paste over without overwriting register

It past the selection first, then the selection with the new text is selected again (gv). Now the register which was last used in visual mode (normally the unnamed register but works also side effect free if you use another register for pasting). And then yank the new value to the register again.

PS: If you need a simpler variant which works also with intellj idea plugin vim-simulation you can take this one (downside: overwrite unnamed register even if another register was given for pasting):

vnoremap p pgvy

register 0 thru 9 are the latest things you yank or cut etc, and DO NOT include deleted things etc. So if you yank/cut something, it is in register 0 also, even if you say deleted stuff all day after that, register 0 is still the last stuff you yanked/cut.

yiw #goes to both default register, and register 0

it yanks the word the cursor is in

deleted stuff etc will go to default register, but NOT register 0

in standard mode:

"0p #put the content of register 0

in insert mode:

ctrl-r 0 #put the content of register 0

I also had a friend who always yanked/cut to register x lol.

You can make a simple macro with: q"_dwq

Now to delete the next word without overwriting the register, you can use @d

The main problem is to use p when in visual mode. Following function will recover the content of unnamed register after you paste something in visual mode.

 function! MyPaste(ex)
  let save_reg = @"
  let reg = v:register
  let l:count = v:count1
  let save_map = maparg('_', 'v', 0, 1)
  exec 'vnoremap _ '.a:ex
  exec 'normal gv"'.reg.l:count.'_'
  call mapset('v', 0, save_map)
  let @" = save_reg
endfunction

vmap p :<c-u>call MyPaste('p')<cr>
vmap P :<c-u>call MyPaste('P')<cr>

Usage is the same as before and the content of register " is not changed.

I find it easier to yank into the 'p' buffer to begin with.

Copy (aka: yank)

# highlight text you want to copy, then:
"py

Paste

# delete or highlight the text you want to replace, then:
"pp

Pros (As opposed to deleting into a specific register):

  • "pp is easy on the fingers
  • Not going to accidentally overwrite your paste buffer on delete.

noremap mm m

and

noremap mx "_x

is how I deal with it.

Related