本部分筆記可作為速查 CheatSheet 使用
本系列教程共分為以下五個部分:
神級編輯器 Vim 使用-基礎篇
神級編輯器 Vim 使用-操作篇
神級編輯器 Vim 使用-插件篇
神級編輯器 Vim 使用-正則操作篇
神級編輯器 Vim 使用-最后
基礎命令
vim code.c: 在終端中打開 code.c 文件 (終端命令)
vim ~/.vimrc: 打開根目錄下的 .vimrc 文件 (終端命令)
vim -u NONE -N: 以不加載任何插件的方式啟動 vim(終端命令)
gvim -o file1 file2: open into a horizontal split (file1 on top, file2 on bottom) [C]
gvim -O file1 file2: open into a vertical split (side by side,for comparing code) [N]
gvim.exe -c "/main" joe.c: Open joe.c then jump to "main"
vim -c "%s/ABC/DEF/ge | update" file1.c: execute multiple command on a single file
vim -c "argdo %s/ABC/DEF/ge | update" *.c: execute multiple command on a group of files
mvim --servername VIM3 --remote-tab foobar.txt: 在 MacVim 中已打開的窗口中打開文件
mvim -f file.txt: 使用 MacVim 編輯, 編輯完后返回結(jié)果給 terminal(如果不加 f 的話就是立刻返回結(jié)果給終端)
vim -c "argdo /begin/+1,/end/-1g/^/d | update" *.c: remove blocks of text from a series of files
vim -s "convert.vim" file.c: Automate editing of a file (Ex commands in convert.vim)
gvim -u NONE -U NONE -N hugefile.txt: "load VIM without.vimrc and plugins (clean VIM) e.g. for HUGE files
gvim -c 'normal ggdG"*p' c:/aaa/xp: Access paste buffer contents (put in a script/batch file)
gvim -c 's/^/\=@*/|hardcopy!|q!': print paste contents to default printer
:h [option]: 顯示對命令的幫助
:help:sort: 同上, 顯示對 :sort 的解釋
:help guimac / :help macvim: 顯示 macvim 的幫助
:gui: 在 MacVim 中打開 vim 中當前的所有 buffer(great!)
:source ~/.vimrc: 重載配置文件 (可以在不重啟 vim 的情況下重載配置文件)
:runtime syntax/c.vim: 將文件加載入 runtimpath, 不使用冒號只會加載第一個符合的
:runtime! **/maps.vim: 將文件夾下所有符合的文件添加到 runtimpath 中, 使用冒號會加載全部符合的
:syntax on: 開啟語法
:set number: 設置行號
:set ft=json: 設置的文件格式為 json 格式
:set ft?: 查看當前文件的 ft 值
.: 修改完之后移動至下一個單詞出按 . 可重復相同操作 (厲害!)
5.: 重復 5 次相同動作
*: 向下查找光標下的單詞
#: 向上查找光標下的單詞
ga: 查看當前光標下字符的 unicode 碼及其他詳細信息
g<C-g>: counts words
:e.: . 代表 pwd 的結(jié)果, 即當前工作路徑, 這個命令會進入 netrw 的文件管理界面
gq: 重新布局 (如果設置了 textwidth 的話會根據(jù) textwidth 進行斷行)
gq} format a paragraph
gqap: format a paragraph
ggVGgq: refromat entire file
Vgq: current line
gw: same as gq, but puts the cursor back at the same position in the text. However, formatprg and formatexpr are not used.
:verbose vmap: show all map under visual model
==: indent current line
=G: indent the all the lines below the current line
n==: indent n lines below the current line
=%: indent a block of code
保存退出
:q: 退出文件
q:: command line history window(puts you in full edit mode)
q/: search history window(puts you in full edit mode)
n1,n2 w [file]: 將 n1 行到 n2 行的內(nèi)容保存到另一個文件
:wq: 保存退出
:wa: 保存所有緩沖區(qū)
:wn: 保存當前緩沖區(qū)并進入下一個參數(shù)列表
:qa: 退出所有緩沖區(qū)
ZZ: 保存退出當前 window(same as :x but not :wq which write the file even if it hasn't been modified)
ZQ: 不保存直接退出當前 window(equal to :q!)
:x: 與 ZZ 及 :zq 功能類似, 但是不會寫入沒有被修改過的文件
:xa: 保存并退出所有緩沖區(qū) (不會保存沒有修改過的)
:sav path/to.txt: 將本緩沖區(qū)保存為文件 (相當于另存為, 命令全名是 saveas)
:sav php.html: Save current file as php.html and "move" to php.html
:sav! %<.bak: Save Current file to alternative extension (old way)
:sav! %:r.cfm: Save Current file to alternative extension
:sav %:s/fred/joe/: do a substitute on file name
:sav %:s/fred/joe/:r.bak2: do a substitute on file name & ext.
:!mv % %:r.bak: rename current file (DOS use Rename or DEL)
:w path/to.txt: 保存到某路徑
:e!: 重載本文件, 即使有未保存的內(nèi)容也會被丟棄 (edit 縮寫)
:e path/to.txt: 打開指定文件
:e.: 進入 netrw 瀏覽目錄
移動
hjkl: 左下上右鍵
10 + hjkl: 向左下上右跳 10 個格
gj: 在一段被折為多行時, 將光標向下移動一行 (向下移動一個屏幕行)
gk: 在一段被折為多行時, 將光標向上移動一行 (向上移動一個屏幕行)
>>: 整行向右縮進
<<: 整行向左縮進
%: 在 (), [], {} 之內(nèi)跳轉(zhuǎn)到包圍符號上
]}: 跳轉(zhuǎn)到下一個 } 上
[{: 跳轉(zhuǎn)到下一個 { 上
[m: jump to beginning of next method
[M: jump to end of next
]m: jump to beginning of previous
]M: jump to end of previous
>%: 將 {}, (), [] 包裹的代碼右移 (必須先將光標放到符號上)
<%: 將 {}, (), [] 包裹的代碼左移 (必須先將光標放到符號上)
:le: 當前行居左對齊
:ce: 當前行居中對齊
:ri: 當前行居右對齊
0: 移動到行首 (非字符)
^: 光標移至行首 (字符)
$: 光標移至行尾 (換行符)
g^: 移動到屏幕行的行首
g$: 移動到屏幕行的行尾
g_: 光標移至最后一個可見字符上
g;: 跳轉(zhuǎn)到上次修改的位置, 可以通過 changes 查看所有更改
g,: 跳轉(zhuǎn)到下次修改的位置
gi: 跳轉(zhuǎn)到上次退出插入模式的位置并直接進入 Insert Mode
gn / gN: 跳轉(zhuǎn)冰選中上個 / 下個 highlight
'', 反撇號, 跳轉(zhuǎn) mark, 詳見 Mark
w: 跳至下一個詞首
b: 跳至上一個詞首
e: 跳至下一個詞末端
ge: 跳轉(zhuǎn)到上一個詞的結(jié)尾
f: 移動到行內(nèi)下一個字符, 如 fx 將查找行內(nèi)出現(xiàn)的下一個 x 字符
F: 移動到行內(nèi)上一個字符, 用法同 f
t: 移動到行內(nèi)下一個字符的前一字符上
T: 移動到行內(nèi)上一個字符的下一字符上
;: 重復查找, 即重復 f 或 t, 非常有用, 可以與 . 想媲美
,: ; 的反面, 當按 ; 過頭了可以用 , 退回來
<C-b>: 向前滾一頁
<C-f>: 向后滾一頁
<C-e>: 向上滾一行
<C-y>: 向下滾一行
<C-u>: 向上滾半頁
<C-d>: 向下滾半頁
gg: 跳至文件頂部
G: 跳至文件底部
M: 光標移至頁中部
L: 光標移至頁底部
H: 光標移至頁頂部
88gg: 跳至第 88 行
88G: 跳至第 88 行
10|: 移動到當前行的第 10 列
zz: 將當前行置于視圖中央
zt: 將當前行置于視圖頂部
zb: 將當前行置于視圖底部
gd: 跳轉(zhuǎn)到局部變量定義處
gD: 跳轉(zhuǎn)到文件內(nèi)全局聲明 (從文件開頭開始查找)
[<C-d>: 跳轉(zhuǎn)到定義處
[<C-i>: 跳轉(zhuǎn)到函數(shù), 變量和定義處
gf: 跳轉(zhuǎn)到相應的頭文件
<C-w>gf: 以 tabnew 的方式進行跳轉(zhuǎn)
<C-o>: Normal 模式下返回上一個操作的位置, Insert 模式下切換到 Normal 模式, 輸入完命令后再次進入 Insert 模式: c-o zz
<C-t>: Normal 模式下返回上一個操作的位置, Search 模式下跳轉(zhuǎn)到上一個匹配位置
<C-g>: Search 模式下跳轉(zhuǎn)到下一個匹配位置
<C-i>: Normal 模式下返回下一個操作的位置
<C-^> / <C-6>: Normal 模式下在本文件與上一個操作文件中跳轉(zhuǎn)
'm: 反撇號, 跳轉(zhuǎn)到設置的標記 m 處
'M: 跳轉(zhuǎn)到全局標記
<C-]>: 跳轉(zhuǎn)到當前光標的定義處 (基于 .tags 文件)
<C-w>]: 用新窗口 (如果在本 buffer 內(nèi)則直接跳轉(zhuǎn)) 打開并查看光標下符號的定義 (光標會跳轉(zhuǎn))(基于 .tags 文件)
<C-w>}: 使用 preview 窗口預覽光標下符號的定義 (光標不會跳轉(zhuǎn))(基于 .tags 文件)
復制 / 粘貼 / 刪除
c: 刪除并進入 插入模式 (理解: cert, 會插入)
cw: 刪除一個單詞并進入 插入模式
C: 刪除自游標處到當前行尾, 并進入 插入模式
c2c: 刪除兩行并進入 插入模式
cc: 刪除一行并進入 插入模式
d^: 刪除至行首 (理解: delete, 不會插入, 直接刪除, 不會復制)
D: 從當前光標處刪除至行尾
dw: 向右刪除一個單詞
d2d: 刪除兩行
dd: 刪除一行
d121gg: 從當前行刪除到 121 行
d121j: 從當前行向下刪除 121 行
dtj: 向前刪除到 j(不包含 j)
dfj: 向前刪除到 j(包含j)
dTj: 向后刪除到 j(不包含j)
dFj: 向后刪除到 j(包含j)
d/ans: 向前刪除到 ans(不包含 ans)
d?ans: 向后刪除到 ans(不包含 ans)
d/\d: 向前刪除到第一個數(shù)字
x: 刪除本字符 (等于 delete)
X: 向前刪除一個字符 (等于 backspace)
s: 刪除右側(cè)并進入插入模式
S: 刪除整行并進入插入模式
yy: 復制一行
y$: 從光標當前處復制到結(jié)尾, 不會復制到換行符, 但是如果 v$y 則會復制到換行符
y: 復制所選 (可視模式)
'a,'by*: yank range into paste
%y*: yank range into paste
.y*: yank current line to paste
set paste: prevent vim from formatting pasted in text
y5j: 向下復制 5 行
v/d/c/y + [文本對象]
操作分隔符的文本對象: 用于確定范圍
i(/[/{/"/'<: 由 (/[/{/"/'< 包圍起來的字符, 不包含 (/[/{/"/'<
a(/[/{/"/'<: 由 (/[/{/"/'< 包圍起來的字符及包圍符號本身
[/?]motion<cr>: d/ans / d?ans / c/ans / c?ans
操作文本塊的文本對象
it: 由 tag 包圍起來的字符
at: 由 tag 包圍起來的字符及 tag 本身
iw: 當前單詞
aw: 當前單詞及一個空格
iW: 當前字串
aW: 當前字串及一個空格
is: 當前句子
as: 當前句子及一個空格
iB: 當前 bracket(在定位 fold marker 時很有用)
aB: 當前 bracket 及一個空格
ip: 當前段落
ap: 當前段落記一個空行
一般來說, d{motion} 命令和 aw, as 和 ap 配合起來使用比較好, 而 c{motion} 命令和 iw 及類似的文本對象一起用效果會更好.
p: 如果整行復制, 粘貼在下方一行. 如果選中復制, 粘貼到當前光標后方
P: 與 p 方向相反
gp: 與 p 類似, 不過會把光標移動至文本的結(jié)尾
gP: 與 P 類似, 不過會把光標移動到文本的結(jié)尾, 在粘貼多行的時候尤其有用
模式切換
i: 當前字符之前插入
I: 行首插入
a: 當前字符之后插入
A: 當前字符行尾插入
o: 在下方插入一行并進入 Insert Mode
O: 在上方插入一行并進入 Insert Mode
<C-v>: 進入列選擇模式, 可沿垂直方向選中多行, 然后使用大寫的 I 和 A 分別可以實現(xiàn)在前側(cè)和后側(cè)批量添加字符, 使用 > 可以向右縮進, 使用 r 可以替換, 特別好用!
v: 進入 visual 模式, 移動光標可進行批量選擇刪除
gv: 重復選擇上次選擇并操作的區(qū)域
O: 在 Visual 模式下切換高亮選取的活動端使之可調(diào)整
大小寫 / 加減
~: 將當前光標處的大小寫翻轉(zhuǎn)
g~5j: 將當前行向下 5 行大小寫反轉(zhuǎn)
gu5j: 將當前行向下 5 行改為小寫
gU5j: 將當前行向下 5 行改為大寫
gUit: 將 tag 包圍的內(nèi)容改為大寫
guu: 將當前行改為小寫
gUU: 將當前行改為大寫
g~~: flip case line
Vu: 將當前行改為小寫
VU: 將當前行改為大寫
veu: 當前光標至尾端的字符改為小寫
vG~: 將當前光標至文本結(jié)尾的字符翻轉(zhuǎn)大小寫
ggguG: lowercase entire file
<C-a>: 對數(shù)字進行增加操作, 在列選擇模式下批量增加數(shù)字, 對 Markdown 的列表排序特別好用
<C-v> + select + C-a: 將選擇區(qū)域數(shù)字統(tǒng)一增加 1
<C-v> + select + 2 + C-a: 將選擇區(qū)域數(shù)字統(tǒng)一增加 2
<C-v> + select + g + C-a: 將選擇區(qū)域的數(shù)字改為遞增為 1 的序列
<C-v> + select + 2 + g + C-a: 將選擇區(qū)域的數(shù)字改為遞增為 2 的序列
<C-x>: 對數(shù)字進行縮小操作 (用法同 C-a)
撤銷
u: 撤銷 undo(命令模式, 可多次撤銷)
U: 無論當前行修改了多少次, 全部撤銷操作
<C-r>: Normal 模式下反撤銷
:undolist: 撤銷歷史 (命令模式)
:undo 5: 撤銷 5 個改變 (命令模式)
Folding
zf: 創(chuàng)建折疊
zc: close, 關閉當前光標下可折疊區(qū)域
zo: open, 打開當前光標下可折疊區(qū)域
za: toggle, 打開 / 關閉當前光標下可折疊區(qū)域
zC/zO/zA: 與小寫不同的是操作對象為全局, 與光標位置無關
zr: reduce, 整體減少折疊等級 (與光標位置無關)
zR: 將所有折疊級別減值最小 (直觀看來就是緩沖區(qū)完全展開了)
zm: more, 整體增加折疊級別 (與光標位置無關)
zM: 增加折疊級別至最高 (直觀看來就是緩沖區(qū)完全折疊了)
zi: 全部折疊與全部展開之間進行切換
[z: 當前打開折疊的開始處
z]: 當前打開折疊的末尾處
zd: 刪除當前折疊 marker
zE: 刪除所有折疊 marker
zj: 移動至下一個折疊
zk: 移動至上一個折疊
zn: 禁用折疊
zN: 啟用折疊
window/tab
:tabnew [filename]: 新建一個 tab 頁, 例: tabnew% 以當前文件新建一個 tab 頁, % 表示當前文件
:tabclose: 關閉當前 tab
:tabonly: 關閉所有其他的 tab
:tabn: 移動至下一個 tab, 直接使用 gt 也可
:tabp: 移動至上一個 tab, 直接使用 gT 也可
:tabs: 查看所有打開的 tab
:tabdo %s/foo/bar/g: 在所有打開的 tab 上執(zhí)行替換
:tab ball: 將所有的緩沖區(qū)在 tab 中打開
:tab sball: 將所有的緩沖區(qū)在 tab 中再次打開
gt: 跳轉(zhuǎn)到下一個 tab
gT: 跳轉(zhuǎn)到上一個 tab
5gt: 跳轉(zhuǎn)到第 5 個 tab 上
:sp: 上下切割當前文件, 同 <C-w> s
:vs: 左右切割當前文件, 同 <C-w> v
:sp [filename]: 上下分割并打開一個新文件, 如果不輸入 filename 會切割打開本文件 (光標在文件開頭位置)
:vs [filename]: 左右分割并打開一個新文件, 如果不輸入 filename 會切割打開本文件 (光標在文件開頭位置)
<C-w> T: 如果當前 tab 存在多個不同的 window, 那么將當前 window 移動到新 tab 上, 必須是大寫
<C-w> s: 水平切割當前窗口
<C-w> v: 垂直切割當前窗口
<C-w> h/j/k/l: 光標向某個方向分屏移動
<C-w> w: 在所有窗口間進行切換
<C-w> _: 使窗口高度最大化
<C-w> |: 使窗口寬度最大化
<C-w> =: 使所有窗口等寬等高
<C-w> q: quit, 關閉當前分屏, 如果是最后一個, 則退出 vim
<C-w> c: close, 關閉當前分屏, 如果是最后一個, 則退出 vim
<C-w> o: only, 關閉所有除當前屏幕外的所有分屏
<C-w> H: 當前分屏向左移動
<C-w> L: 當前分屏向右移動
<C-w> J: 當前分屏向下移動
<C-w> K: 當前分屏向上移動
<C-w> z: 關閉當前打開的 preview 窗口
[N]<C-w> +: 分屏增加 N 列高度 (可選)
[N]<C-w> <: 分屏減少 N 列寬度 (可選)
:close: 關閉活動窗口
:only: 只留下當前活動窗口
new abc.txt: 在新窗口中編輯文件
Buffer
:ls / :buffers: 顯示當前所有 buffer(緩沖區(qū)列表)
a: active buffer
h: hidden buffer
%: the buffer is the current window
#: alternate buffer, 可以使用 :e # 直接編輯
:ls!: 列出非緩沖區(qū)列表文件
:bn: buffer next, 下一個 buffer
:bp: buffer previous, 上一個 buffer
:bf: 打開第一個 buffer
:bl: 打開最后一個 buffer
:b1: 切換到 buffer1(同理可按照數(shù)字切換到不同的 buffer)
:bd: 刪除 buffer(并沒有刪除文件本身, 只是 buffer 而已)
:bd 1 3: 刪除 buffer 編號為 1, 3 的兩個 buffer
:bw 3: 將非緩沖區(qū)文件全部刪除
:bufdo [command]: 對所有緩沖區(qū)執(zhí)行操作
:bufdo /searchstr/: use :rewind to recommence search
:bufdo %s/searchstr/&/gic: say n and then a to stop
:bufdo execute "normal! @a" | w: execute macro a over all buffers
:bufdo exe ":normal Gp" | update: paste to the end of each buffer
:1,3 bd: 刪除 buffer 編號在 1~3 之間的所有 buffer
Tag
<C-]>: 跳轉(zhuǎn)到當前光標的定義處
g<C-]>: 查看當前光標處有多少個定義 (可輸入數(shù)字然后跳轉(zhuǎn))
g]: 查看當前光標處有多少個定義 (可輸入數(shù)字然后跳轉(zhuǎn))
:tag {keyword}: 根據(jù) keyworkd 查找有多少個匹配的 tag
:tag: 正向遍歷 tag 歷史
:tnext: 跳轉(zhuǎn)到下一處匹配的 tag
:tprev: 跳轉(zhuǎn)到上一處匹配的 tag
:tfist: 跳轉(zhuǎn)到第一處匹配的 tag
:tlast: 跳轉(zhuǎn)到最后一處匹配的 tag
:tselect: 提示用戶從 tag 匹配的列表中選擇一項進行跳轉(zhuǎn)
:cs: 顯示 cscope 的所有可用命令
Markvim 中 mark 分為三種:
Local mark (a-z): 每一個 buffer 里皆有自己的 local mark, 也就是說檔案 A 可以有 mark a, 檔案 B 里也可以有自己的 mark a
Global mark (A-Z): 此種 mark 是全域的, 也就是說在檔案 A 里所看到的 mark A 和 B 檔案 B 里的 mark A 是一樣的
Special mark: 其他神奇的 mark, 不在此文章討論范圍
:marks: 顯示所有的 marks
mm: 為當前位置在當前緩沖區(qū)內(nèi)設置本地標記 m
dmm: 刪除本地標記 m
'm: 反撇號, 跳轉(zhuǎn)到設置的本地標記 m 處
mM: 為當前位置設置全局標記 M (必須是大寫, 可以跨文件使用)
'M: 跳轉(zhuǎn)到全局標記
'[: 上一次修改或復制的第一行或第一個字符
']: 上一次修改或復制的最后一行或最后一個字符
'<: 上一次在可視模式下選取的第一行或第一個字符
'>: 上一次在可視模式下選取的最后一行或最后一個字符
'': 上一次跳轉(zhuǎn) (不包含 hjkl 的那種跳轉(zhuǎn)) 之前的光標位置
'": 上一次關閉當前緩沖區(qū)時的光標位置
'^: 上一次插入字符后的光標位置, gi 便是使用了此 mark
'.: 上一次修改文本后的光標位置, 如果想跳轉(zhuǎn)到更舊的 mark, 可以使用 g;
'(: 當前句子的開頭, 與 command ( 相同
'): 當前句子的結(jié)尾, 與 command ) 相同
'{: 當前段落的開頭, 與 command { 相同
'}: 當前段落的結(jié)尾, 與 command } 相同
跳轉(zhuǎn)時我們可以使用 單引號 , 也可以使用 反撇號 , 單引號 只會讓我們跳轉(zhuǎn)到該行的第一個非空白字符, 反撇號 會讓我們跳轉(zhuǎn)到改行的該列, 更加精確
Completion
<C-n>: 觸發(fā)補全, 向下
<C-p>: 觸發(fā)補全, 向上
<C-x>: 進入補全模式
<C-x> <C-l>: 整行補全
<C-x> <C-n>: 根據(jù)當前文件里關鍵字補全
<C-x> <C-k>: 根據(jù)字典補全
<C-x> <C-t>: 根據(jù)同義詞字典補全
<C-x> <C-i>: 根據(jù)頭文件內(nèi)關鍵字補全
<C-x> <C-]>: 根據(jù) tag 補全
<C-x> <C-f>: 補全文件名
<C-x> <C-d>: 補全宏定義
<C-x> <C-v>: 補全 vim 命令
<C-x> <C-u>: 用戶自定義補全方式
<C-x> <C-s>: 例如: 一個英文單詞 拼寫建議
Quick List
:cnext: 顯示當前頁下一個結(jié)果
:cpre: 顯示當前頁上一個結(jié)果
:copen: 打開 Quickfix 窗口
:cfirst: 跳轉(zhuǎn)到第一項
:clast: 跳轉(zhuǎn)到最后一項
:cnfile: 跳轉(zhuǎn)到下一個文件中的第一項
:cpfile: 跳轉(zhuǎn)到上一個文件中的最后一項
:cc N: 跳轉(zhuǎn)到第 n 項
:cclose: 關閉 Quickfix 窗口
:cdo {cmd}: 在 quickfix 列表中的每一行上執(zhí)行 {cmd}
:cfdo {cmd}: 在 quickfix 列表上的每個文件上執(zhí)行一次 {cmd}
:cl[ist]: 打開 location list 窗口, 目前看來不需要使用此選項
Location List與 Quick-List 相似, 最大的不同是: Quick-List 是針對多個窗口共享一個結(jié)果, 而 Location List 則是各個窗口的結(jié)果互相獨立
lopen: 用于打開位置列表窗口
lclose: 用于關閉位置列表窗口
lnext: 用于切換到位置列表中的下一項
lprevious: 用于切換到位置列表中的上一項
lwindow: 用于在錯誤出現(xiàn)時才觸發(fā)位置列表窗口
宏
q + 小寫字母: 進入宏記錄模式, 記錄到 小寫字母 寄存器中, 記錄完成后再次按下 q 即可.
q + 大寫字母: 進入宏記錄模式, 在 小寫字母 寄存器尾部接著添加命令, 記錄完成后再次按下 q 即可.
@ + 小寫字母: 執(zhí)行對應寄存器內(nèi)的宏. 可使用前綴添加數(shù)字的方式重復多次命令
@:: repeat last : command, : 寄存器總是保存著最后執(zhí)行的命令行命令
@@: 直接重復上一次的 @ 命令, 此命令必須建立在 上一次使用了以 @ 開頭的寄存器宏 或者 剛剛建立了一個寄存器宏的 基礎上, 因此經(jīng)常配合 @: 使用.
10@a: 執(zhí)行寄存器 a 中所存儲宏 10 次 (串行處理, 如果有錯誤, 則立刻停止, 后續(xù)命令不再執(zhí)行)
參數(shù)列表參數(shù)列表與緩沖區(qū)的概念很類似, 參數(shù)列表的原始含義是我們在終端中使用 vim a.txt b.txt 時后面的一系列文件或參數(shù)名, 但是我們也可以在進入 vim 后使用 args 手動添加參數(shù)文件. 其與緩沖區(qū)的區(qū)別是:
位于參數(shù)列表的文件必然位于緩沖區(qū)列表中
緩沖區(qū)列表永遠是亂糟糟的, 但是參數(shù)列表永遠是秩序井然
:args *.*: 將當前目錄下的所有類型的文件加入到參數(shù)列表中 (不包括文件夾中的文件)
:args **/*.*: 將當前目錄下的所有文件及子文件夾的所有文件都匹配加入到參數(shù)列表中
:args *.md aa/**/*.md 表示添加子文件夾下的 md 文件及 aa 文件夾下的和其子文件夾下的 md 文件到參數(shù)列表中
:args 'cat list.txt': 用反撇號將命令包圍起來, 然后將命令被執(zhí)行后的結(jié)果作為參數(shù)加入?yún)?shù)列表中
:argdo %s/oldword/newword/egc | update: 對所有存在參數(shù)列表中的文件執(zhí)行命令, s 代表替換, % 指對所有行進行匹配, g 代表整行替換 (必用), e 指使用正則表達式, c 代表每次替換前都會進行確認, update 表示對文件進行讀寫
:argdo exe '%!sort' | w
:argdo write: 將所有參數(shù)列表中的內(nèi)容進行緩沖區(qū)保存
:argdo normal @a: 將當前參數(shù)列表的所有緩沖區(qū)執(zhí)行寄存器 a 中所存儲的宏
:argd *: 清空參數(shù)列表
:argdo bw: 將參數(shù)列表中的所有文件清除出緩沖區(qū)
:args: 顯示當前的所有參數(shù)列表
:next: 跳轉(zhuǎn)到下一個參數(shù)列表的文件
:prev: 跳轉(zhuǎn)到上一個參數(shù)列表的文件
:first: 跳轉(zhuǎn)到第一個參數(shù)列表的文件
:last: 跳轉(zhuǎn)到最后一個參數(shù)列表的文件
:args **/*.md: 將當前文件夾下所有.md 文件加入到參數(shù)列表中 (包括子文件夾中的文件)
:argdo %s/!\[.*\]/!\[img\]/gc: 將所有參數(shù)列表中的以 ![ 開頭, 以 ] 結(jié)尾的所有字段改為 [img]
:argdo source FormatCN.vim: 對參數(shù)列表中的所有文件執(zhí)行腳本 FormatCN.vim
命令行模式
:shell: 調(diào)用系統(tǒng)的 shell 來在 vim 進程中執(zhí)行命令, 執(zhí)行完使用 exit 退出
:term bash: 在底部分割出一個獨立窗口并調(diào)用 bash, 也可以使用 term zsh 來調(diào)用 zsh, 或 :terminal zsh
:history: all commands(equal to :his c)
:his c: commandline history
:his s: search history
<C-w> N: 在進入 :term 的終端模式后, 使用本命令可以獲得 Normal 模式 的效果, 使用 i 返回正常的終端模式
<C-\><C-n>: 同 <C-w> N
:col<C-d>: 在 Ex 命令模式中使用補全查看可能的選項, 然后使用 Tab / S-Tab 進行選擇 / 反向選擇
<C-r><C-w>: 將當前的光標下的單詞 <cword> 插入到命令行中
<C-r><C-a>: 將當前的光標下的單詞 <CWORD> 插入到命令行中
<C-f>: 將正在命令行中輸入的內(nèi)容放入到命令行窗口開始編輯
<C-c>: 與 <C-f> 相反, 此命令可以使命令行窗口的當前行內(nèi)容從命令行窗口放回到命令行中
<C-z>: 在終端中將 vim 最小化, 然后如果再需要調(diào)用的話使用 fg 進行操作, 使用 jobs 查看所有處于后臺的工作
<C-b>: beginning, 在命令行模式中跳轉(zhuǎn)到行首
<C-e>: end, 在命令行模式中跳轉(zhuǎn)到結(jié)尾
<C-p>: 在命令行模式中顯示上次的命令
<C-n>: 在命令行模式中顯示下次的命令
:!!: last :! command
:~: last substitute
:!<command>: 在 shell 中執(zhí)行命令
:!sh %: 將當前文件所有行作為輸入使用外部程序 sh 執(zhí)行, % 代表本文件所有行
!!<command>: 運行命令并將結(jié)果作為當前行的內(nèi)容, 同 :read!<command>, :.!<command>
:read!<command>: 將命令的結(jié)果輸入 (重定向) 到當前緩沖區(qū)
r !printf '\%s' {a..z}: 獲得 a-z
:put=execute('echo expand(\"%:p\")'): 將當前文件名輸出到 buffer
:put=execute('scriptnames'): 將輸出 put 到當前 buffer 上
:enew|put=execute('scriptnames'): 新開一個 buffer, 將輸出 put 到該 buffer 上
:tabnew|put=execute('scriptnames'): 新開一個 tab, 將輸出 put 到該 buffer 上
:redir @">|silent scriptnames|redir END|enew|put: 使用重定向到 " 寄存器, 然后在新 buffer 上 put
:!ls: 顯示當前工作目錄下的所有文件 (此操作屬于調(diào)用系統(tǒng)進程, 使用! 來調(diào)用系統(tǒng)操作是 Vim 的一大特點)
:[range]write!sh: 將當前緩沖區(qū)的內(nèi)容, 在 shell 中逐行執(zhí)行, 與 read!<command> 作用正好相反, ! 表示外部程序
:[range]write! sh: 將當前緩沖區(qū)的內(nèi)容, 在 shell 中逐行執(zhí)行, ! 表示外部程序
:[range]write! sh: 將當前緩存區(qū)內(nèi)容寫入到一個名為 sh 的文件, ! 表示強制覆蓋式寫入
:[range]write! filename: 將當前緩沖區(qū)內(nèi)容另存為到 filename 文件中
:.,$ sort [option] [pattern]: 從當前行到末尾進行排序
!: 翻轉(zhuǎn)順序, 默認小在前, 翻轉(zhuǎn)后大在前
i: 忽略大小寫
n: numeric, 綜合數(shù)字進行排序, 100 會排在 20 的后面
f: 浮點型
b: 二進制排序
o: 八進制排序
x: 十六進制排序
u: 移除重復行, :sort! u 會倒序去重排序 (! 控制正反序, 默認是正序)
pattern: When pattern is specified and there is no r flag the text matched with pattern is skipped, so that you sort on what comes after the match.
:sort /.*\%2v/: sort all lines on second column
:2,$!sort -t',' -k2: 使用外部 sort 程序進行排序, 以 , 為分隔符, 以第二項進行排序
:%!tac: 將整個文檔翻轉(zhuǎn)
:%!sort -R: 隨機排序
:%!shuf: 隨機排序
:w!sudo tee % > /dev/null: 在當前用戶沒有權(quán)限對當前文件做操作時使用超級管理員身份進行操作
:ls: 列出當前所有的緩沖區(qū)文件列表, 執(zhí)行的是 vim 的 ls 命令
:f: 顯示當前文件路徑, (使用了 <C-g> 代替, 此項基本不會用了)
:command: 顯示當前所文件的所有可使用命令
:retab: 重新生成所有的 tab(主要用于在.vimrc 中重新設置了 tab 格式, 然后在已存在舊格式 tab 的文檔進行重生成)
:map g: 查看所有以 g 開頭的映射
echo $VIMRUNTIME: 輸出 vim 的 runtime path
echom $VIMRUNTIM: echo 的信息只能顯示一次, 之后不能查看, 使用 echom 可以通過 messages 調(diào)用查看.
echom &rtp: 輸出 runtimepath
Vim 的先祖是 vi, 正是 vi 開創(chuàng)了區(qū)分模式編輯的范例. 相應的, vi 奉 一個名為 ex 的行編輯器為先祖, 這就是為什么會有 Ex 命令.
Ex 命令在命令行模式中執(zhí)行, 而命令行模式的進入方式為 : 鍵, 因此我們可以看到所有的 Ex 命令都是以 : 開始的, 輸入完命令后按下確定鍵 <CR> 即可執(zhí)行, 雖然 Ex 命令年代久遠, 但是不可否認其語法的簡潔明了以及高效, 很多復雜的操作往往都是通過 Ex 命令來進行處理.
:[range] <command> [target]: 執(zhí)行命令并將結(jié)果放入目標位置
:3,5 w!bash: 將 3~5 行寫入 bash
:. w!bash: 將當前行寫入 bash
:.!bash: 將當前行執(zhí)行結(jié)果寫入當前 buffer
:3,5 delete x: 將當前行執(zhí)行結(jié)果刪除到 x 寄存器
:.,$delete x: 將當前行到文件結(jié)尾的所有內(nèi)容刪除
:3,5 yank x: 將當前行執(zhí)行結(jié)果復制到 x 寄存器
:. put x: 在當前行后粘貼寄存器 x 的內(nèi)容
:3,5 copy .: 將 3~5 行復制到當前行下
:3,5 copy $: 將 3~5 行復制到緩沖區(qū)的尾部
:3,5 move.: 將 3~5 行移動到當前行下
:3,5 join: 將 3~5 行進行合并
[range] normal [cmd]: normal 用來指定在 normal 模式下對文本的操作命令
:3,5 normal .: 對 3~5 行執(zhí)行 . 重復命令
:3,5 normal @q: 對 3~5 行執(zhí)行寄存器 q 內(nèi)存儲的命令
'<,'> normal @a: 在所選高亮區(qū)域上執(zhí)行宏 (如果有錯誤也不停止, 因為是針對每一行執(zhí)行的, 出錯了只需要不處理那一行就行了)
:[range] global/{pattern}/[cmd]: 對指定范圍內(nèi)匹配的所有行執(zhí)行 Ex 命令 (具體實例參見正則替換篇)
:3,5 s/{pattern}/{string}/[flags]: 將 3~5 行進行相應替換
:3,5 join: 將 3~5 行進行合并
:3 p: 打印第 3 行
:3,5 p: 打印 3~5 行
:.,.+3 p: 打印本行以下的三行內(nèi)容, +3 代表偏移
:% p: 打印本 buffer 的所有行, % 代表所有行, 是 1:$ 的簡寫
:0,$ p: 打印本 buffer 所有行, $ 代表最后一行
:.,$ p: 打印本 buffer 內(nèi)從本行到結(jié)尾的所有內(nèi)容, . 代表當前行
/<html>/+1,/<\/html>/-1 p: 使用 patten 指定范圍, +1 表示偏移
:6t.: 把第 6 行復制到當前行下方, tail 代表尾巴, 遵守 from...to... 的含義
:t6: 把當前行復制到第 6 行下方, 當 . 位于首位時可以省略 ., 因此全稱是 :.t6
:t.: 粘貼當前行到下方, 與 yyp 不同的是本方式不會將內(nèi)容放到寄存器中, 而 yyp 會將內(nèi)容復制到 unname 寄存器與 0 寄存器
:t$: 粘貼當前行到文本結(jié)尾
:'<,'>t0: 把高亮選中的行復制到文件開頭, '< 代表高亮選取的第一行, '> 代表高亮選取的最后一行
:'<,'>m$: 把高亮選中的行移動到文件結(jié)尾
:'<,'>A;: 把當前文件的所有行的尾部加上 ;
Insert 模式
<C-p>: 選擇上方補全
<C-n>: 選擇下方補全
?: 退出插入模式 (推薦)
<C-c>: 退出插入模式
<C-[>: 退出插入模式
<C-u>: 向左刪除到行首
<C-w>: 向左刪除一個單詞
<C-h>: 向左刪除一個字符
<C-t>: 整行向右偏移
<C-d>: 整行向左偏移
<C + r>= <function>: 進行計算并將結(jié)果輸出到當前緩沖區(qū)中
<C-x><C-e>: scroll up wile staying put in insert
<C-x><C-y>: scroll down wile staying put in insert
<C-Left>: jump one word backwards
<C-Right>: jump one word forward
<C-v>065: 輸入大寫字母 A
<C-v>u{123}: 按照 unicode 碼以 10 進制來輸入
<C-v>u{1234}: 按照 unicode 碼以 16 進制來輸入
<C-v> <Tab>: 無論 expandtab 選項是否開啟都會插入制表符
插入模式中的粘貼操作參考 這里
路徑vim 的工作路徑是使用中要格外注意的地方, 簡單來說, 終端中的 vim 默認會把終端當前的路徑作為其工作路徑, 當然我們可以使用 cd 使其工作路徑變更
:cd [path]: 設置此次 vim 的工作目錄為 path
:cd %:h: cd 到當前緩沖區(qū)所屬目錄中
:cd../: cd 到上一級
:pwd: 顯示當前工作路徑
:lcd [path]: 設置當前窗口的工作目錄為 path(與 cd 不同的是只會改變當前 window 的工作路徑, 其他 window 的不受此影響)
vim 為我們提供了一些可以使用的宏用來表示相關路徑或文件名稱:
%: 當前文件相對于工作路徑的文件名及擴展
%:h: 表示當前文件所在目錄的相對工作目錄路徑 (不含文件名及擴展)
%:p: 表示當前文件所在目錄的絕對路徑 (含文件名及擴展)
%:r: 移除擴展之后的相對工作目錄路徑所有內(nèi)容
%:e: 擴展名
%:t: 當前文件名 (含擴展), 無任何目錄信息
%<: 當前文件相對工作路徑的文件名, 無擴展
在使用以上這幾種宏時, 我們可以使用 <Tab> 使其自動展開, 有些命令不支持自動展開的話需要使用 expand() 命令
echo expand('%:e'): 打印當前文檔擴展名, markdown 是 md
cd %:h<Tab>: cd 到當前緩沖區(qū)所屬目錄中, 在最后可以使用 <Tab> 進行自動展開
e %<Tab>: 會自動擴展為當前文件含相對工作目錄的路徑全名
寄存器寄存器是 vim 的一種特有概念, 其他文本編輯器默認都會用系統(tǒng)剪貼板作為復制粘貼的根據(jù)地, 然后 vim 另辟蹊徑使用多種不同類型寄存器作為臨時內(nèi)容存儲位置. 我們可以在復制粘貼時使用指定的寄存器定制化我們的需求, 也可以在錄制宏及使用宏時指定寄存器, 大大地提高了我們的工作效率.
很多剛使用 vim 的人會抱怨無法復制內(nèi)容到 vim 外或 vim 內(nèi), 然后各種搜索如何使 vim 的默認復制操作與剪貼板交互, 最后定義了一大堆按鍵, 譬如 "*y, set clipboard=unnamed, 其實大可不必, 寄存器是 vim 的高效操作方式之一, 接受了這種方式才能更好地利用 vim 來為我們服務 (雖然剛開始適應的過程必然是痛苦的)
總的來說 Vim 的刪除, 復制與粘貼命令以及定義宏時都會用到眾多寄存器中的某一個. 可以通過給命令加 "{register} 前綴的方式指定要用的寄存器. 若不指明, Vim 將缺省使用無名寄存器
無名寄存器
所有刪除復制粘貼操作如果不顯示指明寄存器類型的話使用的都是無名寄存器, 其標志符是 "" / "@.
編號寄存器
從 "0 到 "9 共 10 個, "0 保存著拷貝來的字符串, "1 保存著上次刪除掉的字符串, "2 保存著上上次刪除掉的字符串, 依次類推, vim 會保存最近的 9 次刪除. 刪除操作包括 s, c, d, x. 只有整行整行的刪除才會放入 "1 中.
使用 y 復制后內(nèi)容會被放到 "0 寄存器及無名寄存器中, 但是復制寄存器是穩(wěn)定的, 無名寄存器的內(nèi)容會時刻被重置替換. 其標志符是 "0
粘貼板寄存器
用于與系統(tǒng)的其他應用中進行復制粘貼交互, 等于系統(tǒng)的剪貼板. 其標識符是 "* (或 "+), 使用 set clipboard=unnamed 可以使得 "* 與 "" 始終具有相同的值
黑洞寄存器
所有放入黑洞寄存器的內(nèi)容全部被丟棄, 相當于完全刪除, 不留痕跡, 其標識符是 "_
有名寄存器
以單個小寫字母命名的寄存器, 可用于自定義存儲空間, 一共有 26 個
小刪除寄存器
不足一行的小刪除會被放到小刪除寄存器中, 刪除操作包括 s, c, d, x.
只讀寄存器
"%: 存儲著當前文件名, 是當前文件相對于工作目錄的路徑文件名
".: 存儲著上次插入模式中所輸入的所有文本內(nèi)容
":: 存儲著上次執(zhí)行的 Ex 命令, 與 @: 相對應, @: 可執(zhí)行上次的命令
交替文件寄存器
"# 存儲著當前 vim 窗口的交替文件. 交替文件指 buffer 中的上一個文件, 可通過 C-^ 來切換交替文件與本文件
表達式寄存器
表達式寄存器 "= 用于計算 vim 腳本的返回值, 并插入到文本中
當我們在 normal 模式下輸入 "= 后, 再輸入 3+2, 然后再使用 p 即可粘貼 5
在 insert 模式下使用 <C-R>, 然后輸入 =expand('%:p') 即可鍵入當前文件的完整路徑名稱
搜索寄存器
"/, 存儲著上次搜索的關鍵字
使用方式
""p: 從無名寄存器中取值進行粘貼
"ay: 將內(nèi)容復制到有名寄存器 a
"_y: 將內(nèi)容復制到黑洞寄存器, 相當于徹底地刪除
qa: 錄制操作到寄存器 a 中
@a: 執(zhí)行寄存器 a 中的內(nèi)容
u@.: execute command just type in
"ap: 從自定義寄存器中取出內(nèi)容進行粘貼
"0p: 從復制寄存器中取出內(nèi)容進行粘貼, 默認的 p 是從無名寄存器取值
"*p: 從系統(tǒng)粘貼板寄存器中取出內(nèi)容進行粘貼
<C-r>": 在插入模式中將無名寄存器的內(nèi)容粘貼進來
<C-r>*: 在插入模式中將系統(tǒng)粘貼板寄存器的內(nèi)容粘貼進來
<C-r>0: 在插入模式中將復制寄存器的內(nèi)容粘貼進來
<C-r>%: 插入當前文件名 (因為 "% 寄存器中存儲了當前文件名)
:reg a: 查看有名寄存器 a 的內(nèi)容
:reg *: 查看粘貼板寄存器 * 的內(nèi)容
:reg ": 查看無名寄存器 " 的內(nèi)容
:put a: 將有名寄存器 a 的內(nèi)容粘貼到當前緩沖區(qū)中, 與 "ap 不同的是 p 用于只能在光標之前或光標之后進行粘貼, 但是 put 則會始終將內(nèi)容粘貼到新的一行上
:d a: 將內(nèi)容刪除到有名寄存器 a 中
:let @q=substitute(@0, 'iphone', 'iPhone', 'g'): 對寄存器 0 的內(nèi)容進行替換處理然后再賦值到寄存器 q
:let @*=@0: 將粘貼寄存器內(nèi)容賦值到系統(tǒng)剪貼板寄存器
:'<,'>normal @q: 執(zhí)行
let @a=@_: clear register a
let @a="" clear register a
let @a=@": save unnamed register
let @*=@a: copy register a to paste buffer
let @*=@:: copy last command to paste buffer
let @*=@/: copy last search to paste buffer
let @*=@%: copy current filename to paste buffer
使用 Visual Mode 時, 在選中的文本上使用 p 將直接替換該部分文本 (替換后被替換的文本會被放入到無名寄存器中), 可用于解決需要刪除然后粘貼但是會影響到無名寄存器的問題
vimdiff
git 與 vim 可以說是非常好的一對搭檔了, 平時在終端中提交 commit 我們都少不了與 vim 打交道, vimdiff 是 vim 提供的專門用于修正 git 沖突文件的一款工具
若想使用 vimdiff 作為沖突修改工具, 需要設置 ~/.gitconfig 的以下項
1 2 3 4 [diff] tool = vimdiff [merge] tool = vimdiff
在 vimdiff 中, 一共有四個窗口, 上面依次是 LOCAL, BASE, REMOTE, 底部則是一個最終的文件結(jié)果窗口, 整個過程我們只需要將光標在最下方窗口上上下移動, 使用 diffget 命令從 LOCAL, BASE, REMOTE 中選擇需要使用哪一個作為本行的最終結(jié)果 (當然也可以跳到上面的窗口中使用 diffput 放置結(jié)果到底部窗口上
:diffget LOCAL: 選擇 LCOAL 作為本行最終結(jié)果
:diffget REMOTE: 選擇 REMOTE 作為本行最終結(jié)果
:diffget BASE: 選擇 BASE 作為本行最終結(jié)果
:diffput [num]: 放置結(jié)果到緩沖區(qū)上, num 為緩沖區(qū)編號
:diffg L: 這里 vim 為我們做了簡略命令, 同樣可用于 REMTOE 與 BASE 上
:diffget //2: //2 將被替換為左側(cè)文件名
:diffget //3: //3 將被替換為右側(cè)文件名
:%diffget LO: 將所有變更使用 local 的結(jié)果
:'<'>diffget LO: 將當前選中范圍的使用 local 的結(jié)果
dp/do: 如果只有兩個文件則可以使用 dp/do 來替代 :diffput/:diffget
:ls!: 顯示當前所有緩沖區(qū)的號碼
[c: conflict, 移動到上一個沖突處
]c: conflict, 移動到下一個沖突處
$git merge --continue: 沖突全部解決完后在外界終端中使用 git merge --continue 繼續(xù)之前的 merge 操作
:diffsplit filename: 已經(jīng)在 vim 中時, 使用此命令與別的文件進行對比
:vert diffsplit filename: 同上
vimidff file1 file2: 對比 file1 與 file2 的差別
vim -d file1 file2: 同上 ??
:wqa: 沖突修復完成保存退出, 如果仍然有文件沖突則進入下一個沖突
1 2 3 4 5 6 7 8 9 ╔═══════╦══════╦════════╗ ║ ║ ║ ║ ║ LOCAL ║ BASE ║ REMOTE ║ ║ ║ ║ ║ ╠═══════╩══════╩════════╣ ║ ║ ║ MERGED ║ ║ ║ ╚═══════════════════════╝
遠程編輯可以使用如下方式編輯遠程主機上的文件:
e scp://user@host//home/hanley/.sh/README.md: 通過 scp 編輯遠程 (使用絕對路徑)
tabnew scp://user@host//home/hanley/.sh/README.md: 使用新建 tab 的方式編輯
e scp://vm_ubuntu//home/hanley/.sh/README.md: 也可以通過 ~/.ssh/config 中的 alias 進行 key 的使用
e scp://vm_ubuntu/.sh/README.md: 也可以通過 ~/.ssh/config 中的 alias 進行 key 的使用 (使用相對路徑)
最后我的 vim 配置倉庫: HanleyLee/dotvim
本文作者 Hanley Lee, 首發(fā)于 閃耀旅途 , 如果對本文比較認可, 歡迎 Follow