- 本书有点太极端,作者过分强调了操作可重复的,很难适应这种思维,而是给了太多的 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>
列选取编辑模式,调整列表项的空格,追加注释,追加行末分号很有效,^$
可以选出不规则的选取