2017-05-06 56 views
1

是否有可能使用vim绑定将多行if语句转换为单行if语句,反之亦然?Vim多行If-Statements转换为单行If-语句

把这个

if() { 
    statement_1; 
    statement_2; 
} else if() { 
    statement_3; statement_4; 
} else if() { 
    statement_5; 
} else { 

} 

这个

if()  { statement_1; statement_2 } 
else if() { statement_3; statement_4; } 
else if() { statement_5; } 
else  { } 

或任何接近上面的行为呢?我在想有命令在视觉上选择块转换执行,然后使用搜索else if和进入新的生产线,等等。但我的问题是确定else if有多少人在代码

回答

2

加入所有的行到通过在视觉模式V中选择它们并按J;然后在每else:s/else/\relse/之前添加一个换行符。你会结了:

if() { statement_1; statement_2; } 
else if() { statement_3; statement_4; } 
else if() { statement_5; } 
else { } 

在替换模式的\r是一个换行符(你需要使用\n搜索和替换中\r;不要问我为什么)。

下一步是将所有启动大括号放在同一列中。我会用tabular plugin这一点,这使得这很容易:

:%Tabularize /{/ 

随着%我们经营的整个缓冲区,在一个“真实”的文件,你可能需要使用更严格的范围或视觉模式。还有一些其他插件也可以做类似的事情。

你现在应该有你想要的输出。如果你想要一个“VIM-只有”解决方案

:%!column -ts{ -o{ 

,那么它就会更加复杂一些:


如果你不想使用插件,您可以使用column命令:

:let b:column = 10 
:%s/^\(.\{-}\) {/\=submatch(1) . repeat(' ', b:column - len(submatch(1))) . ' {'/ 

打破下来:

  • 我使用b:column变量来指定要对齐的列。你不需要需要这个,但它使得稍后编辑这个数字变得更容易一些。

  • ^\(.\{-}\) {{之前的所有内容放在子组中。

  • 在替换中,我们使用了一个表达式(如\=所示)。请参阅:help sub-replace-\=
  • 首先我们把if ...回来submatch(1)
  • 然后我们插入尽可能多的空间,因为我们需要与repeat(' ', b:column - len(submatch(1)))
  • 最后,我们插入文字{回来。

我告诉过你这有点复杂了;-)如果你不想表格。就个人而言,我只是开始插入模式插入空格,这将比编写&调试(relevant xkcd)快很多。


请注意,我没有做出一些“魔术”命令,它只用一个键的笔画重新排列所有文本。我不认为这样的命令会是一个好主意。实际上,这样的命令将不会处理很多边界情况。使用即席编辑命令和/或正则表达式完全“解析”编程语言并不是真的很好。

Vim的真正亮点在于为用户提供强大的文本编辑命令,这些命令可以以最小的努力进行应用和组合,这正是我上面所做的。还有其他几种方法可以用来获得相同的效果。

但如果你真的愿意,你当然可以结合所有上述的命令:

fun! s:reformat(line1, line2) 
    " Remember number of lines for later 
    let l:before = line('$') 

    " Join the lines 
    execute 'normal! ' . (a:line2 - a:line1 + 1) . 'J' 

    " Put newline before else 
    :s/else/\relse/ 

    " Run tabular; since the number of lines change we need to calculate the range. 
    " You could also use one of the other methods here, if you want. 
    let l:line2 = a:line2 - (l:before - line('$')) 
    execute a:line1 . ',' . l:line2 . 'Tabularize /{/' 
endfun 

command! -range Reformat :call s:reformat(<line1>, <line2>) 
+0

谢谢你这么多的很深入的答案!这是非常有用的。我也喜欢喜剧(非常相关) –