LoginSignup
10
3

More than 5 years have passed since last update.

VisualStudioCodeのVim系キーバインドExtensionの実装方法

Last updated at Posted at 2018-12-09

ちょっと古い話の読み物です。

Visual Studio Codeは最初から、Vimのキーバインドの実現が計画されていました。

2015年の11月、v0.10にて、Extensionのサポートが開始されました。

Screen Shot 2018-12-08 at 17.45.40.png

リリースと同時にいくつものExtensionがリリースされていることからも分かる通り、InsiderBuild版では既にExtension機能が追加されていました。確かこの時点でも既にExtensionに関するドキュメントがあったような気がします。

この時のVimキーバインドの実装方法は、すべてのキーにキーバインドを設定するというものでした。特にVimは、Ctrl、Cmdキーを使わずに、アルファベットや記号のキーに直接機能を割り振ることになります。私が作っていたVimStyleでは以下のような実装がされていました。

package.json
...
{
    "command": "vim.a",
    "key": "a",
    "mac": "a",
    "when": "editorTextFocus"
},
{
    "command": "vim.b",
    "key": "b",
    "mac": "b",
    "when": "editorTextFocus"
},
...
{
    "command": "vim.A",
    "key": "shift+a",
    "mac": "shift+a",
    "when": "editorTextFocus"
},
{
    "command": "vim.B",
    "key": "shift+b",
    "mac": "shift+b",
    "when": "editorTextFocus"
},
...

この実装方法では、問題がありました。@shift+2とキーバインドが設定されており、JISキーボードでは異なるキーが割り当たります。キーバンドは、すべてUSキーボードとして設定することになっていました。

Screen Shot 2018-12-08 at 18.02.22.png

VSCodeはChromeをベースにしてデスクトップアプリを作成できるElectronを使っています。キーの押下はよくあるonkeydownイベントで拾うことができ、そのイベントのkeyIdentifierというプロパティを使っていました。これを、キーボードのキーの名前に当てはめて、キーバインドを設定するようになっていました。

下記の記事にもある通り、JISキーボードとUSキーボードではkeyIdentifierが異なっていたり、重複していたりします。

Chrome: keyIdentifierとOSとキーレイアウト

私はkeyIdentifierベースでは問題があることがわかり、それをIssueで指摘したりしていました。Ubuntu、Windows、MacOSでkeyIdentifierが異なっていたりして、環境依存の実装を入れる必要があるのではないかと考えていました。

Screen Shot 2018-12-08 at 18.06.41.png

これについて議論している中で、環境依存、キーボード依存のコードを入れるのは避けたいと思われたところで、native-keymapモジュールの利用が提案されました。

native-keymap - npm

Screen Shot 2018-12-08 at 18.25.09.png

この実装により、キーバインドが設定できないことはなくなりましたが、US-keyboardベースでのキーバインドの設定は必要でした。私はJISキーボード向けオプションを用意していました。

この後もVimキーバインドExtensionに不満を持つ人はいて、VSCode本体でのVimキーバインドのサポートが望まれるような状態でした。

この議論のさなか、新たなAPIが実装されました。

Screen Shot 2018-12-08 at 18.46.01.png

このAPIは、VSCodeのすべてのキー押下イベントをExtensionに渡す、というものでした。registerCommandNiceというのは、ExtensionからVSCodeへのaddEventListenerのようなもので、このtypeというイベントをフックすると、args.textにキーの文字が入ります。

let vim Ext = new VimExt();

registerCommandNice('type', function(args) {
  vimExt.type(args.text);
});

この強力なAPIにより、今までのキーバインドの問題は解決しました。

各VimキーバインドExtensionの作成者は、このキーバインドに対応させました。

ちなみに、私の作ったVimStyleは、自分の欲しかった機能は作り終えて、次に要望のあるnmap、nnoremapを実装して(やった)、nmapでVSCodeの機能を呼ぶためにExモードを実装しようとして(途中までやった)、設計が大変になって開発が止まっています。他の開発が盛んなVimプラグインを使いましょう。

おわり。

余談ですが、技術書典3でだした『VSCodeデバッグ技術』という本に、2018年現在に対応させて、RubyやGoogleAppEngineへのデバッグ方法を追加した本を出しました。

vscode-small.jpg

定番コードエディタVSCodeの言語別デバッグ機能解説書! 『Visual Studio Codeデバッグ技術』発行 技術書典シリーズ、12月の新刊 | インプレス R&D

10
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
3