為什麼這些死腦筋們在用 VI ?
不管你們信不信,現在有很多人迷戀這個30多年曆史的VI編輯器(最好的克隆和改進版本VIM也已經有15歲了).
他們不是守舊派,跟不上時代潮流——VI用戶的社區正在不斷增長著,我自己用VI已經2年了(在有了10年編程經驗之後),我的很多朋友也都開始使用VI了,有趣的是,有很VI用戶在VI出現前還沒有出生。
當然,VI/VIM編輯模式比其它任何編輯囂都出眾肯定有原因的,你不必非得是Unix高手才能用它,相反,VIM可以免費在任何平台下使用,並且它也可以作為其它主流IDE的插件使用,現在讓我來澄清幾個誤解,並用一些真實例子說明為什麼它是極好的編輯器。
誤解#1:模態編輯
你第一次被VI/VIM難住,可能是對必須先用”i”才能開始編輯感覺震驚和厭惡,記不住使用”hjkl”來移動光標方向,並且需要按”a”才能在光標後麵追加內容.因為你可能已經習慣使用其它編輯囂,並且方向鍵在插入模式管用(90%情況下是這樣的,如果係統配置正確的話),你可能除特別需要,保持在插入模式而不會返回到正常模式. 你可能會花20分鍾在插入模式下,並且會抱怨:”我到底可怎麼記住現在正在插入模式下還是正常模式下?”
很顯然,這是一個完全錯誤的使用VI/VIM的方式,正確方式是,你不會在意模式,你會一直在正常模式下,隻有當需要插入或修改字符時才會進入插入模式,編輯完成之後馬上按<Esc>返回到正常模式.因此,如何記住當前模式問題並不存在.當你在編輯文字的時候,不要在插入模式去接聽電話,而應該退出插入模式,接聽電話,或者返回的時候按<Esc>進入正常模式.不要把插入模式當成一種狀態.
讓我來解釋下這其中的哲學.
VI/VIM中的命令是可以組合使用的,比如”d”代表刪除,”e”代表”移到單詞末尾”,而”de”的功能就是刪除從當前光標位置至單詞結尾間的字符(有點像Ctrl-Shift-Right, Left, Del 快捷鍵在其它編輯器中實現的功能)
這樣的好處之一是,”.”命令可以重複上次執行完成的組合命令(不包括移動命令), 執行完”dw”後,”.”會重複執行”dw”命令, 你可以移動光標,然後再按”.”會快速地刪除當前光標處的下一個單詞,這樣讓人感到難以置信的強大.
現在我們來看下插入模式. 一些命令(比如i,a,s等)可以讓你進入插入模式鍵入文本直到按<Esc>, 說到這些命令, 整條命令也包括你在”i”命令和<Esc>之間鍵入的所有字符.
比如”iHello<Esc>”, 會在當前光標處插入”Hello”字符,而現在”.”命令可以在當前光標處重複插入”Hello”, 現在你應該能夠明白強大之處了吧, 但還有更強大的, “A”會將光標移到當前行末尾並進入編輯模式, 因此, 當按<Esc>結束輸入後,你可以按”.”在任何位置的行末插入相同的字符.
另外一個更加強大的例子是: “ce”命令, 由”c”和”e”組合而成,”c”(修改)命令會刪除指定範圍內的文本並進入插入模式,與”d”(刪除)命令一樣,但唯一不同的是它會進入插入模式而不是停留在正常模式. 這樣的好處是你在這條命令之後所鍵入的文本同樣也會作為這條命令的一部分. 因此如果你輸入”ceHello<Esc>”, 將會替換當前光標位置到行末的內容為”Hello”, 而”.”命令同樣也會重複這個運作.
動作(光標移動命令)也可以更加複雜, 有很多各種進入插入模式的命令(“o”會在當前行下插入新一行,”O”會在上麵插入新一行,”S”會刪除到行末的內容,等等…所有這些命令都會進入插入模式), 因此你可以想象,使用”.”可以創建重複執行多麼強大的編輯命令.
示例#1: 完美的點命令
讓我們來一個示例. 比如你已經在你的頭文件中聲明了三個新函數, 然後你需要在模塊裏實現它們. 你複製下麵文本內容到你的實現文件裏:

編程差不多都這樣開始,不是嗎?
現在你必須刪除這些分號,並且添加一個空的函數體. 在上圖光標處,你可以輸入”A”直接將光標移到行末並進入編輯模式:

按"A"之後,注意進入插入後光標的位置
現在你使用<backspace>鍵刪除分號:

刪除很簡單
然後 鍵入<return>{<return>}<return>,添加函數體:

插入跟其它編輯囂一樣
最後,按下<Esc>返回到正常模式下:

現在我們返回到正常模式下
現在你得重複以上步驟修改另外兩個函數。怎麼做呢?很簡, 首先按”j”移動下移一下光標,然後 點”.” 複製上一次執行的命令(”A”,刪除分號,插入文本), 如果你按”j.j.”, 兩次,你會得到如下結果:

j.j. 命令之後
VI的命令架構是關鍵,<backspace>和正常的輸入都將作為命令的一部分, 並且命令是完全可以重複執行的。回想一下,日常編輯工作中有多少是重複的操作?
誤解#2: 這不僅僅是正則表達式
VI/VIM對正則表達式的支持很好,很多編輯器都支持查找、替換等操作可以使用正則表達式,但是隻有VI(據我所知)可以更加高級地使用正則表達式,比如執行一次正則查找,然後替換”begin”第二次出現的行的包括”proc”的下一行,或者任何你能想到的複雜操作。
這不是貶低正則表達式,或者VI/VIM的正則表達式支持,VI的主要強大之處,當你習慣使用它之後依賴的強大之處 是它的基本編輯模式:
- 一兩個鍵就可以在一行或一個屏幕中任意移動到指定位置
- “d”或”c”等命令可以跟其它運作相結合從而直接編輯某些文字,或者進入插入模式,並且可以使用”.”重複任意多次
- 你的雙手可以不離開主鍵盤區就可以做任何事!這下不必擔心使用筆記本鍵盤了
示例#2: 智能範圍標記

複雜表達式中的函數調用
如你所看到的,光標處是函數調用開始的位置,現在想象我們想要展開它並將它保存在一個內部變量中,首先要做的是選擇這個調用函數,然後複製再將它移動到上麵,輸入變量名,然後再移動到上麵輸入函數聲明。 在通過編輯模型中,你需要用Ctrl-Right 和左右鍵不斷查找定位,在VIM裏不需要這樣。 “%” 會自動移動到相匹配的圓括號(或相似的分組字符), 但是如果你沒有定位到這些特殊字符位置,它會一個字符一個字符地向右掃描,直到找到第一個,然後再去查找跟它匹配的字符。因此,在上麵這種情況下,它會移動到右邊的匹配圓括號。
我們知道”c”命令,可以刪除字符(同樣會把它複製到剪切版 譯注:其它是VI裏的BUFFER, 並不是係統剪切版,下同)並且進入插入模式,我們可以在上麵這種情況下輸入”c%”,然後我們將得到下麵結果:

輸入'c%' ("change match")之後
函數調用代碼被放到了剪切版中了,然後我們現在可以輸入變量名稱了,輸入兩個字符不算太難,輸入完變量名之後按<Esc>返回到正常模式,如下:
現在進入正常模式,你可以鍵入”O”在上麵新建一行並進入插入模式,然後開始鍵入聲明語句:

鍵入 "O" 之後,輸入函數的聲明 語句前半部分
現在,我們需要插入之前的函數表達式,由於它已經在剪切版裏了,我們可以使用Ctrl-R,”在插入模式下插入粘貼(我承認它有點不好記,但它支持複合剪切版功能). 這將把我們之前聲明的函數調用語句插入到當前位置”, 我們鍵入一個分號,然後 按<Esc> 返回到插入模式:

完成
誤解#3:隻有書呆子或天才能用它
好吧,我希望看過以上的解釋和示例,你已經體會到VI/VIM的強大之處了。學習它是艱難的(如下),但如果你會看複一年地第天8小時甚至以上地編碼,這將是繼你學習打字之後的第二次最好的學習投入(你已經理解了,是嗎?如果沒有,不要怪VI,先學習它試試)。幾個周的困難學習會讓你一生受益,並且,至少不會有一個“啞巴助手” 把你煩得要死(譯注: 記得微軟office 97 的曲別針 嗎?)
關鍵是,用VI時,你的鍵盤變成了一個有上百個按鈕的超級文字輸入專用手柄, 上麵的每個鍵至少有兩個功能, 上檔和下檔,因此你至少每次按鍵(不包括Shift鍵)可以實現200個功能。文字編輯命令非常強大,並且你甚至可以組合使用它們來得到最好的結果,當你輸入一些字符時,它是普通的鍵盤,但當你回到正常模式下,它是一個文字錄入設計最好的機器。
示例#3:操縱區塊受限
另一個簡單例子, 這種隻有VIM支持(使用了VIM的一個特別動作),假如你的光標在尖括號之間,就像在XML下經常遇到的:

Life at an XML tag...
怎樣選擇尖括號內的內容呢? 在其它編輯囂中,你需要把手從現在舒適的位置移到到鍵盤的方向鍵區域,或者更糟糕,用鼠標, 無論怎樣,這可能都是很痛苦的,尤其當使用筆記本電腦時。 但,在VIM裏你怎麼做呢?你隻需要用”i”或”a”開頭的文本對象動作命令, “i>”代表“當前尖括號內的區塊”, 所以你可以用”di>”(“刪除尖括號內的內容”)來刪除上麵情形下的尖括號內的全部內容:
你可以使用”(“或”)”代表當前括號的內容區塊(或者”b”), “[" 或"]“,”{“或”}”, “w” 代表語法分隔的單詞,或者”W”代表空格分隔的單詞, 或者在它們前麵加上前綴”i” 或”a”實現相應的插入或追加功能。
誤解#4:用hjkl來移動光標嗎?
很多人對使用hjkl來代替方向鍵移動光標感到很詫異,原因可能是在當時出現VI的那個時代並沒有方向鍵,而且當時的終端電腦的鍵盤上還特別為hjkl鍵加印上了方向提示。但這樣設計帶來的一個副作用就是移動光標方向的時候不必將雙手移開主鍵盤區,這很不錯。

ADM3A:VI作者Bill Joy最初用它來編寫VIADM3A的hjkl鍵
(譯注: 當Bill Joy編寫VI的時候,用的是這台電腦,由於時代久遠,當時這台電腦隻有一個主鍵盤區(如圖),並且它的hjkl鍵上還印有方向)
但無論如何,即使你最初使用hjkl, 一旦你完全掌握了VI/VIM之後,你可能根本不會再用”h”和”l”(左和右),很少使用”j”和”k”。 為什麼呢? 因為有其它更強大的移動命令可以讓你更快地將光標移動到你想到達的位置。 當在一行內移動時,我發現總會有一個移動命令可以將光標直接定位到我想要的地方,所以我會有那些移動命令:”f”後接著任何其它字符 會 定位到字符下次出現的位置,”%”用來匹配任何你想去的地方的模式,等等.. . 當在文件中導航時,有命令可以直接定位到屏幕的 頂部/中間/底部 的位置,”/“ 可以非常容易地輸入想要查找的字符串,”]]” 可以在函數間導航 ,等等。

ADM3A的hjkl鍵
示例#4:非常有用的命令
有些命令非常有用一旦你學會使用定會愛不釋手,”H“,”M“,和”L”可以將光標直接定位到屏幕頂部、中間和底部。”zt”,”zz”和 “zb”會將光標保持在當前位置不變,滾動視圖將它移動到屏幕頂部、中間或底部。“×” 會查找當前光標所在的單詞的下一個出現位置(“#”向後查找,在鍵盤上的對稱位置所以很好記),而且還有更多這樣的命令。。。
誤解#5:由於花90%的時間思考,10%的時間編輯,也許有生產效率,但它仍然沒有用處
這些都是比較誇張的說法,但這經常被提出來反對編輯過程中獲得的對提高開發生產效率很重要的好處。我打賭這是錯誤的。
首先,有時候我的確必須要思考一個問題,而不需要去看代碼,我騎上我的自行車出去騮了一小時,或兩小時,如果天氣好的話,這比呆在電腦前思考好多了。
或者,當我必須要分析一些困難的問題或設計一套方案時,我經常拿出一本筆記本(真的紙做的筆記本),一支筆,然後用它們來梳理我的思路。
我們可以打賭,除非一些特別情況,生產工作不得不在電腦前做。這是因為,大多數時候,你必須看著代碼來思考或設計,而這包括在編輯器裏瀏覽代碼,而且,通常你的確正在繼續鍵入或編輯。你可能剛思考了一分鍾,然後 你花了另一分鍾來編輯實現你剛剛所想到的,而當你編輯的時候,你想要一個最好的工具來工作。
舒服的編輯讓你保持在那個“思考的領域”, 這個集中精神的狀態讓你有最大的生產效率,因為你掌握了一個功能強大的工具像一款文本編輯器, 而它其實從你的意識中消失了,你可以自由地集中精神於解決問題,你會下意識地去編輯實現你的想法。 通常的編輯方法是你查找定位,用Ctrl-Right, Ctrl-Right, Ctrl-Right, Ctrl-Right, Ctrl-Right 定位到你到的地方,然後你要將你的手移到鼠標上,打開菜單,選擇一個選項,進入一連串的對話框然後點擊“OK” 確認應用。 而在VI/VIM中,你所要做的隻是簡單按幾個鍵,簡單明了。
其它一些VI用也跟我分享了這些,所以我知道並不隻我一個人有這種感受: 一旦你掌握了vi, 經常會有這種感覺,在30秒鍾編輯之後,你腦中會響起一種持續敲擊鍵盤聲音的記憶, 當你在文本的各行、區塊中穿梭,移動和編輯時,感覺就像這聲音在你腦中響起,而這時候,你會有一種強大力量的感覺。
示例#5: 縮進一個區塊
VI和VIM能夠理解你的代碼結構,這可以從許多命令中體現出來。像 在上麵示例#3中提到的”aB”:選擇當前”{“和”}”以及它所包含的內容(”a}”同樣). 下麵讓我們把它與”>”操作符相結合,”<”是用來縮進一塊區域的很有用的命令。代碼如下圖:

不恰當的縮進
你多長時間會碰到這種情況?是的,你可以粘貼自動再次縮進(在VIM隻需要”]p”),但通常情況下你會忘記,或者你不是因為粘貼這段代碼而導致的這種情況,而是因為你添加或刪除而導致的。你隻需要再縮進一下即可。在其它編輯囂裏,你要移動光標,選擇,然後再按TAB鍵。而在VIM裏不需要這樣麻煩,隻需要鍵入三個鍵:”>aB”(“縮進一個區塊”):

我們甚至沒有移動光標
很酷是吧?你沒有移動光標或選擇,你隻是直接告訴VI我想怎樣做,然後VI就這樣做了。我相信正是這種“直接”編輯方式讓你感覺到了力量並且讓你進入並保持在你的狀態中。
誤解#6:它隻是執著快要消逝的過去
VI已經存在30多年了,而它現在戛然存在著。VIM,一個引進甚至比VI更多特性的VI的完全克隆,已經存在了15年了,可以在世界上差不多任何一個平台下運行。喜歡VI的人們已經找到一個在任何地方使用它的辦法:在Eclipse裏有VI的模擬插件,在許多Mac OS X apps 有VI的模擬插件,在IntelliJ IDEA裏有VI的模擬插件,這些甚至Emacs都沒有一個,而卻有一款Emacs 的 VI模擬插件several, Viper, 我開發並且出售ViEmu,一個家庭插件套裝,使VI可以在Visual Studio, SQL Server, Word 和Outlook中運行, Paul Graham 仍然用它來編寫list和arc, Tim O’Reilly 也公開承認它是Vi用戶,SlickEdit和Crisp也有VI模擬器…
當然,VI/VIM的社區並不是很多:許多計算機用戶甚至不會熟練打字,並且VI的學習曲線又很陡峭,那些見過輕巧、簡陋的編輯係統的人,因此VI/VIM編輯器肯定會繼續存在很多年。實際上,用VI/VIM的鍵綁定功能可以讓你更習慣使用VI並且在未來任何環境下都可用, 從舊的Unix操作係統到最新的流行IDE。
示例#6:可視性質
作為最後一個示例,即使看起來VI是關於一些神秘難以理解、讓人看不懂的命令,但現在我們將會看到它的一些更加可視化的方麵(事實上,它們是VIM的特性,而不是原始的VI). 其中之一:當”hlsearch”配置打開時(在VIM中默認是關閉的,但是可以使用”:set hlsearch”打開), 當你搜索一個字符時,所有匹配的結果在屏幕中都會高亮顯示。假設你有以下html代碼:

HTML代碼
如果你按”*”,會查找當前光標下的單詞(”div”),結果會是這樣子:

強大的星號
正如你所看到的,光標移動了,而且不同地方的結果都被高亮了。
還有更多,我們知道像”d”和”c”這樣的操作符會根據下一條命令執行,好的,如果我們想要可視化反饋,我們可以使用可視化模式:按”v”, 移動光標時你會看到從初始位置的區域到光標處會被高亮,然後接著按下操作符可以直接看到效果。搜索命令在這裏同樣適用。 如果你用”V”替代“v”, 會以行為單位高亮。 現在我們按下 “V”,然後 “k”(上):

按下 Vk之後
如你所見,這兩行被高亮以示選中。假如我們想要選擇直到div的閉合標簽(如高亮顯示),輸入”N”(上個匹配結果):

按"N"之後
現在我們可以做任何我們想做的了,假如”gU”操作會讓所有字符變為大寫(然後返回到正常模式下):

華麗的大寫
好吧,現在讓我們來為VI/VIM的理解做下正確的解釋:
正確的理解#1:陡峭的學習曲線
有一件事是大家所一致認同的,並且也是正確的,這張圖準確地說明了這一點:
事實是,學習VI/VIM是非常費時(幾周到幾月),並且第一次嚐試是很不愉快的。我把這一點當作是為什麼VI/VIM不是,並且將不可能是流行的編輯器的主要原因。相比其它編輯器,你需要付出相當多的努力去學習、記憶,然後將30條或更多的命令運用嫻熟才會讓你使用VI/VIM更有效率。由於這些命令都是些粗略的一鍵命令(縱使它們都有一些助記方法,甚至有些形式是用起來是一致的),這仍然不是一項簡單的任務,簡單的是認輸並且返回使用熟悉的jedit或pico, UltraEdit或TextMate, 或者甚至emacs, 但是一旦你努力學習了,我知道沒有人會想要再返回用那些編輯器,並且我知道有很多人說他們已經用VI超過了10年,並且他們已經習慣,並且在期待即使是最小的細節改進。
結尾語
隨便你想用還是不用,如果你覺得學習使用VI/VIM會白費力氣,那就去學習Emacs, 或者繼續用你的差勁的IDE。 無論如何,在任何情況下,不要再說”用VI的人都是些死腦筋“,我希望我已經成功地向你展示了為什麼他們(我們)堅持使用VI/VIM, 並且你至少應該能夠理解它的強大,即使你仍然偏向不使用它。
如果你想研究VI/VIM編輯器的更多功能,這裏有一些有用的資料:
- Learn why I got started
- Use my graphical cheat sheet and tutorial to learn vi/vim editing
- The awesome “vi lovers” home page
- Learn Jonathan McPherson’s hints for effective editing with vim
- Go to vim’s homepage for anything you want
(特別感謝 Ivan Vecerina, Andrey Butov, Jose Gonzalvo, Mark Petrik Sosa, Aitor Garay and Woody Thrower 對這篇文章的草稿的評論)
(所有的截圖是從 Visual Studio with ViEmu, 我的商業版VI插件, 以及 codekana, 我的下一個產品,提供更加強大的語法高亮功能)
最後更新:2017-04-03 20:19:52