Vim 實用技術,第 1 部分: 實用技巧

0. Vim 簡介php

做爲開源世界最重要的編輯器之一(另外一個是 Emacs),Vim 以其強大的功能和可定製能力被衆多開發者所喜好。不過,也許就是由於 Vim 的功能太強大了,要真正用好 Vim 並不容易。本文做者在多年的實際使用中逐漸掌握了一些實用技術,在此介紹給你們。——本文並不企圖對 Vim 做全面而系統的介紹,但也絕非零星地點到即止;而是但願經過介紹一些重要特性和提供相關參考信息,引發你們的興趣,去深刻挖掘其能力,真正把這一強大的工 具用好。html

下面首先對 Vim 作一下最基本的介紹,並給出一些參考信息,以方便對 Vim 不熟悉的讀者也可以理解並本身查閱進一步信息。程序員

與大部分其它編輯器不一樣,進入 Vim 後,缺省狀態下鍵入的字符並不會插入到所編輯的文件之中。Vim 的模式(mode,能夠簡單地理解爲「狀態」)概念很是重要。須要知道,Vim 有如下幾個模式:正則表達式

●正常(normal)模式,缺省的編輯模式;下面若是不加特殊說明,提到的命令都直接在正常模式下輸入;任何其它模式中均可以經過鍵盤上的 Esc 鍵回到正常模式。編程

●命令(command)模式,用於執行較長、較複雜的命令;在正常模式下輸入「:」(通常命令)、「/」(正向搜索)或「?」(反向搜索)便可進入該模式;命令模式下的命令要輸入回車鍵(Enter)纔算完成。vim

●插入(insert)模式,輸入文本時使用;在正常模式下鍵入「i」(insert)或「a」(append)便可進入插入模式(也有另一些命令,如「c」,也能夠進入插入模式,但這些命令有其它的做用)。安全

●可視(visual)模式,用於選定文本塊;能夠在正常模式下輸入「v」(小寫)來按字符選定,輸入「V」(大寫)來按行選定,或輸入「Ctrl-V」來按方塊選定。app

●選擇(select)模式,與普通的 Windows 編輯器較爲接近的選擇文本塊的方式;在以可視模式和選擇模式之一選定文本塊以後,可使用「Ctrl-G」切換到另外一模式——該模式不多在 Linux 上使用,本文中就再也不介紹了。編程語言

Vim 帶有完整的幫助文檔。在當前的 Vim 6.4 的標準發佈中,有一百多章、近六十萬英文詞的幫助文件,進入 Vim 後輸入「:help」(命令模式中輸入的命令要敲回車鍵才結束輸入,下面再也不說明這一點)便可訪問。本文在介紹特性時,對文檔中已經說明得很詳細的內容只 會提綱挈領地加以簡短說明和提供應用範例,並提供訪問相應的 Vim 文檔的命令。編輯器

通常的發佈版中還經常帶有一個簡單的 30 分鐘的 Vim 教程,新手在操做系統的命令行上輸入「vimtutor」命令便可開始學習。除上面的簡單說明外,本文並不介紹最基本的 Vim 命令,Vim 的新手應該先經過教程熟悉一下 Vim,再繼續往下閱讀。

建議全部的 Vim 用戶常常訪問 Vim 的主站點 [1]。上面除了基本的發佈、安裝、下載等信息外,最有用的內容是用戶能夠上傳本身寫的 Vim 腳本(script)和撰寫本身認爲有用的提示(tip),供其餘 Vim 用戶使用。在寫這一段的時候,Vim 站點上已有一千三百多個腳本,提示數恰好超過了一千。對於序號爲 nn 的腳本,直接訪問的 URL 是 http://www.vim.org/scripts/script.php?script_id=nn;對於序號爲 nn 的提示,直接訪問的 URL 是 http://www.vim.org/tips/tip.php?tip_id=nn。

不另加說明的話,本文討論的內容適用於 Vim 版本 6(即從 6.0 到 6.4)。建議認真的 Vim 用戶升級到 Vim 6.4,最好是本身編譯升級全部的補丁包。相關信息網站上都有,此處再也不贅述。

1. 實用技巧

1.1 安裝

若是從 Linux 發佈版直接安裝 Vim,須要注意的一點是,缺省狀況下系統並不必定爲你安裝了一個完整的 Vim。好比,在 Red Hat(以及後來的 Fedora Core)的發佈版中,Vim 被拆成了四個包:vim-common(公用部分),vim-minimal(最小安裝),vim-enhanced(除 X Window 支持外的完整安裝),和 vim-X11(X Window 圖形界面支持)。最小安裝不能完整展現 Vim 的優勢,一般只是做爲 vi 的替代品出現,缺乏不少重要的特性如多字節語言支持、鼠標支持和腳本支持。若是裝了 X Window 的話,圖形界面的 gvim 也比文本模式的 vim 具備更多的特性。建議你們儘量安裝徹底的 Vim。

若是願意稍稍費一點功夫,本身編譯 Vim 的話,能夠更好地定製 Vim。——附帶的另外一個好處是,你若是發現什麼錯誤的話,你就能夠本身動手來修復這個錯誤,或至少找到錯誤所在的位置,讓 Bram(Vim 的做者)能夠更快地解決問題。圖 1 是在 Vim 中執行「:version」的結果的一部分,能夠看到 Vim 有不少不一樣的特性(feature)可在編譯時打開或關閉。若是本身編譯的話,就能夠選擇打開須要的功能,關閉不須要的功能,來得到一個既功能強大、又小 巧快速的 Vim 定製版本。

圖 1

Vim 實用技術,第 1 部分: 實用技巧

1.2 中文支持

Vim 支持世界上的主要語言,固然也包括中文。若是你用 Vim 編輯中文,而中文不能正確顯示,那有兩種可能性:一是使用的 Vim 不完整,不含多字節語言支持(multi_byte 特性);二是某個配置出了問題。

說到多語言支持,最基本的概念有兩個:一是文件的語言編碼,而是環境的內部編碼。在較老的操做系統中,無論 Linux 仍是 Windows,這兩個編碼都是同樣的,也就意味着,一次只能處理一種編碼的文件:要麼只能處理西文編碼(Latin1,即 ISO-8859-1 [5]),要麼只能處理中文編碼(GB2312 [2])。而在新的操做系統中,這二者能夠是不同的。在 Linux 上,常見的狀況是環境的內部編碼使用 UTF-8 [6],而 UTF-8 能夠同任何一種語言編碼做無損轉換,這就保證了系統的多語言處理能力。Vim 這方面秉承了 Unix/Linux 的傳統,在內部編碼使 UTF-8 的時候,能夠同時處理不一樣意語言編碼的文件。

如下列出了和語言編碼的相關的設置:

●環境變量 LANG(使用的語言);

●環境變量 LC_CTYPE(使用的內部編碼);

●Vim 選項 encoding(Vim 的內部編碼);

●Vim 選項 termencoding(Vim 在與屏幕/鍵盤交互時使用的編碼);

●Vim 選項 fileencoding(Vim 當前編輯的文件在存儲時的編碼);

●Vim 選項 fileencodings(Vim 打開文件時的嘗試使用的編碼);

●Vim 選項 ambiwidth(對「不明寬度」字符的處理方式;Vim 6.1.455 後引入)。

若是你的環境只須要處理簡體中文的話,那麼,最簡單的方式就是全部的設定所有使用簡體中文。只須要:設定.GB2312,不設定 LC_CTYPE(默認跟 LANG 同樣),不設定與編碼相關的 Vim 選項(默認由 LANG 和 LC_CTYPE 決定),也無需設定 Vim 選項 ambiwidth。也就是說,咱們把語言設定爲中國(CN)使用的中文(zh),編碼爲 GB2312(注意:Vim 內部並不識別國標 GB18030 [3],因此此處只能設 GB2312;參看下面關於 UTF-8 的討論)。

不過,若是按照目前 Linux 下的慣例,內部編碼一概使用 UTF-8 的話,會有一些額外的好處,其中之一就是在這種狀況下 Vim 支持同時編輯多種不一樣編碼的文件,如簡體中文和繁體中文(參見圖 2);另外,此時 Vim 也能夠經過編碼轉換支持 GBK [4] 和 GB18030了。這樣,衆多關於語言編碼的 Vim 選項就有了用武之地了。下面進一步說明一下這些選項和推薦設定(若是適用的話):

圖 2

Vim 實用技術,第 1 部分: 實用技巧

●encoding=utf-8:無論文件的編碼如何,無論如何顯示和輸入,Vim 內部使用的編碼是 UTF-8;這是國際化支持的基礎。

●termencoding:取決於實際的終端或 X Window 的設定。舉例來講,若是選擇語言簡體中文登陸到 X Window,或者正在使用 CXTERM [10] 的話,那麼該選項應被設爲 GB2312;若是使用缺省的語言(LANG=en_US.UTF-8)登陸到 X Window,或者使用 PuTTY [11] 遠程訪問 Linux 機器、而且設定裏的字符編碼(配置中 Window-Translation)設爲 UTF-8 的話,該選項就應該設爲 utf-8。從 Windows 下使用 PuTTY 遠程鏈接 Linux 的請特別注意,測試代表,僅在使用 UTF-8 的狀況下,PuTTY 才能可靠地支持中文的顯示和輸入(顯示字體必須設成中文字體)。

●fileencoding:文件載入時,該選項被置爲 Vim 認定的文件編碼,所以,存儲時文件的編碼不會改變。此處和下面 fileencodings 可以使用的編碼爲 libiconv 支持的全部幾百種編碼(若是編譯時包含了 iconv 特性的話),與中文相關的有 gb23十二、gbk、gb18030、hz-gb-23十二、iso-2022-cn、big五、cp93六、cp950 等。若是建立新文件,你又不但願使用 UTF-8 做爲文件編碼時,那麼,你可能須要手工設定該選項,如「:set fileencoding=gb2312」。須要注意的一點是,使用「set」來設定該選項的話會改變之後新建文件的缺省編碼,而使用 「setlocal」的話則隻影響當前文件(參考「:help setlocal」)。

●fileencodings=ucs-bom,utf-8,chinese:Vim 會首先判斷文件的開頭是不是一個 Unicode [7] 的 BOM(byte order mark)字符 [8],是的話則把文件的其他內容解釋成相應的 Unicode 序列;否的話再試圖把文件內容解釋成 UTF-8 的序列;再失敗的話,則把文件解釋爲簡體中文(chinese 是一個跨平臺的簡體中文字符集的別名,Linux 下至關於 gb2312 和 euc-cn;此處也能夠根據須要以 gb23十二、gbk 或 gb18030 等編碼替代)。須要注意的是,該順序不能顛倒,而且在後面再添加其它編碼如 big五、latin1 也是沒有意義的,由於 Vim 不能識別 8 比特編碼中的錯誤,所以這些編碼後列的編碼永遠不會被用到。

●ambiwidth=double:把全部的「不明寬度」字符 [9]——指的是在 Unicode 字符集中某些同時在東西方語言中使用的字符,如省略號、破折號、書名號和全角引號,在西方文字中一般字符寬度等同於普通 ASCII 字符,而在東方文字中一般字符寬度等同於兩倍的普通 ASCII 字符,於是其寬度「不明」——的寬度置爲雙倍字符寬度(中文字符寬度)。此數值只在 encoding 設爲 utf-8 或某一 Unicode 編碼時纔有效。須要額外注意的是,若是你經過終端使用 Vim 的話,須要令終端也將這些字符顯示爲雙寬度。好比,XTERM [12] 的狀況下應該使用選項「-cjk」,即便用命令「uxterm -cjk」來啓動使用雙寬度顯示這些字符的 Unicode X 終端;使用 PuTTY 遠程鏈接的話則應在配置的 Window-Translation 中選中「Treat CJK ambiguous characters as wide」(參見圖 3)。

圖 3

Vim 實用技術,第 1 部分: 實用技巧

須要設定的選項一般放在用戶的 Vim 資源配置文件中,即在 ~/.vimrc 文件中加入:

1234 set encoding=utf-8 set fileencoding=chinese set fileencodings=ucs-bom,utf-8,chinese set ambiwidth=double

若是想進一步瞭解這些選項的話,可使用「:help ‘選項’」查看幫助文檔中的相關(英文)信息。幫助中也能夠查到這些選項(以及命令)的縮寫:本文中爲方便理解,除一些極少有人使用完整拼寫的命令如 「:e(dit)」、「:s(ubstitute)」等以外,通常使用完整拼寫而不說明或使用縮寫。關於配置文件 .vimrc,可使用「:help .vimrc」查看相關信息。

在使用內部編碼 UTF-8 的狀況下,如需編輯 fileencodings 以外(其不能自動識別)的文件,則可使用如下命令:「:e ++enc=編碼 文件名」。詳情可參考「:help ++enc」。

1.3. 鼠標支持

無論是文本界面仍是圖形界面的 Vim,都支持鼠標。不過,在文本界面中,鼠標支持缺省沒有被激活;這就意味着,在終端上使用鼠標,全部的功能仍和沒有使用 Vim 時相同,並不受 Vim 影響。要激活文本界面中的鼠標支持也很容易,只須要執行一句「:set mouse=a」便可。

啓用了鼠標支持以後,Vim 主要支持的鼠標操做有:

●單擊移動光標到點擊的位置;

●在幫助的關鍵字上雙擊顯示該關鍵字相關的幫助信息;

●在普通文本上雙擊選中點擊位置的單詞;

●拖動鼠標選中文本;

●使用鼠標滾輪滾動當前緩衝區中的文本;

●多窗口編輯時能夠拖動窗口分欄的位置。

進一步的信息可參看「:help ‘mouse’」、「:help mouse-using」和「:help scroll-mouse-wheel」。

特別須要值得一提的是,在遠程訪問 Linux 系統時也是可使用鼠標的。若是使用 X Window 系統,天然沒必要說;而使用 SSH 遠程鏈接時,大部分 Linux 下的終端客戶程序,如 XTERM、GNOME-Terminal [13]、較新版本的 Konsole [14],以及 Windows 下的 PuTTY,支持鼠標的使用:你只需簡單地啓動 Vim、執行一句「:set mouse=a」就能夠了(固然,也能夠把上面的語句去掉起始的冒號放到 .vimrc 文件中)。

1.4. 空格、製表符和縮進

對於編寫代碼,縮進是最基本的概念之一。至於縮進是使用空格仍是製表符(Tab),或者縮進是否正好使用一個製表符來表示,不少程序員,特別是 Windows 開發出身的程序員,很容易混淆。幸虧,Vim 對於這些概念有很是完整的支持,足以應付各類複雜的狀況。如下是相關的主要 Vim 選項:

●shiftwidth(縮進的空格數);

●tabstop(製表符的寬度);

●expandtab(是否在縮進和遇到 Tab 鍵時使用空格替代;使用 noexpandtab 取消設置);

●softtabstop(軟製表符寬度,設置爲非零數值後使用 Tab 鍵和 Backspace 時光標移動的格數等於該數值,但實際插入的字符仍受 tabstop 和 expandtab 控制);

●autoindent(自動縮進,即每行的縮進值與上一行相等;使用 noautoindent 取消設置);

●cindent(使用 C 語言的縮進方式,根據特殊字符如「{」、「}」、「:」和語句是否結束等信息自動調整縮進;在編輯 C/C++ 等類型文件時會自動設定;使用 nocindent 取消設置);

●cinoptions(C 語言縮進的具體方式,請參考「:help cinoptions-values」);

●paste(粘貼模式,會取消全部上述選項的影響來保證後面的操做——一般是從剪貼板粘貼代碼——保持原有代碼的風格;使用 nopaste 取消設置)。

下面給出一些經常使用的組合:

●shiftwidth=4 tabstop=4:不少 Windows 出身的程序員會習慣這樣的設置,讓縮進等於製表符寬度。

●shiftwidth=4 tabstop=8:不少 Unix 程序員的設置,仍使用較經常使用的 4 格縮進,但製表符寬度爲標準的 8。

●cinoptions=>4,n-2,{2,^-2,:2,=2,g0,h2,p5,t0,+2,(0,u0,w1,m1 shiftwidth=2 tabstop=8:標準的 GNU 編碼風格的設置,對 Vim 缺省的 C 縮進風格做了不少微調,好比,if 語句下的「{」、「}」要在「if」後縮進兩格,但函數定義部分「{」、「}」仍和函數名一行對齊。開源軟件常用該種縮進風格。

在編輯代碼時一個頗有用的命令是調整代碼縮進,能夠很方便地增長(或減小)若干級縮進,並自動根據選項設定使用正確的空格或製表符。只須要使用 「V」選中你要調整的代碼行,而後鍵入「<」(或「>」)便可增長(或減小)一級縮進;在鍵入「<」(或「>」)以前鍵入數字則 能夠指定增長(或減小)的縮進級數。

咱們要討論的最後一個相關的命令是「:retab」。在設定了 expandtab 選項時,該選項會把全部的製表符轉換成空格。在沒有設定 expandtab 選項時,使用「:retab!」可把空白字符轉換成製表符(可能誤轉換,慎用),使用「:retab n」能夠把 tabstop 重置爲 n,並轉換含製表符的連續空白字符爲適當的製表符和空格的組合以保證含製表符的行看起來沒有任何變化。詳細信息請參看「:help :retab」。

1.5. 模式行(modeline)

沒人願意每次都手工輸入一大堆的 Tab 和縮進設定。但是,放在 .vimrc 文件中彷佛也不是個好主意:若是我編輯的代碼不止一種風格呢?——考慮一下,若是你參加開源軟件項目,你能保證你參加的全部項目,還有你公司裏的軟件項 目,代碼風格都同樣嗎?——Vim 是我用過的第一個支持在文件中記錄代碼風格設定的編輯器。這個特性在 Vim 中叫作模式行,實際上,它所作的是在打開文件時根據文件中的 Vim 指令設定相關的 Vim 選項。下面就是一個嵌在 C 源代碼中的模式行:

1 /* vim: set tabstop=4 shiftwidth=4 expandtab: */

模式行有好幾種形式。本文只介紹上面的這種形式(其它形式相似,請自行參考「:help modeline」):行首的「/*」和尾部的「*/」告訴 C 編譯器這是一行註釋,不是代碼的一部分;而 Vim 可經過後面的「vim:」識別出模式行的開始(必須出如今行首或前面有一個空白字符);後面則是「set」和空格間隔開的一串 Vim 選項;「:」表示模式行結束。

這種方式很是簡單,功能也很是強大。另外請注意,出於安全的考慮,模式行中的選項隻影響當前文件(「:help modeline-local」),也不能作任何設置選項之外的工做。

1.6. 寄存器

一般的編輯器有一個剪貼板,以存儲複製和剪切的內容。Vim 中的相似概念叫作寄存器(register)。除了有一個無名寄存器外,Vim 還有一大堆有名的寄存器,能夠經過「」」(參見「:help 「」)或「Ctrl-R」(參見「:help i_CTRL-R」和「:help c_CTRL-R」)加寄存器名(字母、數字和某些特殊字符,參見「:help registers」;「無名」寄存器的名字是「」」)來訪問。好比,你先使用「」ayy」複製了一行,而後使用「dd」刪掉了一行,而後移動光標到要復 制到的位置,就可使用「」aP」把先前複製的內容粘貼上去了。手工編輯是有名寄存器的做用還不是很大,但當你想讓 Vim 經過相似於宏的方式自動完成工做時,有名寄存器就變成不可缺乏的重要功能了。下面咱們還會用到。

在使用 X Window 系統時,有兩個特殊的寄存器是須要注意一下的:「」*」訪問的寄存器是 X 的主選擇區域(primary selection),「」+」訪問的寄存器是 X 的剪貼板(clipboard)。若是你要在 Vim 和其它的 X 應用程序之間複製文本內容,你能夠試一下這兩個寄存器。

還有一個很特殊的「寄存器」:「=」。在插入模式或命令模式中,鍵入「Ctrl-R=」,Vim 會提示你輸入一個表達式,普通的整數運算在此徹底有效。若是想要進行浮點運算,請參見第 3.2 節中的技巧。

1.7. 搜索、替換和正則表達式

你們應該都已經知道 Vim 裏使用「/模式」(或「?模式」)進行搜索,使用「:s/模式/字符串/標誌」進行替換,其中的「模式」是一個正則表達式。關於正則表達式,不熟悉的話可 以邊用邊學,本節也不打算對 Vim 的正則表達式做完整的闡述(那可能能夠專門寫一本小冊子了),而只拋磚引玉式地給出一些有用的例子加以說明,以及一些實用技巧。

先說一點點搜索。搜索裏最最有用的一個快捷方式是「*」(向下完整匹配光標下的單詞)。把光標移動到你要搜索的詞(變量名、函數名等)上,好比 「test」,而後按「*」,Vim 將自動產生一個對「\<test\>」(參見「:help /\<」和「:help /\>」)的搜索,也就是說,搜索完整的單詞「test」。不要小看這個技巧,它常常能夠大幅度地提升搜索的速度。事實上,這是 Vim 網站上公佈的第 1 號技巧,也是被評價最高的技巧。類似的技巧還有「#」(向上完整匹配光標下的單詞)、「g*」(向下部分匹配光標下的單詞)等,請自行查看(「:help #」等)。

Vim 在搜索和替換時會對匹配成功的文本進行加亮,在已經完成搜索和替換任務後,這種加亮有時反而會妨礙顯示。Vim 專門提供一個命令取消這種加亮(直到用戶再一次使用搜索或替換命令):「:nohlsearch」。建議用戶建立一個鍵盤映射(key mapping)加入到 .vimrc 中,如:

1 nmap:nohlsearch

以上命令表示,在正常模式下按 F2 鍵至關於輸入「:nohlsearch」後面跟一個回車,即取消搜索加亮顯示。

再看幾個搜索替換的實用例子。

●去掉全部的行尾空格:「:%s/\s\+$//」。「%」表示在整個文件範圍內進行替換,「\s」表示空白字符(空格和製表符),「\+」對 前面的字符匹配一次或屢次(越多越好),「$」匹配行尾(使用「\$」表示單純的「$」字符);被替換的內容爲空;因爲一行最多隻需替換一次,不須要特殊 標誌。這個仍是比較簡單的。

●去掉全部的空白行:「:%s/\(\s*\n\)\+/\r/」。這回多了「\(」、「\)」、「\n」、「\r」和「*」。「*」表明對前 面的字符(此處爲「\s」)匹配零次或屢次(越多越好;使用「\*」表示單純的「*」字符),「\n」表明換行符,「\r」表明回車符,「\(」和「 \)」對錶達式進行分組,使其被視做一個不可分割的總體。所以,這個表達式的完整意義是,把連續的換行符(包含換行符前面可能有的連續空白字符)替換成爲 一個單個的換行符。惟一很特殊的地方是,在模式中使用的是「\n」,而被替換的內容中卻不能使用「\n」,而只能使用「\r」。緣由是歷史形成的,詳情如 果有興趣的話能夠查看「:help NL-used-for-Nul」。

●去掉全部的「//」註釋:「:%s!\s*//.*!!」。首先能夠注意到,這兒分隔符改用了「!」,緣由是在模式或字符串部分使用了「/」 字符,不換用其餘分隔符的話就得在每次使用「/」字符自己時寫成「\/」,上面的命令得寫成「:%s/\s*\/\/.*//」,可讀性較低。命令自己倒 是至關簡單,用過正則表達式的人估計都知道「.」匹配表示除換行符以外的任何字符吧。

●去掉全部的「/* */」註釋:「:%s!\s*/\*\_.\{-}\*/\s*! !g」。這個略有點複雜了,用到了幾個不太經常使用的 Vim 正則表達式特性。「\_.」匹配包含換行在內的全部字符;「\{-}」表示前一個字符可出現零次或屢次,但在整個正則表達式能夠匹配成功的前提下,匹配的 字符數越少越好;標誌「g」表示一行裏能夠匹配和替換屢次。替換的結果是個空格的目的是保證像「int/* space not necessary around comments */main()」這樣的表達式在替換以後仍然是合法的。

但願上面的這些簡單的例子可以引發你使用 Vim 的正則表達式高效完成任務的興趣。進一步的信息可參考「:help regexp」。

1.8. 自動完成和路徑設定

Vim 支持單詞的自動完成。好比,你前面使用了一個很長的變量名,叫 aLongVariable,下面你在輸入時,就不用完整鍵入了。極可能,你只須要鍵入「aL」,而後按下「Ctrl-P」(向前搜索可匹配的單詞並完 成)就能夠獲得完整的變量名(沒有獲得想要的結果的話,多按幾下「Ctrl-P」;或者前面多輸入幾個字符,如「aLongV」)。相似的命令還有 「Ctrl-N」(向後搜索可匹配的單詞並完成)、「Ctrl-X Ctrl-L」(搜索可匹配的行並完成)、「Ctrl-X Ctrl-F」(搜索可匹配的文件名並完成)等,具體可參看「:help ins-completion」。

若是你並不熟悉這些功能,但也並不以爲這有什麼稀奇的話,下面這個例子可能會讓你以爲吃驚。請嘗試打開一個空白的 C 文件(vim test.c),並輸入:

1234 #include int main() { pri

最後一行不要回車,直接在「pri」後面輸入「Ctrl-P」,你將看到「printf」出現。是的,雖然文件裏沒有「printf」,但 Vim 知道到哪裏去尋找它!在做關鍵字匹配完成時,若是當前文件和其它打開的文件中沒有想要的結果,Vim 會自動到「#include」的文件中進行進一步的搜索(爲何是「#include」呢?請查閱「:help ‘include’」),搜尋的目錄則由選項 path 決定,其缺省值在 Unix(含 Linux)下爲「.,/usr/include,,」,表明搜索的目錄依次是文件所在目錄、/usr/include 和當前目錄。根據實際狀況,你可能須要在 .vimrc 文件中設置該選項,加入項目相關的包含目錄,注意通常要保留最後的「,,」,除非你不須要在當前目錄下搜索。

設置了合適的 path 後,另外帶來的一個便利就是可使用「gf」命令方便地跳轉到光標下的文件名所表明的文件中。在上面的例子中,把光標移到「stdio.h」的任一字符 上,鍵入「gf」,則 Vim 會自動打開 /usr/include/stdio.h 文件。使用「Ctrl-O」(參見「:help CTRL-O」)可返回到原先的文件中。

1.9. 文件跳轉和 Tags

你們通常都知道,在 Vim 的幫助窗口中的關鍵字上雙擊鼠標或者鍵入「Ctrl-]」便可跳轉至該關鍵字相關的幫助主題。不過,「跳轉至匹配的關鍵字」這一功能並不只僅侷限於幫助文 件。只要有合適的 tags 文件(參見「:help tags-file-format」),咱們一樣能夠在源代碼中使用這個方便的功能,跳轉到與關鍵字匹配的「標記」處(一般是源代碼中某一函數、類型、變 量或宏的定義位置)。

要產生 tags 文件,一般咱們使用 Exuberant Ctags [15]。通常的 Linux 發佈版中均帶有這一工具。Ctags 帶有的選項數量極多,此處咱們僅簡單介紹如何在一個典型的多文件、多層目錄的項目中使用其基本功能:咱們只需在項目的根目錄處鍵入「ctags -R .」,Ctags 便可自動在文件中查找、識別支持的文件格式、生成 tags 文件。目前 Exuberant Ctags 支持多達 33 種編程語言 [16],包括了 Linux 下經常使用的 C、C++、Java、Perl、PHP 等。有了 tags 文件,如下的 Vim 命令就能夠方便使用了(進一步的信息可參考「:help tags-and-searches」):

●:tag 關鍵字(跳轉到與「關鍵字」匹配的標記處)

●:tselect [關鍵字](顯示與「關鍵字」匹配的標記列表,輸入數字跳轉到指定的標記)

●:tjump [關鍵字](相似於「:tselect」,但當匹配項只有一個時直接跳轉至標記處而再也不顯示列表)

●:tn(跳轉到下一個匹配的標記處)

●:tp(跳轉到上一個匹配的標記處)

●Ctrl-](跳轉到與光標下的關鍵字匹配的標記處;除「關鍵字」直接從光標位置自動得到外,功能與「:tags」相同

●g](與「Ctrl-]」功能相似,但使用的命令是「:tselect」)

●g Ctrl-](與「Ctrl-]」功能相似,但使用的命令是「:tjump」)

●Ctrl-T(跳轉回上次使用以上命令跳轉前的位置)

當咱們在項目的根目錄下工做時,上面這些命令工做得很好。但若是咱們進到多層目錄的裏層再運行 Vim 打開文件時,這些命令的執行結果一般就變成了錯誤信息「E433: No tags file」。這是由於缺省 Vim 只在文件所在目錄和當前目錄下尋找 tags 文件,而咱們前面只在項目的根目錄下生成了 tags 文件,Vim 沒法找到該文件。解決方法有好幾種,我認爲通常較簡單的作法是對每一個項目都在 .vimrc 文件中增長一個路徑相關設定。假設咱們有兩個項目,位置分別是 /home/my/proj1 和 /home/my/proj2,那咱們可使用:

12 au BufEnter /home/my/proj1/* setlocal tags+=/home/my/proj1/tags au BufEnter /home/my/proj2/* setlocal tags+=/home/my/proj2/tags

Vim 選項 tags 用於控制檢查的 tags 文件,缺省值爲「./tags,tags」,即前面所說的文件所在目錄下和當前目錄下的 tags 文件。上面兩行自動命令告訴 Vim,在打開項目目錄下的文件時,tags 選項中的內容要增長項目的 tags 文件的路徑。進一步信息可參看「:help ‘tags’」。

1.10. Make 和 grep

Make [17] 和grep [18] 應當算是 Unix 世界裏無人不曉的基本工具了吧。很天然的,Vim 對它們有着特殊的支持。該支持主要經過訪問一個特殊的快速修訂窗口(quickfix window)來實現。直接在 Vim 的命令模式裏輸入相應的 make 或 grep 命令(如「:grep foo *.c」)便可將命令的執行結果放入該窗口,同時根據返回的結果跳轉到第一個錯誤(make 的狀況;在使用 grep 時是匹配成功之處)。如下是經常使用的「快速修訂」命令:

●:cn(顯示下一個錯誤)

●:cp(顯示上一個錯誤)

●cl(列出全部的錯誤及其編號)

●:cc(跳轉到指定編號的錯誤)

●:copen(打開快速修訂窗口,在其中顯示全部錯誤,可在錯誤上雙擊鼠標或按回車鍵跳轉至該錯誤;示例參見圖 4)

圖 4

Vim 實用技術,第 1 部分: 實用技巧

●:cclose(關閉快速修訂窗口)

Vim 的這個特性也能夠與 make 和 grep 之外的程序一塊兒工做(事實上,在 Windows XP 上,「:grep」命令通常調起的是「findstr /n」)。具體調用那個程序由選項 makeprg(Linux 下缺省爲「make」)和 grepprg(Linux 下缺省爲「grep -n $* /dev/null」)控制,而如何解析返回的內容則由選項 errorformat 和 grepformat 控制。鑑於在 Unix/Linux 下通常不需更改這些選項的內容,此處再也不詳述。

1.11. 執行外部命令

在「:make」這樣的命令中,Vim 會自動調用外部的程序。用戶固然也能夠本身執行外部的程序:估計不少的人都已經知道了用「:!命令」能夠在 Vim 中執行一個外部命令。不過,估計大部分人都不知道,還有其它一些命令能夠執行外部命令,而且,即便「:!」命令裏面也有一些技巧可使用。

最正規的執行外部命令的方法,如前所述,就是「:!」。好比,咱們想要顯示當前目錄下的全部文件,就能夠直接執行:「:!ls」。Vim 會在一個終端窗口中進行文件列表,而後提示咱們按鍵返回 Vim 中。事實上,這種方式對於「cp」、「rm」這樣基本不須要輸出的命令比較實用,而對於「ls」這樣關注於輸出的命令並不太適用。

若是想把外部命令執行的結果插入到當前編輯的緩衝區中,能夠考慮使用「:r!」。好比,咱們使用「:r!ls」,就能夠把「ls」命令的執行結果插入到緩衝區中光標所在行下面。在使用宏時,這可能會特別有用。

Vim 的「:!」命令還有一個特別強大的技巧可使用。拿一個實際例子,咱們須要對在一個文件的每一行以前插入一個編號,該怎麼作呢?——用 Vim 的宏或者腳本能夠完成這一工做,但這不是最高效、最靈活的工做方式。Linux 下通常帶有的 GNU 的 nl,能夠用很是靈活的方式來完成這一任務——要對全部的非空行進行編號,只須要「:%!nl」;要對包含空行的全部行進行編號?OK,「:%!nl -ba」。

稍做一點解釋。當使用可視模式選中文本行後而後鍵入「:!」(命令行上將出現「:’<,’>!」,表示命令的範圍是選定的文本),或者 使用「:%!」(表示命令的範圍是整個緩衝區中的文本),Vim 在執行後面的命令時,將把命令範圍裏的文本行做爲後面執行的命令標準輸入,並用命令執行後的標準輸出替換當前緩衝區中的這些文本行。這就是上面的命令行的 工做原理。

1.12. 定寬文本排版

在傳統的 Unix 環境下,文本文件的定義是具備必定長度限制的文本行的組合 [19]。雖然 Vim 自己對行的長度沒有任何實際的限制,但有一些工具備這樣的限制。爲了最大程度的兼容性,也爲了在顯示、打印等處理上比較方便,通常推薦在郵件和源代碼中一 般不要超出 72 列(最多不超出 80 列)。Vim 在處理定寬的文本方面具備特殊的支持能力。下面是一個在 Vim 中把行寬(使用選項 textwidth)設爲 40 後輸入 Harry Potter and the Half-Blood Prince 的第一句話的結果:

123456 It was nearing midnight and the PrimeMinister was sitting alone in hisoffice, reading a long memo that wasslipping through his brain withoutleaving the slightest trace of meaningbehind.

輸入時我只使用了英文字母和空格,換行符都是 Vim 自動插入的。若是在某一行加入或刪除了一些字符後行不就不齊了嗎,該如何處理?很簡單,把光標移到要從新格式化的文本開頭,使用「gq」命令後面跟一個光 標移動命令肯定從新格式化的範圍。好比「gq}」(格式化一段),「gq5j」(格式化 5 行),「gqG」(格式化至文件末尾)。

除了選項 textwidth 外,選項 formatoptions 肯定了跟文本格式化有關的基本選項,經常使用的數值有:

●t:根據 textwidth 自動折行;

●c:在(程序源代碼中的)註釋中自動折行,插入合適的註釋起始字符;

●r:插入模式下在註釋中鍵入回車時,插入合適的註釋起始字符;

●q:容許使用「gq」命令對註釋進行格式化;

●n:識別編號列表,編號行的下一行的縮進由數字後的空白決定(與「2」衝突,須要「autoindent」);

●2:使用一段的第二行的縮進來格式化文本;

●l:在當前行長度超過 textwidth 時,不自動從新格式化;

●m:在多字節字符處能夠折行,對中文特別有效(不然只在空白字符處折行);

●M:在拼接兩行時(從新格式化,或者是手工使用「J」命令),若是前一行的結尾或後一行的開頭是多字節字符,則不插入空格,很是適合中文

上面提到的註釋,能夠是 C/C++ 中的「//」和「/*」,也能夠是郵件中引用原文使用的「>」等字符(具體由 comments 選項控制;參見「:help ‘comments’」)。Vim 在遇到這些字符時,可以至關智能地進行處理,足以完成平常編輯源代碼和郵件的須要。在使用一些處理純文本不夠強大的郵件客戶端時,我一般使用 Vim 編輯郵件(特別是英文郵件),而後把結果貼回到郵件編輯窗口中進行發送。

Vim 中 formatoptions 的缺省值是「tcq」,通常我會在 .vimrc 文件中加入一行「set formatoptions+=mM」來確保 Vim 能在中文字符之間折行而不要求空格的存在,而且在大部分狀況下能夠正確地處理中文從新格式化。

1.13. 其它小技巧

也許你會以爲這些頗有用:

●%(跳轉到與之匹配的括號處)

●.(重複上次的修改命令)

●`.(跳轉到最近修改過的位置)

●ZQ(無條件退出

●ZZ(存盤退出)

●ga(顯示光標下的字符在當前使用的 encoding 下的內碼)

●guw(光標下的單詞變爲小寫)

●gUw(光標下的單詞變爲大寫)

●:TOhtml(根據 Vim 的語法加亮的方式生成 HTML 代碼;在圖形界面中也可使用菜單「Syntax—Convert to HTML」達到一樣效果)

無聊的時候,還能夠試試(呵呵!):

●:help!

●:help 42

●:help holy-grail

相關文章
相關標籤/搜索