该篇是 VS Code 系列文章的 Vim 基础篇,属于 VS Code + Vim 三篇子系列中的第一篇,另两篇分别是《VS Code 神兵策!--Vim篇(加强版)》、《VSCode 神兵策!--Vim篇(指令版)》。本篇主要介绍 Vim 的操作逻辑和基本应用。
划水
Vim 是啥?
装 B 神器 无出其右!有点难度,不过忍一下就过去了。一个星期的自我训练换时不时装 B,值!
有点复杂,怎么下手?
Vim 乱七八糟的概念确实有点多,但是有必要全搞懂吗?没必要啊!装个 B 而已,何必认真?
大家都是程序员,用日常熟悉的概念解读 Vim 岂不是事半功倍
下面我先按程序员思维对操作方法进行一个简单分类,一看秒懂:
- 操作函数: 比如复制、删除、修改、粘贴,以下简称函数。
- 快捷函数: 就是预设了数量及参数的函数,快捷函数不再接受数量及参数,以下简称快捷。
- 高阶函数: 就是使用函数作为参数的函数。例如: 宏、寄存器、标注。
- 操作范围: 比如字符、单词、行、段落、上半屏、下半屏、全文等等,以下简称参数。
- 操作数量: 比如要复制3个字,这里的3就是操作数量,以下简称数量。
- 切换方法: 仅用于切换状态,没有任何操作类型、操作数量。
插件安装
这里我选择 Vim 安装
其他选择也有:VSCode Neovim 安装 不过体验一段时间后,又切换回去了,想用的可以自己试试。
还有啥交代?
因为咱们的核心目的是在 VS Code 中流畅的使用 Vim,所以与 Linux 环境下的 Vim 操作有所不同,需要一些自定义配置,如果各位有仙人觉得 Vim 含量不纯了,OK,出门请右转!
正文
操作数量
操作数量不能单独使用,必须配合操作类型、操作函数使用, 通常可以与函数调换位置。操作数量在普通模式、视图模式均可使用。案例如下:
2b: 往前跳转2个单词,单词开头2e: 往后跳转2个单词,单词尾部3x: 删除3个字符2dd: 删除2行d2j: 删除光标所在行及下面2行
注意:
关于数量与函数的调换,
d2d与2dd是等价的,dd2是无效的,请仔细斟酌。
操作范围
字符
h: 光标左移j: 光标下移k: 光标上移l: 光标右移
单词
w: (word)到下一个单词开头,不忽略符号W: (word)到下一个单词开头,忽略符号e: (end)到本单词尾部或下一单词结尾,不忽略符号E: (end)到本单词尾部或下一单词结尾,忽略符号b: (begin)到上一个单词开头,不忽略符号B: (begin)到上一个单词开头,忽略符号ge: (goto end)到上一单词结尾gE: 到上一单词结尾,忽略符号
行
0: 到行首^: 移动到行首第一个非空字符H:移动到行首第一个非空字符(自定义)$: 移动到到行尾L:移动到行尾(自定义)gg: 到第一行G: 到最后一行数字G: 跳转到指定数字行,如20G即跳到第20行数字回车: 向后跳转数字行f字符: 快速定位到行内指定字符(向后找)F字符: 快速定位到行内指定字符(向前找)-: 向上移动一行+: 向下移动一行
段落
(: 上一段落): 下一段落
页面
H: 页头L: 页尾M: 页中{: 向上翻一屏(自定义)}: 向下翻一屏(自定义)[: 向上翻半屏(自定义)]: 向上翻半屏(自定义)zt: 快捷,将光标所在行切换到页面的顶部zb: 快捷,将光标所在行切换到页面的底部zz: 快捷,将光标所在行移动到屏幕的中间
普通模式 --NORMAL–
函数
复制 y:前参、后参
y2ge: 向左复制不含光标共2个词y2h: 向左复制不含光标共2个字y3l: 向右复制含光标共3个字y5l: 复制含光标共5个字y1j: 复制含光标行及下一行y2k: 复制含光标行及上2行y3w: 复制含光标单词及后续共3个单词y$: 复制含光标到行尾y^: 复制不含光标到行首yw: 复制一个单词yaw: 复制整个单词ye: 复制光标后一个单词yb: 复制光标前一个单词yj: 复制下一行内容y2j: 复制下2行内容yk: 复制上一行内容y3k: 复制上3行内容y$: 复制到行尾,含光标处y^: 向前复制至行首空字符处,不含光标y0: 复制到行首,不含光标处y(: 复制上一段落y): 复制下一段落yG: 复制到结尾ygg: 复制到开头
大写 Y:快捷,复制光标所在行。
4Y:复制4行,不存在Y4
删除块 d:前参、后参
小写 d:删除指定内容块。案例如下:
d1j: 删除光标所在行及下一行dd: 删除光标所在行dw: 删除光标处开始至单词结尾。例如:单词"password",光标停在w上按dw后剩下"pass"diw: 删除光标处的整个单词。例如:单词"password",光标停在d上按diw后剩下""di符号: 删除光标处符号范围内全部内容。例如"your password",光标停在r上按di"后剩下""da符号: 删除光标处符号范围内连同符号。例如:input “your password”!,光标停在r输入da"剩下input!
大写 D:快捷,删除光标至行尾内容块。
删除字符 x:仅前参
小写 x,向右删除字符,相当于del键。案例如下:
3x: 向右删除含光标共3个字符
大写 X,向左删除字符,相当于Backspace键。案例如下:
2X: 删除光标前面2个字符
删除字符 s:仅前参
小写 s 删除当前光标的字符,并进入 insert 模式
3s: 删除含光标共3个字符,并进入 insert 模式
大写 S 删除当前光标所在行并进入insert模式
3S: 删除含光标共3行,并进入 insert 模式
删除换行 J
J: 快捷,删除当前行行尾的换行符
插入换行 K
K: 快捷,在光标前插入换行符并进编辑模式(自定义)
编辑块 c:前参、后参
编辑 c :删除指定内容块后进编辑模式。案例如下:
ck: 删除光标所在行及上一行cj: 删除光标所在行及下一行cw: 删除光标处开始的一个单词ce: 删除光标处开始的一个单词ciw: 删除光标处开始的整个单词caw: 删除光标处开始的整个单词连外面的符号ci符号:删除光标所在行符号包裹范围内的内容,如编辑函数的参数时使用(光标不需要在符号范围内)ca符号:删除光标所在行,符号包裹范围包括符号的内容(光标不需要在符号范围内)cb: 删除光标前一个单词cc: 删除整行3cc: 直接删3行c$: 删除到行尾,含光标处C: 删除至行尾c^: 向前删除至行首空字符处,不含光标c0: 删除到行首,不含光标处c(: 删除上一段落c): 删除下一段落cG: 删除到结尾cgg: 删除到开头
大写 C:快捷,删除含光标至行尾内容块后进编辑模式。
编辑字符 s:仅前参
小写 s:删除含光标处字符进编辑模式。案例如下:
s: 删除光标处字符进编辑模式5s: 删除含光标处及之后共计5个字符进编辑模式
大写 S:快捷,删除光标所在行后进编辑模式。
粘帖 p:仅前参
小写 p:在光标后粘贴内容。案例如下:
p: 将剪贴板中的最新内容复制一份到光标后面。3p: 将剪贴板中的最新内容复制三份到光标后面。
大写 P:在光标前粘贴内容,用法和小写p一致。
替换 r:仅前参
小写 r:替换光标处字符。案例如下:
r: 将接下来一次的输入替换光标处的那个字符(中文输入一个词也算一次输入)。对“123”的1按r然后输入中文词“中国人”,结果是“中国人23”2r: 将接下来的一次输入替换含光标向右的2个字符(中文输入一个词也算一次输入)。对“123”的1按2r然后输入中文词“中国人”,结果是“中国人中国人3”
大写 R:进入替换模式,用所有输入内容替换原内容
撤销与反撤销 u
u: 快捷,撤销最近一次修改数字u: 撤销最近数字次修改
重复执行 .
.: 快捷,最后一次操作重复执行一次数字.: 最后一次操作重复执行数字次
字母大小写切换 ~
~: 切换将光标所在位置的字符大小写互换(shift+1左边的符号)3~: 将光标开始的3个字符大小写互换(shift+1左边的符号)g~: 切换当前行字母的大小写gUU: 将当前行的字母换成大写gUaw(gUiw): 将光标处的单词换成大写guaw(guiw): 将光标处的单词换成小写gUa符号(gUi符号): 将光标所在行,符号包裹范围内的内容换成大写(光标需要在符号范围内)gua符号(gui符号): 将光标所在行,符号包裹范围内的内容换成小写(光标需要在符号范围内)- 可视模式下,选中字母后,按
U将其换成大写 - 可视模式下,选中字母后,按
u将其换成小写
行内查找字符 F
f{char}: 光标到下个{char}F{char}: 光标到上个{char};: 继续找,: 反向找
行内查找字符 T
t{char}: 光标到下个{char}前T{char}: 光标到上个{char}前;: 继续找,: 反向找
高阶函数
宏定义 q
录制
q字母,然后操作键盘,操作结束后再按 q 即表示宏录制完毕。例如:
qai123,再按<Esc>,q
播放
@字母,重复宏记录的键盘操作。例如:
@a,就可以执行输入i123,结果就是在光标处插入了123
寄存器 "
存入
"小写字母<y、d、x>:将 y 或 d或 x 的内容存入寄存器。例如:
"ayk: 将当前行及上1行内容存入a寄存器
取出
"字母<p或P>: 将寄存器内容取出。例如:
"ap: 将a寄存器内容粘贴到光标后面
标注 m
m字母,记录当前光标的位置。例如:
- 现在光标在第10行,按mc,记录下当前位置。
标注
标注位置后,进行翻页、跳转、移动光标,再按 '字母,光标会迅速跳回到之前记录的位置。例如:
- 输入
gg,光标回到第1行,再按'c,光标会回到第10行。
重复输入
- 先输数字再按
i再按<Esc>可以快速输入重复内容 - 先按5,再按
i,再输入 abc,再按<Esc>,相当于快速输入5个 abc
命令模式
全文查找
/{string}: 光标到下个{string}?{string}: 光标到上个{string}n: 继续找N: 反向找:noh:取消高亮
全文替换
:%s/word1/word2/g: 全文直接将word1替换成word2:%s/word1/word2/gc: 全文直接将word1替换成word2,替换前会询问:1,$s:从第一行到最后一行:10,20:从第10行到第20行:10,20s#^#//#g:在 10 - 20 行添加 // 注释:10,20s#^//##g:在 10 - 20 行删除 // 注释:10,20s/^/#/g:在 10 - 20 行添加 # 注释:10,20s/#//g:在 10 - 20 行删除 # 注释
使用正则表达式
把文中的所有字符串“abc……xyz”替换为“xyz……abc”可以有下列写法
# 在 VS Code 中操作
:%s/abc(.*)xyz/xyz\1abc/g
:%s/(abc)(.*)(xyz)/\3\2\1/g
关于在 Vim 中使用正则表达式的更多细节,请看我的《Vim 神兵策!--正则表达式》
可视模式 --VISUAL–
进入可视模式后按 v 或 <Esc> 键可还原到普通模式
- 字符选择模式,小写
v - 行选择模式,大写
V - 块选择模式,(自定义
//)
移动
h: 光标左移j: 光标下移k: 光标上移l: 光标右移o:切换选择区域的活动端点
其他可用函数
y:复制p:粘贴d:删除x:删除字符
模式切换
替换模式切换 --Replace–
r: 替换光标所在字符R: 进入替换模式
插入模式切换 --INSERT–
insert
i: 在光标前插入I: 在行首插入
append
a: 在光标后插入A: 在行尾插入
other line
o: 在下一行插入O: 在上一行插入
change
c: 删除字符后进插入模式C: 删除光标处至行尾进编辑模式
leader 快捷键(自定义)
空格+u: 还原最近一次的撤销,这个和普通模式下u的逆操作。(等价于ctrl+z撤销,ctrl+shift+z取消撤销)空格+/: 当前页查找字符串跳转(原来是2个空格+/)空格+s: 当前页查找字符跳转(原来是2个空格+s)空格+p: 复制一行
vim 插件设置
我禁止 vim 使用 ctrl,因为 vscode 本身有大量快捷键用了 ctrl。为此另外增加了许多 leader 快捷操作。
"vim.leader": "<space>", // 绑定vim前导键
"vim.easymotion": true, // 启用easymotion插件
"vim.incsearch": true,
"vim.useSystemClipboard": true, // 是否启用系统粘贴板作为vim寄存器
"vim.useCtrlKeys": false, // 是否由vim接管ctrl+any的按键
"vim.hlsearch": true, // 是否突出显示与当前搜索匹配的所有文本
"vim.highlightedyank.enable": true, // 被复制时是否高亮
"vim.highlightedyank.duration": 500, // 被复制时高亮持续时间:0.5秒
// 命令模式下的非递归案件绑定 相当于norecmap
"vim.commandLineModeKeyBindingsNonRecursive": [],
// 插入模式下的非递归按键绑定 相当于 imap
"vim.insertModeKeyBindings": [],
// 可视模式下的非递归按键绑定
"vim.visualModeKeyBindings": [
{ // 粘贴不替换文本
"before": [
"p"
],
"after": [
"P"
]
},
],
// 普通模式下非递归绑定按键 相当于 vim 中的 noremap
"vim.normalModeKeyBindingsNonRecursive": [
{ // 屏幕『向上』移动一页
"before": [
"{"
],
"after": [
"<C-b>"
]
},
{ // 屏幕『向下』移动一页
"before": [
"}"
],
"after": [
"<C-f>"
]
},
{ // 屏幕『向上』移动半页
"before": [
"["
],
"after": [
"<C-u>"
]
},
{ // 屏幕『向上』移动半页
"before": [
"]"
],
"after": [
"<C-d>"
]
},
{ // 断行并进入编辑状态
"before": [
"K"
],
"commands": [
"lineBreakInsert"
],
"silent": true
},
{ // 进入块选择模式
"before": [
"\\",
],
"commands": [
"extension.vim_ctrl+v"
]
},
{ // 取消最近的撤销 等价于ctrl+z撤销,ctrl+shift+z取消撤销
"before": [
"<leader>",
"u"
],
"after": [
"<C-r>",
]
},
{ // 取消最近的撤销
"before": [
"U"
],
"commands": [
"undo"
]
},
{ // 全屏查找字符串
"before": [
"<leader>",
"/"
],
"after": [
"<leader>",
"<leader>",
"/"
]
},
{ // 全屏查找字符串
"before": [
"<leader>",
"s"
],
"after": [
"<leader>",
"<leader>",
"s"
]
},
{ // 复制一行
"before": [
"<leader>",
"p"
],
"after": [
"y",
"y",
"p",
]
},
{ // 保存
"before": [
"<leader>",
"w"
],
"commands": [
"workbench.action.files.save"
]
},
{ // 退出编辑 关闭当前编辑窗口
"before": [
"<leader>",
"q"
],
"commands": [
"workbench.action.closeActiveEditor"
]
},
{ // 移动到当前行第一个非空字符的位置
"before": [
"H"
],
"commands": [
"cursorHome"
]
},
{ // 移动到当前行最后一个非空字符的位置
"before": [
"L"
],
"commands": [
"cursorEnd"
]
},
],
结语
本文主要以程序员视角介绍了 VS Code 中使用 Vim 的基本方法,重点是如何通过配置让操作变得更加丝滑。但实际上,你在实际使用中依然还有一些操作不便的地方,比如中英文的切换、折叠代码移动会自动展开等问题。由于篇幅问题,这些问题我将在下一篇章进行讲解,敬请期待!
引用
本篇文章内容大部分来源于网络,因为内容基本都是最基础的指令,几乎大同小异。重点是能够帮助大家快速掌握 Vim 并在 VS Code 中实践起来,早日走上装 B 之路。