VSCode+DanceでKakouneのキーバインディングを試す

# 概要

VSCodeで動く[Dance](https://marketplace.visualstudio.com/items?itemName=gregoire.dance)という機能拡張を使って、[Kakoune](https://kakoune.org/)風のキーバインディングを設定する方法のメモです。

# Kakouneとは？

複数選択+操作を基本としたLinux/Unix用のモード付きテキストエディタです。
詳しくは[kakoune wiki](https://github.com/mawww/kakoune/wiki)のOnboardingを参考にしてください。Vimからの移行についても言及があります。
これまで試す機会がなかったのですが、VSCode+Danceの組み合わせでWSLやCygwinのないWindowsでも試そうです。

# Danceとは？

Kakouneからインスピレーションを得た、 Visual Studio Codeのキー バインディング、モード、メニュー、およびスクリプトです。(Google翻訳使用)
DanceはUSキーボード用の設定に(おそらく)なっているので、JISキーボードで使うためには一部のキーバインディングを変更する必要があります。
私はJISキーボードを使っているので、`keybindings.json`でキーバインディングを変更しました。

# 手順

- VSCodeに[Dance](https://marketplace.visualstudio.com/items?itemName=gregoire.dance)を導入する
    - VSCodeVim等、競合しそうな機能拡張があるなら無効化しておく
- JISキーボードを使用している場合、`Ctrl+Shift+P` `open keyboard shortcuts json` 等としてkeybindings.jsonを開いて下記の設定をコピペする
- 同様に `open user settings json` 等としてsettings.jsonを開いて下記の設定をコピペする

```javascript:keybindings.json
// JISキーボード用
/*	*	*/	{   "key":   "shift+8",               "command":   "-dance.search.selection.smart",                 "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	*	*/	{   "key":   "shift+oem_1",           "command":   "dance.search.selection.smart",                  "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	*	*/	{   "key":   "shift+alt+8",           "command":   "-dance.search.selection",                       "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	*	*/	{   "key":   "shift+alt+oem_1",       "command":   "dance.search.selection",                        "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	(	*/	{   "key":   "shift+9",               "command":   "-dance.selections.rotate.both",                 "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	(	*/	{   "key":   "shift+alt+9",           "command":   "-dance.selections.rotate.selections",           "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	(	*/	{   "key":   "shift+8",               "command":   "dance.selections.rotate.both",                  "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	(	*/	{   "key":   "shift+alt+8",           "command":   "dance.selections.rotate.selections",            "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	)	*/	{   "key":   "shift+0",               "command":   "-dance.selections.rotate.both.reverse",         "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	)	*/	{   "key":   "shift+alt+0",           "command":   "-dance.selections.rotate.selections.reverse",   "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	)	*/	{   "key":   "shift+9",               "command":   "dance.selections.rotate.both.reverse",          "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	)	*/	{   "key":   "shift+alt+9",           "command":   "dance.selections.rotate.selections.reverse",    "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	&	*/	{   "key":   "shift+7",               "command":   "-dance.edit.align",                             "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	&	*/	{   "key":   "shift+alt+7",           "command":   "-dance.edit.copyIndentation",                   "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	&	*/	{   "key":   "shift+6",               "command":   "dance.edit.align",                              "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	&	*/	{   "key":   "shift+alt+6",           "command":   "dance.edit.copyIndentation",                    "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	_	*/	{   "key":   "shift+oem_minus",       "command":   "-dance.selections.trimWhitespace",              "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	_	*/	{   "key":   "shift+alt+oem_minus",   "command":   "-dance.selections.merge",                       "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	_	*/	{   "key":   "shift+oem_102",         "command":   "dance.selections.trimWhitespace",               "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	_	*/	{   "key":   "shift+alt+oem_102",     "command":   "dance.selections.merge",                        "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	*	*/	{   "key":   "shift+oem_1",           "command":   "-workbench.action.showCommands",                "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	;	*/	{   "key":   "shift+alt+oem_1",       "command":   "-dance.selections.faceForward",                 "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	;	*/	{   "key":   "alt+oem_plus",          "command":   "dance.selections.faceForward",                  "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	@	*/	{   "key":   "oem_3",                 "command":   "-dance.edit.case.toLower",                      "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	@	*/	{   "key":   "alt+oem_3",             "command":   "-dance.edit.case.swap",                         "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	`	*/	{   "key":   "shift+oem_3",           "command":   "-dance.edit.case.toUpper",                      "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	`	*/	{   "key":   "shift+oem_3",           "command":   "dance.edit.case.toLower",                       "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	~	*/	{   "key":   "shift+oem_7",           "command":   "dance.edit.case.toUpper",                       "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	`	*/	{   "key":   "shift+alt+oem_3",       "command":   "dance.edit.case.swap",                          "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	~	*/	{   "key":   "shift+oem_7",           "command":   "-dance.selectRegister",                         "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	"	*/	{   "key":   "shift+2",               "command":   "dance.selectRegister",                          "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	\	*/	{   "key":   "oem_5",                 "command":   "dance.ignore",                                  "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	@	*/	{   "key":   "oem_3",                 "command":   "dance.ignore",                                  "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	=  	*/	{   "key":   "shift+oem_minus",       "command":   "dance.ignore",                                  "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*	' 	*/	{   "key":   "shift+7",               "command":   "dance.ignore",                                  "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*      */	{   "key":   "backspace",             "command":   "dance.ignore",                                  "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*  :   */  {   "key":   "oem_1",                 "command":   "dance.ignore",                                  "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*  :   */  {   "key":   "oem_1",                 "command":   "-dance.selections.reduce",                      "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*  :   */  {   "key":   "alt+oem_1",             "command":   "-dance.selections.changeDirection",             "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*  ;   */  {   "key":   "oem_plus",              "command":   "dance.selections.reduce",                       "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*  ;   */  {   "key":   "alt+oem_plus",          "command":   "dance.selections.changeDirection",              "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*  Y   */  {   "key":   "shift+y",/*leap.nvim*/  "command":   "dance.seek.leap",                               "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },
/*  Y   */  {   "key":   "shift+alt+y",           "command":   "dance.seek.leap.backward",                      "when":   "editorTextFocus    &&   dance.mode   ==   'normal'"   },

/*		*/ // @(oem_3)はexpand tabs、\(oem_5)はdisable hooksだがdanceに機能がない

```

```javascript:settings.json
    "dance.systemClipboardRegister": "*", // 無名レジスタでクリップボードを使わない
    "dance.modes": {
        "insert": {},
        "normal": {
            "cursorStyle": "block", // これがないとnormal-insertの違いが分かりにくい
            "selectionBehavior": "character", // よりkakouneに近づける dやxの使用感が変わる
        }
    },
```

# 注意

- 常用できていないので設定に多分ミスがあります。気付いたら(追記などの表記なしで)サイレントに直します。
- shift+y、shift+alt+yにdanceのleap.nvim相当の機能(sneak風の2打移動)を割り当ててありますが、kakoune本来の機能・割り当てではありません。
    - 個人的にはfindthenjumpをeasymotion代わりに使用しています。

```javascript:keybindings.json
    // == easymotion代わりのfindthenjump機能拡張 ==
    { "key": "ctrl+oem_plus", "command": "-workbench.action.zoomIn" },
    { "key": "ctrl+shift+oem_plus", "command": "-workbench.action.zoomIn" },
    { "key": "ctrl+oem_plus", "command": "findThenJump.initiate" },
    { "key": "ctrl+shift+oem_plus", "command": "findThenJump.initiateWithSelection" },
```