142

Does anyone know of a way to paste over a visually selected area without having the selection placed in the default register?

I know I can solve the problem by always pasting from an explicit register. But it's a pain in the neck to type "xp instead of just p

Justin Johnson
  • 30,978
  • 7
  • 65
  • 89
Starr Horne
  • 1,503
  • 2
  • 11
  • 8

15 Answers15

50

Use the following:

xnoremap p pgvy

this will reselect and re-yank any text that is pasted in visual mode.

Edit: in order this to work with "xp you can do:

xnoremap p pgv"@=v:register.'y'<cr>

v:register expands to the last register name used in a normal mode command.

Benoit
  • 76,634
  • 23
  • 210
  • 236
  • On a `"xp`, this approach overwrites `@"` with `@x`. – Luc Hermitte Feb 24 '11 at 16:44
  • 3
    Your suggestion of `xnoremap p pgv"@=v:register.'y'` didn't work for me. This, however, does: `xnoremap p 'pgv"'.v:register.'y'` – mrak Mar 07 '13 at 08:39
  • This looks interesting. Could you add a line about what `g` does? I've not seen it before. – LondonRob Jul 14 '15 at 16:41
  • 4
    @LondonRob: `g` alone does nothing. It provides extended, multi-key commands, like `z`. For example, `go` goes to nth byte in buffer, `gj` and `gk` go to next and previous displayed line (differ from `jk` when lines are wrapped), `ga` displays information on character under the cursor, `gJ` joins lines without space, and here `gv` restores last visual selection. You can use `:help gv`. – Benoit Jul 16 '15 at 06:42
  • 13
    @mark ``:xnoremap p 'pgv"'.v:register.'y`>' ``, I added `` `>`` To restore the cursor position – rox Feb 10 '17 at 02:40
  • Thanks @LondonRob for the great explanation of what the hell the `gv` in `pgvy` does. I've seen this solution before and used it but hadn't quite realized what it was doing. – Ogre Codes Oct 21 '19 at 19:03
  • Almost do it, but using Ctrl+V (for column selection) only works first time. On a second Ctrl+V it only replaces on first line and remove other lines selection – albfan Mar 13 '22 at 11:37
  • Without remap all that needs to be remembered is pressing `gvy` after pasting. – Martin Braun Apr 19 '22 at 02:03
44

I don't like the default vim behavior of copying all text deleted with d, D, c, or C into the default register.

I've gotten around it by mapping d to "_d, c to "_c, and so on.

From my .vimrc:

"These are to cancel the default behavior of d, D, c, C
"  to put the text they delete in the default register.
"  Note that this means e.g. "ad won't copy the text into
"  register a anymore.  You have to explicitly yank it.
nnoremap d "_d
vnoremap d "_d
nnoremap D "_D
vnoremap D "_D
nnoremap c "_c
vnoremap c "_c
nnoremap C "_C
vnoremap C "_C
Jeff Lake
  • 1,769
  • 2
  • 13
  • 9
  • 8
    As useful as these mappings are (I do something similar myself), they do not answer OP's question, p will still overwrite what you yanked pasting over selected content. – Magnus Aug 03 '20 at 23:58
36

"{register}p won't work as you describe. It will replace the selection with the content of the register. You will have instead to do something like:

" I haven't found how to hide this function (yet)
function! RestoreRegister()
  let @" = s:restore_reg
  return ''
endfunction

function! s:Repl()
    let s:restore_reg = @"
    return "p@=RestoreRegister()\<cr>"
endfunction

" NB: this supports "rp that replaces the selection by the contents of @r
vnoremap <silent> <expr> p <sid>Repl()

Which should be fine as long as you don't use a plugin that has a non-nore vmap to p, and that expects a register to be overwritten.

This code is available as a script there. Ingo Karkat also defined a plugin solving the same issue.

Luc Hermitte
  • 31,979
  • 7
  • 69
  • 83
  • Actually, I though there was a neat way to fetch the register used, but couldn't remember how. Hence the complexity of the function. – Luc Hermitte Nov 14 '08 at 17:23
  • 1
    I think that this is overkill, won't remember the `regtype` (linewise?) and that remapping p to `pgvy` is sufficient. – Benoit Feb 23 '11 at 15:59
  • 2
    It may be overkill, but it has no side effect. On a `"xp`, this does not overwrite `@"` contents with `@x` unlike `pgvy` – Luc Hermitte Feb 24 '11 at 16:43
  • 1
    then what about `:xnoremap p pgv@=v:register.'y'` ? – Benoit Feb 24 '11 at 17:42
  • 1
    It doesn't work for me. I've also tried downloading the script. Here's the list of commands I do: First I press v, then e to to select to the end of the word, then y to yank it. After that, I go to a different word that I want to replace. I press v, e then p to replace that one. Then I do it again, but this time the next word is replaced by the one I replaced earlier. – Eddy Feb 19 '12 at 14:05
  • Eddy, what does `:verbose vmap p` and `:verbose vmap x` tell you ? BTW, have you checked this patch http://stackoverflow.com/a/4446608/15934 ? – Luc Hermitte Feb 20 '12 at 08:48
  • Thanks, I fixed it by applying danprice's patch to the repl-visual-no-reg-overwrite.vim plugin – Eddy Mar 27 '12 at 13:35
26

In your .vimrc

xnoremap p "_dP

I found this from a response on a similar thread, but the original source was http://vim.wikia.com/wiki/Replace_a_word_with_yanked_text. It mentions some drawbacks, however it works fine for me.

Jason Denney
  • 3,191
  • 1
  • 18
  • 14
14

Use P to paste without yanking the deleted text.

:help v_P

With P the unnamed register is not changed (and neither the selection or clipboard), you can repeat the same change.

This behavior was introduced in v8.2.4242 (2022-01-28) and refined in v8.2.4881 (2022-05-06).

Or if your muscle memory is too strong:

xnoremap p P
Steve Ward
  • 486
  • 4
  • 11
  • I just tested it a little and it appears to work. This is the type of much-less-intrusive solution I was looking for. I have to remote into too many machines to have to carry around a bunch of keymaps. – Mark Stouffer Jan 07 '23 at 01:43
6

Luc Hermitte's solution works like a charm. I was using it for about a week or so. Then I discovered a solution from Steve Losh's .vimrc that works nicely if YankRing is part of your plugin/bundle lineup:

function! YRRunAfterMaps()                                                                                                      
    " From Steve Losh, Preserve the yank post selection/put.    
    vnoremap p :<c-u>YRPaste 'p', 'v'<cr>gv:YRYankRange 'v'<cr> 
endfunction  
Taine
  • 61
  • 1
  • 2
6

Try this in your ~/.vimrc:

xnoremap <expr> p 'pgv"'.v:register.'y'
  • xnoremap means that this is only for Visual mode, not Visual + Select modes.

  • <expr> means that {rhs} of the xnoremap {lhs} {rhs} setting is evaluated as an expression.

  • In this case, our expression of 'pgv"'.v:register.'y' is using . for concatenation.

  • v:register is evaluated to the register being used during the fulfillment of the mapping.

The result of "xp would evaluate to pgv"xy, where x is the register.

I was helped by an answer to this stackoverflow question: Vim - mapping with an optional register prefix in conjunction with Benoit's answer on this page

Community
  • 1
  • 1
mrak
  • 494
  • 5
  • 10
5

Luc's function worked well for me after I made a change to support the fact that I have clipboard=unnamed set:

function! RestoreRegister()
    let @" = s:restore_reg
    if &clipboard == "unnamed"
        let @* = s:restore_reg
    endif
    return ''
endfunction
danprice
  • 1,184
  • 1
  • 7
  • 3
2

Luc Hermitte's did the trick! Really good. Here's his solution put in a toggle function, so you can switch between normal behavior and no-replace-register put.

the command ,u toggles the behavior

let s:putSwap = 1 
function TogglePutSwap()
    if s:putSwap
        vnoremap <silent> <expr> p <sid>Repl()
        let s:putSwap = 0 
        echo 'noreplace put'
    else
        vnoremap <silent> <expr> p p 
        let s:putSwap = 1 
        echo 'replace put'
    endif
    return
endfunction
noremap ,p :call TogglePutSwap()<cr>
Joernsn
  • 2,319
  • 4
  • 25
  • 33
1

This is my solution.

vnoremap p p:let @+=@0<CR>

vnoremap P P:let @+=@0<CR>

I find out after paste, the old content is still stored in "0 register. Just restore it to current clipboard by

:let @+=@0
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Xin Wang
  • 11
  • 1
0

duct-tape programming, but works for me:

nmap viwp viwpyiw
nmap vi'p vi'pyi'
nmap vi"p vi"pyi"
nmap vi(p vi(pyi(
nmap vi[p vi[pyi[
nmap vi<p vi<pyi<
steven_noble
  • 4,133
  • 10
  • 44
  • 77
0

Select the text and paste by P(uppercase).

Example:

viwP

See h: v_P for more infomation.

Cyrus Yip
  • 479
  • 5
  • 9
0

map "<leader>p" to '"_d<Left>p' for visual mode.

this will allow you to highlight the text you want to paste over, hit <leader>p and paste the text from the current buffer over it - without copying the highlighted text to your register. Meaning the previous text stays in your "" register.

tjex
  • 163
  • 3
  • 10
0

I've answered here how not to copy deletions in unnamed+ register (or, in fact, overwrite register back to last yank). In the same way you can do when pasting with that autocommand:

vim.cmd([[
  augroup SyncUnnamedRegister
    autocmd!
      autocmd TextYankPost * if v:event.visual || v:event.operator == 'd' | let @+ = @0 |  endif
  augroup END
]])
Dipod
  • 11
  • 2
-4

try -

:set guioptions-=a
:set guioptions-=A
Gowri
  • 1,323
  • 9
  • 11
  • 3
    Those control whether selected text is added to the windowing system's clipboard (e.g., X11 or Win32), not to Vim's internal copy registers. – Rob Kennedy Nov 14 '08 at 16:32