- 本書有點太極端,作者過分強調了操作可重復的,很難適應這種思維,而是給了太多的 tricks,很難在工作中用到,另外書中對 vim 的概念的講解很到位,有這些概念才能 think in vim,比如模式 / normal 命令 / Ex 命令 / 寄存器 / quickfix 等,總之, vim 很牛, 但是本質上只是個編輯器,如果造成太多的心智負擔,編碼時候滿腦子都是怎么實現酷炫的 vim 操作,而不是編碼本身,就本末倒置了。
- 整理不易,轉載請注明。
Practical vim V2
插入模式
normal
i(nsert) / I(nsert at beigin) / c(hange) / a(ppend) / A(ppend at end) / o(A<CR>) / O(I<cr>k) / r(eplace char) / R(eplace mode)
通過以上按鍵即可進入插入模式,在該模式下可以逐字,逐行的插入、刪除或移動光標,跟其他任何的編輯器沒有差別, 在以下情況下會考慮切換到其他模式:
- 1, 瀏覽之前寫的內容;
- 2, 修改之前的輸入,如批量化的修改(批量注釋),或者距離較長,依賴插入模式下逐行/字的移動或退格比較麻煩;
- 3, 撤銷或控制撤銷粒度,控制撤銷粒度,連續的一次輸入應該可以一次撤銷,適用<C-o>快速切換到正常模式。
tricks
id | 命令 | 簡述 | 其他 |
---|---|---|---|
0 | <C+w> | 插入模式下,撤銷前一個單詞 | shell通用 |
1 | <C+u> | 插入模式下,撤銷整行 | shell通用 |
2 | <C+[> | 插入模式切換到普通模式 | |
3 | <C+o> | 插入模式臨時切換到普通模式,執行下一個輸入后返回 | zz / u |
4 | <C+r>0 | 插入模式下使用寄存器0粘貼復制的內容 | |
4 | <C+r>+ | 插入模式下使用寄存器+粘貼系統棧貼板的內容 | |
5 | <C+r>= | 插入模式下使用數學運算寄存器快速計算表達式的值 | |
6 | <C+v>encode | 插入模式下使用寄存器0粘貼復制的內容 | <C+v>u00bf = ? |
ps.
- tip3, 在文檔的上下部分插入時, <C+o>臨時退出,'zz'可以使得當前編輯的行移動到視圖的中央
- tip3, ‘.’重復及‘u’撤銷的粒度都是從上次進入到退出編輯模式直接完整的編輯,因此<C+o>臨時切換到正常模式可以控制撤銷的粒度
- tip4, ‘0’為復制寄存器,‘=’為數學計算寄存器
正常模式
盡量使正常模式下的操作可重復 by Drew Neil, 盡管構造可重復的修改并使用‘.’來重復應用,及‘;’來重復應用定位很炫酷,但是對一般的使用者意義不大, 除非是真正的重復的編輯修改的場景,例如批量的格式化,單詞的替換,此時列操作和替換命令看起來更加直觀
mormal 模式的命令 op{motion}
normal 模式下命令的通常形式為 op{motion}
形式, 指應用op從當前光標到移動命令結束的位置
cmd | introduction |
---|---|
c | change |
d | delete |
y | yank into register (does not change the text) |
~ | swap case (only if 'tildeop' is set) |
g~ | swap case |
gu | make lowercase |
gU | make uppercase |
! | filter through an external program |
= | filter through 'equalprg' or C-indenting if empty |
gq | text formatting |
> | shift right |
< | shift left |
zf | define a fold |
g@ | call function set with the 'operatorfunc' option |
A | $a |
I | ^i |
C | c$ |
s | cl |
S | ^C |
O | A<CR> |
gc | commit, by commentary.vim |
跳轉
id | 命令 | 簡述 | 其他 |
---|---|---|---|
0 | gh/gj/gk/gl/g^/g$ | 對于超長行的文本,會wrap成多個屏幕行,屏幕行上的移動使用 | |
1 | b-w, ge-e | 移動到前/后一個單詞的第/最后一個字符處 | |
2 | B-W, gE-E | 移動到前/后一個字串的第/最后一個字符處 | |
3 | f/F/t/T ; , | 向前/后移動到下一個匹配字符處[前一個字符],‘;’重復移動,‘,’ 撤銷移動 | |
4 | /pat ?pat n/N, # / * | 向后/前查找單詞,跳轉到下一個/上一個匹配項 | |
5 | % | 匹配的括號之間的跳轉 | |
6 | m[a-z],m[A-Z] marks, 'm | 設置頁內標簽a-z頁間標簽A-Z,查看所有標簽,快速跳回 | |
7 | :n +/-nG, gg, G | 跳轉到指定行 | |
8 | {/}, (/) | 跳轉到段首/尾,行首/尾 | |
9 | H / M / L | 跳轉到屏幕頭部 / 中部 / 尾部 | |
10 | gf | 跳轉到光標下的文件名對應的文件中 | |
11 | <C+]> | 跳轉到光標下符號的定義處,配合 ctags 使用 | |
12 | <C+o> / <C+i> | 返回到上一個位置 | |
13 | g; / g, | 向前/后遍歷修改列表中的位置 |
模式匹配
id | 命令 | 簡述 | 其他 |
---|---|---|---|
0 | /foo\c, /foo\C | 查找文本大小寫不敏感 / 敏感 | |
1 | /\vpattern-pythonlike | \v 使用python類似風格的正則表達式,避免了posix風格的大量轉義字符 | |
2 | /\Vpattern-pythonlike | \V按原義查找,不使用正則 | |
3 | /\v<(\w+)\s+\1> | \1代之原括號內元組,<>表示匹配單詞的起止,表示搜索重復的單詞 | |
4 | :vimgrep /pat/[g] % | vimgrep 在當前文件中查找pat, 查找結果在quickfix中, cnext/cprev 切換 |
ps.
* tip6, set incsearch, 在輸入時自動預覽第一處匹配
* tip7, set hls[earch] / nohls[earch] 切換搜索高亮,
* tip8, `/pat/e` 跳轉至搜索并且將光標置于詞尾
* tip9, %s/pat//gn 查找匹配的個數,不真正進行替換
* tip4, copen 打開 quickfix 窗口
* tip0, 查找命令之后的 substitude / vimgrep 可以將 pat 置空表示使用之前的, 如 `/pat \n :s//str/`
對象的使用
在 c[chang] / d[elete] / y[ank] / v[isual] 選取時,可以使用對象來快速的選取
sym | introduction | others |
---|---|---|
a( / a) | '()'及內部 | i(/i) 括號內部 |
a{ / a} | '{}'及內部 | i{/i} 括號內部 |
a[ | '[]'及內部 | i[ 括號內部 |
a' | ''及內部 | i' 引號內部 |
a" | ""及內部 | i" 雙引號內部 |
a` | ``及內部 | i` 反引號內部 |
at | <tag>及內部 | it <tag>內部 |
多文件的管理
緩沖區的概念,vim在編輯時,可以將多個文件加載到緩存中,只有在write/edit命令才進行緩沖區文件的顯式落盤或加載,內存中的文件對應一個緩沖區,vim可以同時打開多個 tab 每個 tab 中可以切分多個 windows, 每個 windows中可以打開多個緩沖區文件
id | 命令 | 簡述 | 其他 |
---|---|---|---|
0 | <C+w>s/v, <C+w><up><Left>.. | 水平/豎直切分窗口,上下左右切換窗口 | |
1 | :vsp/sp [file] | 水平/豎直切分窗口,并打開文件 | |
2 | tabnew [file], tabn/tabp | 新建標簽頁并打開文件,切換上/下一個標簽頁 | |
3 | vim files / ls / nnext/prev | 打開多個緩沖區,查看,切換 | |
4 | :e %:h<Tab>file | 使用相對目錄打開文件 | |
5 | :find file | 查找文件,查找path內的文件 | set path+=dir |
ps.
- tip0,
<C+w>_/|
設置窗口高度/寬度為最大,[N] <C+w>_/|
設置寬度高度指定行 - tip2,
tabmove [N]
將當前標簽頁移動到第n個,缺省為最后一個 - tip3, 兩個文件直接反復切換編輯,可借助緩沖區切換的快捷鍵,
<C-^>
- tip3, 當一個文件被編輯未保存時,切換到其他緩沖區,操作會被組織,可
set hidden
,未被保存的文件會成為 hidden 文件,vim 退出時,詢問是否需要保存
quickfix
-
vimgrep
及make
的結果都會輸出到一個特定的 quickfix 文件中,該文件中的每行點擊后都會跳到對應文件中 - 在 vimgrep 搜索的結果的 quickfix 目錄中使用 cfdo 執行批量查找,可以提換完成所有緩沖區中的替換
cfdo %s/pat/str/g | update
命令模式
id | 命令 | 簡述 | 其他 |
---|---|---|---|
0 | [range]delete[x] | 刪除指定范圍內容,保存到寄存器x中 | |
1 | [range]rank[x] | 拷貝指定范圍內容,保存到寄存器x中 | |
2 | [line]put[x] | 粘貼寄存器x中內容到指定行 | |
3 | [range]copy{address}, t | 拷貝指定范圍的內容到指定位置,address=.表示當前位置 | |
4 | [range]move{address}, m | 移動指定范圍內的內用到指定位置 | |
5 | [range]join | 連接指定范圍內的行 | |
6 | [range]substitute/{pat}/{string}/[flags] | 替換所有匹配處的內容 | |
7 | [range]normal{cmd} | 對范圍內每行執行normal模式下的命令 | |
8 | [range]global/{pattern}/[cmd] | 對范圍內匹配pattern的每行執行Ex命令 | |
8 | [range]vglobal/{pattern}/[cmd] | 對范圍內反向匹配pattern的每行執行Ex命令 |
ps.
* tip7, `/delete/-2,131 normal $x` 刪除表格末尾的'|',`121,131 normal A|` 反向加回
* tip10, ex命令中可以使用寄存器`<C-r>{register}`, 可以使用 `<C-w> <C-u>` 撤銷
* tip11, '.' 當前光標所在行,'$'最后一行, '%'所有行, '0' 表示第一行的上方, 'm 標簽所在行, '< 高亮選取起始行 '> 選區結束行
* tip12, 范圍的起始地址可以使用模式匹配加偏移量來表示,如 :/delete/-2, /global/p
* tip13, `@:` 重復執行上次的 Ex命令, 執行一次后簡化為 `@@`
* tip14, `set wildmenu \n wildmode=full`設置 Ex 命令的提示風格為 Zsh 風格,即列出所有可用項
* tip15, `<C-r><C-w>` 可以復制光標處的單詞到命令行, `<C-r><C-a>`拷貝字符串
* tip16, `%` 表示當前文件的名稱, `%:h`當前的文件的目錄名稱
* tip17, `: <up> / <down>` 回溯之前輸入的命令, `q:` 打開命令歷史
執行 shell 命令
id | 命令 | 簡述 | 其他 | |
---|---|---|---|---|
0 | [!]cmd | 執行shell命令,!表示執行一條立刻返回vim,否則會留在shell,直至exit退出 | ||
1 | read !cmd | 執行shell命令,并將標準輸出重定向到當前文件中, 如read !ls 獲取文件列表 |
||
2 | [range]write ! cmd | 寫出范圍內的內容到新文件,文件名為cmd | ||
3 | [range]write !cmd | 將范圍內內容定義到標準輸入,執行cmd 152,159write !xargs echo
|
||
4 | [range]!{filter} | 使用cmd處理范圍range內的內容并替換原有內容, `152,158!sort -t' | ' -k2` |
substitude
:[range]s[ubstitude]/{pattern}/{string}/{flags}
pattern : 為空表示使用上一次模式,
%s///gn
查找上一個模式共匹配幾處-
string :
- /r : 換行
- /t : 制表
- // : /
- /0, & : pattern匹配的整個字符串
- /1 - /9 : pattern中對應編號的元組, 可以用來重排列表
- ~ : 上一次替換是用的替換字符串
- ={vim script}: 提交為腳本中的執行結果,
%s//\=@0/g
=%s//<C-r>0/g
替換為寄存器0中的值,@寄存器解引用
-
flags :
- g 替換每一行的所有匹配,否則僅替換第一個匹配
- c 確認每一次修改, y(es) / n(ext) / q(uit) / l(ast one) / a(all before, invove this) / <C-e> 向上滾屏 / <C-y> 向下滾屏
- n 不提換只顯示匹配的個數
- & 使用上一次命令的 flags
%s//~/&
重復上一次替換
global
-
[range] global[!] /pat/ {cmd}
: 所有匹配項執行 Ex 命令- range : 默認 % 全文
- [!] : 時能表示反向匹配, 同 vglobal
- cmd 默認為 print,
:190,195g/\V*/p
=:190,195g/\V*/
打印190-195中所有的列表項,g/^#/yank a | reg a
可以將本文中所有列表項保存到寄存器a中
寄存器
delete / yank / put 都可以使用 "{register}
方式指定寄存器,否則使用缺省的寄存器,Ex 命令中, delete / put / yank {register}
也可以指定寄存器
寄存器 | 簡述 | 其他 |
---|---|---|
"" | 缺省寄存器,默認的復制粘貼內容都會拷貝到該寄存器中 | |
"0 | 賦值專用寄存器,yank內容會自動拷貝到該寄存器中 | |
"_ |
黑洞寄存器,"_d{motion} 刪除內容不保留到寄存器中 |
|
"+ | 系統剪貼板寄存器,可以用來同系統的內容交互 | 需要vim版本支持 |
"= | 表達式寄存器,輸入表達式輸出結果 | |
"% | 當前文件名寄存器 | |
". | 上次插入的文本 | |
": | 上次執行的Ex命令 | |
"/ | 上次查找的模式 |
ps.
* tip0 : `reg "{register}` 打印寄存器中的內容
* tip1 : vim 中寄存器 a-z 會替換其中的值, 而A-Z寄存器是追加寫
* tip2 : `vim --version | grep clipboard` 查看,如果不支持,需要重新配置編譯 vim
可視選擇模式
-
v
普通可視模式,選取不規則的分區,o
選擇時會固定一端移動另一端,o
可切換, 選擇后可使用normal命令 -
<C-v>
列選取編輯模式,調整列表項的空格,追加注釋,追加行末分號很有效,^$
可以選出不規則的選取