1import {
2 KeybindingRule as KeybindingRuleSchema,
3 type KeybindingCommand,
4 type KeybindingRule,
5 type ResolvedKeybindingsConfig,
6} from "@t3tools/contracts";
7import * as Schema from "effect/Schema";
8
9export const PROJECT_SCRIPT_KEYBINDING_INVALID_MESSAGE = "Invalid keybinding.";
10
11const decodeKeybindingRule = Schema.decodeUnknownOption(KeybindingRuleSchema);
12
13function normalizeProjectScriptKeybindingInput(
14 keybinding: string | null | undefined,
15): string | null {
16 const trimmed = keybinding?.trim() ?? "";
17 return trimmed.length > 0 ? trimmed : null;
18}
19
20export function decodeProjectScriptKeybindingRule(input: {
21 keybinding: string | null | undefined;
22 command: KeybindingCommand | null;
23}): KeybindingRule | null {
24 const normalizedKey = normalizeProjectScriptKeybindingInput(input.keybinding);
25 if (!normalizedKey) return null;
26
27 if (input.command === null) {
28 throw new Error(PROJECT_SCRIPT_KEYBINDING_INVALID_MESSAGE);
29 }
30
31 const decoded = decodeKeybindingRule({
32 key: normalizedKey,
33 command: input.command,
34 });
35 if (decoded._tag === "None") {
36 throw new Error(PROJECT_SCRIPT_KEYBINDING_INVALID_MESSAGE);
37 }
38 return decoded.value;
39}
40
41export function keybindingValueForCommand(
42 keybindings: ResolvedKeybindingsConfig,
43 command: KeybindingCommand | null,
44): string | null {
45 if (command === null) return null;
46 for (let index = keybindings.length - 1; index >= 0; index -= 1) {
47 const binding = keybindings[index];
48 if (!binding || binding.command !== command) continue;
49
50 const parts: string[] = [];
51 if (binding.shortcut.modKey) parts.push("mod");
52 if (binding.shortcut.ctrlKey) parts.push("ctrl");
53 if (binding.shortcut.metaKey) parts.push("meta");
54 if (binding.shortcut.altKey) parts.push("alt");
55 if (binding.shortcut.shiftKey) parts.push("shift");
56 const keyToken =
57 binding.shortcut.key === " "
58 ? "space"
59 : binding.shortcut.key === "escape"
60 ? "esc"
61 : binding.shortcut.key;
62 parts.push(keyToken);
63 return parts.join("+");
64 }
65 return null;
66}