在Vim的搜索/替换语法中标准化\ n和\ r \ n


1

在Vim中,可以搜索换行符\n,但必须输入替换字符串中的换行符\r。我知道这种行为原因,但就我的目的而言,我觉得它很烦人。我希望能够\n在搜索模式和替换字符串中使用(基本上)相同的东西:具体地说,在搜索模式中它应该匹配换行符,并且在替换字符串中它应该插入换行符。

有没有办法得到这种行为?我认为简单的重映射不起作用,因为需要解析替换命令以确定是否\n是搜索模式或替换字符串的一部分。


1
是的,几乎每个人都感到沮丧,但不太可能改变。Vim在向后兼容性方面非常大,而且这个机会不会。
Heptite 2014年

@Heptite我不是要求改变Vim代码库; 我想知道是否可以通过某种形式的自定义来获取此行为,例如插件,可能使用github.com/coot/CRDispatcher
凯尔斯特兰德2014年

@Kyle不会编辑其他人的答案。如果您想详细说明,请编辑您自己的帖子。
kinokijuf 2014年

@kinkijuf我没有详细说明我的问题; 我正在接受回答者的建议,并根据他自己的建议做出贡献,我的正则表达式版本用于确定是否执行替换。这除了肯定不会在我的问题属于,由于该解决方案的主要部分是用的招c_CTRL-\_egetcmdline() =~# ,使用正则表达式的就不详细介绍了,我不认为它值得自己的答案。
凯尔斯特兰德2014年

Answers:


3

你必须挂钩命令行; 或者在通过时执行<CR>,或者在您输入时立即执行\n。使用:help c_CTRL-\_e,您可以评估函数并修改命令行。这是一个可以构建和改进的演示(现在检查替换是简单的):

cnoremap n <C-\>eTranslateBackslashN()<CR>
function! TranslateBackslashN()
    if getcmdtype() ==# ':' && getcmdline() =~# 's/.*/.*\\$' " Improve this!
        return getcmdline() . 'r'
    endif
    return getcmdline() . 'n'
endfunction

...幻想。<C-\>e是一个我不知道的很酷的功能。
凯尔斯特兰德

我已经添加了我正在使用的正则表达式.vimrc,并附有解释。
凯尔斯特兰德2014年

没关系,我的编辑被拒绝了。我仍然认为你应该得到这个解决方案的核心功劳,但我将发布我自己的答案,以便完整的实现可以获得可见性。
凯尔斯特兰德2014年

1

正如Ingo Karkat所写,可以找到一个解决方案c_CTRL-\_e。这是我正在使用的版本,除了正则表达式之外,它与原始解决方案相同。(由于这只是Ingo Karkat的回答,Ingo Karkat提出了适度的改进,我认为它实际上并不值得回答,但我想我已经投票了:http//chat.stackexchange.com/transcript/消息/ 15021397#15021397

function! TranslateBackslashN()
    if getcmdtype() ==# ':' && getcmdline() =~#
      \ '[%>]s\([um]\w*\)\?\(.\).\{-}\(\\\)\@<!\2.*\\$'
        return getcmdline() . 'r'
    endif
    return getcmdline() . 'n'
endfunction
cnoremap n <C-\>eTranslateBackslashN()<CR>

正则表达式模式的说明:

  • [%>]s确保更换仅在s紧接在范围之后发生
  • \([um]\w*\)\?匹配s命令的变体,例如smagic
  • \(.\)将是第一个非单词字符,因为所有单词字符都已\w在可选组中被吃掉。请注意,这是组2。这是分隔符,通常是/。请注意_,这是一个单词字符,也是一个有效的分隔符,因此如果_以这种方式使用该模式将无法正常工作。我不会_用作分隔符,所以我不会担心它。类似地,有些字符不是单词字符但不应该用作分隔符,但我不担心这里,因为在这种情况下命令应该失败。我想在\W这里使用,但由于某种原因,当我测试时它不起作用。
  • .\{-}应该匹配模式(\{-}就像Perl的*?)。
  • \(\\\)\@<!\2匹配不带反斜杠的分隔符的下一个实例。Perl等价物将是(?<!\\)\2
  • .* 匹配到目前为止替换字符串中的任何内容。
  • \\$ 仅当命令到目前为止以反斜杠结束时才匹配。

看看:h range。你没有捕捉所有范围(我不确定是否有一个好方法。)
FDinoff 2014年

@FDinoff我正在匹配我目前使用的唯一两个范围表达式。但是,它看起来并不像其他人那么难以匹配,所以我会在需要更新时更新。
Kyle Strand 2014年

0

使用插件的替代答案(这是我决定使用的解决方案,虽然它只适用于Vim 7.4+):

使用Enchanted Vim,放入let g:VeryMagicSubstituteNormalise = 1你的.vimrc

(这个插件使用CRDispatcher插件,它允许在按下Enter键之后命令实际执行之前在命令中进行文本替换。因此不需要重新映射\n,并且替换对于用户是不可见的,使得\n看起来具有在两种情况下都具有相同的“意义”。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.