如何粘贴而不覆盖寄存器
Posted
技术标签:
【中文标题】如何粘贴而不覆盖寄存器【英文标题】:How to paste over without overwriting register 【发布时间】:2010-09-22 08:56:19 【问题描述】:有没有人知道一种在视觉选择区域上粘贴而不将选择放置在默认寄存器中的方法?
我知道我可以通过始终从显式寄存器粘贴来解决问题。但是输入 "xp 而不仅仅是 p
会让人头疼【问题讨论】:
【参考方案1】:使用以下内容:
xnoremap p pgvy
这将重新选择并重新拉出以可视模式粘贴的任何文本。
编辑:为了与 "xp
一起工作,您可以这样做:
xnoremap p pgv"@=v:register.'y'<cr>
v:register
扩展为正常模式命令中使用的最后一个寄存器名称。
【讨论】:
在"xp
上,此方法用@x
覆盖@"
。
您对xnoremap p pgv"@=v:register.'y'<cr>
的建议对我不起作用。但是,这样做:xnoremap <expr> p 'pgv"'.v:register.'y'
这看起来很有趣。你能补充一句关于g
的作用吗?我以前没见过。
@LondonRob: g
一个人什么都不做。它提供扩展的多键命令,例如z
。例如,go
转到缓冲区中的第 n 个字节,gj
和 gk
转到下一行和上一行显示(与换行时的 jk
不同),ga
显示光标下字符的信息, gJ
加入没有空格的行,这里gv
恢复最后的视觉选择。您可以使用:help gv
。
@mark :xnoremap <expr> p 'pgv"'.v:register.'y`>'
,我加了```>``恢复光标位置【参考方案2】:
我不喜欢将使用d
、D
、c
或C
删除的所有文本复制到默认寄存器中的默认 vim 行为。
我通过将d
映射到"_d
、c
到"_c
等等来解决这个问题。
来自我的 .vimrc:
"These are to cancel the default behavior of d, D, c, C
" to put the text they delete in the default register.
" Note that this means e.g. "ad won't copy the text into
" register a anymore. You have to explicitly yank it.
nnoremap d "_d
vnoremap d "_d
nnoremap D "_D
vnoremap D "_D
nnoremap c "_c
vnoremap c "_c
nnoremap C "_C
vnoremap C "_C
【讨论】:
尽管这些映射很有用(我自己也做过类似的事情),但它们不会回答 OP 的问题,p 仍会覆盖您在选定内容上粘贴的内容。【参考方案3】:"registerp
不会像你描述的那样工作。它将用寄存器的内容替换选择。您将不得不执行以下操作:
" I haven't found how to hide this function (yet)
function! RestoreRegister()
let @" = s:restore_reg
return ''
endfunction
function! s:Repl()
let s:restore_reg = @"
return "p@=RestoreRegister()\<cr>"
endfunction
" NB: this supports "rp that replaces the selection by the contents of @r
vnoremap <silent> <expr> p <sid>Repl()
只要您不使用与 p 具有非 nore vmap 并且期望寄存器被覆盖的插件,这应该没问题。
此代码以脚本there 的形式提供。 Ingo Karkat 还定义了一个 plugin 来解决同样的问题。
【讨论】:
实际上,我虽然有一种巧妙的方法来获取使用的寄存器,但不记得如何了。因此函数的复杂性。 我认为这是矫枉过正,不会记得regtype
(linewise?)并且将 p 重新映射到 pgvy
就足够了。
可能有点矫枉过正,但没有副作用。在"xp
上,这不会用@x
覆盖@"
内容,这与pgvy
不同
那么:xnoremap p pgv@=v:register.'y'<cr>
呢?
它对我不起作用。我也试过下载脚本。这是我执行的命令列表:首先按 v,然后按 e 选择到单词的末尾,然后按 y 拉动它。在那之后,我去一个我想替换的不同的词。我按 v,e,然后按 p 替换那个。然后我再做一次,但这次下一个单词被我之前替换的那个替换了。【参考方案4】:
在你的.vimrc
xnoremap p "_dP
我从一个类似线程的回复中找到了这个,但原始来源是http://vim.wikia.com/wiki/Replace_a_word_with_yanked_text。它提到了一些缺点,但对我来说效果很好。
【讨论】:
这似乎是最简单的解决方案。 为我工作。这个答案很明确。.vimrc.local
也可以。
如果您的选择延伸到行尾,则不起作用。
这会给我带来一些视觉上的闪烁(vim 在命令之间重绘)。 xnoremap <silent> p p:let @+=@0<CR>:let @"=@0<CR>
没有这个问题【参考方案5】:
Luc Hermitte 的解决方案非常有效。我使用它大约一个星期左右。然后我从Steve Losh's .vimrc 发现了一个解决方案,如果 YankRing 是您的插件/捆绑包阵容的一部分,那么该解决方案效果很好:
function! YRRunAfterMaps()
" From Steve Losh, Preserve the yank post selection/put.
vnoremap p :<c-u>YRPaste 'p', 'v'<cr>gv:YRYankRange 'v'<cr>
endfunction
【讨论】:
【参考方案6】:在您的~/.vimrc
中试试这个:
xnoremap <expr> p 'pgv"'.v:register.'y'
xnoremap
表示这仅适用于Visual
模式,不适用于Visual + Select
模式。
<expr>
表示xnoremap lhs rhs
设置的rhs
被评估为表达式。
在这种情况下,我们的'pgv"'.v:register.'y'
表达式使用.
进行连接。
v:register
被评估为在完成映射期间使用的寄存器。
"xp
的结果将计算为pgv"xy
,其中x
是寄存器。
这个 *** 问题的答案帮助了我:Vim - mapping with an optional register prefix 结合Benoit的回答on this page
【讨论】:
【参考方案7】:在我进行更改以支持我设置了 clipboard=unnamed 的事实后,Luc 的功能对我来说效果很好:
function! RestoreRegister()
let @" = s:restore_reg
if &clipboard == "unnamed"
let @* = s:restore_reg
endif
return ''
endfunction
【讨论】:
供参考:使用clipboard=unnamedplus
这必须是@+
而不是@*
。【参考方案8】:
Luc Hermitte 成功了!真的很好。这是他的解决方案,其中包含切换功能,因此您可以在正常行为和无替换寄存器放置之间切换。
命令 ,u 切换行为
let s:putSwap = 1
function TogglePutSwap()
if s:putSwap
vnoremap <silent> <expr> p <sid>Repl()
let s:putSwap = 0
echo 'noreplace put'
else
vnoremap <silent> <expr> p p
let s:putSwap = 1
echo 'replace put'
endif
return
endfunction
noremap ,p :call TogglePutSwap()<cr>
【讨论】:
您还可以根据 s:putSwap 值更改 s:Repl 以返回“p”而不是“p@=RestoreRegister()\silent! vunmap
而不是vnoremap <silent> <expr> p p
【参考方案9】:
胶带编程,但对我有用:
nmap viwp viwpyiw
nmap vi'p vi'pyi'
nmap vi"p vi"pyi"
nmap vi(p vi(pyi(
nmap vi[p vi[pyi[
nmap vi<p vi<pyi<
【讨论】:
【参考方案10】:试试-
:set guioptions-=a
:set guioptions-=A
【讨论】:
控制是否将选定文本添加到窗口系统的剪贴板(例如,X11 或 Win32),而不是添加到 Vim 的内部复制寄存器。以上是关于如何粘贴而不覆盖寄存器的主要内容,如果未能解决你的问题,请参考以下文章