{"version":3,"file":"keybinding-hints.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/keybinding-hints.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAkB,KAAK,UAAU,EAA0B,MAAM,0BAA0B,CAAC;AACnG,OAAO,EAAE,KAAK,aAAa,EAAe,MAAM,8BAA8B,CAAC;AAG/E,MAAM,WAAW,oBAAoB;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAOD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,MAAM,CAgBrF;AAOD,wBAAgB,OAAO,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAEtD;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAE7D;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAG9D;AAED,wBAAgB,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAE3E;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAEnE;AAQD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,aAAa,GAAG,OAAO,CAItE;AAED,qEAAqE;AACrE,wBAAgB,WAAW,CAAC,EAAE,EAAE,aAAa,GAAG,MAAM,CAKrD","sourcesContent":["/**\n * Utilities for formatting keybinding hints in the UI.\n */\n\nimport { getKeybindings, type Keybinding, type KeyId, matchesKey } from \"@kolisachint/hoocode-tui\";\nimport { type AppKeybinding, KEYBINDINGS } from \"../../../core/keybindings.js\";\nimport { theme } from \"../theme/theme.js\";\n\nexport interface KeyTextFormatOptions {\n\tcapitalize?: boolean;\n}\n\nfunction formatKeyPart(part: string, options: KeyTextFormatOptions): string {\n\tconst displayPart = process.platform === \"darwin\" && part.toLowerCase() === \"alt\" ? \"option\" : part;\n\treturn options.capitalize ? displayPart.charAt(0).toUpperCase() + displayPart.slice(1) : displayPart;\n}\n\nexport function formatKeyText(key: string, options: KeyTextFormatOptions = {}): string {\n\treturn key\n\t\t.split(\"/\")\n\t\t.map((k) => {\n\t\t\tconst parts = k.split(\"+\");\n\t\t\t// A modifier-less single character is printed exactly as it is typed.\n\t\t\t// Capitalising it would name a different key: in this map an uppercase\n\t\t\t// letter *is* shift+letter, and a bare `shift+<letter>` is banned\n\t\t\t// outright because a legacy terminal cannot tell it from typing. So a\n\t\t\t// hint reading \"N\" for a binding on `n` documents a chord that does not\n\t\t\t// exist. Inside a chord the letter is unambiguous — nobody reads\n\t\t\t// \"Ctrl+C\" as ctrl+shift+c — so that keeps its capital.\n\t\t\tif (parts.length === 1 && parts[0].length === 1) return parts[0];\n\t\t\treturn parts.map((part) => formatKeyPart(part, options)).join(\"+\");\n\t\t})\n\t\t.join(\"/\");\n}\n\nfunction formatKeys(keys: KeyId[], options: KeyTextFormatOptions = {}): string {\n\tif (keys.length === 0) return \"\";\n\treturn formatKeyText(keys.join(\"/\"), options);\n}\n\nexport function keyText(keybinding: Keybinding): string {\n\treturn formatKeys(getKeybindings().getKeys(keybinding));\n}\n\nexport function keyDisplayText(keybinding: Keybinding): string {\n\treturn formatKeys(getKeybindings().getKeys(keybinding), { capitalize: true });\n}\n\n/**\n * The taught key for a binding — the first one — and nothing else.\n *\n * `keyDisplayText` names every key an action answers to, which is right for a\n * reference row and wrong wherever the shape of the hint is the thing being\n * taught: the dials read `alt+t/shift+alt+t`, and a second forward key spliced\n * into the middle of that is what the one-shape rule exists to avoid.\n */\nexport function keyDisplayLabel(keybinding: Keybinding): string {\n\tconst keys = getKeybindings().getKeys(keybinding);\n\treturn keys.length > 0 ? formatKeyText(keys[0] as string, { capitalize: true }) : \"\";\n}\n\nexport function keyHint(keybinding: Keybinding, description: string): string {\n\treturn theme.fg(\"dim\", keyText(keybinding)) + theme.fg(\"muted\", ` ${description}`);\n}\n\nexport function rawKeyHint(key: string, description: string): string {\n\treturn theme.fg(\"dim\", formatKeyText(key)) + theme.fg(\"muted\", ` ${description}`);\n}\n\n/** Default keys of an app-level binding, from its definition. */\nfunction appDefaultKeys(id: AppKeybinding): KeyId[] {\n\tconst defaults = KEYBINDINGS[id].defaultKeys;\n\treturn Array.isArray(defaults) ? defaults : [defaults];\n}\n\n/**\n * Match input against an app-level keybinding. The global manager is the\n * app-aware one in normal runs (user overrides apply); when it is the bare TUI\n * default (tests, early boot) the app definition's default keys are used so\n * the component never goes dead.\n */\nexport function matchesAppKey(data: string, id: AppKeybinding): boolean {\n\tconst keybindings = getKeybindings();\n\tif (keybindings.getDefinition(id)) return keybindings.matches(data, id);\n\treturn appDefaultKeys(id).some((key) => matchesKey(data, key));\n}\n\n/** First configured key for an app-level binding, for hint lines. */\nexport function appKeyLabel(id: AppKeybinding): string {\n\tconst keybindings = getKeybindings();\n\tconst keys = keybindings.getDefinition(id) ? keybindings.getKeys(id) : undefined;\n\tif (keys && keys.length > 0) return keys[0] as string;\n\treturn (appDefaultKeys(id)[0] ?? \"\") as string;\n}\n"]}