跳轉到內容

學習 vi 編輯器/Vim/增強 Vim

來自 Wikibooks,開放世界中的開放書籍

學習 vi 編輯器: 熟悉基本任務使工作更輕鬆高階任務細節vi 克隆 (Vim基本導航模式技巧對程式設計師有用的東西增強 VimVim 在 Windows 上VimL 指令碼語言, Vile, BB vi)vi 參考

增強 Vim

[編輯 | 編輯原始碼]

.vimrc 檔案

[編輯 | 編輯原始碼]

您可以在您的主目錄中建立一個名為 .vimrc 的配置檔案,並儲存任何特定設定。vimrc 的存在會產生一個副作用,即使 Vim 啟用 Vim 對 vi 的所有不相容更改,使其更易於使用。檔案的名字取決於使用的作業系統和使用者介面

.vimrc UNIX 和 VMS 上的文字使用者介面
_vimrc MS-Windows 和 VMS 上的文字使用者介面
.gvimrc UNIX 和 VMS 上的圖形使用者介面
_gvimrc MS-Windows 和 VMS 上的圖形使用者介面

帶有下劃線的替代方案是為了與舊版檔案系統相容。如果您在多個作業系統上使用 Vim 並使用現代 MS-Windows 檔案系統,則不必維護兩個配置檔案。將 _vimrc 設定為以下內容完全沒問題:

source ~/.vimrc

並在以下內容中執行所有配置 .vimrc.

這是一個示例 .vimrc 檔案

"Everything after a double quote is a comment.

"Wrap text after 72 characters
set textwidth=72

"Set tabs to 4 spaces
set tabstop=4
set shiftwidth=4
set stselect=4
set expandtab

"Tell Vim I use a dark background. Syntax highlighting (color coded text) will adjust to more appropriate colors.
set background=dark

"Misc overwrites of default color highlighting.
hi Comment ctermfg=DarkGreen
hi String ctermfg=DarkMagenta
hi pythonPreCondit ctermfg=Green

"Make sure that bottom status bar is running.
set ruler
set laststatus=2

"Make a mapping for "Q" which will reformat the current paragraph, comment,
"or code block according to the formatoptions setting:
map Q gqap

語法高亮

[編輯 | 編輯原始碼]

語法高亮允許您使用顏色、粗體和其他字型修改來高亮程式程式碼和其他檔案,以提高可讀性。

您可能想要編寫簡單的語法高亮語句,以便在您的檔案中輕鬆檢測模式。也就是說,如果您認為需要為 HTML 進行語法高亮,請不用擔心:大多數使用者不需要為常見的 檔案型別定義語法高亮檔案 - 大多數常見開發人員感興趣的檔案型別已經由 Vim 提供了預設的語法高亮定義。即使它沒有隨 vim 附帶,您通常也可以在 vim.org 上找到有人分享他們的作品。但是,如果您需要編寫一些簡單的東西,那麼本節適合您。(如果您需要一個語法高亮定義,它能夠正確顯示 Perl 程式碼,即使在 HTML 的 “pre” 標籤內,在 Perl print 語句內,在 shell 指令碼中的 shell heredoc 內,您可能不太走運,本節可能無法滿足您的需求 - 但是您不妨搜尋 vim.org,以防有人已經為您完成了)。

語法高亮是 Vim 最強大的功能之一。但是,如果您的知識儲備不夠(或者您沒有耐心,或者您正在處理複雜的程式語言語法),它也可能是最難設定的功能之一。所以讓我們看一下一些簡單的突出顯示定義

第一課:高亮製表符

[編輯 | 編輯原始碼]
... 或者如何高亮特殊字元

假設您需要知道您的檔案中哪些是製表符,哪些是空格。使用以下高亮,您可以使製表符可見

:syntax match Special "\t"

語法匹配會匹配正則表示式,並將給定的顏色應用於它。在本例中,它是顏色 “Special”。您必須確保顏色 “Special” 具有非標準背景 - 否則您將看不到差異

:highlight Special guifg=SlateBlue guibg=GhostWhite

您也可以在您的 .vimrc 中建立一個對映 - 這樣您就可以始終啟用製表符高亮

:nnoremap <F12><Tab>      :syntax match Special "\t"<CR>
:inoremap <F12><Tab> <C-O>:syntax match Special "\t"<CR>

另一種方法是使用 listchars。這些可能是製表符、尾隨空格和行尾。請注意使用 “>-” 而不是預設的 “^I”。這可以防止顯示/隱藏 listchars 時佈局發生變化

:set lcs=tab:>-,trail:%,eol:$ <CR>
:map <F12> :set list!<CR>

第二課:高亮空格錯誤

[編輯 | 編輯原始碼]
... 或者如何高亮行尾的空格
... 或者如何查詢空格和/或製表符
:syntax match Error "\s\+$"

第三課:高亮製表符錯誤

[編輯 | 編輯原始碼]
... 或者如何不高亮用作分隔符的字元

知道製表符在哪裡很好。但是製表符前的空格怎麼辦?它們只是浪費了檔案中的空間。以下高亮將向您顯示它們

:syntax match Error " \+\t"me=e-1

正則表示式 “ \+\t” 搜尋一個或多個空格,後跟一個製表符。這本身可以解決問題,但也會將製表符高亮為錯誤。如果我們只高亮空格,而製表符保持原樣,那就更好了。實際上,這是可能的,並且透過 “me=e-1” 完成。基本上,它表示:將高亮結束在找到的最後一個字元的前一個字元之前。

第四課:高亮行長度

[編輯 | 編輯原始碼]
... 或者如何在特定列高亮
... 或者如何在其他模式內高亮
... 或者如何允許其他模式在內部

以下匹配將在行長為 78 個字元時高亮第 78 列。當您有一行超過您想要的長度時,這可以用作警告。當然,這種高亮不應該干擾您可能使用的任何其他高亮

:syntax match Error "\(^.\{79\}\)\@<=." contains=ALL containedin=ALL

以下是它的工作原理的描述

  1. 正則表示式 “\(^.\{79}\)” 從行首 “^” 開始搜尋正好 79 個字元,並對結果進行分組 “\( \)”。
  2. “\@<=” 現在將從 1 開始對組進行“零匹配”。“零匹配”表示必須存在文字,但在找到後會被忽略。
  3. 使用 “.”,將匹配一個字元。該字元將使用 Error 顏色高亮。
  4. 使用 “contains=ALL”,我們允許其他高亮模式從我們的模式內部開始。
  5. “containedin=ALL”,我們允許我們的高亮模式從另一個模式內部開始。

Vim 幫助系統建議使用另一種方法。這對命令將高亮虛擬列 79 及以後的所有字元

:highlight rightMargin ctermfg=lightblue
:match rightMargin /.\%>79v/

這將只高亮第 79 列

:highlight col79 ctermbg=red
:highlight col79 guibg=red
:match col79 /\%<80v.\%>79v/

請注意,使用兩個專案也可以匹配佔用多個虛擬列的字元,例如 TAB。在最後一個示例中,添加了單獨的 ctermbg 和 guibg 定義,以便 col79 在 Vim 和 gVim 中都能起作用。

萬能補全

[編輯 | 編輯原始碼]

從版本 7 開始,Vim 支援全方位補全。這種補全方式應該跨越多個檔案,並支援程式語言的所有特性。但是,要使其正常工作,您需要在您的 "autoload/" 目錄中有一個合適的 "*complete.vim" 指令碼。這個指令碼必須定義一個名為 ...#Complete 的函式,該函式負責執行當前程式語言的所有補全工作。

但是編寫一個有用的補全函式可能是一項困難的任務。所有提供的補全函式都跨越了數百行程式碼。

這裡是一個用於 Ada 程式語言 的簡單實現,詳細描述了您可以建立自己的實現。此實現需要一個 "tags" 檔案,對於 Ada,您可以使用 gnat xref -v 命令建立。

完整版本可以從 vim.org 網站 下載。

分步教程

[edit | edit source]

使用 <C-X> <C-O> 將補全設定為自動載入函式。如果此指令碼是直接載入的,而不是使用自動載入功能,則此檢查將生效。

if exists ('+omnifunc') && &omnifunc == ""
    setlocal omnifunc=adacomplete#Complete
endif

全方位補全和自動載入在低於 7.00 的任何 Vim 版本中都不起作用。

if version < 700
    finish
endif

所有 complete#Complete 函式都必須涵蓋兩個選項:a:findstart == 1a:findstart != 1

    function adacomplete#Complete (findstart, base)
Findstart 等於 1
[edit | edit source]

a:findstart == 1 時,我們必須找出游標左側有多少個字元可能是補全的一部分。

	if a:findstart == 1

對於我們的簡單示例,找到單詞的開頭非常簡單。我們向左查詢,直到找到一個不是單詞一部分的字元。對於大多數語言,搜尋 “\i” 應該可以解決問題。但是,對於 Ada,我們還想擴充套件 屬性 - 因此我們將 “'” 新增到單詞字元列表中。

	    let line = getline ('.')
	    let start = col ('.') - 1
	    while start > 0 && line[start - 1] =~ '\i\|'''
		let start -= 1
	    endwhile
	    return start
Findstart 不等於 1
[edit | edit source]

a:findstart != 1 時,我們需要為 a:base 找到可能的補全。有兩個選項可以返回找到的補全。

  1. 使用 return 將所有補全作為 List 返回。
  2. 為每個找到的補全呼叫 complete_add

您也可以組合使用兩者 - 它們隨後會被合併 - 所以注意不要建立重複項。補全可以是 StringDirectory

在本示例中,我們使用 complete_add

	else

搜尋模式應該在匹配的文字開頭查詢 a:base。

	    let l:Pattern    = '^' . a:base . '.*$'

在第一步中,我們新增所有已知的 Ada 關鍵字編譯指示屬性型別。它們已經被 Ada 檔案型別外掛 準備成 List 中的 Directorys。我們所要做的就是遍歷該列表,並將所有 "word" 欄位匹配模式的 Directory 條目新增進去。

	    if exists ('g:Ada_Keywords')
		for Tag_Item in g:Ada_Keywords
		    if l:Tag_Item['word'] =~? l:Pattern

新增值 - 包括簡單的錯誤處理。

			if complete_add (l:Tag_Item) == 0
			    return []
			endif
			{{vi/Ex|if} complete_check ()
			    return []
			endif
		    endif
		endfor
	    endif
搜尋匹配項
[edit | edit source]

這裡完成了實際的工作:我們在標籤檔案中搜索匹配項。當然,您首先需要一個標籤檔案。有很多工具可以建立相容 Vim 的標籤檔案。只需四處尋找一個即可。

	    let l:Tag_List = taglist (l:Pattern)

我們再次需要遍歷所有找到的 List 元素。

	    for Tag_Item in l:Tag_List
		if l:Tag_Item['kind'] == ''
		    let l:Tag_Item['kind'] = 's'
		endif

由於標籤和補全的 Directory 結構不同,因此需要轉換資料。

標籤中可用的資訊取決於標籤檔案建立工具。但最少的是

“name”
標籤的名稱。
“filename”
定義標籤的檔案的名稱。
“cmd”
用於在檔案中定位標籤的示例命令。
“kind”
標籤的型別。此條目的值取決於 ctags 工具生成的語言特定的種類值。

補全的內容是固定的,包含以下內容

“word”
實際的補全
“kind”
補全的型別,一個字元,例如 “v” 表示變數。
“menu”
在補全選單中顯示的簡短額外資訊。
“word”
在額外視窗中顯示的較長額外資訊。
“icase”
忽略大小寫

所以對於沒有額外資訊的簡單標籤,轉換可能看起來像這樣

	        let l:Match_Item = {
		    \ 'word':  l:Tag_Item['name'],
		    \ 'menu':  l:Tag_Item['filename'],
		    \ 'info':  "Symbol from file " . l:Tag_Item['filename'] . " line " . l:Tag_Item['cmd'],
		    \ 'kind':  l:Tag_Item['kind'],
		    \ 'icase': 1}
		if complete_add (l:Match_Item) == 0
		    return []
		endif
		if complete_check ()
		    return []
		endif
	    endfor
請注意
當前的 Ada 外掛已經擴充套件到也支援 ctags,它比 gnat xref -v 提供更多資訊。但是,我們沒有更新教程,因為我們希望保持示例簡單易懂。

我們已經透過 complete_add 添加了所有匹配項,因此我們只返回一個空列表。

	    return []
	endif
    endfunction adacomplete#Complete
    finish
endif

最後一點建議:如果您的標籤工具沒有對條目進行排序,那麼您應該單獨對它們進行排序。在排序後的標籤檔案中進行搜尋速度要快得多。


學習 vi 編輯器: 熟悉基本任務使工作更輕鬆高階任務細節vi 克隆 (Vim基本導航模式技巧對程式設計師有用的東西增強 VimVim 在 Windows 上VimL 指令碼語言, Vile, BB vi)vi 參考

華夏公益教科書