在 <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()
,但这会破坏重做和其他事情。
我目前正在为 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()
,但这会破坏重做和其他事情。