作者正在从 vim 切换到 nvim ,之后的相关插件和配置也会跟进,不断更新,文章会偏向于供作者本人自己回顾,推荐学习路径(按顺序):

  1. Vim Adventures有趣的 vim 冒险游戏,我的入门教学,尽管冒险因为后面的不是免费而戛然而止,但也让我熟悉了 vim 的基本操作。
  2. vimtutor 完成vim自带的教学
  3. 视频 这是一个比 missing-semester 更好的学习视频,全程无废话全干货,目前为止看到最好的 vim 教学视频
  4. Practical Vim 已学完
  5. vim 从入门到精通 正在学习中
  6. LunarVim 一个基于 neovim 的插件集合,功能丰富,配置简单
  7. Vim Cheat Sheet vim 速查表
    提醒:尽量不要花大把时间在配置上,有时间不如多打打代码

我的 Vim 学习

第一批学习的命令

w e b(向后跳到前一个单词的开头) a i y p o u r x ctrl+u/d/f/b v ctrl+v V gg G d . dd ctrl+r

第二批学习的命令:

W E B A(大写命名的魅力时刻) I / ? n $ ^ % caw ci{ ci( zz - K ~(大小写转换) H M L

第三批学习的命令

f(在单行内移动的最快方式) t , F ; qaq @@ ma ctrl+o(相当有用) ctrl+i s(cl进阶) R J ctrl+a(很神奇的增加数字,需要2次)ctrl+x nG J

*(查找光标所在位置单词的下一个) [[(跳转到下一个段落的开头)

第四批学习的命令

S zz zt zb I A O cc(进化为S) yy :sp :vsp :!ls :e >> mm

第五批学习的命令

gv(重新选取上一次可视模式下的内容) ge C(删除当前光标所在处到当前行最后一个字符并进入插入模式) n@a :e %%(重新编辑当前文件,%%意为当前文件名) dap

dit(删除一个HTML标签中的内容) >G(增加从当前行到文件最后一行的所有行的缩进,宽度由 shiftwidth 决定) &(与上次相同的替换操作)

,(反向重复上一次查找的命令) gcc(注释当前行) gcap(注释当前段落) ctrl+r 0(在插入模式下粘贴刚才复制的内容)
gUit(将标签内的单词转换为大写) gUw gx(打开链接)

可视模式

u(选中内容转小写) U(选中内容转大写) <C-v> I选中列快后在开头插入 =自动对齐
viw(在可视模式下选中当前单词) viWc
vit(选中光标所在标签对内部的内容)

键盘映射

vscode 中使用 vim 插件键盘映射方式,在 settings.json 文件中添加以下内容:

1
2
3
{
"keyboard.dispatch": "keyCode"
}

多文件管理

使用标签页(Tab Pages)

标签页(tab pages)可以让你像浏览器标签一样在多个文件之间切换,每个标签页都可以包含多个窗口(window)。

  • :tabnew [filename]:打开一个新的标签页并加载指定的文件。如果不指定文件,会打开一个空的标签页。
  • :bn:切换到下一个标签页。
  • :bp:切换到上一个标签页。
  • :tabedit [filename]:与 :tabnew 类似,打开指定文件到新标签页。
  • gtgT:分别跳转到下一个或上一个标签页。

使用窗口(Windows)

窗口(windows)是将 vim 编辑器分成多个视图,每个视图可以显示不同的文件或同一文件的不同部分。

  • :sp [filename]:水平分割窗口并打开指定文件。
  • :vsp [filename]:垂直分割窗口并打开指定文件。
  • Ctrl-w h/j/k/l:在多个窗口之间切换,hjkl 分别表示左、下、上、右。
  • :close:关闭当前窗口。
  • :only:关闭所有窗口,仅保留当前窗口。

使用缓冲区(Buffers)

缓冲区(buffers)是 vim 中用于处理打开文件的内部表示。每个文件都在内存中作为缓冲区进行处理。

  • :e [filename]:打开一个文件,创建新的缓冲区。

  • :ls:buffers:列出所有打开的缓冲区。

  • :bnext:bn:切换到下一个缓冲区。

  • :bprev:bp:切换到上一个缓冲区。

  • :b [buffer number or name]:切换到指定的缓冲区。

  • :bd:bdelete:删除当前缓冲区。

  • :bw:关闭当前窗口并删除缓冲区(但不退出 vim)。

  • 内置标记

    • ``:上次跳转前的位置。
    • `.:上次修改的位置。
    • `^:上次插入的位置。
  • [% 跳到当前配对符号的起始位置

  • (% 限定在当前段落或块内,跳到段落或块的起始符号

  • {% 向后查找上一个包含{}的代码块的开头位置

寄存器与宏

特别的寄存器

  • “:默认寄存器,平时复制、删除的内容都放在里面。
  • %:当前文件名。
  • .:上一次插入的内容。
  • ::上一次执行的命令。

常用命令

  • :reg {register}查看对应寄存器中的内容。
  • "ayy:将这一行复制到a寄存器中。
  • "bdiw:将单词删除,保存到b寄存器中。
  • "cp:将c寄存器中的内容粘贴出来。

寄存器字符大写:添加(append)而非覆盖。

命令模式

Ex 命令格式

:[range] {excommand} [args]

  • range:作用范围,不指定则默认是当前行。
  • excommand:特殊命令,适用于 Command 模式。
  • args:后续参数,视命令而定。
  • :[range] d {register}
  • :[range] y {register}
  • :[range] p {register}

Range 与 Address

  • address 可以是:
    • {lineno}:行号,如 3 代表第三行(0 代表第一行上面的虚拟行)。
    • $:最后一行。
    • .:光标所在行。
    • /{pattern}/:下一个 pattern 所在的行。
  • address 可以做加减法,如 .+3 代表光标往下第三行,$-3 代表倒数第四行。
  • 1,3:文件的 1-3 行。
  • .,.+4:当前行到当前往下 4 行(共 5 行)。
  • $-3,$:文件的最后 4 行。
  • %:特殊的 range,代表当前文件的所有内容。
  • '<'>:可视模式中选中范围的开头和结尾(可视模式下直接按 : 可以直接设置)。

行的复制、移动、粘贴

  • :[range] copy {address}:把 range 中的行复制到 address 后面。
  • :[range] move {address}:把 range 中的行移动到 address 后面。
  • :[address] put [x]:把寄存器 x 的内容粘贴到 address 后面。
  • 0 作为虚拟行的 address,可以用来将内容插入第一行。

批量操作

normal 命令

  • 格式::[range] normal {commands}
  • 含义:对 range 中的所有行执行 Normal 模式下的命令 commands
  • 常用做法:先做一次修改操作,再用 normal 命令在指定的行上完成操作。
  • . 命令只能记录一次修改,用宏可以实现记录多个操作。
  • :[range] normal @{register}:先把想要的操作录制成宏,再用 normal 命令在指定的行上重放宏。
  • :1,4 normal I#

global 命令

  • 格式::[range] global/{pattern}/[cmd]
  • 含义:对 range 中包含 pattern 的所有行执行 Command 模式下的 E x 命令 [cmd]
  • [cmd]:E x 命令,不指定则默认是打印(print)。
  • 例子::% global /TODO/delete:删除所有带 TODO 的行。

替换命令

:[range]s/{pattern}/{string}/[flags]

  • flags
    • g:替换每一行的所有匹配。
    • i:忽视大小写。
    • c:替换前进行确认。
    • n:计数而不是替换。
  • 例子::%s/Vim//gn:统计文件中所有 Vim 出现的次数(此时替换为什么无所谓,加了 n 就不会执行替换操作)。
  • :%s/^#/##/g:所有标题加一级。还可以用&表示匹配的原始内容。