0

I am currently writing a plugin for Vim and I would like that it restores the default register after I execute it. However, the function in question is called via a <C-r>=Myfunction()<CR> construct, which means that I need to restore it after the function return. I've tried to do this like so:

inoremap <silent> <Space> <C-r>=Myfunction()<CR>
function! Myfunction()
    let oldreg      = getreg('"')
    let oldregtype  = getregtype('"')
    let restore     = "\<ESC>:call setreg('\"','".oldreg."','".oldregtype."')\<CR>a"

    let @" = "whatever"

    return "\<ESC>yya ".restore
endfunction

As you can see, the " register is affected by the return string, so I cannot call setreg directly. Obviously this function doesn't really do anything, but the actual function I'm using is quite long. Also, I apologize if that string is a little hard to read, but I'm not really sure of any other way of accomplishing this. All in all, the function seems to work when the register contains a word, but fails whenever something with a newline is in the register. (The specific error is E115: Missing quote with respect to the oldreg argument.) I've tried to remedy this by shellescaping oldreg first; however, this results in the error E121: Undefined Variable, where the undefined variable is what was in my register. Any thoughts on what might be going wrong here?

EDIT: I found a solution. It's quite hairy, but it works perfectly so far. Here's how to apply to solution to my example code, just in case it helps anyone out there.

inoremap <silent> <Space> <C-r>=Myfunction()<CR>
function! Myfunction()
    let oldreg      = substitute(escape(getreg('"'), '\\'), '\n', '\\n', 'g')
    let oldregtype  = getregtype('"')
    let restore     = "\<ESC>:call setreg('\"',\"".oldreg."\",'".oldregtype."')\<CR>a"

    let @" = "whatever"

    return "\<ESC>yya ".restore
endfunction
  • 1
    Check [How to create a Minimal, Complete, and Verifiable question](http://stackoverflow.com/help/mcve). – Meninx - メネンックス Mar 06 '17 at 20:42
  • Currently, as is, your example does not make much sense to me because I don't see what impedes you from simply calling `setreg` directly at the end of your function. What impedes that? Why you need to reset it back after the function is called? If the function only returns a string? Do you need to use `"@` somewhere else? This would only make sense if you need to use it between the `MyFunction` end and the `` in your call, which won't happen anyway. Sorry that my comment doesn't answer the question , I'm just trying to understand your goal, as it seems that there is other way to do it. :) – sidyll Mar 06 '17 at 21:08
  • @sidyll there is no register called `@` in vim. – Meninx - メネンックス Mar 06 '17 at 22:10
  • So better putting the question **[on-hold]** till further clarification. – Meninx - メネンックス Mar 06 '17 at 22:15
  • @sidyll the `@` register is an alias for the unnamed register. I forgot that `"` is usually the more conventional symbol for the register. I've edited the function to show that the register is being used in the return string, so, unfortunately, I cannot simply call setreg normally. – Bennett Rennier Mar 06 '17 at 23:09
  • @Meninx-メネンックス `:h :let-@` – sidyll Mar 06 '17 at 23:18
  • @sidyll I am refering to `:h registers` where it could be replaced by `{regname}` in manual. – Meninx - メネンックス Mar 06 '17 at 23:26
  • @Meninx-メネンックス I don't understand what you mean, sorry. I myself didn't know about `@` as alias of `"` until now. – sidyll Mar 06 '17 at 23:42
  • @sidyll `@` could be used instead of `"` in some cases. Like the one you have already stated. – Meninx - メネンックス Mar 06 '17 at 23:48

2 Answers2

0

Instead of going to normal mode after you return your function, I think you should go inside it. This way, you can call setreg() normally in it. For example:

function! Myfunction()
    let oldreg      = getreg('"')
    let oldregtype  = getregtype('"')

    let @" = "whatever"

    normal! yya 

    setreg('"', oldreg, oldregtype)
endfunction
sidyll
  • 57,726
  • 14
  • 108
  • 151
0

Here is a way to proceed: Vim: how to paste over without overwriting register

Since then, we have been gifted with setreg(), and I've also developed a more generic solution simplify restoration of most useful things (lh#on#exit()).

In all cases, a solution would be to return @=FunctionToExecute(), and the restoration would happen in that function.

But as others said, you may need to be more explicit about your needs as there may exist more specific solutions to address them. For instance, instead of yanking with yy or with :yank, you could simply use getline() function that would let all registers unmodified. For changing a line, there is setline(), but this would break redo and other things.

Community
  • 1
  • 1
Luc Hermitte
  • 31,979
  • 7
  • 69
  • 83
  • Your suggestions works, so I'm marking this as correct. However, I found a slightly different solution that worked with the structure of my program better. – Bennett Rennier Mar 07 '17 at 00:49