mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-08 08:52:12 +00:00
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]>
This commit is contained in:
1 parent
b9cfd54742
commit
14d7fd0061
4 files changed
+22
-4
No files matched your search
@@ -60,9 +60,9 @@ export function terminalKeyAction(e: KeyLike, hasSelection: boolean): TerminalKe
|
||||
if (e.code === "KeyT") return { kind: "pass" };
|
||||
}
|
||||
if (ctrl && !meta && !alt) {
|
||||
// Use the physical key so layouts and Shift don't change the control code.
|
||||
const m = /^Key([A-Z])$/.exec(e.code);
|
||||
if (m) return { kind: "send", data: String.fromCharCode(m[1]!.charCodeAt(0) - 64) };
|
||||
// The letter the key types, so Shift doesn't change the control code and AZERTY's Ctrl+Z is ^Z, not ^W.
|
||||
const letter = /^[a-zA-Z]$/.test(e.key) ? e.key : /^Key([A-Z])$/.exec(e.code)?.[1];
|
||||
if (letter) return { kind: "send", data: String.fromCharCode(letter.toUpperCase().charCodeAt(0) - 64) };
|
||||
if (e.code === "BracketLeft") return { kind: "send", data: "\x1b" };
|
||||
if (e.code === "Backslash") return { kind: "send", data: "\x1c" };
|
||||
if (e.code === "BracketRight") return { kind: "send", data: "\x1d" };
|
||||
|
||||
@@ -128,6 +128,11 @@ describe("terminal keys", () => {
|
||||
kind: "send",
|
||||
data: "\x14",
|
||||
});
|
||||
// AZERTY: the key typing "z" is physically KeyW; Ctrl+Z must send ^Z (SIGTSTP), not ^W.
|
||||
expect(terminalKeyAction(key({ key: "z", code: "KeyW", ctrlKey: true }), false)).toEqual({
|
||||
kind: "send",
|
||||
data: "\x1a",
|
||||
});
|
||||
});
|
||||
|
||||
it("implements macOS conveniences", () => {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user