2017-05-06 62 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

謝謝你這麼多的很深入的答案!這是非常有用的。我也喜歡喜劇(非常相關) –