為什么這些死腦筋們在用 VI?
不管你們信不信,現(xiàn)在有很多人迷戀這個30多年歷史的VI編輯器(最好的克隆和改進版本VIM也已經(jīng)有15歲了).
他們不是守舊派,跟不上時代潮流——VI用戶的社區(qū)正在不斷增長著,我自己用VI已經(jīng)2年了(在有了10年編程經(jīng)驗之后),我的很多朋友也都開始使用VI了,有趣的是,有很VI用戶在VI出現(xiàn)前還沒有出生。
當然,VI/VIM編輯模式比其它任何編輯囂都出眾肯定有原因的,你不必非得是Unix高手才能用它,相反,VIM可以免費在任何平臺下使用,并且它也可以作為其它主流IDE的插件使用,現(xiàn)在讓我來澄清幾個誤解,并用一些真實例子說明為什么它是極好的編輯器。
誤解#1:模態(tài)編輯
你第一次被VI/VIM難住,可能是對必須先用”i”才能開始編輯感覺震驚和厭惡,記不住使用”hjkl”來移動光標方向,并且需要按”a”才能在光標后面追加內容.因為你可能已經(jīng)習慣使用其它編輯囂,并且方向鍵在插入模式管用(90%情況下是這樣的,如果系統(tǒng)配置正確的話),你可能除特別需要,保持在插入模式而不會返回到正常模式. 你可能會花20分鐘在插入模式下,并且會抱怨:”我到底可怎么記住現(xiàn)在正在插入模式下還是正常模式下?”
很顯然,這是一個完全錯誤的使用VI/VIM的方式,正確方式是,你不會在意模式,你會一直在正常模式下,只有當需要插入或修改字符時才會進入插入模式,編輯完成之后馬上按<Esc>返回到正常模式.因此,如何記住當前模式問題并不存在.當你在編輯文字的時候,不要在插入模式去接聽電話,而應該退出插入模式,接聽電話,或者返回的時候按<Esc>進入正常模式.不要把插入模式當成一種狀態(tài).
讓我來解釋下這其中的哲學.
VI/VIM中的命令是可以組合使用的,比如”d”代表刪除,”e”代表”移到單詞末尾”,而”de”的功能就是刪除從當前光標位置至單詞結尾間的字符(有點像Ctrl-Shift-Right, Left, Del 快捷鍵在其它編輯器中實現(xiàn)的功能)
這樣的好處之一是,”.”命令可以重復上次執(zhí)行完成的組合命令(不包括移動命令), 執(zhí)行完”dw”后,”.”會重復執(zhí)行”dw”命令, 你可以移動光標,然后再按”.”會快速地刪除當前光標處的下一個單詞,這樣讓人感到難以置信的強大.
現(xiàn)在我們來看下插入模式. 一些命令(比如i,a,s等)可以讓你進入插入模式鍵入文本直到按<Esc>, 說到這些命令, 整條命令也包括你在”i”命令和<Esc>之間鍵入的所有字符.
比如”iHello<Esc>”, 會在當前光標處插入”Hello”字符,而現(xiàn)在”.”命令可以在當前光標處重復插入”Hello”, 現(xiàn)在你應該能夠明白強大之處了吧, 但還有更強大的, “A”會將光標移到當前行末尾并進入編輯模式, 因此, 當按<Esc>結束輸入后,你可以按”.”在任何位置的行末插入相同的字符.
另外一個更加強大的例子是: “ce”命令, 由”c”和”e”組合而成,”c”(修改)命令會刪除指定范圍內的文本并進入插入模式,與”d”(刪除)命令一樣,但唯一不同的是它會進入插入模式而不是停留在正常模式. 這樣的好處是你在這條命令之后所鍵入的文本同樣也會作為這條命令的一部分. 因此如果你輸入”ceHello<Esc>”, 將會替換當前光標位置到行末的內容為”Hello”, 而”.”命令同樣也會重復這個運作.
動作(光標移動命令)也可以更加復雜, 有很多各種進入插入模式的命令(“o”會在當前行下插入新一行,”O”會在上面插入新一行,”S”會刪除到行末的內容,等等…所有這些命令都會進入插入模式), 因此你可以想象,使用”.”可以創(chuàng)建重復執(zhí)行多么強大的編輯命令.
示例#1: 完美的點命令
讓我們來一個示例. 比如你已經(jīng)在你的頭文件中聲明了三個新函數(shù), 然后你需要在模塊里實現(xiàn)它們. 你復制下面文本內容到你的實現(xiàn)文件里:
編程差不多都這樣開始,不是嗎?
現(xiàn)在你必須刪除這些分號,并且添加一個空的函數(shù)體. 在上圖光標處,你可以輸入”A”直接將光標移到行末并進入編輯模式:
按"A"之后,注意進入插入后光標的位置
現(xiàn)在你使用<backspace>鍵刪除分號:
刪除很簡單
然后 鍵入<return>{<return>}<return>,添加函數(shù)體:
插入跟其它編輯囂一樣
最后,按下<Esc>返回到正常模式下:
現(xiàn)在我們返回到正常模式下
現(xiàn)在你得重復以上步驟修改另外兩個函數(shù)。怎么做呢?很簡, 首先按”j”移動下移一下光標,然后 點”.” 復制上一次執(zhí)行的命令(”A”,刪除分號,插入文本), 如果你按”j.j.”, 兩次,你會得到如下結果:
j.j. 命令之后
VI的命令架構是關鍵,<backspace>和正常的輸入都將作為命令的一部分, 并且命令是完全可以重復執(zhí)行的?;叵胍幌?,日常編輯工作中有多少是重復的操作?
誤解#2: 這不僅僅是正則表達式
VI/VIM對正則表達式的支持很好,很多編輯器都支持查找、替換等操作可以使用正則表達式,但是只有VI(據(jù)我所知)可以更加高級地使用正則表達式,比如執(zhí)行一次正則查找,然后替換”begin”第二次出現(xiàn)的行的包括”proc”的下一行,或者任何你能想到的復雜操作。
這不是貶低正則表達式,或者VI/VIM的正則表達式支持,VI的主要強大之處,當你習慣使用它之后依賴的強大之處 是它的基本編輯模式:
- 一兩個鍵就可以在一行或一個屏幕中任意移動到指定位置
- “d”或”c”等命令可以跟其它運作相結合從而直接編輯某些文字,或者進入插入模式,并且可以使用”.”重復任意多次
- 你的雙手可以不離開主鍵盤區(qū)就可以做任何事!這下不必擔心使用筆記本鍵盤了
示例#2: 智能范圍標記
讓我們下看下下面這個典型示例。這是一個嵌入在某個復雜表達式中的函數(shù)調用:
復雜表達式中的函數(shù)調用
如你所看到的,光標處是函數(shù)調用開始的位置,現(xiàn)在想象我們想要展開它并將它保存在一個內部變量中,首先要做的是選擇這個調用函數(shù),然后復制再將它移動到上面,輸入變量名,然后再移動到上面輸入函數(shù)聲明。 在通過編輯模型中,你需要用Ctrl-Right 和左右鍵不斷查找定位,在VIM里不需要這樣。 “%” 會自動移動到相匹配的圓括號(或相似的分組字符), 但是如果你沒有定位到這些特殊字符位置,它會一個字符一個字符地向右掃描,直到找到第一個,然后再去查找跟它匹配的字符。因此,在上面這種情況下,它會移動到右邊的匹配圓括號。
我們知道”c”命令,可以刪除字符(同樣會把它復制到剪切版 譯注:其它是VI里的BUFFER, 并不是系統(tǒng)剪切版,下同)并且進入插入模式,我們可以在上面這種情況下輸入”c%”,然后我們將得到下面結果:
輸入'c%' ("change match")之后
函數(shù)調用代碼被放到了剪切版中了,然后我們現(xiàn)在可以輸入變量名稱了,輸入兩個字符不算太難,輸入完變量名之后按<Esc>返回到正常模式,如下:
輸入字符然后按<Esc>
現(xiàn)在進入正常模式,你可以鍵入”O”在上面新建一行并進入插入模式,然后開始鍵入聲明語句:
鍵入 "O" 之后,輸入函數(shù)的聲明 語句前半部分
現(xiàn)在,我們需要插入之前的函數(shù)表達式,由于它已經(jīng)在剪切版里了,我們可以使用Ctrl-R,”在插入模式下插入粘貼(我承認它有點不好記,但它支持復合剪切版功能). 這將把我們之前聲明的函數(shù)調用語句插入到當前位置”, 我們鍵入一個分號,然后 按<Esc> 返回到插入模式:
完成
誤解#3:只有書呆子或天才能用它
好吧,我希望看過以上的解釋和示例,你已經(jīng)體會到VI/VIM的強大之處了。學習它是艱難的(如下),但如果你會看復一年地第天8小時甚至以上地編碼,這將是繼你學習打字之后的第二次最好的學習投入(你已經(jīng)理解了,是嗎?如果沒有,不要怪VI,先學習它試試)。幾個周的困難學習會讓你一生受益,并且,至少不會有一個“啞巴助手” 把你煩得要死(譯注: 記得微軟office 97 的曲別針 嗎?)
關鍵是,用VI時,你的鍵盤變成了一個有上百個按鈕的超級文字輸入專用手柄, 上面的每個鍵至少有兩個功能, 上檔和下檔,因此你至少每次按鍵(不包括Shift鍵)可以實現(xiàn)200個功能。文字編輯命令非常強大,并且你甚至可以組合使用它們來得到最好的結果,當你輸入一些字符時,它是普通的鍵盤,但當你回到正常模式下,它是一個文字錄入設計最好的機器。
示例#3:操縱區(qū)塊受限
另一個簡單例子, 這種只有VIM支持(使用了VIM的一個特別動作),假如你的光標在尖括號之間,就像在XML下經(jīng)常遇到的:
Life at an XML tag...
怎樣選擇尖括號內的內容呢? 在其它編輯囂中,你需要把手從現(xiàn)在舒適的位置移到到鍵盤的方向鍵區(qū)域,或者更糟糕,用鼠標, 無論怎樣,這可能都是很痛苦的,尤其當使用筆記本電腦時。 但,在VIM里你怎么做呢?你只需要用”i”或”a”開頭的文本對象動作命令, “i>”代表“當前尖括號內的區(qū)塊”, 所以你可以用”di>”(“刪除尖括號內的內容”)來刪除上面情形下的尖括號內的全部內容:
After typing di> ("delete inner angle-block")
你可以使用”(“或”)”代表當前括號的內容區(qū)塊(或者”b”), “[" 或"]“,”{“或”}”, “w” 代表語法分隔的單詞,或者”W”代表空格分隔的單詞, 或者在它們前面加上前綴”i” 或”a”實現(xiàn)相應的插入或追加功能。
誤解#4:用hjkl來移動光標嗎?
很多人對使用hjkl來代替方向鍵移動光標感到很詫異,原因可能是在當時出現(xiàn)VI的那個時代并沒有方向鍵,而且當時的終端電腦的鍵盤上還特別為hjkl鍵加印上了方向提示。但這樣設計帶來的一個副作用就是移動光標方向的時候不必將雙手移開主鍵盤區(qū),這很不錯。
ADM3A:VI作者Bill Joy最初用它來編寫VIADM3A的hjkl鍵
(譯注: 當Bill Joy編寫VI的時候,用的是這臺電腦,由于時代久遠,當時這臺電腦只有一個主鍵盤區(qū)(如圖),并且它的hjkl鍵上還印有方向)
但無論如何,即使你最初使用hjkl, 一旦你完全掌握了VI/VIM之后,你可能根本不會再用”h”和”l”(左和右),很少使用”j”和”k”。 為什么呢? 因為有其它更強大的移動命令可以讓你更快地將光標移動到你想到達的位置。 當在一行內移動時,我發(fā)現(xiàn)總會有一個移動命令可以將光標直接定位到我想要的地方,所以我會有那些移動命令:”f”后接著任何其它字符 會 定位到字符下次出現(xiàn)的位置,”%”用來匹配任何你想去的地方的模式,等等.. . 當在文件中導航時,有命令可以直接定位到屏幕的 頂部/中間/底部 的位置,”/“ 可以非常容易地輸入想要查找的字符串,”]]” 可以在函數(shù)間導航 ,等等。
ADM3A的hjkl鍵
示例#4:非常有用的命令
有些命令非常有用一旦你學會使用定會愛不釋手,”H“,”M“,和”L”可以將光標直接定位到屏幕頂部、中間和底部。”zt”,”zz”和 “zb”會將光標保持在當前位置不變,滾動視圖將它移動到屏幕頂部、中間或底部。“×” 會查找當前光標所在的單詞的下一個出現(xiàn)位置(“#”向后查找,在鍵盤上的對稱位置所以很好記),而且還有更多這樣的命令。。。
誤解#5:由于花90%的時間思考,10%的時間編輯,也許有生產(chǎn)效率,但它仍然沒有用處
這些都是比較夸張的說法,但這經(jīng)常被提出來反對編輯過程中獲得的對提高開發(fā)生產(chǎn)效率很重要的好處。我打賭這是錯誤的。
首先,有時候我的確必須要思考一個問題,而不需要去看代碼,我騎上我的自行車出去騮了一小時,或兩小時,如果天氣好的話,這比呆在電腦前思考好多了。
或者,當我必須要分析一些困難的問題或設計一套方案時,我經(jīng)常拿出一本筆記本(真的紙做的筆記本),一支筆,然后用它們來梳理我的思路。
我們可以打賭,除非一些特別情況,生產(chǎn)工作不得不在電腦前做。這是因為,大多數(shù)時候,你必須看著代碼來思考或設計,而這包括在編輯器里瀏覽代碼,而且,通常你的確正在繼續(xù)鍵入或編輯。你可能剛思考了一分鐘,然后 你花了另一分鐘來編輯實現(xiàn)你剛剛所想到的,而當你編輯的時候,你想要一個最好的工具來工作。
舒服的編輯讓你保持在那個“思考的領域”, 這個集中精神的狀態(tài)讓你有最大的生產(chǎn)效率,因為你掌握了一個功能強大的工具像一款文本編輯器, 而它其實從你的意識中消失了,你可以自由地集中精神于解決問題,你會下意識地去編輯實現(xiàn)你的想法。 通常的編輯方法是你查找定位,用Ctrl-Right, Ctrl-Right, Ctrl-Right, Ctrl-Right, Ctrl-Right 定位到你到的地方,然后你要將你的手移到鼠標上,打開菜單,選擇一個選項,進入一連串的對話框然后點擊“OK” 確認應用。 而在VI/VIM中,你所要做的只是簡單按幾個鍵,簡單明了。
其它一些VI用也跟我分享了這些,所以我知道并不只我一個人有這種感受: 一旦你掌握了vi, 經(jīng)常會有這種感覺,在30秒鐘編輯之后,你腦中會響起一種持續(xù)敲擊鍵盤聲音的記憶, 當你在文本的各行、區(qū)塊中穿梭,移動和編輯時,感覺就像這聲音在你腦中響起,而這時候,你會有一種強大力量的感覺。
示例#5: 縮進一個區(qū)塊
VI和VIM能夠理解你的代碼結構,這可以從許多命令中體現(xiàn)出來。像 在上面示例#3中提到的”aB”:選擇當前”{“和”}”以及它所包含的內容(”a}”同樣). 下面讓我們把它與”>”操作符相結合,”<”是用來縮進一塊區(qū)域的很有用的命令。代碼如下圖:
不恰當?shù)目s進
你多長時間會碰到這種情況?是的,你可以粘貼自動再次縮進(在VIM只需要”]p”),但通常情況下你會忘記,或者你不是因為粘貼這段代碼而導致的這種情況,而是因為你添加或刪除而導致的。你只需要再縮進一下即可。在其它編輯囂里,你要移動光標,選擇,然后再按TAB鍵。而在VIM里不需要這樣麻煩,只需要鍵入三個鍵:”>aB”(“縮進一個區(qū)塊”):
我們甚至沒有移動光標
很酷是吧?你沒有移動光標或選擇,你只是直接告訴VI我想怎樣做,然后VI就這樣做了。我相信正是這種“直接”編輯方式讓你感覺到了力量并且讓你進入并保持在你的狀態(tài)中。
誤解#6:它只是執(zhí)著快要消逝的過去
VI已經(jīng)存在30多年了,而它現(xiàn)在戛然存在著。VIM,一個引進甚至比VI更多特性的VI的完全克隆,已經(jīng)存在了15年了,可以在世界上差不多任何一個平臺下運行。喜歡VI的人們已經(jīng)找到一個在任何地方使用它的辦法:在Eclipse里有VI的模擬插件,在許多Mac OS X apps 有VI的模擬插件,在IntelliJ IDEA里有VI的模擬插件,這些甚至Emacs都沒有一個,而卻有一款Emacs 的 VI模擬插件several, Viper, 我開發(fā)并且出售ViEmu,一個家庭插件套裝,使VI可以在Visual Studio, SQL Server, Word 和Outlook中運行, Paul Graham 仍然用它來編寫list和arc, Tim O’Reilly 也公開承認它是Vi用戶,SlickEdit和Crisp也有VI模擬器…
當然,VI/VIM的社區(qū)并不是很多:許多計算機用戶甚至不會熟練打字,并且VI的學習曲線又很陡峭,那些見過輕巧、簡陋的編輯系統(tǒng)的人,因此VI/VIM編輯器肯定會繼續(xù)存在很多年。實際上,用VI/VIM的鍵綁定功能可以讓你更習慣使用VI并且在未來任何環(huán)境下都可用, 從舊的Unix操作系統(tǒng)到最新的流行IDE。
示例#6:可視性質
作為最后一個示例,即使看起來VI是關于一些神秘難以理解、讓人看不懂的命令,但現(xiàn)在我們將會看到它的一些更加可視化的方面(事實上,它們是VIM的特性,而不是原始的VI). 其中之一:當”hlsearch”配置打開時(在VIM中默認是關閉的,但是可以使用”:set hlsearch”打開), 當你搜索一個字符時,所有匹配的結果在屏幕中都會高亮顯示。假設你有以下html代碼:
HTML代碼
如果你按”*”,會查找當前光標下的單詞(”p”),結果會是這樣子:
強大的星號
正如你所看到的,光標移動了,而且不同地方的結果都被高亮了。
還有更多,我們知道像”d”和”c”這樣的操作符會根據(jù)下一條命令執(zhí)行,好的,如果我們想要可視化反饋,我們可以使用可視化模式:按”v”, 移動光標時你會看到從初始位置的區(qū)域到光標處會被高亮,然后接著按下操作符可以直接看到效果。搜索命令在這里同樣適用。 如果你用”V”替代“v”, 會以行為單位高亮。 現(xiàn)在我們按下 “V”,然后 “k”(上):
按下 Vk之后
如你所見,這兩行被高亮以示選中。假如我們想要選擇直到p的閉合標簽(如高亮顯示),輸入”N”(上個匹配結果):
按"N"之后
現(xiàn)在我們可以做任何我們想做的了,假如”gU”操作會讓所有字符變?yōu)榇髮懀ㄈ缓蠓祷氐秸DJ较拢?
華麗的大寫
好吧,現(xiàn)在讓我們來為VI/VIM的理解做下正確的解釋:
正確的理解#1:陡峭的學習曲線
有一件事是大家所一致認同的,并且也是正確的,這張圖準確地說明了這一點:
事實是,學習VI/VIM是非常費時(幾周到幾月),并且第一次嘗試是很不愉快的。我把這一點當作是為什么VI/VIM不是,并且將不可能是流行的編輯器的主要原因。相比其它編輯器,你需要付出相當多的努力去學習、記憶,然后將30條或更多的命令運用嫻熟才會讓你使用VI/VIM更有效率。由于這些命令都是些粗略的一鍵命令(縱使它們都有一些助記方法,甚至有些形式是用起來是一致的),這仍然不是一項簡單的任務,簡單的是認輸并且返回使用熟悉的jedit或pico, UltraEdit或TextMate, 或者甚至emacs, 但是一旦你努力學習了,我知道沒有人會想要再返回用那些編輯器,并且我知道有很多人說他們已經(jīng)用VI超過了10年,并且他們已經(jīng)習慣,并且在期待即使是最小的細節(jié)改進。
結尾語
隨便你想用還是不用,如果你覺得學習使用VI/VIM會白費力氣,那就去學習Emacs, 或者繼續(xù)用你的差勁的IDE。 無論如何,在任何情況下,不要再說”用VI的人都是些死腦筋“,我希望我已經(jīng)成功地向你展示了為什么他們(我們)堅持使用VI/VIM, 并且你至少應該能夠理解它的強大,即使你仍然偏向不使用它。