VSCodeVim 最佳实践
20 Sep 2019 - 周岩
1. Preface
初学者在学了一些 Vim 入门教程,掌握了一些基本操作后,往往不知道从何下手,日常工作中不太可能在终端下直接写代码,何况直接终端用 Vim 写代码,还需要大量插件的支持。
其实我认识的很多 Vim 用户,现在已经不用原生 Vim 了,都是先选一个自己喜欢的编辑器/IDE, 再装 Vim 插件,基本上没有哪个现代编辑器/IDE没有 Vim 插件的了。
我比较喜欢 VSCode,日常工作也是用 VSCode 写代码,所以今天就来介绍下 VSCode 里 Vim 插件的一些设置和应用技巧,至于是不是最佳实践不重要,起这样的标题完全是不知道用什么好,权当做一回标题党吧。
2. 编辑器选择
在讲具体内容之前,先介绍几个编辑器的 Vim 插件现状, 顺便解释下我为什么要选 VSCode
:
- Sublime Text, 编辑器内建了对 Vim 的支持,所以不装插件只要改下配置就能用,但是功能比较原始,实在谈不上好用,只能说能用。也许有很多第三方插件提供了类似 easymotion 这样的功能吧,我没研究过,想用的可以看看有没有,如果有还是可以用的。
- VisualStudio, 由于 VS 内建了海量的快捷键,且用熟了之后也很方便,所以对于 VS 资深用户,装个 Vim 插件反而不好用,这上面的 Vim 插件我也用过,体验非常糟糕,不推荐。
- MacVim, 配合 spf13-vim 还是可以用的,我个人在对 VSCode 审美疲劳时也会用一用,轻量、好看、好用。
- IntelliJ IDEA, 这是个 IDE 了,非常重,但功能还是十分强大的,Vim 插件也基本够用,好像也是有 easymotion 的,基本上很完整,还有社区免费版可用,所以用的人非常多,但是我一开 CPU 就狂转,所以最终没用它。
- VSCode, 目前我最喜欢的,Vim 插件支持非常成熟,其他编辑器的 Vim 插件一般只是提供了 Vim 的原生功能,而 VSCode 的 Vim 插件居然提供了很多原生 Vim 里的插件功能,也就是说,它是一个 Vim + Vim插件的插件集合体,功能非常强大,像是最常用的 easymotion 就提供了支持。原生 Vim 其实并不好用,想要高效还是要配合插件一起用,而 VSCode 的 Vim 插件做到了,我认为现在没有什么编辑器的 Vim 插件能够做到。
3. VSCode Vim 插件的安装
上面说了那么多,对于初学者来说,建议直接用 VSCode 吧,不折腾。
安装非常方便,打开插件界面,输入 Vim,第一个就是,点安装即可。
800多万的安装量,感受下 Vim 用户的庞大,是不是感觉不用 Vim 和时代脱离了:)
4. 最佳实践
4.1 settings.json 配置
{
"vim.easymotion": true,
"vim.leader": ",",
"vim.searchHighlightColor": "#5f00af",
"vim.hlsearch": true,
"vim.normalModeKeyBindingsNonRecursive": [
{ "before": ["H"], "after": ["g", "T"], },
{ "before": ["L"], "after": ["g", "t"] },
],
"editor.lineNumbers": "relative",
"files.autoSave": "onFocusChange",
"workbench.editor.enablePreviewFromQuickOpen": false,
"editor.renderWhitespace": "boundary",
"editor.detectIndentation": false,
"showMusicMetrics": false,
"showGitMetrics": false,
"showWeeklyRanking": false,
"editor.minimap.enabled": false,
"git.autofetch": true,
}
首先把上面的配置放到自己的配置文件里,Mac 平台点左上角 Code->Preferences->Settings-> 在右边往下拉,找到 Edit in settings.json, 把上面内容放进去,大括号自己去掉。
解释几个:
Vim 相关的
- “vim.easymotion”: true, 打开 easymotion, 这个是文件内快速跳转的插件(Jump everywhere)
- “vim.leader”: “,”, 设置 leader 键为逗号,leader 键是 Vim 里某些指令的前置按键,默认是反斜线,比较难按。这个按键非常常用,必须改成逗号
- “vim.searchHighlightColor”: “#5f00af”, 设置搜索高亮,不设的话没有高亮,很蠢
- “vim.hlsearch”: true, 高亮显示最近的搜索结果,就是你按一下 *, 把结果都高亮出来,这个很重要
- “vim.normalModeKeyBindingsNonRecursive”, 这个是改按键映射关系的,改完可以使用 H/L 切换标签
Vim 无关的
- “editor.lineNumbers”: “relative”, 设置相对行号,这个对于多行删除,多行注释非常重要,有了这个才算是可以用,否则自己数行数那基本上没法用
- “files.autoSave”: “onFocusChange”, 设置文件自动保存,onFocusChange 指的是焦点离开后就保存,这个跟 Vim 无关,但非常好用,不用一直按 Cmd+s 了
- “workbench.editor.enablePreviewFromQuickOpen”: false, 用 ctrl-p 打开的文件,默认是处理预览状态的,重新预览其他文件时就没了,要双击标签才会固定住,这个设置就是解决这个问题的,设置完后打开就是固定住的,读代码很方便
- “editor.renderWhitespace”: “boundary”, 设置显示行首的空白字符(空格和制表符),这个也很不错,直观的看到自己输出的空白,有些开源项目要求必须全用空格。
- “editor.minimap.enabled”: false, 关掉右边的小地图,就是宽宽的那个,这个看个人喜好了,我不太喜欢,开分栏时会减少显示面积
4.2 行级操作(删除、注释、左移右移)
上面设置了相对行号后,才能方便的做多行操作,在做具体操作前,先说单行操作分别是什么:
dd
删除一行,d
是delete
, 两个 d 表示对一行操作,Vim 里的约定吧gcc
注释一行,gc
是go comment
, 两个 c 表示注释一行<<
左移一行>>
右移一行
上面的操作,在 v 模式下,都可以生效,可以试一下按 Shift+v
选中一行,然后分别按 d
, gc
,<
, >
, 看看是不是删除、注释、左移、右移
好了,有了上面的这些知识,我们可以开始多行操作了,具体操作方法如下:
- 光标移到想要删除或注释的第一行
- 通过左边的相对行号,看一下想操作的最后一行的相对行号n
- 得出要操作的行数 m = n+1 (因为光标所在那行相当于第0行,所以要+1)
- 这时就可以用 Vim 的多行操作了,删除一行是 dd, 删除多行是 mdd; 注释一行是 gcc, 注释多行是 mgcc, 其他的类推
4.3 切换标签
H
大写的 H 移动到左边那个标签L
大写的 L 移动到右边那个标签ngt
移动到第 n 个标签(从左往右从1开始),当标签开的比较多时,由于标签上没显示数字,要自己数是第几个,所以基本上没法用。
对于标签开的比较多时怎么操作,我的习惯是这样的:
- 如果标签离的近,就是 H/L 移动过去
- 如果离的不是特别远,按5下 H/L 还是可以接受的
- 如果特别远,对于要长时间写代码的几个标签,用鼠标把几个常用标签拖到一起;如果是一次性的,就用鼠标直接点了;也会用 ctrl-p 直接搜文件重新打开。
4.4 调整光标所在行的位置(Vim基本功能)
zz
调整光标所在行到屏幕中间 (z 什么意思我也不知道,就硬记吧)zt
调整光标所在行到屏幕最上方 (t == top)zb
调整光标所在行到屏幕最下方 (b == bottom)
这三个用的非常多,尤其是 zz
, 一定要熟练使用
4.5 文件内快速搜索某个函数、变量(Vim基本功能)
把光标移到想搜索的那个函数名或变量名上,按*
就可以搜索了,按n
下一个,按N
上一个。
比如看到类里有个成员变量,想去回到它的定义处看有没有注释说它是干嘛的,一般定义的地方肯定是文件内第一次出现的地方,我们可以这么操作:
- 先在这个变量上按下
*
锁定它 - 按
gg
回到行首 - 按
n
到下一个它出现的地方 - 按
zz
调整到屏幕中间,方便阅读
这4步熟悉后基本一气呵成
4.6 对一个单词进行操作
这里先说两个概念,操作符(operator)和动作命令(motion), 操作符就是 d(delete)
, c(change)
, y(yank)
等等,动作命令是iw(in word)
, aw(a word)
这些,可以通过 操作符 + 动作命令
的方式,组合出千变万化的操作出来,帮助我们快速移动、修改等等。
完整列表可以在 Vim 里输入 :h motion.txt 查看,这里只列出一些常用的。
4.6.1 操作符(Operators)
操作符 | 功能 |
---|---|
c | change (先删除再进入插入模式) |
d | delete |
y | yank into register (does not change the text) |
~ | swap case (转换大小写) |
gu | make lowercase (转为小写) |
gU | make uppercase (转为大写) |
> | shift right (右移) |
< | shift left (左移) |
4.6.2 动作命令(Motions)
动作命令 | 功能 |
---|---|
f{char} | find, 行内搜索一个字符 |
t{char} | till, 功能类型 f{chat}, 但是是在这个搜索到的字符前停下,意思是到这个字符之前,很常用的motion |
gg | 跳到行首 |
G | 跳到行尾 |
w | 移到下个单词的第一个字符 |
b | 移到上个单词的第一个字符 |
e | 移到单词最后一个字符 |
ge | 上个单词的最后一个字符 |
aw | “a word”, 选择一整个单词,包括它边上的空格 |
iw | in word, 选择一整个单词,不包括空格 |
4.6.3 举例:
diw
, delete in word, 删除一个单词,只删除单词本身,不会旁边的空格daw
, delete a word, 删除一个单词,并删除旁边的一个空格(至于是左还是右边空格,Vim 会根据上下文自己判断,非常智能)d
是删除,diw
就是删除一个单词v
是进入 visual 模式的,如果用viw
, 就表示选中一个单词y
是复制(yank),yiw
表示复制一个单词gu
是变成小写,guiw
就是让一个单词变成小写gU
是变成大写,gUiw
就是让一个单词变成大写 *
还有很多,这样只要记住一个,就可以举一反三,所以 Vim 是不需要死记硬背的,理解着记会更快。(当然不排除一些要死记硬背,但比较少)
4.7 把一个单词改成另一个(通过复制)
比如有下面一段代码:
local _hello = true
function test()
print(_world)
end
-- 用复制的方式把 _world 改成 _hello
这个问题看起来很简单,但实际上用起来后就会发现并不简单,我们用鼠标时的操作逻辑是下面这样的:
- 双击 _hello,Ctrl+C 复制
- 双击 _world,Ctrl+V 粘贴
想象中的 Vim 操作逻辑是下面这样的:
- 光标移到
_hello
,yiw
复制 - 光标移到
_world
,diw
删除,再p
粘贴
这时你会发现,咦,贴出来的还是 _world
, 而不是期望中的 _hello
, 这是因为 Vim 里的删除,实际上是剪切,会把删除的东西放到“剪切板”里,所以我们不能这样操作,而应像下面这样操作:
- 光标移到
_hello
,yiw
复制 - 光标移到
_world
,viw
选中,再p
粘贴
这个操作是目前的最优解了,《Vim 实用技巧》这本书里给的也是这个方案(我是先自己发明这个方案才看的书:),这个方案虽然也很别扭,但是够用了,习惯了也不是不能接受。
4.8 EasyMotion 文件内快速跳转
,,j
按下后,会在每一行的行首高亮且有一个字母标在高亮处,这时输入指定字母就可以跳过去了,这个可以说是起飞的关键之一,必须要熟练掌握,,k
上面是向下搜索,这个是向上,其他都一样,,w
同,,j
,只不过是单词级的向后搜索,,b
同,,k
, 只不过是单词级的向前搜索(,,w
,,b
不如行级好用,因为太花了,我们可以用行级 Jump 到指定行,再用 f 过去,或者按几个 w 也可以,如果靠近行尾,可以先按$到行尾再按几个 b,方法很多。
4.9 回到上一个编辑点
ctrl+o
, 回到上一个编辑点ctrl+i
, 前进到下一个编辑点,和上面的相反方向gi
, 回到上一个进入插入模式的地方,并进入插入模式,这个在写代码时写到一半想看一下其他地方的代码,看完再按下gi
回去,当然也可以ctrl+o
回去。
4.10 代码的快速翻页
ctrl+f
, 下一页ctrl+b
, 上一页ctrl+d
, 下半页ctrl+u
, 上半页
这四个非常常用,尤其是读代码时,我们不可能按住 j/k
不放去翻代码。
4.11 分栏
:vs
, 创建一个竖向分栏:sp
, 创建一个横向分栏
在创建多个分栏后,怎样在分栏之间移动?总不能用鼠标吧!当然不需要,下面就是移动分栏的方法:
- 先按
ctrl+w
再按h
, 移到左边一个分栏 - 先按
ctrl+w
再按l
, 移到右边一个分栏 - 先按
ctrl+w
再按j
, 移到下边一个分栏 - 先按
ctrl+w
再按k
, 移到上边一个分栏
按下 ctrl+w
后,就进入“移动分栏待决模式”了,这时按 hjkl
就可以移动了。
分栏在屏幕比较大时还是很方便的,有时候写代码时,要看着另一块代码,也很方便。
5. Postface
暂时就想到这些,还有很多比较常用的,想到了再补充。以上这些如果能掌握,基本上在 VSCode-Vim 环境下写代码足够了,等真正用进去了,才会发现有很多不会的或者不方便的点,这时要学会去 Google 或请教别人,只有这样才能不断强化,最终让 Vim 操作变成肌肉记忆。