Skip to content

Commit d838294

Browse files
Merge pull request #200 from RtlZeroMemory/guardrails/keybinding-limits
fix(core): add max chord length and duplicate keybinding warnings
2 parents 0d5d127 + a6c2e55 commit d838294

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

packages/core/src/keybindings/manager.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@
88
* @see docs/guide/input-and-focus.md
99
*/
1010

11+
const NODE_ENV =
12+
(globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env?.NODE_ENV ??
13+
"development";
14+
const DEV_MODE = NODE_ENV !== "production";
15+
16+
function warnDev(message: string): void {
17+
if (!DEV_MODE) return;
18+
const c = (globalThis as { console?: { warn?: (msg: string) => void } }).console;
19+
c?.warn?.(message);
20+
}
21+
1122
import type { ZrevEvent } from "../events.js";
1223
import {
1324
CHORD_TIMEOUT_MS,
@@ -187,6 +198,11 @@ function mergeBindingsReplacingSequences<C>(
187198
for (let i = merged.length - 1; i >= 0; i--) {
188199
const current = merged[i];
189200
if (current && keySequencesEqual(current.sequence, next.sequence)) {
201+
if (DEV_MODE) {
202+
warnDev(
203+
`[rezi] keybinding "${sequenceToString(next.sequence)}" registered multiple times, later definition wins`,
204+
);
205+
}
190206
merged.splice(i, 1);
191207
}
192208
}

packages/core/src/keybindings/parser.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import { EMPTY_MODS, KEY_NAME_TO_CODE, MODIFIER_NAMES, charToKeyCode } from "./keyCodes.js";
1717
import type { KeyParseError, KeySequence, Modifiers, ParseKeyResult, ParsedKey } from "./types.js";
1818

19+
const MAX_CHORD_LENGTH = 8;
20+
1921
/**
2022
* Parse a single key part (e.g., "ctrl+s" or just "a").
2123
*
@@ -228,6 +230,16 @@ export function parseKeySequence(input: string): ParseKeyResult {
228230
};
229231
}
230232

233+
if (keys.length > MAX_CHORD_LENGTH) {
234+
return {
235+
ok: false,
236+
error: {
237+
code: "INVALID_KEY",
238+
detail: `chord sequence length ${String(keys.length)} exceeds maximum of ${String(MAX_CHORD_LENGTH)}`,
239+
},
240+
};
241+
}
242+
231243
return {
232244
ok: true,
233245
value: Object.freeze({ keys: Object.freeze(keys) }),

0 commit comments

Comments
 (0)