背景
MacのVSCodeでemacsキーバインドで使いたく、vscode-emacs-friendly を入れていました。しかし Ctrl+F でカーソルが進まず、Mac標準の検索ダイアログが開いてしまいました。
私は普段WindowsでCaps LockをControlに変更しており、Macも同様に CtrlとCommandを入れ替えるために、システム設定 キーボード > キーボードショートカット > 修飾キー を変更していました。
このため、VSCode内ではCtrlをEmacsの修飾キーとして使いたいのに、OSレベルの入れ替えでCommandになってしまうため、VSCodeのemacs拡張のバインドが発火しない、という状況です。
方法
アプローチ
Karabiner-Elements でアプリ別の修飾キー入れ替えを実現します。具体的には「VSCodeとiTerm2では入れ替えない、それ以外では入れ替える」というルールを書きます。
iTerm2 を除外対象に入れているのは、シェル上でもemacs風のキー操作 (Ctrl+A, Ctrl+E, Ctrl+K など) をそのまま使いたいためです。
Karabiner の Complex Modifications 設定
~/.config/karabiner/karabiner.json の complex_modifications.rules に以下を入れます。
{
"description": "iTerm2, VS Code 以外で Control と Command を入れ替える",
"manipulators": [
{
"type": "basic",
"conditions": [
{
"type": "frontmost_application_unless",
"bundle_identifiers": [
"^com\\.googlecode\\.iterm2$",
"^com\\.microsoft\\.VSCode$"
]
}
],
"from": {
"key_code": "left_control",
"modifiers": { "optional": ["any"] }
},
"to": [{ "key_code": "left_command" }]
},
{
"type": "basic",
"conditions": [
{
"type": "frontmost_application_unless",
"bundle_identifiers": [
"^com\\.googlecode\\.iterm2$",
"^com\\.microsoft\\.VSCode$"
]
}
],
"from": {
"key_code": "left_command",
"modifiers": { "optional": ["any"] }
},
"to": [{ "key_code": "left_control" }]
}
]
}
macOSのシステム修飾キー入れ替えは無効化する
私のようにOSの修飾キー入れ替えを行っている場合、Karabiner設定だけでは不十分で、macOSシステム設定側の修飾キー入れ替えを必ずデフォルトに戻す必要があります。
システム設定 > キーボード > キーボードショートカット > 修飾キー… を開いて、内蔵キーボード・外付けキーボードの両方で Control と Command をデフォルト割り当てに戻します。
結果
Karabinerに一本化したことで、キーイベントの流れは以下のようになります。
- 物理 Ctrl キーを押す
- Karabiner: VSCode なので入れ替えない →
left_controlのまま下流に流す - macOS: 入れ替え設定なし → そのまま
- VSCode:
ctrl+fを受け取る → emacs拡張のforwardCharが発火
VSCode・iTerm2 では物理Ctrlが Ctrlとして、物理Cmdが Cmdとして渡り、それ以外のアプリ (Finder、ブラウザなど) では入れ替わって物理Ctrlがコピーなどに使えます。
議論
二重スワップの罠
私が最初にハマったのは、Karabinerを設定したのにVSCodeで Ctrl+F が効かないという状態でした。原因は、システム設定側の入れ替えが ON のままだったことです。
[物理 Ctrl]
↓
[Karabiner] VSCodeなので入れ替えない → left_control
↓
[macOS システム修飾キー設定] 全アプリで Ctrl↔Cmd 入れ替え ON → left_command に変換
↓
[VSCode] cmd+f を受け取る → 検索ダイアログ
Karabinerは macOSのシステム入れ替えより先に効くので、Karabiner側で「入れ替えない」としても、その後段でシステムが再度入れ替えてしまいます。修飾キーの入れ替えは Karabiner かシステム設定のどちらか一方に寄せる、というのが教訓です。
VSCode内でのコピーの挙動
VSCodeを除外対象にしたので、VSCode内ではコピーは Mac標準の Cmd+C になります。Windows風の Ctrl+C でコピーはできなくなりますが、emacsバインドを使う前提なら M-w / C-w がメインになるので実害は小さいです。
右側修飾キーの扱い
現状の設定は left_control / left_command のみ対象です。右手側の Ctrl/Cmd を実際に使う場面があれば、right_control / right_command のペアを同じ条件で追加すれば足ります。