fix(keymap): match letter shortcuts by typed character on AZERTY (#291)

Letter shortcuts were matched by physical key (KeyboardEvent.code), so on AZERTY the key typing z (physical KeyW) dispatched Ctrl+W and closed the tab instead of undoing. Letters are now named by the character typed when Alt is not held; Alt combos keep the physical key since they may type a symbol (macOS Option, AltGr). The terminal's Ctrl+letter control codes use the typed letter too.

Co-authored-by: florentvdry <[email protected]>
Цей коміт міститься в:
Florent Vтаflorentvdry authored and GitHub committed 2026-10-29 22:49:08 +08:00
1 джерело b9cfd54742
коміт 14d7fd0061
4 files changed
+22 -4

No files matched your search

+10
Переглянути файл
@@ -29,6 +29,16 @@ describe("keymap", () => {
expect(formatBinding("Ctrl+NumpadSubtract", false)).toBe("Ctrl+NumPad -");
});
it("names letters by the character typed, so AZERTY's Ctrl+Z is not Ctrl+W", () => {
// AZERTY: the key typing "z" is physically KeyW.
expect(strokeOf({ code: "KeyW", key: "z", metaKey: false, ctrlKey: true, altKey: false, shiftKey: false })).toBe(
"Ctrl+Z",
);
expect(strokeOf({ code: "KeyW", key: "Z", metaKey: false, ctrlKey: true, altKey: false, shiftKey: true })).toBe(
"Ctrl+Shift+Z",
);
});
it("uses physical key codes", () => {
expect(strokeOf({ code: "KeyF", key: "ƒ", metaKey: false, ctrlKey: false, altKey: true, shiftKey: false })).toBe(
"Alt+F",
+4 -1
Переглянути файл
@@ -258,7 +258,10 @@ export function strokeOf(
e: Pick<KeyboardEvent, "code" | "key" | "metaKey" | "ctrlKey" | "altKey" | "shiftKey">,
): string | null {
let key: string | undefined;
if (/^Key[A-Z]$/.test(e.code)) key = e.code.slice(3);
// A letter is named by the character it types: on AZERTY the Z key sits on the physical KeyW,
// so Ctrl+Z must not read as Ctrl+W. Alt combos may type a symbol (⌥ on macOS, AltGr), so they keep the physical key.
if (/^[a-zA-Z]$/.test(e.key) && !e.altKey) key = e.key.toUpperCase();
else if (/^Key[A-Z]$/.test(e.code)) key = e.code.slice(3);
else if (/^Digit\d$/.test(e.code)) key = e.code.slice(5);
else if (/^Numpad\d$/.test(e.code)) key = e.code.slice(6);
else if (/^F\d{1,2}$/.test(e.code)) key = e.code;