ChatGPT解决这个技术问题 Extra ChatGPT

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

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?

vim-easyclip (github.com/svermeulen/vim-easyclip) is designed to address this exact problem
I asked a question, unknowingly (at the time) duplicate of your actual problem, but not so much of the title question. TL;DR - replace with what you yanked using viwp (for word).

i
ib.

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.


At first I thought this command was not working properly. Then I realized I was using a "dead keys" version of the american keyboard. With this keyboard layout I have to type "<space>_d. The space is needed to actually type the ".
Any ideas on doing this selectively on only empty lines? (If I dd on an empty line it goes into the blackhole, otherwise it dds like normal).
To remove one character, try: "_x
This is one area where a standard text editor wins. You simply press the delete key.
You can also yank something with yy or '3yy' (or whatever), which puts it in the unnamed register, but also in 0. You can then keep pasting it with "0p, despite having used d after that.
O
Olivier Verdier

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


If you select lines with you delete them with just d, not dd
1 to 9 works for deletions. To paste last thing really yanked (with 'y') you have to use "0p. That's useful in cases where you first yanks something intending to replace something else, but then the something else overwrites the default paste register.
For more undo sophistication check out the Gundo (graphical undo) script.
@RafaeldeF.Ferreira: Your comment isn't an answer to this question, but it actually solves probably the actual problem that led the OP to ask the question in the first place. For me, that was the real problem.
w
wisbucky

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


E
Eric Duminil

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 a more advanced version, check: stackoverflow.com/questions/290465/…
I'd like to use vmap <C-P> "_dP
You can just put the text without deleting the selection. For example Vp replaces your current line with the yanked one right away.
This solution doesn't fix issue with d that is being often used for deletion.
M
Magnus

I put the following in my vimrc:

noremap  y "*y
noremap  Y "*Y
noremap  p "*p
noremap  P "*P
vnoremap y "*y
vnoremap Y "*Y
vnoremap p "*p
vnoremap P "*P

Now I yank to and put from the clipboard register, and don't have to care what happens with the default register. An added benefit is that I can paste from other apps with minimal hassle. I'm losing some functionality, I know (I am no longer able to manage different copied information for the clipboard register and the default register), but I just can't keep track of more than one register/clipboard anyway.


Instead of all those remaps, you could also set clipboard=unnamed or set clipboard=unnamedplus, which changes the default clipboard to * or +, respectively.
@Steve If you do that, then d will overwrite the last yank to the clipboard register also, which is what the question is trying to avoid.
@79E09796, I didn't mean to imply that it would; I was commenting on this answer and not the original question.
I put these in my .vimrc and now yanking does not work. Any idea why?
@tba replace noremap with nnoremap (two n's) and it should work fine.
W
Wayne

All yank and delete operations write to the unnamed register by default. However, the most recent yank and most recent delete are always stored (separately) in the numbered registers. The register 0 holds the most recent yank. The registers 1-9 hold the 9 most recent deletes (with 1 being the most recent).

In other words, a delete overwrites the most recent yank in the unnamed register, but it's still there in the 0 register. The blackhole-register trick ("_dd) mentioned in the other answers works because it prevents overwriting the unnamed register, but it's not necessary.

You reference a register using double quotes, so pasting the most recently yanked text can be done like this:

"0p

This is an excellent reference:

http://blog.sanctum.geek.nz/advanced-vim-registers/


E
EBGreen

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)

This works well except when you want to paste over multiple selections.
C
Community

To emphasize what EBGreen said:

If you paste while selecting text, the selected text is replaced with the pasted text.

If you want to copy some text and then paste it in multiple locations, use "0p to paste. Numbered register 0 contains the text from the most recent yank command.

Also, you can list the contents of all of your registers:

:registers

That command makes it easier to figure out what register you want when doing something like dbr's answer. You'll also see the /,%,# registers. (See also :help registers)

And finally, check out cW and cW to change a word including and not including an trailing space. (Using capital W includes punctuation.)


m
maeghith

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.


S
Swaroop C H

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

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


For 'replace up to next paragraph', try c} in normal mode.
Why "cap" does this? Isn't "a" and "p" stand for "append" and "paste"?
@WiSaGaN "ap" stands for "a paragraph" : vimhelp.appspot.com/motion.txt.html#object-select
T
Torben

A minimal invasive solution for the lazy ones:

Register 0 always contains the last yank (as Rafael, alex2k8 and idbrii have already mentioned). Unfortunately selecting register 0 all the time can be quite annoying, so it would be nice if p uses "0 by default. This can be achieved by putting the following lines into your .vimrc:

noremap p "0p
noremap P "0P
for s:i in ['"','*','+','-','.',':','%','/','=','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
    execute 'noremap "'.s:i.'p "'.s:i.'p'
    execute 'noremap "'.s:i.'P "'.s:i.'P'
endfor

The first line maps each p stroke to "0p. However, this prevents p from accessing any other registers. Therefore all p strokes with an explicitly selected register are mapped to the equivalent commandline expression within the for-loop. The same is done for P.

This way the standard behaviour is preserved, except for the implicit p and P strokes, which now use register 0 by default.

Hint 1: The cut command is now "0d instead of just d. But since I'm lazy this is way too long for me ;) Therefore I'm using the following mapping:

noremap <LEADER>d "0d
noremap <LEADER>D "0D

The leader key is \ by default, so you can easily cut text by typing \d or \D.

Hint 2: The default timeout for multi-key mappings is pretty short. You might want to increase it to have more time when selecting a register. See :help timeoutlen for details, I'm using:

set timeout timeoutlen=3000 ttimeoutlen=100

E
EBGreen

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.


["x]d{motion} Delete text that {motion} moves over [into register x] -- Vim :h d
V
Victoria Stuart

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.


g
gregory

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.


Great solution. Slightly more intuitive paste mappings for me are nnoremap dp "dp and nnoremap dP "dP.
This is great. Love it.
佚名

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


but deleting any significant amount of text in default mode is SLOW
e
expelledboy

The two solutions I use in the right contexts are;

highlight what you want to replace using Vims VISUAL mode then paste the register.

I use this mostly out of habit as I only found the second solution much later, eg

yiw   " yank the whole word
viwp  " replace any word with the default register

YankRing. With this plugin you can use the keybinding +

to replace the previous numbered register with the one you just pasted.

Basically you go about pasting as you would, but when you realise that you have since overwritten the default register thus losing what you actually wanted to paste you can <C-P> to find and replace from the YankRing history!

One of those must have plugins...


H
Hieu Nguyen

I found a very useful mapping for your purpose:

xnoremap p "_dP

Deleted text is put in "black hole register", and the yanked text remains.

Source: http://vim.wikia.com/wiki/Replace_a_word_with_yanked_text


J
JayG

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.


C
Clueless

I often make a mistake when following the commands to 'y'ank then '"_d'elete into a black hole then 'p'aste. I prefer to 'y'ank, then delete however I like, then '"0p' from the 0 register, which is where the last copied text gets pushed to.


V
Vic Goldfeld

For Dvorak users, one very convenient method is to just delete unneeded text into the "1 register instead of the "_ black hole register, if only because you can press " + 1 with the same shift press and a swift pinky motion since 1 is the key immediately above " in Dvorak (PLUS d is in the other hand, which makes the whole command fast as hell).

Then of course, the "1 register could be used for other things because of it's convenience, but unless you have a purpose more common than replacing text I'd say it's a pretty good use of the register.


A
Adrien Vakili

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.


E
Ed Kolosovsky

For those who use JetBrans IDE (PhpStorm, WebStorm, IntelliJ IDEA) with IdeaVim. You may be experiencing problems with remapping like nnoremap d "_d and using it to delete a line dd. Possible solution for you: nnoremap dd "_dd

There are issues on youtrack, please vote for them: https://youtrack.jetbrains.com/issue/VIM-1189 https://youtrack.jetbrains.com/issue/VIM-1363


Thank you very much for taking the time to post this reply. I have looked everywhere in the world to fix this issue with IdeaVim.
s
snap

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


C
Community

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.


I already knew about viw, but never realized about : ciw diw yiw
m
mohammadreza berneti

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" ]
        }
    ]
}

s
sebtheiler

You can make a simple macro with: q"_dwq

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


Z
ZhiyuanLck

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.


J
Jacob Vanus

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.


Z
Zaid Gharaybeh

noremap mm m

and

noremap mx "_x

is how I deal with it.