2011-09-23 74 views
10

使用Vim我非常喜歡視覺模式,允許您在列前插入文本。在Vim中插入列的縮進

插入一些間隔中的箭頭後,

> one 
> two 
> three 

可以通過<Ctrl-V>jjI <Esc>來完成:

> one 
> two 
> three 
  • 去視覺模式<Ctrl-V>
  • 延伸視覺選擇jj
  • 插入一些空格I__
  • 傳播更改可視列塊選擇<Esc>

的所有行現在我有一個需要某些格式的文本文件。這是什麼樣子:

start() -- xxx 
initialize() -- xxx 
go() -- xxx 

現在我要對齊這個文本的一部分,安排成列如下:

start()  -- xxx 
initialize() -- xxx 
go()   -- xxx 

我的問題是,我不能插入不同的量的縮進到每行中,而僅縮進固定數量的空格/製表符是不夠的。 如何縮進所有縮進文本必須在同一列對齊?


編輯:我只是想出了一個相當冗長和笨重方法:

  • 查找字符串位置從縮進:\--
  • 插入N(比方說20)之前的空間: 20i <Esc>
  • 刪除這些空間回某列的部分(比方說15):d|15
  • 保存這些步驟作爲宏根據需要經常重複宏,

...雖然很醜!

+0

可能的重複[如何插入空格到列X排列列中的東西?](http://stackoverflow.com/questions/6154306/how-to-insert-spaces-up-to-column- x-to-line-up-columns-columns) – DocMax

回答

14

沒有任何vim插件,我好多了。 這裏是我的解決方案:

<Shift-V>jj:!column -ts --

然後插入--成多行,就像你在問題中寫道。


您還可以在插入時附加一些評論。

:set virtualedit=all

<Ctrl-V>jjA-- xxx<Esc>

+2

這當然是您在插入時應該這樣做的方式。 +1。 – Benoit

+0

在我的情況下不起作用......每行上的「--- xxx」部分從不同的列開始。所以你不能對齊你的視覺選擇的編輯部分。 (我需要編輯的文件已經有了這個結構,我需要重新格式化它) – oliver

+1

你在* nix上工作嗎?如果是這樣,你可以嘗試Vim內的'column'命令。 ' jj:!column -ts --',然後將'--'插入你想要的多行。 – ernix

4

您必須使用特定的插件,在這種情況下,您可以使用TabularAlign插件。

它們都允許您在特定字符上對齊文本,如示例中的--。他們的語法雖然有點不同。選擇一個最適合你的人。

+0

剛剛安裝了Tabular,它的工作原理是正確的。尼斯......儘管我希望這個相當小的任務不會涉及安裝插件。感謝您的建議! – oliver

+0

@oliver:無需安裝插件即可解決此任務。不過,該解決方案並不像使用其中一個插件時那麼緊湊。 –

3

無插件,如果你已經進入了你的意見,而不EMIX的解決方案:

:,+2 s/--/         & 

這將確保所有的意見都是爲了對準他們轉移leftwise正常。

然後逐塊選擇列要對齊文本和:100<

+0

不錯,簡單。喜歡它! – oliver

+0

另外,考慮':,2s/\ ze -/\ = repeat('',32)'。 –

+0

@ib .:這也不錯,但取決於你的鍵盤設置,鍵入的速度會更慢! – Benoit

3

一個簡單的方法在列對齊文本是用TabularAlign 插件。如果這些都沒有準備好,可以使用以下 有點棘手(並且看起來有點麻煩),但完美的工作(對於 這種情況)命令。 1,2-

:let m=0|g/\ze -- /let m=max([m,searchpos(@/,'c')[1]]) 
:%s//\=repeat(' ',m-col('.')) 

第一命令的目的是確定列的寬度來 隔板的左側(我假定爲--這裏)。寬度爲 ,計算爲 所有行中第一列中文本的最大長度。 :global命令用於枚舉包含分隔符的行 (其他行不需要對齊)。位於模式開始之後的\ze 原子會將 匹配的結尾設置在開始的相同位置(請參閱:help \ze)。更改匹配的 邊界不會影響:global命令的工作方式, 模式的寫入方式只是爲了匹配下一個 替換命令的需要:由於這兩個命令可以共享相同的模式,因此可以使用 在第二個中被省略。

在所述匹配線上運行的命令,

:let m=max([m,searchpos(@/,'c')[1]]) 

調用searchpos()功能來搜索在父 :global命令中使用的模式,並獲取匹配的列位置。 模式被稱爲@/使用最後的搜索模式寄存器(見:help "/)。這利用了:global命令開始執行後立即更新寄存器 /的事實。該c標誌作爲searchpos()呼叫 第二個參數允許(:global位置光標在 行一開始就執行的命令)的比賽在一行的第一 字符,因爲它可能是有在分隔符的左側沒有文本 。 searchpos()函數返回一個列表,其中第一個元素是匹配位置的行號, 第二個元素是列位置。如果該命令在一行上運行,則行 與包含:global命令的模式相匹配。由於searchpos()是 尋找相同的模式,肯定是在該行的匹配。 因此,只有開始匹配的列有興趣,所以它從[1]下標得到返回列表中的 。這個位置 等於該行第一列文本的寬度,加上1。 因此,m設置爲其當前值和該列位置的最大值。

第二個命令,則隔膜的上所有包含 它的行的第一次出現

:%s//\=repeat(' ',m-col('.')) 

墊,用缺少,使文本的 分離器採取之前的空格數m個字符,減1。該命令是一個全球性 取代只是分離器之前更換空的間隔(見關於上面的:global命令 評語)與 評價結果的表達(見:help sub-replace-\=

repeat(' ',m-col('.')) 

repeat()函數重複它的第一個參數(作爲字符串)在第二個參數中給出的 次數。由於在每次替換時光標移動到模式匹配的開始位置時,m-col('.')正好等於 將分隔符右移到對齊列所需的空格數 (col('.')返回光標的當前列位置)。


以下是該對命令的一個行版本。

:let m=0|exe'g/\ze -- /let m=max([m,searchpos(@/,"c")[1]])'|%s//\=repeat(' ',m-col('.')) 

在答案的以前版本以前那樣 如下的命令。

:let p=[0]|%s/^\ze\(.*\) -- /\=map(p,'max([v:val,len(submatch(1))+1])')[1:0]/ 
:exe'%s/\ze\%<'.p[0].'c -- /\=repeat(" ",'.p[0].'-col("."))' 

這些誰是興趣在這些特定的命令,可以在編輯的歷史詳細 描述。

+1

哇...看起來有點牽涉!你會不會解釋你的解決方案? – oliver

+0

@oliver:當然。我已經爲答案添加了詳細的解釋。 –

+0

感謝您的詳細解釋!雖然我不認爲我會用這個(我永遠不會記得:)在實踐中,我真的很喜歡閱讀你的答案,並肯定了解了有關vim的一些事情......再次! – oliver

0

這是對Benoit的回答的修改,它有兩個步驟。

第一步,塊選擇文本搜索和替換 - 有很多空間。

'<,'>s/--/       --/ 

現在所有的評論應該有很多的空間,但仍然不均衡。

第二步,塊再次選擇文本,並使用另一個正則表達式來匹配你想要保留的所有字符(比如說前20個字符)加上所有後面的空格,並用它們的副本替換它們20個字符:

'<,'>s/\(.\{20}\)\s*/\1/ 

並不像Benoit那麼容易,但我無法弄清楚如何讓他的第二步工作。