1

How do I replace a visual selection with some register content without overwriting the unnamed ("") register by the visual selection?

The question

https://stackoverflow.com/questions/3837772/vim-replace-selection-with-default-buffer-without-overwriting-the-buffer

is basically the same, however the answer xnoremap p "_dP provided there doesn't work properly if applied to a selection that includes the last character of the line (not even the end of line character $). Furthermore, with this solution, the paste register is hardcoded (to the unnamed one).

I found a partial solution using c, namely "_c<C-R>"<Esc>. This still has the problem that the paste register is hard coded. Furthermore, I don't know how to use this in a vimscript function.

(My main goal is to write a command that takes a motion and then replaces everything between the current cursor position to the motion target by a given register. I currently have this:

noremap s :set opfunc=SensibleSubstitute<CR>g@
function! SensibleSubstitute(type)
    normal `[v`]
    normal "_c<C-R>"
endfunction

but the <C-R>" is not recognized and just inserted verbally. Furthermore I don't know how to use the selected register if the user for example types "asiw)

(PS: the accepted answer here has the same problems with selections at the end of hte line)

2

There are a lot of weird workarounds, but I do have an answer.

but the <C-R>" is not recognized and just inserted verbally.

If you want ctrl-r, you'll need "\<C-r>". (Note: Specifically with double quotes, not single. Try :echo "\<C-r>" and :echo '\<C-r>') Which unfortunately means you'll need the whole thing to be a rather convoluted exec command:

exec 'normal "_c'."\<C-r>".'"'

Furthermore I don't know how to use the selected register if the user for example types "asiw

You can get this in the v:register variable. Unfortunately, it's not quite that simple in your example. Try this for example:

noremap s :set opfunc=SensibleSubstitute<CR>g@
function! SensibleSubstitute(type)
  echo v:register
endfunction

Try something like "asiw. This always prints " instead of a. Why is that? Because of your remapping, you're effectively running

"a:set opfunc=SensibleSubstitute<CR>g@

When you really want to run

:set opfunc=SensibleSubstitute<CR>"ag@

So you'll have to use an <expr> mapping.

Putting this all together, this should work for you (though I haven't tested it a whole lot):

noremap <expr> s ":set opfunc=SensibleSubstitute\<CR>".'"'.v:register."g@"
function! SensibleSubstitute(type)
  normal `[v`]
  exec 'normal "_c'."\<C-r>".v:register
endfunction
  • I find that exec’s look a little prettier when the string is generated with printf instead of string concatenation, but YMMV. – D. Ben Knoble Dec 19 '18 at 18:45
  • Doesn't work, I think the v:register get's consumed by entering the visual mode. I got it to work by storing v:register at the beginning of the function – Bananach Dec 19 '18 at 22:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.