使用 Vim 进行的编辑的核心使用逻辑为执行,重复,回退。即先执行一次编辑动作,再在别的地方重复同一操作,如果不小心出错了就回退操作。可以理解为每次的编辑动作都被 Vim 自动保存为了一小段宏,再移动到另一个地方执行同一段宏,如果发现宏录错了,就快速回退,再重复这一过程,直到编辑完成。
所以,掌握 Vim 的第一步就是理解哪些是可以重复的操作以及如何回退。
可重复操作和对应的回退操作
Vim 中有很多操作是同一操作的两个方向,这类操作一般使用大小写来区分方向,比如 f{char} 向前到指定字符,F{char} 向后前进到指定字符。
一些编辑操作也有特别的撤销的操作,如下表所示:
| 目的 | 操作 | 重复 | 回退 |
|---|---|---|---|
| 做出一个修改 | {edit} | . | u |
| 在行内查找下一个制定字符 | f{char}/t{char} | ; | , |
| 在行内查找上一个制定字符 | F{char}/T{char} | ; | , |
| 在文档中查找下一处匹配项 | /pattern<CR> | n | N |
| 在文档中查找上一处匹配项 | ?pattern<CR> | n | N |
| 执行替换 | :s/target/replacement | & | u |
| 执行一系列修改 | qx{changes}q | @x | u |
Undo 命令
Normal 模式下使用 u 可以撤销一次编辑动作。
注意
命令撤销的不是上一次的输入,而是一次编辑动作。
一次编辑动作可以被以下三种情况规定:
- 在 Normal Mode 中使用编辑动作, 比如
.,<C-a>,s/target/replace; - 进入 Insert Mode 到退出 Insert Mode 中间的所有操作,除了包含 3 中所述的情况;
- 在 Insert Mode 中使用光标移动的操作,会立即将已有的输入保存为一次编辑动作块,包括
<UP>,<Down>,<Left>,<Right>等,可以理解为我们回到了 Normal Mode 进行了光标的移动。
Tips
使用 Redo 命令来撤销 Undo,快捷键为
<Ctrl + r>。
快速增减数字
<c-a> 会正向跳到第一个数字上,并将数字 +1, <c-x> 会将数字 -1, 也可手动制定增减的值,如 180<c-a> 。但有两点需要注意:
- 进制问题,类似
007这种数字,会默认识别为 8 进制数 - 日期增减问题,如果日期格式为
2020-10-07,当试图对月日进行增减时,会被识别为负数,其增减方向和期望的方向恰好相反
以 root 权限保存文件
:w !sudo tee % > /dev/null
% 符号会自动展开为当前文件路径,所以这条命令工作的原理就是通过 Vim :write 命令将文件内容通过标准输出写入到有 root 权限的 sudo tee <filepath>命令,这样就能成功保存了。
注意
这个技巧只能用于 Vim,而不适用于 Neovim,Neovim 中不支持
!命令中交互输入密码,所以只能使用插件或者将tee命令设置为不使用密码也能使用sudo,再使用命令:w sudo -n tee %调用。 See Also: Neovim FAQ, Neovim Issue, Another Issue
输入特殊字符
Vim/Neovim中支持使用ASCII或Unicode编码输入键盘上无法找到的字符,在输入模式下使用 Ctrl + v 快捷键就能进入编码输入的模式,这模式下有三种不同输入。
- 直接输入 3 位数字,如
<Ctrl + v>065会以十进制编码输入字符,这里会输入大写字母 “A” - 输入
u之后可以输入 4 位数字的 Unicode 字符,如<Ctrl + v>u00bf会输入字符 ”¿” - 输入非数字键则会直接输入键入的字符,比如
<Ctrl + v><TAB>会输入一个 tab 符,并且不会因为在配置中设置了 tab 转空格而自动的被转化为空格
如果已经在文本中存在的字符,如果想知道其字符编码,可以在 Normal Mode 将光标移动到对应字符使用快捷键 ga,屏幕下方就会显示出其对应的编码。
另外也可以通过二合字母来插入特殊字符,使用方式是在插入模式下使用 <Ctrl + k>{char1}{char2} 的快捷键,比如 <Ctrl + k><< 可以输入左书名号 ”«“,<Ctrl + k>12 可以输入 “½”,二合字母比起使用数字更容易记忆使用,使用 :h digraphs 了解更多信息,或者使用 :h digraph-table 查询所有可以输入的字符表。
| 按键 | 用途 |
|---|---|
<Ctrl+v>{123} | 以十进制字符编码输入字符 |
<Ctrl+v>u{1234} | 以十六进制编码输入字符 |
<Ctrl+v>{nondigital} | 按原义插入非数字字符 |
<Ctrl+k>{char1}{char2} | 插入二合字母表示的字符 |