vim實用技術(2)

來源:互聯網
上載者:User
寄存器

通常的編輯器有一個剪貼簿,以儲存複製和剪下的內容。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節中的技巧。

搜尋、替換和Regex

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

先說一點點搜尋。搜尋裡最最有用的一個捷徑是"*"(向下完整匹配游標下的單詞)。把游標移動到你要搜尋的詞(變數名、函數名等)上,比如 "test",然後按"*",Vim將自動產生一個對"\<test\>"(參見":help /\<"和":help /\>")的搜尋,也就是說,搜尋完整的單詞"test"。不要小看這個技巧,它經常可以大幅度地提高搜尋的速度。事實上,這是Vim網站上公布的 第1號技巧,也是被評價最高的技巧。相似的技巧還有"#" (向上完整匹配游標下的單詞)、"g*" (向下部分匹配游標下的單詞)等,請自行查看(":help #"等)。

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

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*\/\/.*//",可讀性較低。 命令本身倒是相當簡單,用過Regex的人估計都知道"."匹配表示除分行符號之外的任何字元吧。
  • 去掉所有的"/* */"注釋:":%s!\s*/\*\_.\{-}\*/\s*! !g"。這個略有點複雜了,用到了幾個不太常用的VimRegex特性。"\_."匹配包含換行在內的所有字元;"\{-}"表示前一個字元可出現零次或 多次,但在整個Regex可以匹配成功的前提下,匹配的字元數越少越好;標誌"g"表示一行裡可以匹配和替換多次。替換的結果是個空格的目的是保證像 "int/* space not necessary around comments */main()"這樣的運算式在替換之後仍然是合法的。

希望上面的這些簡單的例子能夠引起你使用Vim的Regex高效完成任務的興趣。進一步的資訊可參考":help regexp"。

自動完成和路徑設定

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),並輸入:

#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")可返回到原先的檔案中。

檔案跳轉和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,那我們可以使用

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'"。

Make 和 grep

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

  • :cn(顯示下一個錯誤)
  • :cp(顯示上一個錯誤)
  • :cl(列出所有的錯誤及其編號)
  • :cc(跳轉到指定編號的錯誤)
  • :copen(開啟快速修訂視窗,在其中顯示所有錯誤,可在錯誤上雙擊滑鼠或按斷行符號鍵跳轉至該錯誤;樣本參見)

  • :cclose(關閉快速修訂視窗)

Vim 的這個特性也可以與make和grep以外的程式一起工作(事實上,在Windows XP上,":grep"命令一般調起的是"findstr /n")。具體調用那個程式由選項makeprg(Linux下預設為"make")和grepprg(Linux下預設為"grep -n $* /dev/null")控制,而如何解析返回的內容則由選項errorformat和grepformat控制。鑒於在Unix/Linux下一般不需更 改這些選項的內容,此處不再詳述。

執行外部命令

在":make"這樣的命令中,Vim會自動調用外部的程式。使用者當然也可以自己執行外部的程式:估計很多的人都已經知道了用":!命令"可以在 Vim中執行一個外部命令。不過,估計大部分人都不知道,還有其它一些命令可以執行外部命令,並且,即使":!"命令裡面也有一些技巧可以使用。

最正規的執行外部命令的方法,如前所述,就是":!"。比如,我們想要顯示目前的目錄下的所有檔案,就可以直接執行:":!ls"。Vim會在一個終 端視窗中進行檔案清單,然後提示我們按鍵返回Vim中。事實上,這種方式對於"cp"、"rm"這樣基本不需要輸出的命令比較實用,而對於"ls"這樣關 注於輸出的命令並不太適用。

如果想把外部命令執行的結果插入到當前編輯的緩衝區中,可以考慮使用":r!"。比如,我們使用":r!ls",就可以把"ls"命令的執行結果插入到緩衝區中游標所在行下面。在使用宏時,這可能會特別有用。

Vim的":!"命令還有一個特彆強大的技巧可以使用。拿一個實際例子,我們需要對在一個檔案的每一行之前插入一個編號,該怎麼做呢?--用Vim 的宏或者指令碼可以完成這一工作,但這不是最高效、最靈活的工作方式。Linux下一般帶有的GNU的nl,可以用非常靈活的方式來完成這一任務--要對所 有的非空行進行編號,只需要":%!nl";要對包含空行的所有行進行編號?OK,":%!nl -ba"。

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

定寬文本排版

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

It was nearing midnight and the Prime
Minister was sitting alone in his
office, reading a long memo that was
slipping through his brain without
leaving the slightest trace of meaning
behind.

輸入時我只使用了英文字母和空格,分行符號都是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能在中文字元之間折行而不要求空格的存在,並且在大部分情況下可以正確地處理中文重新格式化。

其它小技巧

也許你會覺得這些很有用:

  • %(跳轉到與之匹配的括弧處)
  • .(重複上次的修改命令)
  • `.(跳轉到最近修改過的位置)
  • ZQ(無條件退出)
  • ZZ(存檔退出)
  • ga(顯示光線標下的字元在當前使用的encoding下的內碼)
  • guw(游標下的單詞變為小寫)
  • gUw(游標下的單詞變為大寫)
  • :TOhtml(根據Vim的文法加亮的方式產生HTML代碼;在圖形介面中也可以使用菜單"Syntax-Convert to HTML"達到同樣效果)

無聊的時候,還可以試試(呵呵!):

  • :help!
  • :help 42
  • :help holy-grail
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.