Vim 8文本處理實戰:教您得心應手在日常任務中使用Vim

通過閱讀本章,讀者將能更加得心應手地在日常任務中使用Vim。本章使用一個Python工程作為示例,模擬了一系列日常編碼的場景。當然,讀者完全可以拿自己手頭的項目練手;只不過,本章中的使用場景不一定都適用於讀者自己的代碼。

本章包括如下主題。

  • 介紹一種粗暴但快捷的Vim插件安裝方式。
  • 介紹如何使用緩衝區、窗口、標籤頁和摺疊來處理多個文件或長文件,從而使工作區更為整潔。
  • 介紹插件Netrw、NERDTree、Vinegar和CtrlP,通過這些插件,讀者可以在不退出Vim的情況下瀏覽複雜的文件樹。
  • 介紹文件中的高級文本瀏覽方式、極其高效的光標移動插件EasyMotion以及多種文本對象,介紹通過grep和ack實現跨文件的搜索。
  • 介紹如何利用寄存器來複制和粘貼。

1 技術要求

本章將介紹如何用Vim在一個Python工程上作業。讀者可以在異步社區中找到本章用到的代碼。

2 安裝插件

本章會介紹幾個Vim插件,但暫時不會涉及較為複雜的插件管理,相關的內容參見第3章。

首先,讀者必須要做好準備工作。

1.創建一個存儲插件的目錄,執行下列命令。

<code>$ mkdir -p ~/.vim/pack/plugins/start/<code>

如果在Windows系統中使用gVim,則需要在用戶目錄(通常是C:\\Users\\ )下創建vimfiles目錄,然後在其中創建子目錄pack\\ plugins\\ start。

2.使Vim能夠自動加載每個插件的文檔(Vim默認不會這麼做)。在~/.vimrc文件(在Windows系統中為用戶目錄下的_vimrc文件)中添加下列代碼。

<code>packloadall               " 加載所有插件
silent! helptags ALL " 為所有插件加載幫助文檔/<code>

然後,每次安裝插件都可按照下列步驟進行。

1.在 GitHub 上找到想要安裝的插件。比如,讀者想安裝scrooloose/ nerdtree(注意,這裡的scrooloose/nerdtree為該GitHub倉庫的唯一標識,實際地址為https://github.com/scrooloose/nerdtree.git)。假設讀者已經安裝了Git,則可以找到此Git倉庫的克隆地址,然後運行如下命令。

<code>$ git clone https://github.com/scrooloose/nerdtree.git 
~/.vim/pack/plugins/start/nerdtree/<code>

如果讀者沒有安裝Git,或者在Windows系統中使用gVim,則可以在GitHub頁面上找到克隆或下載(Clone or download)按鈕,下載ZIP壓縮包,然後將其解壓到相應的插件目錄中,比如在Linux系統中為目錄~/.vim/pack/ plugins/start/nerdtree,而在Windows系統中為用戶目錄下的子目錄vimfiles/pack/plugins/start/nerdtree。

2.重啟Vim之後,即可使用插件進行相關操作。

3 組織工作區

到目前為止,本書還只是用Vim處理單個文件。但是在編寫程序時,經常需要同時處理多個文件,涉及來回切換、跨文件編輯或到其他界面查詢資料等操作。幸運的是,Vim提供了一個能夠處理多個文件的插件。

  • Vim內部用緩衝區來表示文件;通過緩衝區,讀者可以在不同文件之間快速切換。
  • Vim用多個窗口在同一屏幕中顯示多個文件。
  • Vim用標籤頁對窗口進行分組。
  • Vim用摺疊效果來隱藏或展開一個文件的部分內容,從而讓讀者可以更容易地瀏覽文件的內容。

圖1中展示了上述要點,解釋如下。

Vim 8文本處理實戰:教您得心應手在日常任務中使用Vim

圖1

  • 多個窗口用於同時打開多個文件(farm.py、animal/cat.py和animal_farm.py)。
  • 頂部顯示有兩個標籤頁(3 farm.py和a/dog.py)。
  • 以+--開頭的行表示摺疊,它隱藏了文件的部分內容。

本節將詳細介紹窗口、標籤頁和摺疊,通過這些功能,讀者可以在工作中同時處理任意多個文件。

3.1 緩衝區

緩衝區是文件的內部表示,每個打開的文件都有一個緩衝區。比如,通過命令行vim animal_farm.py打開一個文件,然後可以用:ls命令看到現有的緩衝區列表。

很多命令都有別名或等價命令,:ls也不例外,它和:buffers及:files實現的是同樣的功能,讀者可以從中選擇一個最容易記的命令。

圖2所示為ls命令的執行結果(最下面的那3行)。

Vim 8文本處理實戰:教您得心應手在日常任務中使用Vim

圖2

圖2.2中的狀態欄顯示了已經打開的緩衝區(這裡只有一個)的相關信息,這些信息的含義如下。

  • 1為緩衝區編號,在整個Vim會話中,它的值保持不變。
  • % 表示該緩衝區位於當前窗口中。
  • a 表示該緩衝區處於活動狀態,即它已被加載並可見。
  • "animal_farm.py"為文件名。
  • line 30表示當前光標位置。

現在,用下列命令打開另一個文件。

<code>:e animals/cat.py/<code>

然後,可以看到之前打開的文件已經被當前文件所取代。不過,animal_farm.py仍然存儲在某個緩衝區中,讀者可以再次用:ls命令將其顯示出來。

現在,可以看到兩個文件名都被列出來了,如圖3所示。

Vim 8文本處理實戰:教您得心應手在日常任務中使用Vim


圖3

那麼怎樣才能跳轉到之前的文件呢?

Vim通過數字和名稱來標識每個緩衝區,在同一個Vim會話中,它們都是唯一的(除非退出Vim)。為了在不同的緩衝區之間切換,可使用:b命令,其參數為緩衝區的編號數字。

<code>:b 1/<code>

:b 1命令中的空格可以省略,得到簡化版的命令:b1。

通過一條很簡單的命令就可以回到原來的文件。由於緩衝區還可以用文件名來標識,因此讀者可以用文件名的一部分來切換緩衝區。下列命令將打開animals/cat.py的緩衝區。

<code>:b cat/<code>

不過,如果名稱匹配了多個緩衝區,則Vim會報錯。比如,用下面的命令查找所有文件名包含py的緩衝區。

<code>:b py/<code>

Vim的狀態欄中會顯示錯誤,如圖4所示。

Vim 8文本處理實戰:教您得心應手在日常任務中使用Vim

圖4

為解決這個問題,可以使用Tab鍵補全文件名,從而實現在不同緩衝區之間循環切換。輸入:b py(先不要按Enter鍵),然後按Tab鍵,在所有匹配的結果之間循環遍歷。

讀者也可以使用:bn(:bnext)和:bp(:bprevious)命令循環遍歷緩衝區。

當不再需要某緩衝區的時候(如不再需要編輯該文件),可以將其刪除。通過如下命令可以將一個緩衝區從打開的緩衝區列表中刪除,而無須退出Vim。

<code>:bd/<code>

但如果沒有保存當前緩衝區,則Vim會報錯。因此,在不小心刪除緩衝區之前,讀者還有一次保存文件的機會。

3.2 插件——unimpaired

Tim Pope的vim-unimpaired是一個Vim插件,它為很多內置命令(以及一些新的命令)添加映射。本書作者每天都會使用這個插件,因為它提供了更為直觀的映射,比如]b和[b用於循環遍歷緩衝區,]f和[f用於遍歷目錄中的文件。該插件可以在GitHub倉庫tpope/vim-unimpaired中找到(安裝方法參見本章2.2節)。

下面是vim-unimpaired提供的部分映射。

  • ]b和[b循環遍歷緩衝區。
  • ]f和[f循環遍歷同一目錄中的文件,並打開為當前緩衝區。
  • ]l和[l遍歷位置列表(參見第5章)。
  • ]q和[q遍歷快速修復列表(參見第5章)。
  • ]t和[t遍歷標籤列表(參見第4章)。

此插件還支持用少數幾次按鍵來切換某些選項,比如yos切換拼寫檢查,或yoc切換光標行高亮顯示。更多功能參見:help unimpaired中vim-unimpaired所提供的完整映射和功能清單。

3.3 窗口

Vim將緩衝區加載到窗口中。一個屏幕上可以同時顯示多個窗口,它們將屏幕分割成幾塊。

1.窗口的創建、刪除和跳轉

本節將介紹Vim窗口的使用方式。首先,打開animal_farm.py文件(在命令行中執行$ vim animal_farm.py或從Vim中執行:e animal_farm.py)。

然後,使用如下命令將窗口分割成兩個,其中一個顯示新的文件。

<code>:split animals/cat.py/<code>

:split命令可以簡化為:sp。

可以看到animals/cat.py被打開,顯示在原文件上方的窗口中,而且光標也出現在裡面,如圖5所示。

Vim 8文本處理實戰:教您得心應手在日常任務中使用Vim


圖5

也可以使用下面的命令按水平方向分割窗口。

<code>:vsplit farm.py/<code>

如圖6所示,當前窗口又水平分隔出一個新的窗口(光標也隨之移動到左邊的新窗口中)。


Vim 8文本處理實戰:教您得心應手在日常任務中使用Vim

圖6

:vs是:vsplit的簡化版。

通過組合:split和:vsplit,可以生成任意多個窗口。

目前本書提到的所有命令都適用於窗口,包括切換緩衝區。為了使光標能在不同窗口間移動,先按Ctrl + w組合鍵,然後輸入一個方向鍵:h、j、k、l中的一個或鍵盤方向鍵。

按Ctrl + h組合鍵,之後再按Ctrl + j組合鍵(Ctrl鍵可以不鬆開,記為Ctrl + w,j組合鍵),光標會進入下面的窗口,而使用Ctrl + w,k組合鍵則進入上面的窗口。

如果經常使用窗口,讀者可以按照如下配置綁定快捷鍵。" 使用<ctrl> + hjkl快速在窗口間跳轉 noremap noremap noremap noremap /<ctrl>

然後,就可以用Ctrl + h組合鍵跳到左邊的窗口,用Ctrl + j組合鍵跳到底部的窗口,依此類推。

讀者可以用下列方式來關閉窗口。

  • 使用Ctrl + w,q組合鍵關閉當前窗口。
  • 使用:q命令關閉窗口並卸載緩衝區;不過,當只有一個窗口打開的時候,這會導致退出Vim。
  • 使用:bd命令刪除當前緩衝區,並關閉當前窗口。
  • 使用Ctrl + w,o組合鍵(或:only,或:on命令)關閉除當前窗口之外的所有窗口。

當打開了多個窗口時,可通過:qa命令關閉所有窗口並退出。也可以結合:w命令,即:wqa,它會先保存所有打開的文件,再退出Vim。

如果只想關閉緩衝區,而保留它所在的窗口,則可以在.vimrc文件中加入如下配置。

<code>" 關閉緩衝區而不關閉窗口
command! Bd :bp | :sp | :bn | :bd/<code>

然後,讀者就可以使用:Bd來關閉緩衝區,而保留分割窗口。

2.窗口的移動

窗口也可以移動、交換或改變大小。因為Vim中沒有鼠標拖曳的功能,所以只能記住一些命令了。

讀者並不需要記住所有這些命令,只要知道Vim支持哪些窗口操作,剩下的操作可以通過查看文檔。使用:help window-moving和:help window- resize打開Vim手冊中相應的條目,即可找到所有相關的快捷鍵。

窗口命令的快捷鍵都要先按Ctrl + w組合鍵,後面跟一個大寫的方向鍵(H、J、K和L中的一個),當前窗口會被移動到相應的位置。

  • 使用Ctrl + w,H組合鍵將當前窗口移動到屏幕的最左邊。
  • 使用Ctrl + w,J組合鍵將當前窗口移動到屏幕的底部。
  • 使用Ctrl + w,K組合鍵將當前窗口移動到屏幕的頂部。
  • 使用Ctrl + w,L組合鍵將當前窗口移動到屏幕的最右邊。

比如圖 7 所示的窗口布局(先打開animal_farm.py,然後再依次運行:sp animals/cat.py和:vs farm.py,可得到這個佈局)。

Vim 8文本處理實戰:教您得心應手在日常任務中使用Vim


圖7

注意,圖7中光標位於animals/cat.py文件所在的窗口中。通過前面介紹的幾個快捷鍵,可以讓這個窗口朝不同的方向移動。

  • 使用Ctrl + w,H組合鍵將animals/cat.py移動到最左邊,如圖8(a)所示。
  • 使用Ctrl + w,J組合鍵將animals/cat.py移動到底部,而且左右分割變成了上下分割,如圖8(b)所示。
  • 使用Ctrl + w,K組合鍵將animals/cat.py移動到頂部,如圖8(c)所示。
  • 使用Ctrl + w,L組合鍵將animals/cat.py移動到最右邊,如圖8(d)所示。


Vim 8文本處理實戰:教您得心應手在日常任務中使用Vim

(a)

Vim 8文本處理實戰:教您得心應手在日常任務中使用Vim

(b)

Vim 8文本處理實戰:教您得心應手在日常任務中使用Vim

(c)

Vim 8文本處理實戰:教您得心應手在日常任務中使用Vim

(d)

圖8

若想修改一個窗口的內容,則只需要跳轉到這個窗口,然後用:b命令來選擇所需的緩衝區。不過,也有一些快捷鍵可以用於交換兩個窗口的內容。

  • 使用Ctrl + w,r組合鍵將當前行或當前列(行優先於列)中的每個窗口的內容向右或向下移動。使用Ctrl + w,R組合鍵則以相反的方向執行類似的操作。
  • 使用Ctrl + w,x組合鍵將當前窗口與下一個窗口的內容交換(如果當前窗口是最後一個,則與前一個交換)。

Vim內部用數字來標識窗口。不過,與緩衝區不同,窗口的編號是隨著佈局變化而改變的,而且並沒有直接的方法來修改窗口編號。有些窗口管理命令以窗口編號為參數,但本書不會涉及這部分內容。有一條原則僅供參考,窗口編號順序為由上至下、由左至右遞增。

3.改變窗口的大小

Vim窗口默認的寬高比為50/50,這可能並不滿足讀者的需求,因此窗口的大小可以通過一些方法來改變。

快捷鍵Ctrl + w,=(按Ctrl+w後再按=鍵)能夠將所有打開窗口的寬和高調整為一致。如果不恰當地調整了窗口大小,這個命令將非常有用。

:resize命令會增加或減少當前窗口的高度,而:vertical resize將調整窗口的寬度。讀者還可以使用如下命令。

  • :resize +N用於將當前窗口的高度增加N行。
  • :resize -N用於將當前窗口的高度減少N行。
  • :vertical resize +N用於將當前窗口的寬度增加N列。
  • :vertical resize -N用於將當前窗口的寬度減少N列。

:resize和:vertical resize可分別簡寫為:res和:vert res。另外,還有將窗口高度和寬度改變一行/列的快捷鍵:Ctrl + w,-和Ctrl + w,+用於調整高度,而Ctrl+w,>和Ctrl + w,

兩種命令都可以將寬度/高度設置為具體的行數/列數。

  • :resize N用於將窗口高度設置為N。
  • :vertical resize N用於將窗口寬度設置為N。

3.4 標籤頁

在很多現代編輯器中,標籤頁(Tabs)用於表示不同的文件。在Vim中自然也是如此,但讀者需要考慮其原始目的。

Vim用標籤頁來組織一個窗口的集合,進而支持在不同的窗口集合之間切換,這讓用戶方便地擁有了多個工作區。標籤頁通常用來在同一個Vim會話中區分不同的問題或者文件集合。標籤頁功能不一定是一個頻繁使用的功能,但如果希望在不同項目或同一項目的不同上下文之間切換,那麼標籤頁將是一個不錯的選擇。

用戶願意使用標籤頁的另一個原因可能與Vim的diff功能有關,因為diff作用於一個標籤頁內。更多詳情請參考第5章中關於vimdiff的介紹。

在一個新標籤頁中打開一個空緩衝區的命令如下。

<code>:tabnew/<code>

在新標籤頁中打開一個已有文件的命令為:tabnew 。

如圖9所示,標籤頁顯示在屏幕的頂部。在標記為3 farm.py的標籤頁中打開了三個窗口及一個活動緩衝區farm.py。[No Name]標籤頁則是剛才打開過的空緩衝區。


Vim 8文本處理實戰:教您得心應手在日常任務中使用Vim


圖9

在一個標籤頁中,可以通過常用的方式(:e )來加載文件,也可以用:b命令在不同緩衝區之間切換。

為了在不同標籤頁之間跳轉,可以使用如下命令。

  • 快捷鍵gt或:tabnext命令用於切換到下一個標籤頁。
  • 快捷鍵gT或:tabprevious命令用於切換到上一個標籤頁。

標籤頁可通過:tabclose命令來關閉,標籤頁關閉也會導致其中的窗口關閉(如果只剩一個標籤頁,則需要用:q來關閉)。

:tabmove N命令將當前標籤頁移動到第N個標籤頁之後(如果N為0,則變成第一個標籤頁)。

3.5 摺疊

Vim為瀏覽大型文件提供的一個強大工具是摺疊。摺疊功能支持文件部分內容的隱藏,隱藏的依據既可以是預定義的規則,也可以是手動添加的摺疊標記。

如圖10所示,animal_farm.py中的部分代碼片斷被摺疊了,代碼中每個方法的具體內容被隱藏了,從而可以在整體上來查看代碼。


Vim 8文本處理實戰:教您得心應手在日常任務中使用Vim


圖10

1.摺疊Python代碼

因為本書以Python編程為例,所以這裡只介紹Python示例代碼的摺疊方式。首先,需要在.vimrc文件中將foldmethod設置為indent,設置代碼如下。

<code>set foldmethod=indent/<code>

不要忘記重新加載~/.vimrc,方法是重啟Vim或在Vim中執行:source $MYVIMRC命令。

設置foldmethod為indent,使Vim基於縮進來摺疊代碼。

再次打開animal_farm.py,可以看到該文件中的部分代碼已經被隱藏,如圖11所示。


Vim 8文本處理實戰:教您得心應手在日常任務中使用Vim


圖11

將光標移動到其中一個摺疊行上,輸入zo可以打開當前摺疊,如圖12所示。


Vim 8文本處理實戰:教您得心應手在日常任務中使用Vim


圖12

只要光標在一個潛在的摺疊文本中(本例中為縮進的代碼塊),輸入zc都會將此摺疊關閉。

為了方便看清摺疊的位置,可以使用:set foldcolumn=N命令,其中N的取值為0~12。這會告訴Vim用從屏幕左邊開始的N列來標記摺疊,其中符號-表示一個打開的摺疊,符號|表示打開的摺疊的內容,符號+表示關閉的摺疊。

輸入za可切換摺疊狀態(打開關閉的摺疊或關閉打開的摺疊)。輸入zR和zM分別用於同時打開和關閉所有摺疊。

將foldmethod設置為自動類型(如indent)會默認將所有文件摺疊。這只是一種偏好,讀者也可能會選擇在打開新文件時打開摺疊。在.vimrc文件中添加autocmd BufRead * normal zR會在打開新文件時令摺疊處於打開狀態,即Vim在讀取新的緩衝區時執行zR命令(打開所有摺疊)。

2.摺疊的類型

從某種意義上來說,Vim在摺疊代碼方面是比較智能的,而且支持多種摺疊方式。摺疊的方法由.vimrc文件中的foldmethod選項來指定。Vim支持如下摺疊方式。

  • manual:手動摺疊,這種方法對於長文本而言並不適用。
  • indent:基於縮進的摺疊,這對於依賴縮進的編程語言非常合適(不管哪種語言,標準的編碼風格中總是會採用某種一致性的縮進。因此,當讀者想要快速隱藏不關心的代碼時,indent摺疊方式不失為一種高效率的選擇)。
  • expr:基於正則表達式的摺疊。如果讀者想要用複雜的規則來定義摺疊,那麼可以選擇這種方式。
  • marker:使用文本中特殊的標記來定義摺疊,比如{{{和}}}。這種方法對於管理很長的.vimrc文件非常有效,但是在Vim之外不常用,因為這種方式需要修改文件內容。
  • syntax提供了可識別語法的摺疊,但它並非對所有語言都開箱即用(不支持Python)。
  • diff:當Vim處於diff模式時會自動採用這種摺疊方式,diff模式下需要展示兩個文件的不同之處,而相同之處往往需要隱藏起來(參見第5章)。

設置摺疊方式的方法為在.vimrc文件中加入set foldmethod=。

4 文件樹的瀏覽

軟件項目往往包含大量的文件和目錄,能夠利用Vim快速瀏覽和展示這些文件和目錄將是一件很方便的事。本節介紹5種不同的文件瀏覽方式,它們分別是內置的Netrw文件管理器、啟用了wildmenu的:e命令、NERDTree、Vinegar和CtrlP插件。這些方式都可用於處理文件,並可按需求組合使用。

本文截選自《Vim 8文本處理實戰》

Vim 8文本處理實戰:教您得心應手在日常任務中使用Vim

  • Vim8文本處理技術指南,vim實用技巧
  • 文本編輯器書籍
  • 程序員編程開發技能,python語言結合

作為全面介紹Vim使用方法的教程,本書介紹了各種常用的文本編輯方法和程序設計中的實用操作,深入Vim內部的數據結構和VimScript腳本編程,內容詳實。本書基於Vim 8平臺,介紹了前沿分支Neovim,還推薦了更先進的Oni編輯器,兼容幷包,集Vim社區典型使用經驗和發展趨勢於一體。

本書面向的讀者群體是所有使用Vim的程序員,書中的示例文本為Python代碼,並詳細介紹了Git和正則表達式。讀者需要對操作系統和程序設計有基本的瞭解,特別是需要了解Linux操作系統的基本使用。雖然本書嘗試兼顧三大操作系統,但毫無疑問書中內容以Linux為主。本書可以幫助讀者完善Vim技能,增加程序設計的知識儲備。


分享到:


相關文章: