Vim 實用技術,第 3 部分: 定製 Vim

來源:互聯網
上載者:User

轉自:http://www.ibm.com/developerworks/cn/linux/l-tip-vim3/index.html

3.1. Vim 指令碼基礎

在 .vimrc 檔案中,和在第二章提到的外掛程式和文法檔案中,使用的語言就是 Vim 指令碼語言。這種指令碼語言文法有點像 BASIC,運算式有點像 C,還是比較容易理解的。本章中並不打算對其作很系統的介紹(要完整瞭解的話,請參見“:help usr_41.txt”),而只是介紹一些基本知識,特別是,瞭解定製 .vimrc 所需要的基本知識。

Vim 指令碼相當於可直接在命令模式下執行的命令,只是不需要輸入前面的冒號(如果用了冒號也不會出錯)。因此,像設定選項、建立鍵盤對應這樣的命令是直接可用的。當然,作為一種指令碼語言,除了普通鍵盤上會輸入的命令外,我們還需要一些更複雜的功能,特別是:變數,運算式,條件和迴圈語句,函數。

3.1.1. 變數

Vim 中使用如下的文法對變數進行賦值(建立變數):

let 變數名 = 數值

 

變數類型有兩種,整數和字串,在第一次賦值之前都不能使用。變數名除了可使用常規的字母、底線和數字外,還可以使用幾種特殊的首碼:

  • “b:”——只對當前緩衝區(buffer)有效變數;
  • “w:”——只對當前編輯視窗(window)有效變數。
  • “g:”——全域變數(在函數中訪問全域變數必須使用該首碼,不加首碼的話則認為是函數內的局部變數);
  • “s:”——變數名只在當前指令碼中有效;
  • “a:”——函數的參數;
  • “v:”——Vim 內部預定義的特殊變數(參見“:help vim-variable”)。

下面三個首碼用來訪問特殊的數值,由於行為和變數較為相似(可以讀取和修改),也放在這兒一起講:

  • “$”——訪問環境變數;
  • “&”——訪問 Vim 選項;
  • “@”——訪問寄存器。

當變數不再使用時,可以使用“unlet 變數名”刪除變數。

3.1.2. 運算式

和 C 非常類似,可以使用變數和常量,可以使用括弧,可以調用函數(“函數名(...)”),支援加法(“+”)、減法(“-”)、乘法(“*”)、除法(“/”)和模數(“%”),支援邏輯操作(“&&”、“||”和“!”),支援三元條件運算式(“a ? b : c”)。字串操作方面當然比 C 要強,可以使用“.”進行字串拼接;可使用“==”、“<=”等進行字串大小比較,可使用“=~”和“!~”進行Regex匹配,而且可以在比較操作符後面添加“#”或“?”來強制進行大小寫敏感或不敏感的比較(預設受 Vim 選項 ignorecase 影響)。顯示一個運算式的結果,可以使用“:echo 運算式”顯示到狀態列上,或者在插入模式下使用“Ctrl-R=運算式”插入到緩衝區的文本中。

和其它很多在 Unix 下成長起來的語言一樣,Vim 的字串常量有雙引號和單引號兩種方式。使用單引號的話,單引號間的任何字元都是字串的一部分,其中不能再包含單引號。使用雙引號的話,則可以使用“\”產生換碼序列(具體可參考“:help expr-quote”),如“\n”代表分行符號,“\"”代表雙引號,“\\”代表反斜線本身,等等。

需要注意的話,雙引號除了可以表示字串常量外,還可以表示注釋。行首的“"”,以及運算式中出現的成單的“"”,都表示“"”後面的部分全部是注釋。

3.1.3. 條件和迴圈語句

條件陳述式形式如下:

 

if 運算式  語句endif

 

 

if 運算式  語句else  語句endif

 

 

if 運算式  語句elseif 運算式  語句endif

 

迴圈語句形式如下:

 

while 運算式  語句endwhile

 

條件和迴圈語句都可以嵌套。這些比較簡單,就不多加說明了。

3.1.4. 函數

在運算式中使用函數時,就跟 C 裡面的方式類似,直接使用函數名加括弧,括弧裡寫上參數(可選)。在不需要傳回值的情況下調用函數時,稍稍有些不同,要使用“call”命令,後面跟函數名和括弧(括弧裡面寫上可能有的參數)。

定義函數使用下面的文法:

 

function 函數名稱(參數列表)  語句endfunction

 

如果已有同名函數存在,Vim 會報錯,除非在“function”後面加上一個“!”。

如果參數中不包含“...”,那麼參數的數量是固定的,函數的調用者必須提供跟定義同樣多的參數(在函數定義中使用參數名之前加上“a:”進行訪問)。如果參數中包含“...”,那麼參數的數量不固定,除了可以使用參數名稱訪問傳遞過來的參數外,還可以使用“a:0”知道額外傳遞的參數數量,使用“a:1”、“a:2”等訪問這些額外傳遞的參數。

要在函數的中間返回,或者要返回數值的話,可以使用“return”語句。

Vim 內部定義了一百多個函數,詳細列表請參見“:help function-list”。

 

回頁首

3.2. 我的 .vimrc

作為一個 Vim 指令碼的一個具體樣本,我將講解一下最實用的情況,我的 .vimrc 檔案。檔案 .vimrc.html (請下載到本地開啟) 是我的 .vimrc 檔案通過以下步驟產生的 HTML 檔案:

1.在 Vim 中開啟 .vimrc 檔案;

2.執行命令“:colorscheme koehler”(預設配色可能在瀏覽器中效果不佳)

3.執行命令“:%!nl -w4 -s' '”(1.11 節)

4.執行命令“:TOhtml”(1.13 節)

5.執行命令“:w”

可以把瀏覽器中的常值內容粘貼到 Vim 中,然後使用下面這個替換命令“:%s/^ \+[0-9]\+ //”刪除前面的行號,來恢複出最初的 .vimrc 檔案。

下面逐行進行講解,並包含理解其內容所需的資料的連結。建議大家直接閱讀 .vimrc 檔案的內容,並在有疑問時查閱下面的解釋。

第 1 行:注釋(3.1.2 節末段),其中包含一個模式行(1.4 節和 1.5 節)。

第 2 行:首先判斷系統是否具有“自動命令”(autocmd)的支援,有的話才執行第3到第六行的內容(1.1 節、“:help has”和“:help feature-list”)。

第 3 行:純注釋(後面我將跳過注釋行不再說明)。

第 4 行:清除所有的自動命令(“:help autocmd-remove”),以方便調試,可以使用“source ~/.vimrc”查看一些修改後的效果(“:help source”)。

第 6 行:對於尾碼為“.asm”的檔案,認為其是微軟的 Macro Assembler 格式(“:help masm-syntax”)。

第 7 行:與第 2 行的 if 語句配對。

第 8-10 行:當使用了圖形介面時(“:help feature-list”),確保所有的檔案類型會在菜單“文法”(“Syntax”)下出現,而不是出現一個功能表項目“Show filetypes in menu”。預設行為可以讓 Vim 啟動得更快一點點。

第 11-13 行:當使用了圖形介面,並且環境變數 LANG 中不含“.”(即沒有規定編碼)時,把 Vim 的內部編碼設為 UTF-8。

第 14 行:不需要保持和 vi 非常相容(“:help 'compatible'”)。

第 15 行:執行 Vim 預設提供的 .vimrc 檔案的樣本,包含了開啟文法加亮顯示等最常用的功能。

第 16 行:開啟自動縮排(1.4 節)。

第 17 行:預設不產生備份檔案(“:help 'backup'”)。

第 18 行:在輸入括弧時游標會短暫地跳到與之相匹配的括弧處,不影響輸入(“:help 'showmatch'”)。

第 19 行:正確地處理中文字元的折行和拼接(1.12 節)。

第 20 行:可自動識別的檔案類型為帶 BOM 字元的 Unicode 檔案、UTF-8 編碼的檔案和 GBK 編碼的檔案。

第 21 行:設定狀態行,使其能額外顯示檔案的編碼資訊, 2 中的“gbk”和“big5”(“:help 'statusline'”)。


圖 2
 

第 22-24 行:如果該 Vim 支援滑鼠,則啟用滑鼠支援(1.3 節)。

第 25-29 行:判斷 Vim 是否包含多位元組語言支援(multi_byte 特性),並且版本號碼(“:help v:version”)大於 6.1(包含 ambiwidth 選項)。

第 26-28 行:如果 Vim 的語言(“:help v:lang”;受環境變數 LANG 影響)是中文(zh)、日文(ja)或韓文(ko)的話,將模糊寬度的 Unicode 字元的寬度(ambiwidth選項,1.2 節)設為雙寬度(double)。

第 31-36 行:改變上、下方向鍵行為方式:通常情況下這些鍵的作用範圍是邏輯行,所以如果行很長的話游標的移動可能會不太方便;這些鍵盤對應把這些鍵的作用範圍改成螢幕行(“help gk”),還為習慣使用“j”、“k”的人增加了映射“Ctrl-j”和“Ctrl-k”作用於螢幕行。前面四個映射使用的命令是“noremap”,作用於正常模式、可視模式和命令執行時;後面兩個映射使用的命令是“inoremap”,僅作用於插入模式,其中使用“Ctrl-O”臨時執行一個普通模式的命令(“:help i_CTRL-O”)。

第 38-41 行:在 Vim 中的插入模式中可以使用“Ctrl-R =”計算整數運算式的數值,但 Vim 本身沒有計算浮點運算式的能力。這四個映射提供了浮點運算式的計算能力:使用“\ma”(假設 Leader 字元為預設的“\”,參見“:help <Leader>”)可將計算的結果放到下一行上(待計算的運算式為當前行或在可視模式選中的內容),使用“\mr”則用計算的結果替換待計算的運算式(同樣為當前行或在可視模式選中的內容)。這些映射假設有一個命令“calcu”可用來計算一個運算式的內容。該命令可用下面的 shell 指令碼簡單實現:

 

#! /bin/shecho "$*" | sed -e $'s/\r$//' -e 's/sin *(/s(/g' -e 's/cos *(/c(/g' -e 's/atan *         (/a(/g' -e 's/log *(/l(/g' -e 's/exp *(/e(/g' | bc -l

 

該指令碼把運算式轉換成 bc [1] 能接受的形式(把“sin(x)”轉換成“s(x)”,等等),並通過標準輸出送到 bc 的標準輸入。

該映射較為複雜,此處不詳加解釋了——其中心思想都是選取待計算的運算式,放到無名寄存器中,然後使用“Ctrl-R"”粘貼到命令列上,使用 calcu 進行計算,再把結果粘貼回正在編輯的緩衝區中;最後一個最複雜,因為為了替換原先的運算式,還需要記住原先被選中的內容的起始和結束位置,你可能希望看一下“:help gv”、“:help v_o”、“:help m”、“:help `”,並複習節 1.11。可以注意一下,在映射中使用了“<silent>”(“:help map-<silent>”),這會防止命令列上回顯執行的內容。

第 43-44 行:允許使用者使用 F2 來取消搜尋/替換的加亮顯示。此處一個映射用於正常模式(nmap),一個用於插入模式(imap)。上面已經提過一次,“Ctrl-O”可以在插入模式中執行一個正常模式的命令。

第 46-47 行:這兩個映射用於 taglist 外掛程式,使用 F9 直接開啟(或關閉)taglist 的視窗。

第 49-50 行:方便快速修訂視窗(1.10 節)的使用,可使用 F11(和 F12)查看下一個(上一個)錯誤(或 grep 項等)。

第 52-65 行:一些適用於文字模式啟動並執行 Vim 的設定;詳見下面的具體說明。

第 54-56 行:將變數 Tlist_Inc_Winwidth 的值設為 0,防止 taglist 外掛程式改變終端視窗的大小(有些情況下會引起系統不穩定)。使用“has('eval')”是讓該語句僅在功能較為完整、至少支援運算式的 Vim 版本中運行。

第 58-64 行:在系統支援 wildmenu 特性(“:help 'wildmenu'”)啟用文字模式的菜單。

第 59 行:開啟 wildmenu 選項,啟動具有功能表項目提示的命令列自動完成。

第 60 行:確保字元序列“<C-Z>”被理解為 Ctrl-Z 而不是分開的五個字元(“:help 'cpoptions'”)。

第 61 行:設定使用 Ctrl-Z 啟用自動完成提示。

第 62-63 行:把正常模式和插入模式下的 F10 映射成執行功能表項目,並自動提示菜單內容。注意預設菜單仍不會自動載入,我使用該特性的主要目的是在文字模式的 Vim 中使用 CVS 菜單。圖 16 是按 F10 鍵後再按 Tab 鍵的結果。


圖 16
 

第 66-161 行:使用自動命令(autocmd)特性的設定。使用“has”來防止該部分內容在不支援自動命令的 Vim 版本中運行。

第 67-129 行:定義了若干個下面的自動命令會用到的函數,具體在下面的自動命令中講。請注意在每個“function”之後都用了一個“!”(“:help E122”):這也是為了方便調試,讓“source ~/.vimrc”能正確運行而不會報告函數已定義的錯誤。

第 131-133 行:只要沒有將環境變數 VIM_HATE_SPACE_ERRORS 的值設為零,則把變數 c_space_errors 的值設為 1——效果是在 C/C++ 代碼中“不正確”的空白字元(行尾的空白字元和緊接在定位字元之前的空白字元)將會被高亮顯示。圖 17所示的代碼中,第 3 行的行尾多了兩個空格,第 5 行的第一個定位字元之前多了個空格。Vim 提示#935 裡有一些額外的說明。同時請參看對第 160 行的說明。


圖 17
 

第 135 行:使用的英文拼字變體為加拿大風格,即:使用拼字“abridgement”(而不是“abridgment”)、“colour”(而不是“color”)、“realize”(而不是“realise”)、“theatre”(而不是“theater”)等,比較符合中國人一般的英語教科書中的拼字方式,也比較適合於寫“國際”英語。

第 138 行:使用鍵盤對應“\a”來查看游標下字元的屬性,主要用於調試 Vim 的文法檔案。圖 18顯示了游標下的字元所屬的文法“組”為 vimOption,使用色彩配置中的 PreProc(預先處理符號)項,前景色彩為紫色(RGB:#a020f0)。有興趣可查看 Vim 指令碼#383 的具體內容。


圖 18
 

第 140 行:在函數找不到時(“:help FuncUndefined”),自動在運行環境(Linux 下一般為 ~/.vim)的 autoload 目錄下讀入與函數名同名的 .vim 檔案。這是指令碼#383 的建議安裝方式(SyntaxAttr.vim 檔案放在 autoload 目錄下,僅在執行時載入)。

第 142 行:設定適用於 C/C++ 檔案的選項(1.4 節)。

第 143 行:把補丁檔案的縮排和定位字元寬度設定設成和 C/C++ 檔案相同(1.4 節)。

第 144 行:取消 Vim 對 HTML 標籤自動產生的縮排,但開啟自動縮排選項(1.4 節)。

第 145 行:對於變更日誌類型的檔案,設定行寬為 76 個字元(1.12 節)。

第 147 行:當檔案尾碼為“.gb”時,認為這是一個 GBK 編碼的檔案,在讀入檔案之前(“:help BufReadPre”)調用函數 SetFileEncodings 把原先的 fileencodings 選項的內容儲存在本緩衝區的一個變數中(3.1.1 節),然後把 fileencodings 設成 gbk,即只嘗試對檔案內容作為 GBK 字元序列來解釋。

第 148 行:類似於上面把“.big5”尾碼的檔案當作 Big5 編碼的檔案,在讀入檔案之前把 fileencodings 設成 big5,只嘗試對檔案內容作為 Big5 字元序列來解釋。

第 149 行:類似於上面把“.nfo”尾碼的檔案當作 CP437 編碼(即英文 DOS 的 OEM 字元集編碼)的檔案。效果可參看圖 19。


圖 19
 

第 150 行:在讀入 .gb、.big5 或 .nfo 檔案之後(“:help BufReadPost”),調用函數 RestoreFileEncodings 恢複儲存起來的 fileencodings 原數值。

第 151 行:對於 .txt 尾碼的檔案,在顯示檔案時(“:help BufWinEnter”,確保在模式行被執行之後)調用函數 CheckFileEncoding 檢查檔案是否已修改並且 fileencoding 設有數值。條件滿足的話說明該檔案在模式行中修改了 fileencoding,因而使用該編碼(“:help ++enc”)重新強制(“!”)讀入該檔案以保證檔案被正確解碼。Vim 提示#911 裡有一些額外的說明。

第 153 行:在遇到 HTML 檔案時,如果 Vim 判斷出的編碼類別型和 HTML 程式碼中使用“<meta http-equiv="Content-Type" content="text/html; charset=編碼">”規定的編碼不一致,將使用網頁中規定的編碼重新讀入該檔案。函數 ConvertHtmlEncoding 會把一些網頁中使用的編碼名稱轉換成 Vim 能夠正確處理的編碼名稱;函數 DetectHtmlEncoding 在判斷檔案類型確實是 HTML 之後,會記下當前的游標位置,並搜尋上面這樣的 HTML 程式碼行,找出字元集編碼後,在編碼不等於當前檔案編碼(fileencoding)時且當前檔案編碼為空白或等於系統判斷出的檔案編碼時,使用該編碼強制重新讀入檔案,忽略任何錯誤(“silent!”)。該自動命令寫成是可嵌套執行的(“:help autocmd-nested”),目的是保證文法高亮顯示有效,且上次開啟檔案的游標位置能夠正確保持。Vim 提示#1074 裡有一些額外的說明。

第 155-156 行:確保把 /usr/include/c++ 和 /usr/include/g++-3 目錄下的所有檔案都當成 C++ 類型的檔案,不管 Vim 原先認定這些檔案類型是什麼(“:help BufEnter”)。C++ 的很多標準標頭檔(如“algorithm”)沒有檔案尾碼,預設情況下不會被 Vim 當作 C++ 檔案。

第 158 行:第 142 行把 C/C++ 檔案的定位字元寬度設成了 4(個人設定),但系統的原始碼一般使用 GNU 編碼規範,定位字元寬度為 8。該行設定所有 /usr 目錄下的檔案都使用 GNU 編碼規範(1.4 節)。

第 160 行:在寫檔案之前(“:help BufWritePre”),調用函數 RemoveTrailingSpace:只要沒有將環境變數 VIM_HATE_SPACE_ERRORS 的值設為零,則對於檔案類型為 C、C++、Vim 指令碼類型的檔案,自動悄悄清除所有的行尾空白字元;“normal m`”記憶當前的游標位置,“normal ``”恢複記憶下來的游標位置。

至此為此,我已經介紹了 Vim 的基本知識、很多實用技巧和一些最常用的 Vim 外掛程式,並通過定製 .vimrc 檔案介紹了指令碼的基本知識。如果有需要進一步深入學習 Vim 或是想提什麼關於 Vim 的特定問題的話,不妨參加從 Vim 的網站上參加 Vim 的郵件討論列表,應該會獲益良多。而作者也希望本文至此也已經完成了引導讀者學習、瞭解 Vim 的進階特性的任務。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.