編輯器 (Vim)
寫作和寫程式實際上差異很大。 當我們寫程式的時候,會常常切換檔案、閱讀、尋找與改正程式碼,而寫作時往往會連續鍵入文字。 所以對於寫作和寫程式常常由不同種類的程式來處理(比如 Microsoft Word 和 Visual Studio Code)。
作為程式設計師,我們會與編輯器共同度過許久,因此使用些時間熟練使用適合自己需求的編輯器是值得的。
- 閱讀指導 (例如此課程與我們列出的資源)
- 堅持使用它來完成所有文字輸入(即使在開始時速度很慢)
- 隨時查閱:如果看起來可能有更好地辦法做某件事,通常確實會有
若我們可以遵循上述方法,並使用新編輯器完成所有文書處理工作,學習一個複雜的文字編輯器的時間線大概如此: 在一兩小時之內,學習到基本操作,例如開啟或編輯檔案、儲存與退出、瀏覽暫存區域。 學習二十小時之後,我們可以達到與使用舊編輯器同樣的速度。 在此之後,優勢盡顯:我們已經有了足夠的知識與肌肉記憶,使得我們可以使用新編輯器節省時間。 現代文字編輯器都是奇妙且強大的工具,學習不止,學得越多,效率越高。
應該選擇什麼編輯器?
程式設計師往往對自己的文字編輯器有很強的執著
現今最受歡迎的編輯器是什麼? 這裡有一份Stack Overflow 的調查 (這個調查可能有偏見,因為Stack Overflow的使用者不能代表所有程式設計師)。 Visual Studio Code 是最受歡迎的編輯器。 Vim則是最受歡迎的命令列編輯器。
Vim
此課程的所有講師都使用 Vim 作為編輯器。 Vim 歷史悠久,起源於 Vi 編輯器 (1976),並且直至今日還在成長。 Vim 有非常簡潔的行事理論,因此,許多工具支援類 Vim 的編輯模式(例如,140萬人安裝了Vim emulation for VS code)。 即使你決定使用其他編輯器,Vim依然是值得學習的。
在 50 分鐘之內教授完 Vim 的功能是不可能的,所以我們只會專注與介紹 Vim 的處世哲學,教授一點基礎知識,展示一些高階功能,並為你提供掌握 Vim 的學習資源。
Vim之哲學
寫程式時,我們的大部分時間都使用在閱讀/編輯而非寫本身。 因此,Vim是 模式化 編輯器:它具有鍵入文字和處理文字的不同模式。 Vim是可程式化的(利用 Vimscript 以及 Python 等其他語言),並且 Vim 介面自身就是程式語言: 鍵擊(使用助記符)是指令,並且這些指令可以相互組合。 Vim 避免使用滑鼠,因為滑鼠是低效率的;Vim甚至避免使用方向鍵,因為需要太多次移動。
最終的結果是,使用 Vim 編輯跟得上我們思考的速度。
編輯模態
Vim 設計基於使用者花費大量時間進行閱讀,瀏覽與小修改, 而不是編寫長文字。因此,Vim 擁有多種模式:
- 標準(Normal): 在檔案中移動並更正文字
- 插入(Insert): 插入文字
- 替換(Replace): 替換文字
- 視覺化(Visual) (以字元,列, 或文字塊): 選中文字
- 命令列(Command-line): 執行指令
在不同的模式下鍵擊的作用也不同。例如,x
在插入模式下會鍵入 ‘x’,但在標準模式下
會刪除當前遊標下的字元,若在可視模式下會刪除選中的文字。
在預設配置下,Vim會在底部左端顯示當前的模式。 Vim 的預設模式是標準模式。 通常我們會將大部分時間用在標準與插入模式上。
我們可以按下 <ESC>
來從任意模式轉換為標準模式。
在標準模式中,使用 i
進入插入模式,使用 R
進入替換模式,使用 v
進入可視模式,
使用 V
進入可視(列)模式,使用 <C-v>
(Ctrl-V, 有時寫成 ^V
) 來進入可視(塊)模式,
使用 :
進入命令列模式。
在使用Vim時,時常會用到 <ESC>
: 请考慮將 Caps Lock 重對映至 Escape (macOS
指引).
基本
插入文字
在標準模式下,按下 i
來進入插入模式。
現在 Vim 和許多其他編輯器一樣,直到我們按下 <ESC>
來回到標準模式。
只需知道這一點與之前介紹的內容,就足以使用 VIm 來編輯檔案了(雖然只使用插入模式效率不高)。
緩存,標籤頁,視窗
Vim 會維護一系列打開的檔案,其叫做 “緩存”。 一個 Vim 會話包含許多標籤頁,每個標籤頁持有許多視窗(分割窗格)。 每個視窗顯示一個緩存。 與網頁瀏覽器等其他我們熟悉的程式不一樣的是,緩存與視窗不是一一對應的關係; 視窗是單純的瀏覽介面。一個緩存可以被 多個 視窗所開啟,也可以在同一個標籤頁內開啟。 這個功能很好用,例如在檢視同一個檔案的不同部分的時候。
預設情況下,Vim 會開啟一個標籤頁,這個標籤頁包含一個視窗。
命令列
在標準模式下鍵入 :
來進入命令列模式。
此時遊標會立即跳至螢幕下方的命令列。
這個模式包含許多功能,如開啟,儲存,關閉檔案,以及退出 Vim.
:q
退出 (關閉視窗):w
儲存 (“寫入”):wq
儲存後退出:e {檔案名}
開啟檔案:ls
顯示現有的緩存:help {topic}
顯示幫助:help :w
顯示關於:w
指令的幫助:help w
顯示關於w
移動方式的幫助
Vim 的介面是一種程式語言
Vim 最重要的想法就是 Vim 自身的介面就是一種程式語言。 鍵擊是指令, 這些指令可以 結合。 這使得移動與編輯更加高效,尤其是在這些指令成為肌肉記憶的情況下。
移動
通常情況下我們應該在標準模式下使用移動指令來導航緩存。 在 Vim 中移動被稱為 “名詞”,因為這些移動指令參考了文字塊。
- 基礎移動:
hjkl
(左,下,上,右) - 詞:
w
(下一詞),b
(詞首),e
(詞尾) - 列:
0
(列首),^
(第一個非空字元),$
(列尾) - 螢幕:
H
(螢幕首列),M
(中間),L
(螢幕末尾) - 滾動:
Ctrl-u
(向上),Ctrl-d
(向下) - 檔案:
gg
(檔案頭),G
(檔案尾) - 列數:
:{列數}<CR>
or{列數}G
(列 {列數}) - 雜項:
%
(尋找配對) - 查詢:
f{character}
,t{character}
,F{character}
,T{character}
- 在此列中 查到/到 向前/向後查詢 {character}
,
/;
來導向結果
- 搜尋:
/{regex}
,n
/N
用於匹配導航
選擇
視覺化模式:
- 視覺化
- 視覺化(列)
- 視覺化(塊)
可以使用移動鍵來選擇
編輯
所有我們曾用滑鼠做的事情,現在都可以使用鍵盤上的編輯與移動指令來完成。 從此時起 Vim 的介面開始有些像程式語言了。 Vim 的編輯命令也被稱為 “動詞”, 因為動詞可以操作名詞。
i
進入插入模式- 但是對於操作/刪除文字,想使用除了 backspace 的方法完成
o
/O
在此列前/後插入新列d{motion}
刪除 {motion}- 例如
dw
刪除詞,d$
刪除至列尾,d0
刪除至列首
- 例如
c{motion}
變更 {motion}- 例如
cw
更改詞 - 如同
d{motion}
後執行i
- 例如
x
刪除字元 (與dl
效果相同)s
替換字元 (與xi
效果相同)- 視覺化模式搭配操作
- 選中文字, 使用
d
刪除或使用c
更改
- 選中文字, 使用
u
復原,<C-r>
重做y
複製 / “yank” (有些其他指令如d
也會複製)p
貼上- 還有許多其他值得學習的: 例如
~
改變字元的大小寫
計數
我們可以將名詞和動詞與計數結合使用,這將多次執行指定的動作。
3w
前移 3 個詞語5j
下移 5 列7dw
刪除 7 個詞語
修飾詞
我們可以使用修飾詞來更改名詞的含義。 例如“ i”,表示“inside”,“核心”或“內部”,以及“ a”,表示“around”,“周圍”。
ci(
更改當前括號對中的內容ci[
更改當前方括號對的內容da'
刪除單引號字串,包括周圍的單引號
示例
這是一個錯誤的 fizz buzz 實現:
def fizz_buzz(limit):
for i in range(limit):
if i % 3 == 0:
print('fizz')
if i % 5 == 0:
print('fizz')
if i % 3 and i % 5:
print(i)
def main():
fizz_buzz(10)
我們將會修復以下問題:
- Main 從未被呼叫
- 從 0 而非 1 開始
- 在 15 的倍數時,在不同列內列印 “fizz” 和 “buzz”
- 在 5 的倍數時,列印 “fizz”
- 使用了硬編碼引數10,而非獲取命令列引數
觀看講座視訊的演示。 比較使用 Vim 進行上述更正的方式與使用其他程式進行相同更正的方式。 注意 Vim 中幾乎不需要擊鍵的特性,使我們可以用與思考相同的速度編輯。
自訂Vim
Vim是通過 ~/.vimrc
中的純文字配置檔案定製的。
(包含Vimscript指令)。 這裡可能有許多我們想啟用的基本設定。
我們提供了詳盡說明的基礎配置檔案,你可以使用它作為起點。
我們建議使用它來避免遇到一些Vim的古怪預設行為。
在這裡下載我們的配置檔案,並將其儲存至 ~/.vimrc
Vim是可高度自訂的,值得用些時間去探索自訂選項。 我們可以在GitHub上檢視其他人的 dotfile 獲取靈感。 例如,你的講師們的 Vim 配置檔案 (Anish, Jon (uses neovim), Jose)。 關於這些也有許多相當多的優秀網誌文章。 嘗試不直接複製貼上,而是閱讀,理解並獲取你想要的部分。
擴充Vim
這裡有許多外掛可以用來擴充Vim。
可能與你在網路上找到的過時建議相反,我們 不 需要外掛管理器(自從 Vim 8.0後)。
取而代之,我們可以使用內建的包管理系統。
只需建立目錄 ~/.vim/pack/vendor/start/
,然後將外掛放入其中(例如使用 git clone
)。
這些是一部分我們最愛的外掛:
- ctrlp.vim: 模糊檔案檢索
- ack.vim: 程式碼搜尋
- nerdtree: 檔案總管
- vim-easymotion: 迅速跳轉
我們不會在此處給出太多外掛,你可以在講師的 dotfile 處檢視更多 (Anish, Jon, Jose)。 從Vim Awesome處可以獲得更多奇妙外掛。 這裡也有許多網誌分享,僅需檢索”best Vim plugins”。
其他程式中的 Vim 模式
許多工具都支援模擬 Vim,他們中的大部分質素上佳。 取決於工具,可能不會包含 Vim 的實驗性特性,但是大多都實現了 Vim 的基礎操作。
Shell
如果你使用 Bash,執行 set -o vi
。如果你使用 Zsh,bindkey -v
。若你使用 Fish,嘗試 fish_vi_key_bindings
。
另外,無論什麼 shell,都應可以使用 export EDITOR=vim
。這是用於決定啟動哪個編輯器的環境變數。
例如, git
使用此編輯器來提交訊息。
Readline
許多程式使用 GNU Readline 庫作為其命令列介面。
Readline 也支援基本的 Vim 模式。
在 ~/.inputrc
中加入此行開啟它。
set editing-mode vi
在此設定下,Python REPL 將會支援 Vim 快捷鍵。
其他
甚至有針對網頁 瀏覽器 的 Vim 快捷鍵擴充。 受歡迎的款式有適用於 Google Chrome 的 Vimium 和適用於 Firefox 的 Tridactyl。 在 Jupyter notebooks 中同樣可以使用。
Vim 進階
這裡有一些向你展現編輯器能力的例子。我們無法涵蓋所有事情,不過在你使用的過程中也會學到這些。 一個好辦法是:如果你在使用編輯器的時候感到“一定有什麼更好地的辦法做這個”,通常來說真的是這樣,在網上搜尋一下。
搜尋與替換
:s
(substitute) 指令 (文件).
%s/foo/bar/g
- 將 foo 全域替換為 bar
%s/\[.*\](\(.*\))/\1/g
- 將有名字的 Markdown 連結替換為單純URLs
多視窗
:sp
/:vsp
分離視窗- 可以有多個視窗同時顯示同一個緩存
巨集
q{character}
在暫存器{character}
中錄製巨集q
停止錄製@{character}
重放- 其執行遇到錯誤時將會停止
{number}@{character}
執行 {number} 次- 巨集可以遞迴
- 首先使用
q{character}q
清除巨集 - 錄製巨集, 使用
@{character}
來遞迴呼叫它 (錄製結束前不會執行)
- 首先使用
- 例如: 將 xml 轉製成 json (檔案)
- 一個有 “name” / “email” 鍵物件的陣列
- 用一個 Python 程式?
- 用sed / 正則表達式
g/people/d
%s/<person>/{/g
%s/<name>\(.*\)<\/name>/"name": "\1",/g
- …
- Vim 命令 / 巨集
Gdd
,ggdd
刪除第一行和最後一行- 格式化單一元素的巨集 (暫存器
e
)- 跳轉到有
<name>
的行 qe^r"f>s": "<ESC>f<C"<ESC>q
- 跳轉到有
- 格式化一個人的巨集
- 跳轉到有
<person>
的行 qpS{<ESC>j@eA,<ESC>j@ejS},<ESC>q
- 跳轉到有
- 格式化一個人然後轉到另外一個人的巨集
- 跳轉到有
<person>
的行 qq@pjq
- 跳轉到有
- 執行巨集到文件尾
999@q
- 手動移除最後的
,
然後加上[
與]
分隔符
資料
vimtutor
是安裝 Vim 時內建的教學 - 如果 Vim 已經被安裝,可以在 shell 內執行vimtutor
- Vim Adventures 透過遊戲學習 Vim
- Vim Tips Wiki
- Vim Advent Calendar 有許多小技巧
- Vim Golf 是一個以 Vim UI 作為程式語言的 code golf
- Vi/Vim Stack Exchange
- Vim Screencasts
- Practical Vim (參考書)
課後練習
- 完成
vimtutor
。 註: 它在一個 80x24(80行,24列)的終端窗口看起來最好。 - 下載我們的 基本 vimrc, 然後把它保存到
~/.vimrc。
閱讀這個詳細註解的文件 (使用 Vim!),然後觀察 Vim 在這個新的設置下看起來和使用起來有哪些細微的區別。 - 安裝和配置一個插件:
ctrlp.vim.
- 用
mkdir -p ~/.vim/pack/vendor/start
創建插件文件夾 - 下載插件
cd ~/.vim/pack/vendor/start; git clone https://github.com/ctrlpvim/ctrlp.vim
- 閱讀該插件的文件,嘗試使用 CtrlP 在一個專案路徑裡定位一個文件,打開 Vim, 然後用 Vim 命令列執行
:CtrlP
- 自定義 CtrlP: 添加 configuration 到你的
~/.vimrc
來用按 Ctrl-P 打開 CtrlP
- 用
- 練習使用 Vim, 在你自己的電腦上重做範例
- 下個月用 Vim 做你 所有 文件編輯。若使用上效率不好, 或者你感覺 “一定有一個更好的方式”,嘗試上網搜尋, 很有可能有一個更好的方式。如果你遇到難題,來我們的office hours或者給我們發郵件。
- 在你的其他工具中設置 Vim 快捷鍵(見上面的操作指南)。
- 進一步自定義你的
~/.vimrc
和安裝更多插件。 - (進階) 用 Vim 巨集將 XML 轉換到 JSON (範例文件)。嘗試著先自己實做, 但是在你卡住的時候可以查看上面巨集章節。
Licensed under CC BY-NC-SA.