为Vim的命令行创建一个映射,在插入之前转义寄存器的内容

nel*_*rom 8 vim escaping

假设我有这样的文档,我想搜索URL的所有出现:

Vim resources: [http://example.com/search?q=vim][q]
...
[q]: http://example.com/search?q=vim
Run Code Online (Sandbox Code Playgroud)

我不想完整地输入它,所以我将光标放在第一个URL上,然后运行"uyi[将其拖入'u'寄存器.现在要搜索它,我想通过运行以下命令将该寄存器的内容粘贴到搜索字段中:

/\V<c-r>u<CR> 
Run Code Online (Sandbox Code Playgroud)

这导致Vim搜索字符串'http:' - 因为'/'字符终止了搜索字段.

我可以通过运行它来解决问题:

/\V<c-r>=escape(@u, '\/')<CR><CR>
Run Code Online (Sandbox Code Playgroud)

但这是很多打字!

如何为Vim的命令行创建一个简化此工作流程的映射?

我理想的工作流程将是这样的:

  • 按下/\V以显示搜索提示,并使用非常无意义的模式
  • 点击ctrl-x触发自定义映射(ctrl-x可用)
  • Vim听下一次按键...(按下<Esc>会取消)
  • 按'u'将转义'u'寄存器的内容,并在命令行中插入

And*_*dev 7

试试这个:

cnoremap <c-x> <c-r>=<SID>PasteEscaped()<cr>
function! s:PasteEscaped()
  " show some kind of feedback
  echo ":".getcmdline()."..."

  " get a character from the user
  let char = getchar()

  if char == "\<esc>"
    return ''
  else
    let register_content = getreg(nr2char(char))
    return escape(register_content, '\/')
  endif
endfunction
Run Code Online (Sandbox Code Playgroud)

顺便说一句,知道(如果你还没有)可能有用的东西是你可以?用作分隔符:s.这意味着你可以像这样写一个url的搜索和替换:

:s?http://foo.com?http://bar.com?g
Run Code Online (Sandbox Code Playgroud)

  • 在我原来的问题中,我没有引起人们的注意,但我故意使用包含'/'和'?'的URL.字符.如果搜索目标只包含这两个中的一个,那么您可以使用另一个拨号搜索提示,避免任何转义. (2认同)

nel*_*rom 7

我接受了安德鲁拉德夫的解决方案,解决了困难的部分.但这是我添加到我的vimrc文件的版本,它增加了一些增强功能:

cnoremap <c-x> <c-r>=<SID>PasteEscaped()<cr>
function! s:PasteEscaped()
  echo "\\".getcmdline()."\""
  let char = getchar()
  if char == "\<esc>"
    return ''
  else
    let register_content = getreg(nr2char(char))
    let escaped_register = escape(register_content, '\'.getcmdtype())
    return substitute(escaped_register, '\n', '\\n', 'g')
  endif
endfunction
Run Code Online (Sandbox Code Playgroud)

这应该工作:

  • 是否使用/?(向前搜索或向后搜索)
  • 当粘贴的寄存器包含多行时

另外,我改变了提示.在等待寄存器时,提示切换到\- 这似乎是'PasteEscaped'的合适提示.另外,我添加了一个",<c-r>在命令行按下后模仿Vim的行为.

如果您有任何进一步的改进建议,请发表评论.