Vim 入門指南:與鍵盤最優雅的距離

據說:世界上的程序員分三種,一種使用 Emacs,一種使用 Vim,剩餘的是異端。

上面是一則笑談,但也確實反映了 Emacs 和 Vim 在很多人心中的地位(若有興趣瞭解其兩者間的相愛相殺,可以查看「編輯器之戰」)。鄙人不才,還尚未學會 Emacs,但是對於 Vim 可以算是摸清點門道了。

Vim(全稱:Vi IMproved)是編輯神器 vi 的改進。很多人說它是史上最好的文本編輯器 (Editor),我無法證明,但是我更願意說它是一種習慣、一種語言。Vim 代表着簡潔、高效、優雅的文字輸入態度和精神,它雖然微小且簡單,卻能在無形之中加速工作的效率。

vi 和 vim 的具體區別大家可以對比 Wikipedia 的介紹。日常的基礎使用上 vi 和 vim 沒有太大區別,二者同根同源一脈相承,只是因爲 vim 是 vi 的改進版,所以添加了很多有用的功能,使用起來也更加方便一些,本文主要講解 vim。

學習 vim 是一個從建立規矩到打破規矩的過程,最開始是瞭解命令、瞭解不同的模式,到最後眼中就不會有那些複雜的命令,全然轉化爲一門語言和一種內在的習慣了。本篇文章並不會講解 vim 全部的功能,只是作爲引導,不想聽筆者囉嗦的也可以直接參閱下面推薦的參考資料。

除了下面提供的參考資料,筆者還強力推介 vim 自帶的 vimtutor。大部分 distro 都可以找到 vimtutor 的 pkg,如果需要的話網上也有很多的資源

vi 的資料:

vim 的資料:

下面就讓我們一點點地瞭解 vim,如果對具體章節感興趣,也可以通過下面的目錄來跳轉到自己需要的內容,希望能對諸位看官有所幫助。

目錄

上手:學會打字

在學習之前注意:

首先,請安裝 vim(這裏提供的是「Arch Linux」的命令):

$ sudo pacman -S vim

安裝完畢後,創建一個新文件:

$ vim hello

然後你就進入了 vim,但是先不要激動,因爲你根本不能正常編輯,這時我們就需要瞭解 vim 其實有三個編輯模式:

每種模式會在左下角顯示出來,Normal 模式的時候什麼都不顯示,一開始進入的也就是 Normal 模式,在這個模式下你可以輸入一些命令:

i   // 進入 Insert 模式
v   // 進入 Visual 模式

h   // 向左移動光標
j   // 向下移動光標
k   // 向上移動光標
l   // 向右移動光標

:w  // write 存儲文件
:q  // quit 退出文件

進入 Insert 和 Visual 模式之後只需要按 ESC 就可以返回 Normal 模式。另外,在 vim 中也可以使用方向鍵代替 hjkl 的移動,不過筆者還是推薦熟練 hjkl 的用法。到此爲止我們就可以將 vim 當作一個正常的編輯器使用了。

入門:我們還可以幹什麼

從上面的例子我們不難看出,大部分的命令都是在 Normal 模式實現的,所以我們有的時候也叫這個模式 Command 模式(當然有些大神把輸入 : 單獨稱爲 Command 模式,或者 Ex 模式,要是有大神對這裏能給出準確定義請指正)。在 vim 中,我們所用到的指令其實都可以理解爲語言,我們只需要瞭解每個按鍵的含義,就可以自己組合出不同的功能,在這一部分我們會進行細緻的講解。

首先,先擴充一下模式切換的按鍵:

i     // insert 在光標位置插入
a     // append 在光標後面插入

v     // visually select 逐個字符可視化選擇
V     // 逐行可視化選擇
<C-v> // visual block 區塊可視化選擇

更多的編輯和存儲

然後我們說一下基礎的編輯功能:

d // delete 刪除
c // change 更改
y // yank (copy) 複製

其中 dc 最主要的區別在於,使用 c 之後會進入 Insert 模式,這就是爲什麼其名爲更改的原因。

除了編輯文字之外我們還得瞭解怎麼打開和存儲文件,除了上面介紹的幾種方法以外你還可能會使用:

:q! //強制退出,放棄所有修改
:wq //保存並退出

:w /some/path/[filename]      //另存爲新的文件名
:saveas /some/path/[filename] //同樣也是另存爲,和上一條效果一致

:x //如果沒有修改則直接退出,如果進行修改則保存修改後退出,可以稱爲 :wq 的更快捷方法
ZZ //更快捷的 :wq 的方法

不但是查找,還是高效的光標移動

vim 中還包含着很強大的查找功能:

t // 光標停留在被查找字符之前
f // 光標停留在被查找字符的位置

事實上,T、F 的功能和 t、f 相同,區別在於前者是向前查找。這些搜索功能不但可以看作搜索功能,更可以當作移動光標的功能,這樣在之後選擇內容上就

會非常高效。除了搜索單一字符或相同內容外,vim 還可以直接搜索我們想要的內容:

/ // 向下尋找一串字符
? // 向上尋找一串字符

在搜索一串字符的時候我們可以進行向上、向下查詢:

n // 下一個字符
N // 上一個字符

這兩個按鍵針對不同查詢方式反應是不一樣的,各位看官自己嘗試一下便能感受其中的神奇。另外,有興趣的朋友還可以仔細觀察左下角的命令變化。

除了這些還有兩個更爲靈活的命令,介於查找和移動之間,筆者將其放在這裏:

* // 尋找光標所在位置的相同內容(一般是以一個單詞或者一個符號爲單位,vim 非常智能會自動判斷你想表達的意思)

% // 在對應的左右括號([、(、{)之間切換

在字符之中自由的遊走

接下來筆者將介紹更多的移動方式:

0 // 將光標移動到所在行的起始位置
$ // 將光標移動到所在行的結束位置
^ // 將光標移動到第一個非空字符

w // 移動到下一個單詞
b // 移動到上一個單詞
e // 移動到下一個單詞的末尾

W // 移動到下一個單詞(使用 W 的時候粗略地將兩個空格之間的一切看成一個單詞,而 w 會考慮其他符號影響)
B // 移動到上一個單詞(原理同上)

除了這些以外,我們還可以進行更大幅度的移動:

:line_number // 移動到指定行

H // 移動到屏幕頂部
M // 移動到屏幕中央
L // 移動到屏幕底部

[line_number]G  // 移動到指定行(命令中不包含 []),效果和 : 相同
gg              // 移動到文件頂部(相當於 1G)
G               // 移動到文件底部

<C-U> // 向上移動半個屏幕
<C-D> // 向下移動半個屏幕
<C-F> // 向上翻頁
<C-B> // 向下翻頁

更多插入內容的方法

I // 在所在行的開頭(不計入空字符)插入字符
A // 在所在行末尾插入字符

o // open 打開新的一行,在所在行之後插入新的一行
O // open 打開新的一行,在所在行之前插入新的一行

r // replace 替換,替換當前光標所在字符
R // replace 替換,從當前光標開始替換字符

C // change 更改,更改當前行

更多修改內容的方法

在 vim 的世界中,我們並不一定要在 Insert 模式中修改字符,很多時候都可以直接在 Normal 模式中修改。當然,多說一句,其實真正高手的眼中是沒有不同模式之分的,之後筆者會進行更加詳盡的解釋。

x   // exterminate 消除,消除當前光標所在字符
X   // exterminate 消除,消除當前光標前的一個字符

dd  // 刪除當前行
D   // 從光標所在位置刪除到當前行結束

yy  // 複製當前行(和 ddP 的作用一致)

J   // join 合併,合併當前行和下一行

vim 非常方便的一點是,無論是複製 y (yank)、c (change) 還是 d (delete) 亦或是 x (exterminate) 的操作,vim 都會將修改的內容保存下來方便我們隨時粘貼,下面就列出粘貼的方法:

p // paste 粘貼,在當前光標之後粘貼
P // paste 粘貼,在當前光標之前粘貼

如何反悔和重做

在修改文字的時候難免會犯錯,這時候就需要撤銷 (undo) 和重做 (redo):

u     // 撤銷上次操作
<C-r> // 重複上次操作

把 vim 當作一種語言

在學習完前面的內容之後,我們只是瞭解了 vim 的部分,真正 vim 的使用要像說話一樣,而且隨着對 vim 的使用更加熟練,我們會發現當同樣一個命令在作爲名詞或者動詞組合在一起的時候可能會有完全不同的意思,下面就先把我們已經熟悉的一些命令和其中部分的不同含義列出來:

i // inside 之中
a // around 周圍

w // word 單詞
s // sentence 句子
p // paragraph 段落

t // tag (HTML/XML) 標籤
b // block 區塊(編程中的概念)

下面筆者先列舉一些簡單的例子:

dw  // 刪除到下一個單詞
cb  // 更改到上一個單詞
y2w // 複製下兩個單詞

以上是比較簡單的用法,原理其實就是一個動作,比如 d 代表刪除,w 是移動到下一個單詞,所以就是刪除到下一個單詞的意思了。在例子 y2w 中,我們可以知道在命令前面加上數字就代表重複這個命令幾次,這個可以推而廣之,幾乎所有的命令都可以這樣使用,通過重複命令可以使輸入效率有明顯提升。同理我們還可以更加靈活地使用一些命令:

0y$     // 從所在行的起始位置複製到所在行的結束位置
y2/foo  // 複製到第二次 foo 出現的位置

接下來我們再加大難度:

ci" // 更改「"」中的內容(change in `"`)
da( // 刪除「(」以及其中的內容(delete around `(`)
ct" // 修改到「"」(change to `"`)

這個可能會讓人疑惑,ia 不是插入的字符嗎?但是在這裏它們其實是修飾詞 (Modifiers),所以含義上也和之前有所不同。

vim 的神奇之處並不僅限於此,當我們懂得了 vim 是一門語言之後我們就有了更多的施展空間,小夥伴們可以自己隨意組合出不同的命令。

入門之後:將瑣事交給 vim

經過上述的學習加上不斷的練習,我們對 vim 的語言理解更加深入了,但是學會一種語言並不難,精通纔是根本。就如我們平常說話一樣,越精通越簡練,很多時候 vim 可以自動幫你完成你需要的事情。下面筆者就介紹幾個常用的功能:

自動補全

在寫作或者編程的時候我們經常會使用到自動補全 (auto-complete) 功能,在 vim 中這項功能尤爲強大,只需要在 Insert 模式下輸入:

<C-p> // 向上自動補全
<C-n> // 向下自動補全

有人可能會好奇爲什麼要有兩個補全?原因是爲了更高效的輸入,在進行龐大文字輸入工作的時候這樣做會極大地提高效率,這也再次印證了 vim 是爲高效而生的。當然,除了這兩種自動補全的方法以外,還有使用 <C-x> 的更具體的方式,在這裏爲了方便大家吸收就不補充了,在本篇文章的後半部分可能會擴充這部分的知識。

自動縮進

自動縮進 (auto-indent) 這個功能筆者自然不必過多贅述,單單這一項功能就可以讓人愛上 vim:

= // 自動縮進

只需要使用 <C-v> 選擇我們需要縮進的行然後按下 =,所有的代碼就整整齊齊地呈現在我們面前了。當然,vim 中也含有手動縮進的方法:

< // 向左縮進
> // 向右縮進

有的時候寫文章自動縮進就不再有效,手動縮進就顯得比較方便。

總結

這篇文章從創建開始到現在陸陸續續寫了好長時間,主要的原因是筆者這期間事情較多,所以決定先將這篇文章發佈出來之後再做修改。除了筆者介紹的這些功能以外,vim 還有很多亮點,比如更高級的 Visual 模式的使用方法,或者是錄製命令等等。又或者,更加厲害的高手可能就不需要 Visual 模式了,一切均可以通過簡單的幾個按鍵來進行操作,vim 還有很多值得我們發掘的地方。不積跬步,無以至千里;不積小流,無以成江海,使用 vim 的熟練程度不是一天造就的,筆者願與各位共勉~

(未完待續~)