macOSのJIS半角全角キー
code:fable5.txt
物理キーとしては完全に別物です。両方で動作する理由は、Zed(および macOS)がキーバインドを物理キーの位置ではなく「そのキー操作が生成する文字」で照合するからです。
2つの世界の違い
┌──────────────┬────────────────────────────┬──────────────────────────────────────────────────────────────────────┐
│ 方式 │ 識別単位 │ 採用例 │
├──────────────┼────────────────────────────┼──────────────────────────────────────────────────────────────────────┤
│ 物理キー方式 │ キーの位置(スキャンコード) │ Karabiner-Elements の grave_accent_and_tilde、VS Code の Backquote │ ├──────────────┼────────────────────────────┼──────────────────────────────────────────────────────────────────────┤
│ 文字方式 │ キー操作が生成した文字 │ Zed、macOS のメニューショートカット(key equivalents) │
└──────────────┴────────────────────────────┴──────────────────────────────────────────────────────────────────────┘
grave_accent_and_tilde という名前は、USB HID 規格の Keyboard/Keypad ページ usage 0x35(「Keyboard Grave Accent and Tilde」)に由来する物理キーの識別名です。一方 Zed の "cmd-" は「Cmd を押しながら 文字 が生成される操作」という意味で、どの物理キーかは一切見ていません。
JIS 環境で ` を生成する経路が2つある
経路1: 左上の grave_accent_and_tilde キー
このキーは macOS に仮想キーコード 50(kVK_ANSI_Grave)として届きます。重要なのは、**Apple の JIS キーレイアウト定義テーブルにも keycode 50 = という割り当てが存在する**ことです(JIS ハードウェアに通常このキーが無いだけで、定義は残っています)。そのため PC 用 JIS 配列キーボードの左上キーなど、HID 0x35 を送る物理キーを押すと、JIS 入力ソースでも文字 が生成されます。
経路2: P の右の @ キー(Shift 併用)
JIS レイアウトでこのキーは Shift 付きで を生成します。Zed は記号キーについて「Shift は文字の生成に消費される**」という規則を持ちます — 公式ドキュメントで shift-2 を @ と書くのと同じ規則です。つまり Cmd+Shift+@キー は cmd-shift-@ ではなく **cmd- として解釈されます。
結果として、どちらの物理キーを押しても Zed に届くキーストロークは同一の「cmd + 文字`」になり、同じバインドが発火します。
補足
- Zed はさらに macOS 上で、非 ASCII レイアウト(キリル文字等)向けに「USレイアウトと実レイアウトの両方に対して照合する」仕組みも持っています(ドキュメント曰く "it can always match key-presses against either the ASCII layout or the real layout")。JIS ローマ字入力は ASCII 互換なので今回の主要因ではありませんが、Zed が「1つのバインド = 複数の物理キーで発火」を意図的に許容している設計であることの表れです
- 逆に言うと、Zed には物理キー単位でバインドする構文が存在しないため、「左上の grave キーだけで発火させ、Shift+@ では発火させない」といった区別は Zed 単体では実現できません。それが必要な場合は Karabiner-Elements で物理キー(grave_accent_and_tilde)単位のリマップを挟む形になります
code:karabiner_and_zed
可能です。ただし **Zed 単体では不可能**で、HID レベルで動く外部ツール(Karabiner-Elements 等)を1枚挟む必要があります。
## Zed 単体では不可能な理由
前回説明した通り、両方の経路(物理 grave キー / Shift+@キー)は **Zed に届いた時点で同一のキーストローク「cmd + 文字 」に正規化されており、区別する情報がもう残っていません**。Zed のキーバインド構文には文字と名前付きキー(f1, tab` 等)しかなく、スキャンコードや HID usage を指定する構文が存在しないため、Zed 側でどう書いても両者を分離できません。
## Karabiner-Elements を併用する構成(可能)
Karabiner は HID レベル(usage 0x35 = grave_accent_and_tilde)で動作するため、**レイアウトに関係なく物理キーそのものを識別できる唯一の層**です。原理は:
1. Karabiner で「Cmd + 物理 grave キー」を、**他のどのキー操作でも生成されない一意な中間キー**(例: Cmd+F19)に変換する
2. Zed では cmd-f19 にアクションをバインドする
3. 既存の cmd-` バインドは削除する(残すと Shift+@ 経路が生き続ける)
### Karabiner 側 (complex modification)
`json
{
"description": "Zed: Cmd+物理graveキー → Cmd+F19",
"manipulators": [
{
"type": "basic",
"from": {
"key_code": "grave_accent_and_tilde",
},
"to": "key_code": "f19", "modifiers": "command" }, "conditions": [
{
"type": "frontmost_application_if",
}
]
}
]
}
`
### Zed 側 (keymap.json)
`json
{
"bindings": {
"cmd-f19": "workspace::ActivateNextWindow"
}
}
`
これで:
| 操作 | 結果 |
| --------------------- | --------------------------------------------------------- |
| Cmd + 物理 grave キー | Karabiner が cmd-f19 に変換 → ウィンドウ切り替え発火 ✅ |
| Cmd + Shift + @キー | cmd-` のまま Zed に到達 → バインド無し → 発火しない ❌ |
## 補足
- frontmost_application_if 条件により Zed がフォアグラウンドのときだけ変換されるので、**他アプリの Cmd+`(macOS ネイティブのウィンドウ切り替え等)には影響しません**。全アプリで統一したければ conditions を外します
- 中間キーは f13〜f19 あたりが定番です(物理キーとして存在しないため衝突しない)
- 既存の cmd- バインドを削除すると、エディタ内ではデフォルトの editor::ExpandAllDiffHunks が復活します。それも不要なら "cmd-": null を Editor コンテキストに残します
- Karabiner を使いたくない場合、Hammerspoon でも仮想キーコード番号(grave は 50)を直接指定してホットキーを張れるため、同様の分離が可能です
つまり「物理キーの識別」という仕事を HID 層のツールに任せ、Zed には一意な合図だけを渡す、という役割分担にすれば厳密な Cmd + grave_accent_and_tilde 限定ショートカットを実現できます。