VSCode 是微软推出的一款轻量级文本编辑器,主要特点为插件丰富,可自定义程度强。 Vim 是一种常见的编辑模式,受到几乎所有编辑器和 IDE 的支持;在熟悉键位之后有着非常不错的编辑效率。 另外,Vim(或者 Vi)几乎是你在 Linux 服务器环境中唯一可用的编辑器(除了 Nano)。
然而,Vim 对中文环境相当不友好。
在撰写中文文档时,由于 Normal 模式下的快捷键会被输入法所拦截,导致每在 Normal 和 Insert 模式之间切换一次就要开关一次输入法。
此外,大多数 Vim 不支持中文分词,导致原本非常好用的 bnw 这些快捷键会一下跳过整个句子。
幸运的是,VSCode 社区提供了丰富的插件,能够解决大多数问题。 不幸的是,一小部分问题仍然只能通过比较 Hack 的手段解决。
插件配置
这里推荐 VSCodeVim 这个插件,直接在插件窗口中搜索 vim 就可以找到。
这个插件无需配置就可以满足大多数人的使用需求。
如果你想进行更加个性化的配置,可以参考其 Github 仓库中的配置指南。
Jieba 插件提供了中文分词支持。 简单配置即可:
"vim.normalModeKeyBindings": [
{
"before": [
"w"
],
"commands": [
"jieba.forwardWord"
]
},
{
"before": [
"b"
],
"commands": [
"jieba.backwardWord"
]
},
{
"after": [
"i"
],
"before": [
"c",
"w"
],
"commands": [
"jieba.killWord"
]
},
{
"after": [
"i"
],
"before": [
"c",
"b"
],
"commands": [
"jieba.backwardKillWord"
]
},
{
"before": [
"d",
"w"
],
"commands": [
"jieba.killWord"
]
},
{
"before": [
"d",
"b"
],
"commands": [
"jieba.backwardKillWord"
]
}
],
上述配置允许w、b、cw、cb、dw和db在中文环境下正常运行,但W、B、e和E指令不行,原因是 Jieba 插件没有提供相对应的指令。
中文输入法切换
这是最难的部分。 首先,我们必须有让 VSCode 识别当前输入法和自己切换输入法的方式。 如果你正在使用两种输入法(例如,搜狗拼音和英文输入法),那么可以使用 im-select 这个工具。 但是,如果你正在使用同一种输入法中的不同模式(例如,微软拼音的中文模式和英文模式),你就需要一些另外的方法。 这里是一种使用 AutoHotkey 的方法。 但我不想引入第三方软件,所以把它移植到了 C# 上:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
class Program
{
private const int WM_IME_CONTROL = 0x283;
private const int IMC_GETCONVERSIONMODE = 0x1;
private const int IMC_SETCONVERSIONMODE = 0x2;
[DllImport("imm32.dll")]
private static extern IntPtr ImmGetDefaultIMEWnd(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
static void Main(string[] args)
{
IntPtr hIME = ImmGetDefaultIMEWnd(GetForegroundWindow());
if (args.Length > 1)
Console.Error.WriteLine("ImSwitch should not be used with more than one argument.");
else if (args.Length == 0)
Console.WriteLine(SendMessage(hIME, WM_IME_CONTROL, new IntPtr(IMC_GETCONVERSIONMODE), IntPtr.Zero));
else if (args.Length == 1)
SendMessage(hIME, WM_IME_CONTROL, new IntPtr(IMC_SETCONVERSIONMODE), new IntPtr(int.Parse(args[0])));
}
}
注意该方法仅在 Windows 11 上测试过,并不保证对先前版本的 Windows 有效。
关于其中的魔法数值,可以参考 IMC_GETCONVERSIONMODE 和 IMC_SETCONVERSIONMODE。
编译之后,就可以在 VSCodeVim 中配置:
"vim.autoSwitchInputMethod.enable": true,
"vim.autoSwitchInputMethod.defaultIM": "0",
"vim.autoSwitchInputMethod.obtainIMCmd": "D:\\Drivers\\ImSwitch.exe",
"vim.autoSwitchInputMethod.switchIMCmd": "D:\\Drivers\\ImSwitch.exe {im}",
这样就能够在进入 Normal 模式时自动选择英文输入法,它还能够记忆 Insert 模式下的输入法选择。