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

时间:2011-09-13 10:57:44

标签: vim escaping

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

Vim resources: [http://example.com/search?q=vim][q]
...
[q]: http://example.com/search?q=vim

我不想完整地输入它,所以我将光标放在第一个URL上,然后运行"uyi[将其拖入'u'寄存器。现在要搜索它,我想通过运行:

将该寄存器的内容粘贴到搜索字段中
/\V<c-r>u<CR> 

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

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

/\V<c-r>=escape(@u, '\/')<CR><CR>

但这是很多打字!

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

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

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

4 个答案:

答案 0 :(得分: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

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

:s?http://foo.com?http://bar.com?g

答案 1 :(得分:7)

我接受了Andrew Radev's solution,它解决了困难的部分。但这是我添加到我的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

这应该有效:

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

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

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

答案 2 :(得分:2)

不同的工作流程怎么样?例如,创建自己的运算符以按原样搜索目标文本:

" https://gist.github.com/1213642
" Requiement: https://github.com/kana/vim-operator-user
map YourFavoriteKeySequence  <Plug>(operator-search-target-text)
call operator#user#define('search-target-text', 'OperatorSerachTargetText')
function! OperatorSerachTargetText(motion_wise)
  execute 'normal!' '`['.operator#user#visual_command_from_wise_name(a:motion_wise).'`]"xy'
  let @/ = '\V' . escape(substitute(@x, '[\r\n]$', '', ''), '\')
  normal! n
endfunction

答案 3 :(得分:1)

我喜欢@ nelstrom的解决方案并进行了一些小改动以支持转义[和]。

 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())
     let escaped_register2 = substitute(escaped_register,'[','\\[','g')
     let escaped_register3 = substitute(escaped_register2,']','\\]','g')
     return substitute(escaped_register3, '\n', '\\n', 'g')
   endif
 endfunction