私は普段からMacの操作にEmacsのキーバインディングを利用しています。
せっかくキーバインディングをカスタマイズするなら、エディタはもちろんのこと、ブラウザ操作やメモ帳など、すべてのアプリケーションで同一のキーバインディングを利用できると、コンテキストスイッチがなく快適にアプリケーションの利用に集中できます。
しかし、ある時から(思い当たる節がない)VSCodeだけ意図しないコマンドが実行されてしまいました。
その結果、意図した操作をするために、あろうことか矢印キーを使う羽目になっていました。
どうやらVSCodeのキーバインディングの設定がおかしくなってしまったようです。
今回は、VSCodeのキーバインディングのデバッグ方法を紹介します。
前提
VSCode上での表現を確認します。
- キーバインディング(Key Binding)は、キーの入力の組み合わせ
- コマンド(Command)は、キーバインディングによって実行されるもの
- 条件(Condition)は、キーバインディングによってどのコマンドが実行されるか制御されるもの
まとめると、VSCodeは、キー入力によってキーバインディングを検知すると、条件によってどのコマンドが実行されるかを制御しているということです。
ショートカットによってどのコマンドが実行されているか確認する
まずはログからキー入力によってどのコマンドが実行されているかを確認します。
cmd+shift+p
でコマンドパレットを開き、Developer: Toggle Keyboard Shortcuts Troubleshooting
を選択し、コンソールを開きます。
このコンソールには、キー入力によってどのコマンドが実行されているかがわかるログが表示されています。
下記は、ctrl+n
を入力した時のログです。
コメントと改行を付けて、補足します。
# ctrlのキーダウンのイベントを検知
[2021-12-30 13:34:50.458] [renderer2] [info] [KeybindingService]: / Received keydown event - modifiers: [ctrl], code: ControlLeft, keyCode: 17, key: Control
# ctrlののキーダウンのイベントを変換
[2021-12-30 13:34:50.460] [renderer2] [info] [KeybindingService]: | Converted keydown event - modifiers: [ctrl], code: ControlLeft, keyCode: 5 ('Ctrl')
# キーイベントは送出できない
[2021-12-30 13:34:50.461] [renderer2] [info] [KeybindingService]: \ Keyboard event cannot be dispatched in keydown phase.
# ctrlとnのキーダウンのイベントを検知
[2021-12-30 13:34:50.593] [renderer2] [info] [KeybindingService]: / Received keydown event - modifiers: [ctrl], code: KeyN, keyCode: 78, key: n
# ctrlとnのキーダウンのイベンとを変換
[2021-12-30 13:34:50.594] [renderer2] [info] [KeybindingService]: | Converted keydown event - modifiers: [ctrl], code: KeyN, keyCode: 44 ('N')
# ctrlとnのキーダウンのイベンとを解決
[2021-12-30 13:34:50.595] [renderer2] [info] [KeybindingService]: | Resolving ctrl+[KeyN]
# キーバインディングは 条件 editorTextFocus && !suggestWidgetVisible において emacs.cursorDown のコマンドがマッチした
[2021-12-30 13:34:50.595] [renderer2] [info] [KeybindingService]: \ From 12 keybinding entries, matched emacs.cursorDown, when: editorTextFocus && !suggestWidgetVisible, source: user extension lfs.vscode-emacs-friendly.
# ctrlは他のキーと同時に入力されたため、ctrl単独での入力は無視された
[2021-12-30 13:34:50.811] [renderer2] [info] [KeybindingService]: + Ignoring single modifier ctrl due to it being pressed together with other keys.
実行したいコマンドにショートカットを割り当てる
コマンドパレットからPreferences: Open Keyboard Shortcuts
を開き、キーバインディングとコマンド、条件を設定します。
ここで設定した値は、keybindings.json
に反映され、既存のキーバインディングが上書きされます。
コマンドパレットからPreferences: Open Keyboard Shortcuts(JSON)
を開き、keybindings.json
を開くと、キーバインディングの設定変更が記載されます。
ちなみに私の設定ファイルは下記のとおりです。
# ~/Library/Application Support/Code/User/keybindings.json
// 既定値を上書きするには、このファイル内にキー バインドを挿入します
[
{
"key": "ctrl+alt+p",
"command": "editor.action.moveLinesUpAction",
"when": "editorTextFocus && !editorReadonly"
},
{
"key": "alt+up",
"command": "-editor.action.moveLinesUpAction",
"when": "editorTextFocus && !editorReadonly"
},
{
"key": "ctrl+alt+n",
"command": "editor.action.moveLinesDownAction",
"when": "editorTextFocus && !editorReadonly"
},
{
"key": "alt+down",
"command": "-editor.action.moveLinesDownAction",
"when": "editorTextFocus && !editorReadonly"
},
{
"key": "ctrl+shift+alt+p",
"command": "editor.action.copyLinesUpAction",
"when": "editorTextFocus && !editorReadonly"
},
{
"key": "shift+alt+up",
"command": "-editor.action.copyLinesUpAction",
"when": "editorTextFocus && !editorReadonly"
},
{
"key": "ctrl+shift+alt+n",
"command": "editor.action.copyLinesDownAction",
"when": "editorTextFocus && !editorReadonly"
},
{
"key": "shift+alt+down",
"command": "-editor.action.copyLinesDownAction",
"when": "editorTextFocus && !editorReadonly"
},
{
"key": "ctrl+cmd+p",
"command": "cursorTop",
"when": "textInputFocus"
},
{
"key": "cmd+up",
"command": "-cursorTop",
"when": "textInputFocus"
},
{
"key": "ctrl+cmd+n",
"command": "cursorBottom",
"when": "textInputFocus"
},
{
"key": "cmd+down",
"command": "-cursorBottom",
"when": "textInputFocus"
},
{
"key": "ctrl+shift+cmd+enter",
"command": "workbench.action.terminal.focus"
},
{
"key": "ctrl+shift+n",
"command": "cursorDownSelect",
"when": "textInputFocus"
},
{
"key": "shift+down",
"command": "-cursorDownSelect",
"when": "textInputFocus"
},
{
"key": "ctrl+shift+p",
"command": "cursorUpSelect",
"when": "textInputFocus"
},
{
"key": "shift+up",
"command": "-cursorUpSelect",
"when": "textInputFocus"
},
{
"key": "ctrl+shift+f",
"command": "cursorRightSelect",
"when": "textInputFocus"
},
{
"key": "shift+right",
"command": "-cursorRightSelect",
"when": "textInputFocus"
},
{
"key": "ctrl+shift+b",
"command": "cursorLeftSelect",
"when": "textInputFocus"
},
{
"key": "shift+left",
"command": "-cursorLeftSelect",
"when": "textInputFocus"
},
{
"key": "ctrl+shift+cmd+j",
"command": "workbench.action.search.toggleQueryDetails",
"when": "inSearchEditor || searchViewletFocus"
},
{
"key": "shift+cmd+j",
"command": "-workbench.action.search.toggleQueryDetails",
"when": "inSearchEditor || searchViewletFocus"
},
{
"key": "shift+cmd+j",
"command": "editor.action.revealDefinition",
"when": "editorHasDefinitionProvider && editorTextFocus && !isInEmbeddedEditor"
},
{
"key": "f12",
"command": "-editor.action.revealDefinition",
"when": "editorHasDefinitionProvider && editorTextFocus && !isInEmbeddedEditor"
},
{
"key": "shift+cmd+i",
"command": "workbench.action.navigateBack"
},
{
"key": "ctrl+-",
"command": "-workbench.action.navigateBack"
}
]
Visual Studio Code Key Bindings
補足) ショートカットの設定はSetting Syncでバックアップを
今回紹介したキーバインディングの設定などその他の設定を含め、バックアップをとっておくことをおすすめします。
Settings Syncを利用して、サクッとバックアップしておきましょう。
いざというときに、助かります。
まとめ
Mac上でVSCodeを使いEmacsのキーバインディングを利用する場合、複数のレイヤーでキーバインディングの設定が絡んでおり、ボトルネックを特定するのが難しいと感じました。
具体的には、
- Macのシステム設定のキーボードの設定
- Karabiner Elementsの設定
- VSCodeの設定
がキーバインディングに影響を与えています。
今回は、VSCodeとその他のアプリで挙動が異なる原因がわからなかったため、最終的な出力先であるVSCodeの設定を変更するという力技で対応しました。
PCを利用する以上、買い替えなどによって数年おきに開発環境のセットアップをする必要があるため、次やるときはもう少し効率的に設定できると嬉しいです。