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

Restoring a register after a <C-r> function call

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

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

如你所见,"寄存器受return字符串影响,所以我不能直接调用setreg。显然这个函数并没有真正做任何事情,但我使用的实际函数相当长。另外,如果该字符串有点难以阅读,我深表歉意,但我不确定是否有任何其他方法可以做到这一点。总而言之,当寄存器包含一个单词时,该函数似乎可以工作,但只要寄存器中有换行符,该函数就会失败。 (关于 oldreg 参数的具体错误是 E115: Missing quote。)但是,这会导致错误 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

而不是在 return 你的函数之后进入正常模式,我想 你应该进去。这样就可以正常调用setreg() 在里面。例如:

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

    let @" = "whatever"

    normal! yya 

    setreg('"', oldreg, oldregtype)
endfunction

这里有一个方法:Vim: how to paste over without overwriting register

从那时起,我们得到了 setreg() 的天赋,我还开发了一个更通用的解决方案来简化最有用的东西的恢复 (lh#on#exit())。

在所有情况下,解决方案都是 return @=FunctionToExecute(),恢复将在该函数中进行。

但正如其他人所说,您可能需要更明确地说明您的需求,因为可能存在更具体的解决方案来解决这些问题。例如,不是使用 yy:yank 进行抽取,而是可以简单地使用 getline() 函数来让所有寄存器保持不变。对于更改一行,有 setline(),但这会破坏重做和其他事情。