Practical Vim Notes
VIM实用技巧 第二版 笔记
.命令
上一次修改可以指代很多东西,修改的范围不仅仅是字符,还可以是整行,甚至是整个文件。
>G命令会增加从当前行到文档末尾处的缩进层级。.命令会对当前行重新执行>G命令。
进入插入模式 (i)也会形成一次修改,Vim会记录直到返回普通模式<Esc>的所有按键命令。在这样的修改后,使用.命令会重新执行所有按键操作。
在插入模式中,使用了上下左右方向键,会产生新的撤销块,等价于<Esc>+移动后重新i。
.命令可以视作一个微型的宏。
*命令会查找当前光标下的单次。
.命令最佳范式
使用一次按键移动,另一次按键执行。
普通模式
[count]<Ctrl-a>:对当前光标之上或之后的数值添加[count]。
[count]<Ctrl-x>:对当前光标之上或之后的数值减少[count]。
0开头的数字会被Vim认为八进制。
l字符、aw单词、as句子、ap段落;与d结合删除,与g~/gu/gU结合转换大小写。
>增加缩进,<减少缩进,=自动缩进。
插入模式
插入模式下,<ctrl-w>删除前一个单词,<ctrl-u>删除至行首。
插入-普通模式
在插入模式中,使用<Ctrl-o>可暂时进入普通模式,执行一次命令后回到插入模式。
例如:<Ctrl-o>zz使当前行滚动到屏幕中心。
插入模式下使用寄存器
<Ctrl-r>{register}
常用:上次复制内容<Ctrl-r>0
其他特殊寄存器:
"未命名寄存器(上次复制或删除)%当前文件名#上次打开的文件名+系统剪贴板/上次搜索内容.上次插入的文本:上次执行的命令
<Ctrl-r>{register}对于大量文本会出现延迟,也可能出现不必要的换行或额外缩进。
(不好用) <Ctrl-r><Ctrl-p>{register}按原义插入寄存器内文本,并修正不必要的缩进。
表达式寄存器
插入模式中:<Ctrl-r>=访问表达式寄存器,可以在其中进行运算,回车键将结果插入到光标处。
可视模式
<Ctrl-v>激活面相列块的可视模式gv重新选择上次高亮选区o切换活动端点
可视化模式,特别是块模式下,擅长处理表格等数据。
<Ctrl-v>可以同时在多行进行编辑。
Vr-将整行替换为等长的-。
<Ctrl-v>多行编辑时,插入操作只会在顶行显示,但实际会修改所有行。
$可以打破<Ctrl-v>方形限制。
可视模式下,
i和a会被视作一个文本对象的组成部分,不会进入插入模式。
命令行模式
:[range]join连接指定范围内的行:[range]normal {commands}对范围内每一行执行普通模式命令:[range]s(ubstitute)/pattern/replacement/[flags]对范围内每一行执行替换:[range]global/{pattern}/[cmd]在指定范围内匹配的所有行,在其上执行命令行命令
命令行中的特殊行:
.当前行$最后一行^第一行%所有行0文件头部虚拟行'm包含位置标记m的行'<高亮选区起始行'>高亮选区结束行
使用模式指定范围
例如::/<html>/,/<\/html>/[command]处理标签内所有行。
范围可以进行偏移
e.g. :/<html>/+1,/<\/html>/-1[command]处理html标签内所有行,但不包括标签本身。
常用命令简写
:copy->:t:move->:m
重复上次的命令行命令:@:,使用<Ctrl-o>撤销重复。
使用:[range]normal [.]在多行中执行.命令或其他normal模式命令。
<Tab>会智能补全,多次按<Tab>会遍历候选项。
在Vim命令行模式中,在命令前添加!前缀就可以调用shell外部程序。
e.g. :!ls
不添加!执行的是Vim内置命令,如ls显示的是Vim缓冲区列表。
添加read前缀会将命令的输出写入缓冲区。
e.g.:read !{cmd}
文件
遍历缓冲区列表
:bp,:bn缓冲区列表中移动-
:bf,bl跳转到缓冲区列表的首尾 :[range]db删除缓冲区(不会影响文件),其中[range]为ls中输出的buffer分配编号
选择文件可以使用占位符:
*匹配0个或多个字符,但仅限于指定目录,不会递归其子目录**匹配0个或多个字符,包括子目录
分割窗口
<Ctrl-w>v垂直分割窗口<Ctrl-w>s水平分割窗口:sp {file_name}水平分割窗口并打开文件:vs {file_name}垂直分割窗口并打开文件
切换分割窗口
<Ctrl-w>w窗口间循环切换 (可以直接按住<Ctrl>+ww两次)<Ctrl-w>h/j/k/l切换到左右上下窗口
关闭窗口
:clo[se]或<Ctrl-w>c关闭活动窗口:on[ly]或<Ctrl-w>o关闭除活动窗口外的所有窗口
调整窗口
<Ctrl-w>=所有窗口等宽、等高<Ctrl-w>_将活动窗口调整到最大高度<Ctrl-w>|将活动窗口调整到最大宽度[N]<Ctrl-w>_将活动窗口的高度调整到N行[N]<Ctrl-w>|将活动窗口的宽度调整到N列
打开文件
Vim具有工作目录的概念,可以通过:pwd打印当前工作目录。
使用:edit {path}基于工作目录打开文件,使用<Tab>可以补全。
:e(dit) %<Tab>会展开为当前活动窗口的完整文件路径:e(dit) %:h<Tab>不会包含文件名
使用edit指定的目录中包含不存在的目录,仍然会打开空白文件,但不能直接保存。需要调用外部:!mkdir -p %:h程序创建目录,其中-p参数使mkdir创建任何不存在的中间目录。
快速移动
在visual模式和操作符待决模式(d, c, y)中,使用i, a结合承成对限定符选中内容。(可选中多行)
at和it在可视模式下会选中XML标签。
d{motion}与aw,as,ap配合起来比较好;c{motion}和i类命令结合效果会更好。
%命令在一组括号内跳转,作用于(), {}, []。
修改括号的技巧:首先执行一次%命令,跳转到匹配的括号,修改后执行``跳转回括号。
(,)跳转到上/下一句开头{,}跳转到上/下一段开头H/M/L跳转到屏幕顶部、中、底部<Ctrl-]>跳转到定义
位置标记
Vim会自动设置一些位置标记:
| 位置标记 | 描述 |
|---|---|
| `` | 上次跳转之前的位置 |
| `. | 上次修改的位置 |
| `^ | 上次插入的位置 |
| `[ | 上次修改或复制的起始位置 |
| `] | 上次修改或复制的结束位置 |
| `< | 上次高亮选区的起始位置 |
| `> | 上次高亮选区的结束位置 |
- m{letter}在当前光标处创建位置标记
- 小写字母创建局部缓冲区的标记
- 大写字母创建全局标记(跨文件)
修改位置跳转
Vim会记录每次修改的行列号,使用:changes查看修改记录。
g;和g,可以正反向在changes列表中遍历修改位置。
gi可以快速回到上次退出插入模式的位置,并进入插入模式。
跨文件跳转
<Ctrl-o> & <Ctrl-i>跳转(缓冲区列表)文件
:jumps查看跳转列表
寄存器
黑洞寄存器:删除内容并且不写入无明寄存器 -> "_d{motion}
复制专用寄存器("0):使用y命令时,会同步赋值,但仅当使用y命令时才会更新,不受x, s, c, d等命令影响 -> `“0p”
表达式寄存器 -> "=
选中一段内容后,使用p命令可以替换选中文本。
宏
当宏执行过程中存在命令报错时,宏就会停止执行,无论还剩余多少次。
以并行的方式(命令行模式)执行宏,实际上每行都是单独的宏,当特定行出错时,不会影响其他行。
e.g. :'<,'>normal @a
修改宏
追加命令
使用大写字母追加命令到宏中:ex. qA + 追加命令 + q
修改宏
首先要将宏处理为文本,建议使用:put a的方式,相较于ap该方法会在下一行插入。
此时可以像修改文本一样进行修改。
通过:d a将宏文本读取到a中。(该方法会在寄存器末尾追加^J,通常没有大问题,可通过"ay$避免)
编号递增的宏
需要使用Vim脚本。
创建变量::let i = 1
查看变量值::echo i
递增变量::let i += 1
插入模式下,使用运算寄存器插入变量值:<Ctrl+r>=i<Enter>
ex.
:let i = 1qaI<Ctrl+r>=i<Enter><Esc>:let i += 1q
模式
\cfoo不限制大小写,可以匹配foo,Foo,FOOfoo\C区分大小写,只能匹配foo
Vim支持magic搜索模式(i.e. \v后面的所有字符均具有特殊含义,无需转义),\x指代[0-9A-Fa-f] (详情见P201)
使用/键调出查找时,Vim会进行正向扫描;若使用?键,则进行反向扫描。
在查找模式中,按<up>键可以回溯之前的查找模式。
查询匹配数量:% s/{pattern}//gn。
特殊符号:
\r:换行符\t:制表符\\:反斜杠\1:第一个子匹配\2:第二个子匹配 (至多到9)\0或&:整个匹配- 正常模式使用
g&重新执行上次模式
- 正常模式使用
~:上次调用:s时的替换文本:%s//~/&
\={Vim script}执行vim script表达式
flags: (可多个同时使用)
g全局i忽略大小写c每次确认替换n计数
替换两文本
要求两个文本数量一致。
1
2
/\v(<A>|<B>)/\v(<A>|<B>)
:%s//\={"B":"A","B":"A"}[submatch(0)]/g
global命令
:[range] global[!] /{pattern}/ [cmd]
不同于其他ex命令,global命令范围的省缺时默认整个文件(%),不是当前行。
[cmd]可以是除了global外的所有ex命令,包括normal。
global!或vglobal表示反选,即所有不匹配的行。
global简写为gvglobal或global!简写为v
ex. 匹配所有HTML标签,并删除:
1
2
3
/\v\<\/?\w+>
<!-- \w 为单词字符 -->
:g//d
ex. 将TODO行复制到寄存器a中
1
2
:g/TODO/yank A
<!-- 以附加的方式依次添加到寄存器中 -->
Vim内置:sort排序命令
ex. :'<,'>sort对当前选中的行按首字母排序
可以将:g/{pattern}匹配作为参考点,动态的设置[cmd]的[range]。
:g/{pattern}/[range] [cmd]
ex. :g/{/ .+1,/}/-1 sort
其中+1和-1都是行号偏移量。
grep
使用:grep可以在vim内部调用grep命令。