# 初出茅庐：调用 vscode 命令

经过这么多天的练习，相信大家对 vim 已经有了一定的了解；基本的常用命令，也已经不说熟悉也大概明了；作为 vim 章节的最后一节训练，我们会来探讨如何通过 vim 调用 vscode 的命令，以使我们在 vscode 中使用 vim 的过程中减淡操控的割裂感。

:::tip 温馨提醒
本节提到的快捷键映射既为进一步的快捷键拓展，也是为了说明 vim 命令与 vscode 快捷键的如何融汇贯通，大家了解了映射原理后，就可尽情拓展自己的其他需求和场景的快捷键，举一反三才是最好的实践。
:::

## 从需求说起

在日常开发中，我们常常（可能）会有这几个需求：

- 格式化文档
- 重名名变量
- 折叠代码

但是这几个“需求”，严格意义来说本来是不存在的；它们出现只是因为我们用了 vim；在我们还（大量）使用鼠标时，我们可以全选代码，然后右键格式化即可；折叠代码我们之间点行前的加减号就可以完成；或者有一些朋友之前已经很熟练使用这几个功能对应的 vscode 快捷键：

- 格式化文档：`shift` + `alt` + `f` / `shift` + `option` + `f`
- 重命名变量：`f2`
- 折叠代码：`option` + `command` + '['

## 使用 vim 调用 vscode 命令

虽然上面提到的 vscode 自带的快捷键已经可以实现对应的需求，但由于我们现在使用 vim 了，为了让组合按键更舒服，也为了降低记忆快捷键的心智负担，统一键位刻不容缓（夸张手法，其实看个人；你用的舒服其实不改也没有关系）。

我们先打开 vscode 的快捷键配置页面（非 json 文件；在 vscode 界面左下角齿轮按钮选项栏 - 键盘快捷方式或快捷键 `command + k + command + s` 打开），可以通过关键词搜索或组合键录制查找到格式化文档快捷键详细数据，在对应记录右键后选择 [复制命令 ID]（copy command id），这时你复制到的内容其实是 `editor.action.formatDocument`，然后打开 vscode `setting.json`，配置如下内容：

```json
"vim.normalModeKeyBindingsNonRecursive": [
  ...
  {
    "before": ["<Leader>", "f", "d"],
    "commands": ["editor.action.formatDocument"] 
  }
  ...
]
```
这就代表我们把 `<Leader>` + `f` + `d` 映射成调用 vscode 的格式化文档命令 `editor.action.formatDocument`。

同理我们也可以把 `<Leader>` + `[` 映射成折叠代码；但在使用折叠代码的命令时，我们会发现，折叠完代码后，一旦我们把光标往下移动，折叠的代码就又被展开了，这明显是不应当的；这时我们可以利用 vim 的 `$` 和 `%` 命令；即在折叠完后，我们把光标移到行尾所在的花括号（以 JavaScript 为例，即移到行尾的可闭合符号上），再使用 `%` 跳到另一侧的闭合符号，这样就可以避免展开折叠的代码块了。配置如下：

```json
{
  "before": ["<Leader>", "["],
  "commands": [
    {
      "command": "editor.fold",
    },
    {
      "command": "vim.remap",
      "args": {
          "after": ["$", "%"]
      }
    }
  ]
}
```

这样配置后，当我们使用 `<Leader>` + `[` 折叠代码块时，折叠完后光标就在折叠后的代码块的后面了。同样的，重命名变量或其他的功能我们也可以重新映射新的快捷键。

在实际使用场景中，折叠代码的功能还是有许多其他问题，比如上面配置的命令是无法折叠 html 标签的；而 vim 中也有默认的折叠代码的命令（以下对应描述摘自官方文档，自译）：

`zc`：折叠光标所在的可折叠区域，如果前面加数字，则把该区域外的对应层数都折叠起来；
`zC`：把光标所在的可折叠区域及其内部可折叠的内容递归地折叠起来；
`za`：展开或折叠当前可折叠区域，折叠起区域时；
`zA`：递归地展开或折叠当前可折叠区域；

这几个命令也是用于折叠或展开代码，而且它对 html 标签页同样起效，但按起来比较别扭，更重要的是折叠完后还是会遇到那个问题：我们光标一往下走进入被折叠起来的内容时，还是会把折叠起来的内容展开了。官方的建议是可以在 `setting.json` 中添加如下配置：

```json
...
"vim.foldfix": true,
...
```

但配置后会有一定副作用，比如笔者配置后出现使用 `shift` + `j` 和 `shift` + `k` 时光标出现延迟了（这两个组合键配置对应了 `5j` 和 `5k`），具体副作用可以参考官方 [issue](https://github.com/VSCodeVim/Vim/issues/2163)。