在<c-r>函数调用后恢复寄存器

时间:2017-03-06 20:38:01

标签: vim restore vim-registers

我正在为Vim编写一个插件,我希望它在执行后恢复默认寄存器。但是,有问题的函数是通过<C-r>=Myfunction()<CR>构造调用的,这意味着我需要在函数返回后恢复它。我试图这样做:

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

如您所见,"寄存器受返回字符串的影响,因此我无法直接调用setreg。显然这个功能并没有真正做任何事情,但我使用的实际功能很长。另外,如果该字符串有点难以理解,我很抱歉,但我还不确定是否有其他方法可以实现这一点。总而言之,当寄存器包含一个单词时,该函数似乎有效,但只要在寄存器中有换行符,就会失败。 (关于oldreg参数的具体错误是E115: Missing quote。)我试图通过先废除oldreg来解决这个问题。但是,这会导致错误E121: Undefined Variable,其中未定义的变量是我的寄存器中的变量。关于这里可能出现什么问题的任何想法?

编辑:我找到了解决方案。它很毛茸茸,但到目前为止效果很好。以下是如何将解决方案应用于我的示例代码,以防万一它可以帮助任何人。

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

2 个答案:

答案 0 :(得分:0)

我认为,在您返回功能后,不要进入正常模式 你应该进去吧。这样,您可以正常呼叫setreg() 在里面。例如:

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

    let @" = "whatever"

    normal! yya 

    setreg('"', oldreg, oldregtype)
endfunction

答案 1 :(得分:0)

以下是继续进行的方式:Vim: how to paste over without overwriting register

从那以后,我们一直有setreg()天赋,我也开发了一个更通用的解决方案,简化了大多数有用的东西的恢复(lh#on#exit())。

在所有情况下,解决方案都是返回@=FunctionToExecute(),并且恢复将在该函数中发生。

但正如其他人所说,您可能需要更明确地了解您的需求,因为可能存在更具体的解决方案来解决它们。例如,您可以简单地使用yy函数来使所有寄存器不被修改,而不是使用:yankgetline()进行操作。对于更改一行,有setline(),但这会破坏重做和其他事情。