orient-cli 0.3.3 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/orient/orient-extension.js +71 -2
- package/dist/orient/orient-extension.js.map +1 -1
- package/dist/orient/phase-context.d.ts +17 -0
- package/dist/orient/phase-context.js +88 -0
- package/dist/orient/phase-context.js.map +1 -0
- package/docs/configuration.md +24 -9
- package/package.json +1 -1
- package/vendor/@orient-cli/agent-core/README.md +456 -0
- package/vendor/@orient-cli/agent-core/dist/agent-loop.d.ts.map +1 -1
- package/vendor/@orient-cli/agent-core/dist/agent-loop.js.map +1 -1
- package/vendor/@orient-cli/agent-core/dist/agent.d.ts +7 -0
- package/vendor/@orient-cli/agent-core/dist/agent.d.ts.map +1 -1
- package/vendor/@orient-cli/agent-core/dist/agent.js +2 -24
- package/vendor/@orient-cli/agent-core/dist/agent.js.map +1 -1
- package/vendor/@orient-cli/agent-core/dist/index.d.ts.map +1 -1
- package/vendor/@orient-cli/agent-core/dist/proxy.d.ts.map +1 -1
- package/vendor/@orient-cli/agent-core/dist/proxy.js.map +1 -1
- package/vendor/@orient-cli/agent-core/dist/types.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/README.md +1315 -0
- package/vendor/@orient-cli/ai/dist/api-registry.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/api-registry.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/bedrock-provider.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/cli.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/cli.js +0 -0
- package/vendor/@orient-cli/ai/dist/cli.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/env-api-keys.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/env-api-keys.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/index.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/models.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/models.generated.d.ts +488 -488
- package/vendor/@orient-cli/ai/dist/models.generated.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/models.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/oauth.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/amazon-bedrock.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/amazon-bedrock.js +1 -1
- package/vendor/@orient-cli/ai/dist/providers/amazon-bedrock.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/anthropic.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/anthropic.js +1 -1
- package/vendor/@orient-cli/ai/dist/providers/anthropic.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/azure-openai-responses.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/faux.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/faux.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/github-copilot-headers.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/github-copilot-headers.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/google-gemini-cli.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/google-shared.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/google-shared.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/google-vertex.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/google-vertex.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/google.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/google.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/mistral.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/mistral.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/openai-completions.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/openai-responses-shared.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/openai-responses.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/openai-responses.js +1 -1
- package/vendor/@orient-cli/ai/dist/providers/openai-responses.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/register-builtins.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/register-builtins.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/simple-options.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/simple-options.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/transform-messages.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/providers/transform-messages.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/stream.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/stream.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/types.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/event-stream.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/event-stream.js +3 -7
- package/vendor/@orient-cli/ai/dist/utils/event-stream.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/hash.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/hash.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/json-parse.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/json-parse.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/oauth/anthropic.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/oauth/anthropic.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/oauth/google-antigravity.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/oauth/google-antigravity.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/oauth/google-gemini-cli.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/oauth/google-gemini-cli.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/oauth/index.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/oauth/index.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/oauth/oauth-page.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/oauth/oauth-page.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/oauth/openai-codex.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/oauth/openai-codex.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/oauth/pkce.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/oauth/pkce.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/oauth/types.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/overflow.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/overflow.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/sanitize-unicode.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/sanitize-unicode.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/typebox-helpers.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/typebox-helpers.js.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/validation.d.ts.map +1 -1
- package/vendor/@orient-cli/ai/dist/utils/validation.js.map +1 -1
- package/vendor/@orient-cli/coding-agent/dist/bun/cli.js +1 -1
- package/vendor/@orient-cli/coding-agent/dist/bun/cli.js.map +1 -1
- package/vendor/@orient-cli/coding-agent/dist/cli.js +2 -1
- package/vendor/@orient-cli/coding-agent/dist/cli.js.map +1 -1
- package/vendor/@orient-cli/coding-agent/dist/config.d.ts.map +1 -1
- package/vendor/@orient-cli/coding-agent/dist/config.js +4 -2
- package/vendor/@orient-cli/coding-agent/dist/config.js.map +1 -1
- package/vendor/@orient-cli/coding-agent/dist/core/package-manager.js +1 -1
- package/vendor/@orient-cli/coding-agent/dist/core/package-manager.js.map +1 -1
- package/vendor/@orient-cli/coding-agent/dist/core/settings-manager.js +2 -2
- package/vendor/@orient-cli/coding-agent/dist/core/settings-manager.js.map +1 -1
- package/vendor/@orient-cli/coding-agent/dist/core/timings.d.ts +1 -1
- package/vendor/@orient-cli/coding-agent/dist/core/timings.js +2 -2
- package/vendor/@orient-cli/coding-agent/dist/core/timings.js.map +1 -1
- package/vendor/@orient-cli/coding-agent/dist/main.d.ts.map +1 -1
- package/vendor/@orient-cli/coding-agent/dist/main.js +4 -2
- package/vendor/@orient-cli/coding-agent/dist/main.js.map +1 -1
- package/vendor/@orient-cli/coding-agent/dist/modes/interactive/interactive-mode.js +2 -2
- package/vendor/@orient-cli/coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/vendor/@orient-cli/coding-agent/dist/utils/tools-manager.js +1 -1
- package/vendor/@orient-cli/coding-agent/dist/utils/tools-manager.js.map +1 -1
- package/vendor/@orient-cli/tui/README.md +767 -0
- package/vendor/@orient-cli/tui/dist/autocomplete.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/autocomplete.js +0 -3
- package/vendor/@orient-cli/tui/dist/autocomplete.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/box.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/box.js +1 -6
- package/vendor/@orient-cli/tui/dist/components/box.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/cancellable-loader.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/cancellable-loader.js +4 -3
- package/vendor/@orient-cli/tui/dist/components/cancellable-loader.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/editor.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/editor.js +37 -48
- package/vendor/@orient-cli/tui/dist/components/editor.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/image.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/image.js +0 -8
- package/vendor/@orient-cli/tui/dist/components/image.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/input.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/input.js +14 -14
- package/vendor/@orient-cli/tui/dist/components/input.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/loader.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/loader.js +4 -7
- package/vendor/@orient-cli/tui/dist/components/loader.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/markdown.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/markdown.js +0 -10
- package/vendor/@orient-cli/tui/dist/components/markdown.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/select-list.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/select-list.js +4 -9
- package/vendor/@orient-cli/tui/dist/components/select-list.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/settings-list.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/settings-list.js +4 -12
- package/vendor/@orient-cli/tui/dist/components/settings-list.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/spacer.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/spacer.js +0 -1
- package/vendor/@orient-cli/tui/dist/components/spacer.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/text.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/text.js +0 -8
- package/vendor/@orient-cli/tui/dist/components/text.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/truncated-text.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/components/truncated-text.js +0 -3
- package/vendor/@orient-cli/tui/dist/components/truncated-text.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/editor-component.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/fuzzy.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/fuzzy.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/index.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/keybindings.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/keybindings.js +2 -4
- package/vendor/@orient-cli/tui/dist/keybindings.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/keys.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/keys.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/kill-ring.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/kill-ring.js +3 -1
- package/vendor/@orient-cli/tui/dist/kill-ring.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/stdin-buffer.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/stdin-buffer.js +4 -5
- package/vendor/@orient-cli/tui/dist/stdin-buffer.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/terminal-image.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/terminal-image.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/terminal.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/terminal.js +20 -22
- package/vendor/@orient-cli/tui/dist/terminal.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/tui.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/tui.js +25 -27
- package/vendor/@orient-cli/tui/dist/tui.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/undo-stack.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/undo-stack.js +3 -1
- package/vendor/@orient-cli/tui/dist/undo-stack.js.map +1 -1
- package/vendor/@orient-cli/tui/dist/utils.d.ts.map +1 -1
- package/vendor/@orient-cli/tui/dist/utils.js +13 -11
- package/vendor/@orient-cli/tui/dist/utils.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/components/text.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpF;;GAEG;AACH,MAAM,OAAO,IAAI;
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/components/text.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Component } from \"../tui.js\";\nimport { applyBackgroundToLine, visibleWidth, wrapTextWithAnsi } from \"../utils.js\";\n\n/**\n * Text component - displays multi-line text with word wrapping\n */\nexport class Text implements Component {\n\tprivate text: string;\n\tprivate paddingX: number; // Left/right padding\n\tprivate paddingY: number; // Top/bottom padding\n\tprivate customBgFn?: (text: string) => string;\n\n\t// Cache for rendered output\n\tprivate cachedText?: string;\n\tprivate cachedWidth?: number;\n\tprivate cachedLines?: string[];\n\n\tconstructor(text: string = \"\", paddingX: number = 1, paddingY: number = 1, customBgFn?: (text: string) => string) {\n\t\tthis.text = text;\n\t\tthis.paddingX = paddingX;\n\t\tthis.paddingY = paddingY;\n\t\tthis.customBgFn = customBgFn;\n\t}\n\n\tsetText(text: string): void {\n\t\tthis.text = text;\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\tsetCustomBgFn(customBgFn?: (text: string) => string): void {\n\t\tthis.customBgFn = customBgFn;\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\tinvalidate(): void {\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\t// Check cache\n\t\tif (this.cachedLines && this.cachedText === this.text && this.cachedWidth === width) {\n\t\t\treturn this.cachedLines;\n\t\t}\n\n\t\t// Don't render anything if there's no actual text\n\t\tif (!this.text || this.text.trim() === \"\") {\n\t\t\tconst result: string[] = [];\n\t\t\tthis.cachedText = this.text;\n\t\t\tthis.cachedWidth = width;\n\t\t\tthis.cachedLines = result;\n\t\t\treturn result;\n\t\t}\n\n\t\t// Replace tabs with 3 spaces\n\t\tconst normalizedText = this.text.replace(/\\t/g, \" \");\n\n\t\t// Calculate content width (subtract left/right margins)\n\t\tconst contentWidth = Math.max(1, width - this.paddingX * 2);\n\n\t\t// Wrap text (this preserves ANSI codes but does NOT pad)\n\t\tconst wrappedLines = wrapTextWithAnsi(normalizedText, contentWidth);\n\n\t\t// Add margins and background to each line\n\t\tconst leftMargin = \" \".repeat(this.paddingX);\n\t\tconst rightMargin = \" \".repeat(this.paddingX);\n\t\tconst contentLines: string[] = [];\n\n\t\tfor (const line of wrappedLines) {\n\t\t\t// Add margins\n\t\t\tconst lineWithMargins = leftMargin + line + rightMargin;\n\n\t\t\t// Apply background if specified (this also pads to full width)\n\t\t\tif (this.customBgFn) {\n\t\t\t\tcontentLines.push(applyBackgroundToLine(lineWithMargins, width, this.customBgFn));\n\t\t\t} else {\n\t\t\t\t// No background - just pad to width with spaces\n\t\t\t\tconst visibleLen = visibleWidth(lineWithMargins);\n\t\t\t\tconst paddingNeeded = Math.max(0, width - visibleLen);\n\t\t\t\tcontentLines.push(lineWithMargins + \" \".repeat(paddingNeeded));\n\t\t\t}\n\t\t}\n\n\t\t// Add top/bottom padding (empty lines)\n\t\tconst emptyLine = \" \".repeat(width);\n\t\tconst emptyLines: string[] = [];\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tconst line = this.customBgFn ? applyBackgroundToLine(emptyLine, width, this.customBgFn) : emptyLine;\n\t\t\temptyLines.push(line);\n\t\t}\n\n\t\tconst result = [...emptyLines, ...contentLines, ...emptyLines];\n\n\t\t// Update cache\n\t\tthis.cachedText = this.text;\n\t\tthis.cachedWidth = width;\n\t\tthis.cachedLines = result;\n\n\t\treturn result.length > 0 ? result : [\"\"];\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"truncated-text.d.ts","sourceRoot":"","sources":["../../src/components/truncated-text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C;;GAEG;AACH,qBAAa,aAAc,YAAW,SAAS;IAC9C,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;
|
|
1
|
+
{"version":3,"file":"truncated-text.d.ts","sourceRoot":"","sources":["../../src/components/truncated-text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C;;GAEG;AACH,qBAAa,aAAc,YAAW,SAAS;IAC9C,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;gBAEb,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAU,EAAE,QAAQ,GAAE,MAAU;IAMpE,UAAU,IAAI,IAAI;IAIlB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CA2C/B"}
|
|
@@ -3,9 +3,6 @@ import { truncateToWidth, visibleWidth } from "../utils.js";
|
|
|
3
3
|
* Text component that truncates to fit viewport width
|
|
4
4
|
*/
|
|
5
5
|
export class TruncatedText {
|
|
6
|
-
text;
|
|
7
|
-
paddingX;
|
|
8
|
-
paddingY;
|
|
9
6
|
constructor(text, paddingX = 0, paddingY = 0) {
|
|
10
7
|
this.text = text;
|
|
11
8
|
this.paddingX = paddingX;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"truncated-text.js","sourceRoot":"","sources":["../../src/components/truncated-text.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE5D;;GAEG;AACH,MAAM,OAAO,aAAa;
|
|
1
|
+
{"version":3,"file":"truncated-text.js","sourceRoot":"","sources":["../../src/components/truncated-text.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE5D;;GAEG;AACH,MAAM,OAAO,aAAa;IAKzB,YAAY,IAAY,EAAE,WAAmB,CAAC,EAAE,WAAmB,CAAC;QACnE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;IAED,UAAU;QACT,0CAA0C;IAC3C,CAAC;IAED,MAAM,CAAC,KAAa;QACnB,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,6BAA6B;QAC7B,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAEpC,6BAA6B;QAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC;QAED,qDAAqD;QACrD,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;QAE9D,6CAA6C;QAC7C,IAAI,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC;QAC/B,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,YAAY,KAAK,CAAC,CAAC,EAAE,CAAC;YACzB,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;QACvD,CAAC;QAED,sDAAsD;QACtD,MAAM,WAAW,GAAG,eAAe,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;QAEpE,yBAAyB;QACzB,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/C,MAAM,eAAe,GAAG,WAAW,GAAG,WAAW,GAAG,YAAY,CAAC;QAEjE,uCAAuC;QACvC,MAAM,gBAAgB,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;QACvD,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,gBAAgB,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,eAAe,GAAG,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAE9D,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAEvB,6BAA6B;QAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC;QAED,OAAO,MAAM,CAAC;IACf,CAAC;CACD","sourcesContent":["import type { Component } from \"../tui.js\";\nimport { truncateToWidth, visibleWidth } from \"../utils.js\";\n\n/**\n * Text component that truncates to fit viewport width\n */\nexport class TruncatedText implements Component {\n\tprivate text: string;\n\tprivate paddingX: number;\n\tprivate paddingY: number;\n\n\tconstructor(text: string, paddingX: number = 0, paddingY: number = 0) {\n\t\tthis.text = text;\n\t\tthis.paddingX = paddingX;\n\t\tthis.paddingY = paddingY;\n\t}\n\n\tinvalidate(): void {\n\t\t// No cached state to invalidate currently\n\t}\n\n\trender(width: number): string[] {\n\t\tconst result: string[] = [];\n\n\t\t// Empty line padded to width\n\t\tconst emptyLine = \" \".repeat(width);\n\n\t\t// Add vertical padding above\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tresult.push(emptyLine);\n\t\t}\n\n\t\t// Calculate available width after horizontal padding\n\t\tconst availableWidth = Math.max(1, width - this.paddingX * 2);\n\n\t\t// Take only the first line (stop at newline)\n\t\tlet singleLineText = this.text;\n\t\tconst newlineIndex = this.text.indexOf(\"\\n\");\n\t\tif (newlineIndex !== -1) {\n\t\t\tsingleLineText = this.text.substring(0, newlineIndex);\n\t\t}\n\n\t\t// Truncate text if needed (accounting for ANSI codes)\n\t\tconst displayText = truncateToWidth(singleLineText, availableWidth);\n\n\t\t// Add horizontal padding\n\t\tconst leftPadding = \" \".repeat(this.paddingX);\n\t\tconst rightPadding = \" \".repeat(this.paddingX);\n\t\tconst lineWithPadding = leftPadding + displayText + rightPadding;\n\n\t\t// Pad line to exactly width characters\n\t\tconst lineVisibleWidth = visibleWidth(lineWithPadding);\n\t\tconst paddingNeeded = Math.max(0, width - lineVisibleWidth);\n\t\tconst finalLine = lineWithPadding + \" \".repeat(paddingNeeded);\n\n\t\tresult.push(finalLine);\n\n\t\t// Add vertical padding below\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tresult.push(emptyLine);\n\t\t}\n\n\t\treturn result;\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor-component.d.ts","sourceRoot":"","sources":["../src/editor-component.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C;;;;;;GAMG;AACH,MAAM,WAAW,eAAgB,SAAQ,SAAS;IAKjD,mCAAmC;IACnC,OAAO,IAAI,MAAM,CAAC;IAElB,2BAA2B;IAC3B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5B,qEAAqE;IACrE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAMhC,iDAAiD;IACjD,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAMlC,iDAAiD;IACjD,YAAY,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAMlC,6CAA6C;IAC7C,kBAAkB,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAExC;;;OAGG;IACH,eAAe,CAAC,IAAI,MAAM,CAAC;IAM3B,oCAAoC;IACpC,uBAAuB,CAAC,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAM/D,4BAA4B;IAC5B,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAEtC,6BAA6B;IAC7B,WAAW,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpC,qDAAqD;IACrD,yBAAyB,CAAC,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACrD"
|
|
1
|
+
{"version":3,"file":"editor-component.d.ts","sourceRoot":"","sources":["../src/editor-component.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C;;;;;;GAMG;AACH,MAAM,WAAW,eAAgB,SAAQ,SAAS;IAKjD,mCAAmC;IACnC,OAAO,IAAI,MAAM,CAAC;IAElB,2BAA2B;IAC3B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5B,qEAAqE;IACrE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAMhC,iDAAiD;IACjD,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAMlC,iDAAiD;IACjD,YAAY,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAMlC,6CAA6C;IAC7C,kBAAkB,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAExC;;;OAGG;IACH,eAAe,CAAC,IAAI,MAAM,CAAC;IAM3B,oCAAoC;IACpC,uBAAuB,CAAC,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAM/D,4BAA4B;IAC5B,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAEtC,6BAA6B;IAC7B,WAAW,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpC,qDAAqD;IACrD,yBAAyB,CAAC,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACrD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fuzzy.d.ts","sourceRoot":"","sources":["../src/fuzzy.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,UAAU;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,CA6ElE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAAG,CAAC,EAAE,CAsC3F"
|
|
1
|
+
{"version":3,"file":"fuzzy.d.ts","sourceRoot":"","sources":["../src/fuzzy.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,UAAU;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,CA6ElE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAAG,CAAC,EAAE,CAsC3F"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fuzzy.js","sourceRoot":"","sources":["../src/fuzzy.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,IAAY
|
|
1
|
+
{"version":3,"file":"fuzzy.js","sourceRoot":"","sources":["../src/fuzzy.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Fuzzy matching utilities.\n * Matches if all query characters appear in order (not necessarily consecutive).\n * Lower score = better match.\n */\n\nexport interface FuzzyMatch {\n\tmatches: boolean;\n\tscore: number;\n}\n\nexport function fuzzyMatch(query: string, text: string): FuzzyMatch {\n\tconst queryLower = query.toLowerCase();\n\tconst textLower = text.toLowerCase();\n\n\tconst matchQuery = (normalizedQuery: string): FuzzyMatch => {\n\t\tif (normalizedQuery.length === 0) {\n\t\t\treturn { matches: true, score: 0 };\n\t\t}\n\n\t\tif (normalizedQuery.length > textLower.length) {\n\t\t\treturn { matches: false, score: 0 };\n\t\t}\n\n\t\tlet queryIndex = 0;\n\t\tlet score = 0;\n\t\tlet lastMatchIndex = -1;\n\t\tlet consecutiveMatches = 0;\n\n\t\tfor (let i = 0; i < textLower.length && queryIndex < normalizedQuery.length; i++) {\n\t\t\tif (textLower[i] === normalizedQuery[queryIndex]) {\n\t\t\t\tconst isWordBoundary = i === 0 || /[\\s\\-_./:]/.test(textLower[i - 1]!);\n\n\t\t\t\t// Reward consecutive matches\n\t\t\t\tif (lastMatchIndex === i - 1) {\n\t\t\t\t\tconsecutiveMatches++;\n\t\t\t\t\tscore -= consecutiveMatches * 5;\n\t\t\t\t} else {\n\t\t\t\t\tconsecutiveMatches = 0;\n\t\t\t\t\t// Penalize gaps\n\t\t\t\t\tif (lastMatchIndex >= 0) {\n\t\t\t\t\t\tscore += (i - lastMatchIndex - 1) * 2;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Reward word boundary matches\n\t\t\t\tif (isWordBoundary) {\n\t\t\t\t\tscore -= 10;\n\t\t\t\t}\n\n\t\t\t\t// Slight penalty for later matches\n\t\t\t\tscore += i * 0.1;\n\n\t\t\t\tlastMatchIndex = i;\n\t\t\t\tqueryIndex++;\n\t\t\t}\n\t\t}\n\n\t\tif (queryIndex < normalizedQuery.length) {\n\t\t\treturn { matches: false, score: 0 };\n\t\t}\n\n\t\treturn { matches: true, score };\n\t};\n\n\tconst primaryMatch = matchQuery(queryLower);\n\tif (primaryMatch.matches) {\n\t\treturn primaryMatch;\n\t}\n\n\tconst alphaNumericMatch = queryLower.match(/^(?<letters>[a-z]+)(?<digits>[0-9]+)$/);\n\tconst numericAlphaMatch = queryLower.match(/^(?<digits>[0-9]+)(?<letters>[a-z]+)$/);\n\tconst swappedQuery = alphaNumericMatch\n\t\t? `${alphaNumericMatch.groups?.digits ?? \"\"}${alphaNumericMatch.groups?.letters ?? \"\"}`\n\t\t: numericAlphaMatch\n\t\t\t? `${numericAlphaMatch.groups?.letters ?? \"\"}${numericAlphaMatch.groups?.digits ?? \"\"}`\n\t\t\t: \"\";\n\n\tif (!swappedQuery) {\n\t\treturn primaryMatch;\n\t}\n\n\tconst swappedMatch = matchQuery(swappedQuery);\n\tif (!swappedMatch.matches) {\n\t\treturn primaryMatch;\n\t}\n\n\treturn { matches: true, score: swappedMatch.score + 5 };\n}\n\n/**\n * Filter and sort items by fuzzy match quality (best matches first).\n * Supports space-separated tokens: all tokens must match.\n */\nexport function fuzzyFilter<T>(items: T[], query: string, getText: (item: T) => string): T[] {\n\tif (!query.trim()) {\n\t\treturn items;\n\t}\n\n\tconst tokens = query\n\t\t.trim()\n\t\t.split(/\\s+/)\n\t\t.filter((t) => t.length > 0);\n\n\tif (tokens.length === 0) {\n\t\treturn items;\n\t}\n\n\tconst results: { item: T; totalScore: number }[] = [];\n\n\tfor (const item of items) {\n\t\tconst text = getText(item);\n\t\tlet totalScore = 0;\n\t\tlet allMatch = true;\n\n\t\tfor (const token of tokens) {\n\t\t\tconst match = fuzzyMatch(token, text);\n\t\t\tif (match.matches) {\n\t\t\t\ttotalScore += match.score;\n\t\t\t} else {\n\t\t\t\tallMatch = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (allMatch) {\n\t\t\tresults.push({ item, totalScore });\n\t\t}\n\t}\n\n\tresults.sort((a, b) => a.totalScore - b.totalScore);\n\treturn results.map((r) => r.item);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACN,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,4BAA4B,EAC5B,KAAK,YAAY,GACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAE,KAAK,EAAE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAClF,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,KAAK,gBAAgB,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC/F,OAAO,EACN,KAAK,UAAU,EACf,UAAU,EACV,KAAK,uBAAuB,EAC5B,KAAK,eAAe,EACpB,KAAK,gCAAgC,GACrC,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,KAAK,WAAW,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACvG,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAE/D,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,OAAO,EAAE,KAAK,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEtE,OAAO,EACN,cAAc,EACd,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,kBAAkB,EAClB,cAAc,EACd,eAAe,GACf,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACN,oBAAoB,EACpB,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,GAAG,EACH,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,UAAU,EACV,QAAQ,EACR,sBAAsB,GACtB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,WAAW,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEnG,OAAO,EAAE,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE/D,OAAO,EACN,eAAe,EACf,KAAK,cAAc,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,aAAa,EACb,WAAW,EACX,sBAAsB,EACtB,iBAAiB,EACjB,KAAK,oBAAoB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,KAAK,SAAS,EACd,SAAS,EACT,aAAa,EACb,KAAK,SAAS,EACd,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,GAAG,GACH,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACN,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,4BAA4B,EAC5B,KAAK,YAAY,GACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAE,KAAK,EAAE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAClF,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,KAAK,gBAAgB,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC/F,OAAO,EACN,KAAK,UAAU,EACf,UAAU,EACV,KAAK,uBAAuB,EAC5B,KAAK,eAAe,EACpB,KAAK,gCAAgC,GACrC,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,KAAK,WAAW,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACvG,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAE/D,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,OAAO,EAAE,KAAK,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEtE,OAAO,EACN,cAAc,EACd,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,kBAAkB,EAClB,cAAc,EACd,eAAe,GACf,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACN,oBAAoB,EACpB,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,GAAG,EACH,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,UAAU,EACV,QAAQ,EACR,sBAAsB,GACtB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,WAAW,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEnG,OAAO,EAAE,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE/D,OAAO,EACN,eAAe,EACf,KAAK,cAAc,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,aAAa,EACb,WAAW,EACX,sBAAsB,EACtB,iBAAiB,EACjB,KAAK,oBAAoB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,KAAK,SAAS,EACd,SAAS,EACT,aAAa,EACb,KAAK,SAAS,EACd,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,GAAG,GACH,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keybindings.d.ts","sourceRoot":"","sources":["../src/keybindings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAc,MAAM,WAAW,CAAC;AAEnD;;;GAGG;AACH,MAAM,WAAW,WAAW;IAE3B,qBAAqB,EAAE,IAAI,CAAC;IAC5B,uBAAuB,EAAE,IAAI,CAAC;IAC9B,uBAAuB,EAAE,IAAI,CAAC;IAC9B,wBAAwB,EAAE,IAAI,CAAC;IAC/B,2BAA2B,EAAE,IAAI,CAAC;IAClC,4BAA4B,EAAE,IAAI,CAAC;IACnC,4BAA4B,EAAE,IAAI,CAAC;IACnC,0BAA0B,EAAE,IAAI,CAAC;IACjC,wBAAwB,EAAE,IAAI,CAAC;IAC/B,yBAAyB,EAAE,IAAI,CAAC;IAChC,mBAAmB,EAAE,IAAI,CAAC;IAC1B,qBAAqB,EAAE,IAAI,CAAC;IAC5B,+BAA+B,EAAE,IAAI,CAAC;IACtC,8BAA8B,EAAE,IAAI,CAAC;IACrC,+BAA+B,EAAE,IAAI,CAAC;IACtC,8BAA8B,EAAE,IAAI,CAAC;IACrC,8BAA8B,EAAE,IAAI,CAAC;IACrC,4BAA4B,EAAE,IAAI,CAAC;IACnC,iBAAiB,EAAE,IAAI,CAAC;IACxB,oBAAoB,EAAE,IAAI,CAAC;IAC3B,iBAAiB,EAAE,IAAI,CAAC;IAExB,mBAAmB,EAAE,IAAI,CAAC;IAC1B,kBAAkB,EAAE,IAAI,CAAC;IACzB,eAAe,EAAE,IAAI,CAAC;IACtB,gBAAgB,EAAE,IAAI,CAAC;IAEvB,eAAe,EAAE,IAAI,CAAC;IACtB,iBAAiB,EAAE,IAAI,CAAC;IACxB,mBAAmB,EAAE,IAAI,CAAC;IAC1B,qBAAqB,EAAE,IAAI,CAAC;IAC5B,oBAAoB,EAAE,IAAI,CAAC;IAC3B,mBAAmB,EAAE,IAAI,CAAC;CAC1B;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC;AAE3C,MAAM,WAAW,oBAAoB;IACpC,WAAW,EAAE,KAAK,GAAG,KAAK,EAAE,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;AACzE,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,GAAG,KAAK,EAAE,GAAG,SAAS,CAAC,CAAC;AAE5E,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgFc,CAAC;AAE3C,MAAM,WAAW,kBAAkB;IAClC,GAAG,EAAE,KAAK,CAAC;IACX,WAAW,EAAE,MAAM,EAAE,CAAC;CACtB;AAgBD,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,WAAW,CAAwB;IAC3C,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAkC;IAClD,OAAO,CAAC,SAAS,CAA4B;IAE7C,YAAY,WAAW,EAAE,qBAAqB,EAAE,YAAY,GAAE,iBAAsB,EAInF;IAED,OAAO,CAAC,OAAO;IA2Bf,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAMrD;IAED,OAAO,CAAC,UAAU,EAAE,UAAU,GAAG,KAAK,EAAE,CAEvC;IAED,aAAa,CAAC,UAAU,EAAE,UAAU,GAAG,oBAAoB,CAE1D;IAED,YAAY,IAAI,kBAAkB,EAAE,CAEnC;IAED,eAAe,CAAC,YAAY,EAAE,iBAAiB,GAAG,IAAI,CAGrD;IAED,eAAe,IAAI,iBAAiB,CAEnC;IAED,mBAAmB,IAAI,iBAAiB,CAOvC;CACD;AAID,wBAAgB,cAAc,CAAC,WAAW,EAAE,kBAAkB,GAAG,IAAI,CAEpE;AAED,wBAAgB,cAAc,IAAI,kBAAkB,CAKnD","sourcesContent":["import { type KeyId, matchesKey } from \"./keys.js\";\n\n/**\n * Global keybinding registry.\n * Downstream packages can add keybindings via declaration merging.\n */\nexport interface Keybindings {\n\t// Editor navigation and editing\n\t\"tui.editor.cursorUp\": true;\n\t\"tui.editor.cursorDown\": true;\n\t\"tui.editor.cursorLeft\": true;\n\t\"tui.editor.cursorRight\": true;\n\t\"tui.editor.cursorWordLeft\": true;\n\t\"tui.editor.cursorWordRight\": true;\n\t\"tui.editor.cursorLineStart\": true;\n\t\"tui.editor.cursorLineEnd\": true;\n\t\"tui.editor.jumpForward\": true;\n\t\"tui.editor.jumpBackward\": true;\n\t\"tui.editor.pageUp\": true;\n\t\"tui.editor.pageDown\": true;\n\t\"tui.editor.deleteCharBackward\": true;\n\t\"tui.editor.deleteCharForward\": true;\n\t\"tui.editor.deleteWordBackward\": true;\n\t\"tui.editor.deleteWordForward\": true;\n\t\"tui.editor.deleteToLineStart\": true;\n\t\"tui.editor.deleteToLineEnd\": true;\n\t\"tui.editor.yank\": true;\n\t\"tui.editor.yankPop\": true;\n\t\"tui.editor.undo\": true;\n\t// Generic input actions\n\t\"tui.input.newLine\": true;\n\t\"tui.input.submit\": true;\n\t\"tui.input.tab\": true;\n\t\"tui.input.copy\": true;\n\t// Generic selection actions\n\t\"tui.select.up\": true;\n\t\"tui.select.down\": true;\n\t\"tui.select.pageUp\": true;\n\t\"tui.select.pageDown\": true;\n\t\"tui.select.confirm\": true;\n\t\"tui.select.cancel\": true;\n}\n\nexport type Keybinding = keyof Keybindings;\n\nexport interface KeybindingDefinition {\n\tdefaultKeys: KeyId | KeyId[];\n\tdescription?: string;\n}\n\nexport type KeybindingDefinitions = Record<string, KeybindingDefinition>;\nexport type KeybindingsConfig = Record<string, KeyId | KeyId[] | undefined>;\n\nexport const TUI_KEYBINDINGS = {\n\t\"tui.editor.cursorUp\": { defaultKeys: \"up\", description: \"Move cursor up\" },\n\t\"tui.editor.cursorDown\": { defaultKeys: \"down\", description: \"Move cursor down\" },\n\t\"tui.editor.cursorLeft\": {\n\t\tdefaultKeys: [\"left\", \"ctrl+b\"],\n\t\tdescription: \"Move cursor left\",\n\t},\n\t\"tui.editor.cursorRight\": {\n\t\tdefaultKeys: [\"right\", \"ctrl+f\"],\n\t\tdescription: \"Move cursor right\",\n\t},\n\t\"tui.editor.cursorWordLeft\": {\n\t\tdefaultKeys: [\"alt+left\", \"ctrl+left\", \"alt+b\"],\n\t\tdescription: \"Move cursor word left\",\n\t},\n\t\"tui.editor.cursorWordRight\": {\n\t\tdefaultKeys: [\"alt+right\", \"ctrl+right\", \"alt+f\"],\n\t\tdescription: \"Move cursor word right\",\n\t},\n\t\"tui.editor.cursorLineStart\": {\n\t\tdefaultKeys: [\"home\", \"ctrl+a\"],\n\t\tdescription: \"Move to line start\",\n\t},\n\t\"tui.editor.cursorLineEnd\": {\n\t\tdefaultKeys: [\"end\", \"ctrl+e\"],\n\t\tdescription: \"Move to line end\",\n\t},\n\t\"tui.editor.jumpForward\": {\n\t\tdefaultKeys: \"ctrl+]\",\n\t\tdescription: \"Jump forward to character\",\n\t},\n\t\"tui.editor.jumpBackward\": {\n\t\tdefaultKeys: \"ctrl+alt+]\",\n\t\tdescription: \"Jump backward to character\",\n\t},\n\t\"tui.editor.pageUp\": { defaultKeys: \"pageUp\", description: \"Page up\" },\n\t\"tui.editor.pageDown\": { defaultKeys: \"pageDown\", description: \"Page down\" },\n\t\"tui.editor.deleteCharBackward\": {\n\t\tdefaultKeys: \"backspace\",\n\t\tdescription: \"Delete character backward\",\n\t},\n\t\"tui.editor.deleteCharForward\": {\n\t\tdefaultKeys: [\"delete\", \"ctrl+d\"],\n\t\tdescription: \"Delete character forward\",\n\t},\n\t\"tui.editor.deleteWordBackward\": {\n\t\tdefaultKeys: [\"ctrl+w\", \"alt+backspace\"],\n\t\tdescription: \"Delete word backward\",\n\t},\n\t\"tui.editor.deleteWordForward\": {\n\t\tdefaultKeys: [\"alt+d\", \"alt+delete\"],\n\t\tdescription: \"Delete word forward\",\n\t},\n\t\"tui.editor.deleteToLineStart\": {\n\t\tdefaultKeys: \"ctrl+u\",\n\t\tdescription: \"Delete to line start\",\n\t},\n\t\"tui.editor.deleteToLineEnd\": {\n\t\tdefaultKeys: \"ctrl+k\",\n\t\tdescription: \"Delete to line end\",\n\t},\n\t\"tui.editor.yank\": { defaultKeys: \"ctrl+y\", description: \"Yank\" },\n\t\"tui.editor.yankPop\": { defaultKeys: \"alt+y\", description: \"Yank pop\" },\n\t\"tui.editor.undo\": { defaultKeys: \"ctrl+-\", description: \"Undo\" },\n\t\"tui.input.newLine\": { defaultKeys: \"shift+enter\", description: \"Insert newline\" },\n\t\"tui.input.submit\": { defaultKeys: \"enter\", description: \"Submit input\" },\n\t\"tui.input.tab\": { defaultKeys: \"tab\", description: \"Tab / autocomplete\" },\n\t\"tui.input.copy\": { defaultKeys: \"ctrl+c\", description: \"Copy selection\" },\n\t\"tui.select.up\": { defaultKeys: \"up\", description: \"Move selection up\" },\n\t\"tui.select.down\": { defaultKeys: \"down\", description: \"Move selection down\" },\n\t\"tui.select.pageUp\": { defaultKeys: \"pageUp\", description: \"Selection page up\" },\n\t\"tui.select.pageDown\": {\n\t\tdefaultKeys: \"pageDown\",\n\t\tdescription: \"Selection page down\",\n\t},\n\t\"tui.select.confirm\": { defaultKeys: \"enter\", description: \"Confirm selection\" },\n\t\"tui.select.cancel\": {\n\t\tdefaultKeys: [\"escape\", \"ctrl+c\"],\n\t\tdescription: \"Cancel selection\",\n\t},\n} as const satisfies KeybindingDefinitions;\n\nexport interface KeybindingConflict {\n\tkey: KeyId;\n\tkeybindings: string[];\n}\n\nfunction normalizeKeys(keys: KeyId | KeyId[] | undefined): KeyId[] {\n\tif (keys === undefined) return [];\n\tconst keyList = Array.isArray(keys) ? keys : [keys];\n\tconst seen = new Set<KeyId>();\n\tconst result: KeyId[] = [];\n\tfor (const key of keyList) {\n\t\tif (!seen.has(key)) {\n\t\t\tseen.add(key);\n\t\t\tresult.push(key);\n\t\t}\n\t}\n\treturn result;\n}\n\nexport class KeybindingsManager {\n\tprivate definitions: KeybindingDefinitions;\n\tprivate userBindings: KeybindingsConfig;\n\tprivate keysById = new Map<Keybinding, KeyId[]>();\n\tprivate conflicts: KeybindingConflict[] = [];\n\n\tconstructor(definitions: KeybindingDefinitions, userBindings: KeybindingsConfig = {}) {\n\t\tthis.definitions = definitions;\n\t\tthis.userBindings = userBindings;\n\t\tthis.rebuild();\n\t}\n\n\tprivate rebuild(): void {\n\t\tthis.keysById.clear();\n\t\tthis.conflicts = [];\n\n\t\tconst userClaims = new Map<KeyId, Set<Keybinding>>();\n\t\tfor (const [keybinding, keys] of Object.entries(this.userBindings)) {\n\t\t\tif (!(keybinding in this.definitions)) continue;\n\t\t\tfor (const key of normalizeKeys(keys)) {\n\t\t\t\tconst claimants = userClaims.get(key) ?? new Set<Keybinding>();\n\t\t\t\tclaimants.add(keybinding as Keybinding);\n\t\t\t\tuserClaims.set(key, claimants);\n\t\t\t}\n\t\t}\n\n\t\tfor (const [key, keybindings] of userClaims) {\n\t\t\tif (keybindings.size > 1) {\n\t\t\t\tthis.conflicts.push({ key, keybindings: [...keybindings] });\n\t\t\t}\n\t\t}\n\n\t\tfor (const [id, definition] of Object.entries(this.definitions)) {\n\t\t\tconst userKeys = this.userBindings[id];\n\t\t\tconst keys = userKeys === undefined ? normalizeKeys(definition.defaultKeys) : normalizeKeys(userKeys);\n\t\t\tthis.keysById.set(id as Keybinding, keys);\n\t\t}\n\t}\n\n\tmatches(data: string, keybinding: Keybinding): boolean {\n\t\tconst keys = this.keysById.get(keybinding) ?? [];\n\t\tfor (const key of keys) {\n\t\t\tif (matchesKey(data, key)) return true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tgetKeys(keybinding: Keybinding): KeyId[] {\n\t\treturn [...(this.keysById.get(keybinding) ?? [])];\n\t}\n\n\tgetDefinition(keybinding: Keybinding): KeybindingDefinition {\n\t\treturn this.definitions[keybinding];\n\t}\n\n\tgetConflicts(): KeybindingConflict[] {\n\t\treturn this.conflicts.map((conflict) => ({ ...conflict, keybindings: [...conflict.keybindings] }));\n\t}\n\n\tsetUserBindings(userBindings: KeybindingsConfig): void {\n\t\tthis.userBindings = userBindings;\n\t\tthis.rebuild();\n\t}\n\n\tgetUserBindings(): KeybindingsConfig {\n\t\treturn { ...this.userBindings };\n\t}\n\n\tgetResolvedBindings(): KeybindingsConfig {\n\t\tconst resolved: KeybindingsConfig = {};\n\t\tfor (const id of Object.keys(this.definitions)) {\n\t\t\tconst keys = this.keysById.get(id as Keybinding) ?? [];\n\t\t\tresolved[id] = keys.length === 1 ? keys[0]! : [...keys];\n\t\t}\n\t\treturn resolved;\n\t}\n}\n\nlet globalKeybindings: KeybindingsManager | null = null;\n\nexport function setKeybindings(keybindings: KeybindingsManager): void {\n\tglobalKeybindings = keybindings;\n}\n\nexport function getKeybindings(): KeybindingsManager {\n\tif (!globalKeybindings) {\n\t\tglobalKeybindings = new KeybindingsManager(TUI_KEYBINDINGS);\n\t}\n\treturn globalKeybindings;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"keybindings.d.ts","sourceRoot":"","sources":["../src/keybindings.ts"],"names":[],"mappings":"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"}
|
|
@@ -95,11 +95,9 @@ function normalizeKeys(keys) {
|
|
|
95
95
|
return result;
|
|
96
96
|
}
|
|
97
97
|
export class KeybindingsManager {
|
|
98
|
-
definitions;
|
|
99
|
-
userBindings;
|
|
100
|
-
keysById = new Map();
|
|
101
|
-
conflicts = [];
|
|
102
98
|
constructor(definitions, userBindings = {}) {
|
|
99
|
+
this.keysById = new Map();
|
|
100
|
+
this.conflicts = [];
|
|
103
101
|
this.definitions = definitions;
|
|
104
102
|
this.userBindings = userBindings;
|
|
105
103
|
this.rebuild();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keybindings.js","sourceRoot":"","sources":["../src/keybindings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,UAAU,EAAE,MAAM,WAAW,CAAC;AAqDnD,MAAM,CAAC,MAAM,eAAe,GAAG;IAC9B,qBAAqB,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,gBAAgB,EAAE;IAC3E,uBAAuB,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,kBAAkB,EAAE;IACjF,uBAAuB,EAAE;QACxB,WAAW,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC;QAC/B,WAAW,EAAE,kBAAkB;KAC/B;IACD,wBAAwB,EAAE;QACzB,WAAW,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;QAChC,WAAW,EAAE,mBAAmB;KAChC;IACD,2BAA2B,EAAE;QAC5B,WAAW,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,OAAO,CAAC;QAC/C,WAAW,EAAE,uBAAuB;KACpC;IACD,4BAA4B,EAAE;QAC7B,WAAW,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,CAAC;QACjD,WAAW,EAAE,wBAAwB;KACrC;IACD,4BAA4B,EAAE;QAC7B,WAAW,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC;QAC/B,WAAW,EAAE,oBAAoB;KACjC;IACD,0BAA0B,EAAE;QAC3B,WAAW,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;QAC9B,WAAW,EAAE,kBAAkB;KAC/B;IACD,wBAAwB,EAAE;QACzB,WAAW,EAAE,QAAQ;QACrB,WAAW,EAAE,2BAA2B;KACxC;IACD,yBAAyB,EAAE;QAC1B,WAAW,EAAE,YAAY;QACzB,WAAW,EAAE,4BAA4B;KACzC;IACD,mBAAmB,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE;IACtE,qBAAqB,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE;IAC5E,+BAA+B,EAAE;QAChC,WAAW,EAAE,WAAW;QACxB,WAAW,EAAE,2BAA2B;KACxC;IACD,8BAA8B,EAAE;QAC/B,WAAW,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;QACjC,WAAW,EAAE,0BAA0B;KACvC;IACD,+BAA+B,EAAE;QAChC,WAAW,EAAE,CAAC,QAAQ,EAAE,eAAe,CAAC;QACxC,WAAW,EAAE,sBAAsB;KACnC;IACD,8BAA8B,EAAE;QAC/B,WAAW,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC;QACpC,WAAW,EAAE,qBAAqB;KAClC;IACD,8BAA8B,EAAE;QAC/B,WAAW,EAAE,QAAQ;QACrB,WAAW,EAAE,sBAAsB;KACnC;IACD,4BAA4B,EAAE;QAC7B,WAAW,EAAE,QAAQ;QACrB,WAAW,EAAE,oBAAoB;KACjC;IACD,iBAAiB,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE;IACjE,oBAAoB,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE;IACvE,iBAAiB,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE;IACjE,mBAAmB,EAAE,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,gBAAgB,EAAE;IAClF,kBAAkB,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE;IACzE,eAAe,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE;IAC1E,gBAAgB,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE;IAC1E,eAAe,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,mBAAmB,EAAE;IACxE,iBAAiB,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,qBAAqB,EAAE;IAC9E,mBAAmB,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE;IAChF,qBAAqB,EAAE;QACtB,WAAW,EAAE,UAAU;QACvB,WAAW,EAAE,qBAAqB;KAClC;IACD,oBAAoB,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE;IAChF,mBAAmB,EAAE;QACpB,WAAW,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;QACjC,WAAW,EAAE,kBAAkB;KAC/B;CACwC,CAAC;AAO3C,SAAS,aAAa,CAAC,IAAiC,EAAW;IAClE,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAS,CAAC;IAC9B,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACpB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClB,CAAC;IACF,CAAC;IACD,OAAO,MAAM,CAAC;AAAA,CACd;AAED,MAAM,OAAO,kBAAkB;IACtB,WAAW,CAAwB;IACnC,YAAY,CAAoB;IAChC,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC1C,SAAS,GAAyB,EAAE,CAAC;IAE7C,YAAY,WAAkC,EAAE,YAAY,GAAsB,EAAE,EAAE;QACrF,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,OAAO,EAAE,CAAC;IAAA,CACf;IAEO,OAAO,GAAS;QACvB,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QAEpB,MAAM,UAAU,GAAG,IAAI,GAAG,EAA0B,CAAC;QACrD,KAAK,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YACpE,IAAI,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC,WAAW,CAAC;gBAAE,SAAS;YAChD,KAAK,MAAM,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,EAAc,CAAC;gBAC/D,SAAS,CAAC,GAAG,CAAC,UAAwB,CAAC,CAAC;gBACxC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAChC,CAAC;QACF,CAAC;QAED,KAAK,MAAM,CAAC,GAAG,EAAE,WAAW,CAAC,IAAI,UAAU,EAAE,CAAC;YAC7C,IAAI,WAAW,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;YAC7D,CAAC;QACF,CAAC;QAED,KAAK,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YACjE,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YACvC,MAAM,IAAI,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YACtG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAgB,EAAE,IAAI,CAAC,CAAC;QAC3C,CAAC;IAAA,CACD;IAED,OAAO,CAAC,IAAY,EAAE,UAAsB,EAAW;QACtD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QACjD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACxB,IAAI,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC;QACxC,CAAC;QACD,OAAO,KAAK,CAAC;IAAA,CACb;IAED,OAAO,CAAC,UAAsB,EAAW;QACxC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAAA,CAClD;IAED,aAAa,CAAC,UAAsB,EAAwB;QAC3D,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAAA,CACpC;IAED,YAAY,GAAyB;QACpC,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,WAAW,EAAE,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;IAAA,CACnG;IAED,eAAe,CAAC,YAA+B,EAAQ;QACtD,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,OAAO,EAAE,CAAC;IAAA,CACf;IAED,eAAe,GAAsB;QACpC,OAAO,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;IAAA,CAChC;IAED,mBAAmB,GAAsB;QACxC,MAAM,QAAQ,GAAsB,EAAE,CAAC;QACvC,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAgB,CAAC,IAAI,EAAE,CAAC;YACvD,QAAQ,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,QAAQ,CAAC;IAAA,CAChB;CACD;AAED,IAAI,iBAAiB,GAA8B,IAAI,CAAC;AAExD,MAAM,UAAU,cAAc,CAAC,WAA+B,EAAQ;IACrE,iBAAiB,GAAG,WAAW,CAAC;AAAA,CAChC;AAED,MAAM,UAAU,cAAc,GAAuB;IACpD,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACxB,iBAAiB,GAAG,IAAI,kBAAkB,CAAC,eAAe,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO,iBAAiB,CAAC;AAAA,CACzB","sourcesContent":["import { type KeyId, matchesKey } from \"./keys.js\";\n\n/**\n * Global keybinding registry.\n * Downstream packages can add keybindings via declaration merging.\n */\nexport interface Keybindings {\n\t// Editor navigation and editing\n\t\"tui.editor.cursorUp\": true;\n\t\"tui.editor.cursorDown\": true;\n\t\"tui.editor.cursorLeft\": true;\n\t\"tui.editor.cursorRight\": true;\n\t\"tui.editor.cursorWordLeft\": true;\n\t\"tui.editor.cursorWordRight\": true;\n\t\"tui.editor.cursorLineStart\": true;\n\t\"tui.editor.cursorLineEnd\": true;\n\t\"tui.editor.jumpForward\": true;\n\t\"tui.editor.jumpBackward\": true;\n\t\"tui.editor.pageUp\": true;\n\t\"tui.editor.pageDown\": true;\n\t\"tui.editor.deleteCharBackward\": true;\n\t\"tui.editor.deleteCharForward\": true;\n\t\"tui.editor.deleteWordBackward\": true;\n\t\"tui.editor.deleteWordForward\": true;\n\t\"tui.editor.deleteToLineStart\": true;\n\t\"tui.editor.deleteToLineEnd\": true;\n\t\"tui.editor.yank\": true;\n\t\"tui.editor.yankPop\": true;\n\t\"tui.editor.undo\": true;\n\t// Generic input actions\n\t\"tui.input.newLine\": true;\n\t\"tui.input.submit\": true;\n\t\"tui.input.tab\": true;\n\t\"tui.input.copy\": true;\n\t// Generic selection actions\n\t\"tui.select.up\": true;\n\t\"tui.select.down\": true;\n\t\"tui.select.pageUp\": true;\n\t\"tui.select.pageDown\": true;\n\t\"tui.select.confirm\": true;\n\t\"tui.select.cancel\": true;\n}\n\nexport type Keybinding = keyof Keybindings;\n\nexport interface KeybindingDefinition {\n\tdefaultKeys: KeyId | KeyId[];\n\tdescription?: string;\n}\n\nexport type KeybindingDefinitions = Record<string, KeybindingDefinition>;\nexport type KeybindingsConfig = Record<string, KeyId | KeyId[] | undefined>;\n\nexport const TUI_KEYBINDINGS = {\n\t\"tui.editor.cursorUp\": { defaultKeys: \"up\", description: \"Move cursor up\" },\n\t\"tui.editor.cursorDown\": { defaultKeys: \"down\", description: \"Move cursor down\" },\n\t\"tui.editor.cursorLeft\": {\n\t\tdefaultKeys: [\"left\", \"ctrl+b\"],\n\t\tdescription: \"Move cursor left\",\n\t},\n\t\"tui.editor.cursorRight\": {\n\t\tdefaultKeys: [\"right\", \"ctrl+f\"],\n\t\tdescription: \"Move cursor right\",\n\t},\n\t\"tui.editor.cursorWordLeft\": {\n\t\tdefaultKeys: [\"alt+left\", \"ctrl+left\", \"alt+b\"],\n\t\tdescription: \"Move cursor word left\",\n\t},\n\t\"tui.editor.cursorWordRight\": {\n\t\tdefaultKeys: [\"alt+right\", \"ctrl+right\", \"alt+f\"],\n\t\tdescription: \"Move cursor word right\",\n\t},\n\t\"tui.editor.cursorLineStart\": {\n\t\tdefaultKeys: [\"home\", \"ctrl+a\"],\n\t\tdescription: \"Move to line start\",\n\t},\n\t\"tui.editor.cursorLineEnd\": {\n\t\tdefaultKeys: [\"end\", \"ctrl+e\"],\n\t\tdescription: \"Move to line end\",\n\t},\n\t\"tui.editor.jumpForward\": {\n\t\tdefaultKeys: \"ctrl+]\",\n\t\tdescription: \"Jump forward to character\",\n\t},\n\t\"tui.editor.jumpBackward\": {\n\t\tdefaultKeys: \"ctrl+alt+]\",\n\t\tdescription: \"Jump backward to character\",\n\t},\n\t\"tui.editor.pageUp\": { defaultKeys: \"pageUp\", description: \"Page up\" },\n\t\"tui.editor.pageDown\": { defaultKeys: \"pageDown\", description: \"Page down\" },\n\t\"tui.editor.deleteCharBackward\": {\n\t\tdefaultKeys: \"backspace\",\n\t\tdescription: \"Delete character backward\",\n\t},\n\t\"tui.editor.deleteCharForward\": {\n\t\tdefaultKeys: [\"delete\", \"ctrl+d\"],\n\t\tdescription: \"Delete character forward\",\n\t},\n\t\"tui.editor.deleteWordBackward\": {\n\t\tdefaultKeys: [\"ctrl+w\", \"alt+backspace\"],\n\t\tdescription: \"Delete word backward\",\n\t},\n\t\"tui.editor.deleteWordForward\": {\n\t\tdefaultKeys: [\"alt+d\", \"alt+delete\"],\n\t\tdescription: \"Delete word forward\",\n\t},\n\t\"tui.editor.deleteToLineStart\": {\n\t\tdefaultKeys: \"ctrl+u\",\n\t\tdescription: \"Delete to line start\",\n\t},\n\t\"tui.editor.deleteToLineEnd\": {\n\t\tdefaultKeys: \"ctrl+k\",\n\t\tdescription: \"Delete to line end\",\n\t},\n\t\"tui.editor.yank\": { defaultKeys: \"ctrl+y\", description: \"Yank\" },\n\t\"tui.editor.yankPop\": { defaultKeys: \"alt+y\", description: \"Yank pop\" },\n\t\"tui.editor.undo\": { defaultKeys: \"ctrl+-\", description: \"Undo\" },\n\t\"tui.input.newLine\": { defaultKeys: \"shift+enter\", description: \"Insert newline\" },\n\t\"tui.input.submit\": { defaultKeys: \"enter\", description: \"Submit input\" },\n\t\"tui.input.tab\": { defaultKeys: \"tab\", description: \"Tab / autocomplete\" },\n\t\"tui.input.copy\": { defaultKeys: \"ctrl+c\", description: \"Copy selection\" },\n\t\"tui.select.up\": { defaultKeys: \"up\", description: \"Move selection up\" },\n\t\"tui.select.down\": { defaultKeys: \"down\", description: \"Move selection down\" },\n\t\"tui.select.pageUp\": { defaultKeys: \"pageUp\", description: \"Selection page up\" },\n\t\"tui.select.pageDown\": {\n\t\tdefaultKeys: \"pageDown\",\n\t\tdescription: \"Selection page down\",\n\t},\n\t\"tui.select.confirm\": { defaultKeys: \"enter\", description: \"Confirm selection\" },\n\t\"tui.select.cancel\": {\n\t\tdefaultKeys: [\"escape\", \"ctrl+c\"],\n\t\tdescription: \"Cancel selection\",\n\t},\n} as const satisfies KeybindingDefinitions;\n\nexport interface KeybindingConflict {\n\tkey: KeyId;\n\tkeybindings: string[];\n}\n\nfunction normalizeKeys(keys: KeyId | KeyId[] | undefined): KeyId[] {\n\tif (keys === undefined) return [];\n\tconst keyList = Array.isArray(keys) ? keys : [keys];\n\tconst seen = new Set<KeyId>();\n\tconst result: KeyId[] = [];\n\tfor (const key of keyList) {\n\t\tif (!seen.has(key)) {\n\t\t\tseen.add(key);\n\t\t\tresult.push(key);\n\t\t}\n\t}\n\treturn result;\n}\n\nexport class KeybindingsManager {\n\tprivate definitions: KeybindingDefinitions;\n\tprivate userBindings: KeybindingsConfig;\n\tprivate keysById = new Map<Keybinding, KeyId[]>();\n\tprivate conflicts: KeybindingConflict[] = [];\n\n\tconstructor(definitions: KeybindingDefinitions, userBindings: KeybindingsConfig = {}) {\n\t\tthis.definitions = definitions;\n\t\tthis.userBindings = userBindings;\n\t\tthis.rebuild();\n\t}\n\n\tprivate rebuild(): void {\n\t\tthis.keysById.clear();\n\t\tthis.conflicts = [];\n\n\t\tconst userClaims = new Map<KeyId, Set<Keybinding>>();\n\t\tfor (const [keybinding, keys] of Object.entries(this.userBindings)) {\n\t\t\tif (!(keybinding in this.definitions)) continue;\n\t\t\tfor (const key of normalizeKeys(keys)) {\n\t\t\t\tconst claimants = userClaims.get(key) ?? new Set<Keybinding>();\n\t\t\t\tclaimants.add(keybinding as Keybinding);\n\t\t\t\tuserClaims.set(key, claimants);\n\t\t\t}\n\t\t}\n\n\t\tfor (const [key, keybindings] of userClaims) {\n\t\t\tif (keybindings.size > 1) {\n\t\t\t\tthis.conflicts.push({ key, keybindings: [...keybindings] });\n\t\t\t}\n\t\t}\n\n\t\tfor (const [id, definition] of Object.entries(this.definitions)) {\n\t\t\tconst userKeys = this.userBindings[id];\n\t\t\tconst keys = userKeys === undefined ? normalizeKeys(definition.defaultKeys) : normalizeKeys(userKeys);\n\t\t\tthis.keysById.set(id as Keybinding, keys);\n\t\t}\n\t}\n\n\tmatches(data: string, keybinding: Keybinding): boolean {\n\t\tconst keys = this.keysById.get(keybinding) ?? [];\n\t\tfor (const key of keys) {\n\t\t\tif (matchesKey(data, key)) return true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tgetKeys(keybinding: Keybinding): KeyId[] {\n\t\treturn [...(this.keysById.get(keybinding) ?? [])];\n\t}\n\n\tgetDefinition(keybinding: Keybinding): KeybindingDefinition {\n\t\treturn this.definitions[keybinding];\n\t}\n\n\tgetConflicts(): KeybindingConflict[] {\n\t\treturn this.conflicts.map((conflict) => ({ ...conflict, keybindings: [...conflict.keybindings] }));\n\t}\n\n\tsetUserBindings(userBindings: KeybindingsConfig): void {\n\t\tthis.userBindings = userBindings;\n\t\tthis.rebuild();\n\t}\n\n\tgetUserBindings(): KeybindingsConfig {\n\t\treturn { ...this.userBindings };\n\t}\n\n\tgetResolvedBindings(): KeybindingsConfig {\n\t\tconst resolved: KeybindingsConfig = {};\n\t\tfor (const id of Object.keys(this.definitions)) {\n\t\t\tconst keys = this.keysById.get(id as Keybinding) ?? [];\n\t\t\tresolved[id] = keys.length === 1 ? keys[0]! : [...keys];\n\t\t}\n\t\treturn resolved;\n\t}\n}\n\nlet globalKeybindings: KeybindingsManager | null = null;\n\nexport function setKeybindings(keybindings: KeybindingsManager): void {\n\tglobalKeybindings = keybindings;\n}\n\nexport function getKeybindings(): KeybindingsManager {\n\tif (!globalKeybindings) {\n\t\tglobalKeybindings = new KeybindingsManager(TUI_KEYBINDINGS);\n\t}\n\treturn globalKeybindings;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"keybindings.js","sourceRoot":"","sources":["../src/keybindings.ts"],"names":[],"mappings":"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","sourcesContent":["import { type KeyId, matchesKey } from \"./keys.js\";\n\n/**\n * Global keybinding registry.\n * Downstream packages can add keybindings via declaration merging.\n */\nexport interface Keybindings {\n\t// Editor navigation and editing\n\t\"tui.editor.cursorUp\": true;\n\t\"tui.editor.cursorDown\": true;\n\t\"tui.editor.cursorLeft\": true;\n\t\"tui.editor.cursorRight\": true;\n\t\"tui.editor.cursorWordLeft\": true;\n\t\"tui.editor.cursorWordRight\": true;\n\t\"tui.editor.cursorLineStart\": true;\n\t\"tui.editor.cursorLineEnd\": true;\n\t\"tui.editor.jumpForward\": true;\n\t\"tui.editor.jumpBackward\": true;\n\t\"tui.editor.pageUp\": true;\n\t\"tui.editor.pageDown\": true;\n\t\"tui.editor.deleteCharBackward\": true;\n\t\"tui.editor.deleteCharForward\": true;\n\t\"tui.editor.deleteWordBackward\": true;\n\t\"tui.editor.deleteWordForward\": true;\n\t\"tui.editor.deleteToLineStart\": true;\n\t\"tui.editor.deleteToLineEnd\": true;\n\t\"tui.editor.yank\": true;\n\t\"tui.editor.yankPop\": true;\n\t\"tui.editor.undo\": true;\n\t// Generic input actions\n\t\"tui.input.newLine\": true;\n\t\"tui.input.submit\": true;\n\t\"tui.input.tab\": true;\n\t\"tui.input.copy\": true;\n\t// Generic selection actions\n\t\"tui.select.up\": true;\n\t\"tui.select.down\": true;\n\t\"tui.select.pageUp\": true;\n\t\"tui.select.pageDown\": true;\n\t\"tui.select.confirm\": true;\n\t\"tui.select.cancel\": true;\n}\n\nexport type Keybinding = keyof Keybindings;\n\nexport interface KeybindingDefinition {\n\tdefaultKeys: KeyId | KeyId[];\n\tdescription?: string;\n}\n\nexport type KeybindingDefinitions = Record<string, KeybindingDefinition>;\nexport type KeybindingsConfig = Record<string, KeyId | KeyId[] | undefined>;\n\nexport const TUI_KEYBINDINGS = {\n\t\"tui.editor.cursorUp\": { defaultKeys: \"up\", description: \"Move cursor up\" },\n\t\"tui.editor.cursorDown\": { defaultKeys: \"down\", description: \"Move cursor down\" },\n\t\"tui.editor.cursorLeft\": {\n\t\tdefaultKeys: [\"left\", \"ctrl+b\"],\n\t\tdescription: \"Move cursor left\",\n\t},\n\t\"tui.editor.cursorRight\": {\n\t\tdefaultKeys: [\"right\", \"ctrl+f\"],\n\t\tdescription: \"Move cursor right\",\n\t},\n\t\"tui.editor.cursorWordLeft\": {\n\t\tdefaultKeys: [\"alt+left\", \"ctrl+left\", \"alt+b\"],\n\t\tdescription: \"Move cursor word left\",\n\t},\n\t\"tui.editor.cursorWordRight\": {\n\t\tdefaultKeys: [\"alt+right\", \"ctrl+right\", \"alt+f\"],\n\t\tdescription: \"Move cursor word right\",\n\t},\n\t\"tui.editor.cursorLineStart\": {\n\t\tdefaultKeys: [\"home\", \"ctrl+a\"],\n\t\tdescription: \"Move to line start\",\n\t},\n\t\"tui.editor.cursorLineEnd\": {\n\t\tdefaultKeys: [\"end\", \"ctrl+e\"],\n\t\tdescription: \"Move to line end\",\n\t},\n\t\"tui.editor.jumpForward\": {\n\t\tdefaultKeys: \"ctrl+]\",\n\t\tdescription: \"Jump forward to character\",\n\t},\n\t\"tui.editor.jumpBackward\": {\n\t\tdefaultKeys: \"ctrl+alt+]\",\n\t\tdescription: \"Jump backward to character\",\n\t},\n\t\"tui.editor.pageUp\": { defaultKeys: \"pageUp\", description: \"Page up\" },\n\t\"tui.editor.pageDown\": { defaultKeys: \"pageDown\", description: \"Page down\" },\n\t\"tui.editor.deleteCharBackward\": {\n\t\tdefaultKeys: \"backspace\",\n\t\tdescription: \"Delete character backward\",\n\t},\n\t\"tui.editor.deleteCharForward\": {\n\t\tdefaultKeys: [\"delete\", \"ctrl+d\"],\n\t\tdescription: \"Delete character forward\",\n\t},\n\t\"tui.editor.deleteWordBackward\": {\n\t\tdefaultKeys: [\"ctrl+w\", \"alt+backspace\"],\n\t\tdescription: \"Delete word backward\",\n\t},\n\t\"tui.editor.deleteWordForward\": {\n\t\tdefaultKeys: [\"alt+d\", \"alt+delete\"],\n\t\tdescription: \"Delete word forward\",\n\t},\n\t\"tui.editor.deleteToLineStart\": {\n\t\tdefaultKeys: \"ctrl+u\",\n\t\tdescription: \"Delete to line start\",\n\t},\n\t\"tui.editor.deleteToLineEnd\": {\n\t\tdefaultKeys: \"ctrl+k\",\n\t\tdescription: \"Delete to line end\",\n\t},\n\t\"tui.editor.yank\": { defaultKeys: \"ctrl+y\", description: \"Yank\" },\n\t\"tui.editor.yankPop\": { defaultKeys: \"alt+y\", description: \"Yank pop\" },\n\t\"tui.editor.undo\": { defaultKeys: \"ctrl+-\", description: \"Undo\" },\n\t\"tui.input.newLine\": { defaultKeys: \"shift+enter\", description: \"Insert newline\" },\n\t\"tui.input.submit\": { defaultKeys: \"enter\", description: \"Submit input\" },\n\t\"tui.input.tab\": { defaultKeys: \"tab\", description: \"Tab / autocomplete\" },\n\t\"tui.input.copy\": { defaultKeys: \"ctrl+c\", description: \"Copy selection\" },\n\t\"tui.select.up\": { defaultKeys: \"up\", description: \"Move selection up\" },\n\t\"tui.select.down\": { defaultKeys: \"down\", description: \"Move selection down\" },\n\t\"tui.select.pageUp\": { defaultKeys: \"pageUp\", description: \"Selection page up\" },\n\t\"tui.select.pageDown\": {\n\t\tdefaultKeys: \"pageDown\",\n\t\tdescription: \"Selection page down\",\n\t},\n\t\"tui.select.confirm\": { defaultKeys: \"enter\", description: \"Confirm selection\" },\n\t\"tui.select.cancel\": {\n\t\tdefaultKeys: [\"escape\", \"ctrl+c\"],\n\t\tdescription: \"Cancel selection\",\n\t},\n} as const satisfies KeybindingDefinitions;\n\nexport interface KeybindingConflict {\n\tkey: KeyId;\n\tkeybindings: string[];\n}\n\nfunction normalizeKeys(keys: KeyId | KeyId[] | undefined): KeyId[] {\n\tif (keys === undefined) return [];\n\tconst keyList = Array.isArray(keys) ? keys : [keys];\n\tconst seen = new Set<KeyId>();\n\tconst result: KeyId[] = [];\n\tfor (const key of keyList) {\n\t\tif (!seen.has(key)) {\n\t\t\tseen.add(key);\n\t\t\tresult.push(key);\n\t\t}\n\t}\n\treturn result;\n}\n\nexport class KeybindingsManager {\n\tprivate definitions: KeybindingDefinitions;\n\tprivate userBindings: KeybindingsConfig;\n\tprivate keysById = new Map<Keybinding, KeyId[]>();\n\tprivate conflicts: KeybindingConflict[] = [];\n\n\tconstructor(definitions: KeybindingDefinitions, userBindings: KeybindingsConfig = {}) {\n\t\tthis.definitions = definitions;\n\t\tthis.userBindings = userBindings;\n\t\tthis.rebuild();\n\t}\n\n\tprivate rebuild(): void {\n\t\tthis.keysById.clear();\n\t\tthis.conflicts = [];\n\n\t\tconst userClaims = new Map<KeyId, Set<Keybinding>>();\n\t\tfor (const [keybinding, keys] of Object.entries(this.userBindings)) {\n\t\t\tif (!(keybinding in this.definitions)) continue;\n\t\t\tfor (const key of normalizeKeys(keys)) {\n\t\t\t\tconst claimants = userClaims.get(key) ?? new Set<Keybinding>();\n\t\t\t\tclaimants.add(keybinding as Keybinding);\n\t\t\t\tuserClaims.set(key, claimants);\n\t\t\t}\n\t\t}\n\n\t\tfor (const [key, keybindings] of userClaims) {\n\t\t\tif (keybindings.size > 1) {\n\t\t\t\tthis.conflicts.push({ key, keybindings: [...keybindings] });\n\t\t\t}\n\t\t}\n\n\t\tfor (const [id, definition] of Object.entries(this.definitions)) {\n\t\t\tconst userKeys = this.userBindings[id];\n\t\t\tconst keys = userKeys === undefined ? normalizeKeys(definition.defaultKeys) : normalizeKeys(userKeys);\n\t\t\tthis.keysById.set(id as Keybinding, keys);\n\t\t}\n\t}\n\n\tmatches(data: string, keybinding: Keybinding): boolean {\n\t\tconst keys = this.keysById.get(keybinding) ?? [];\n\t\tfor (const key of keys) {\n\t\t\tif (matchesKey(data, key)) return true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tgetKeys(keybinding: Keybinding): KeyId[] {\n\t\treturn [...(this.keysById.get(keybinding) ?? [])];\n\t}\n\n\tgetDefinition(keybinding: Keybinding): KeybindingDefinition {\n\t\treturn this.definitions[keybinding];\n\t}\n\n\tgetConflicts(): KeybindingConflict[] {\n\t\treturn this.conflicts.map((conflict) => ({ ...conflict, keybindings: [...conflict.keybindings] }));\n\t}\n\n\tsetUserBindings(userBindings: KeybindingsConfig): void {\n\t\tthis.userBindings = userBindings;\n\t\tthis.rebuild();\n\t}\n\n\tgetUserBindings(): KeybindingsConfig {\n\t\treturn { ...this.userBindings };\n\t}\n\n\tgetResolvedBindings(): KeybindingsConfig {\n\t\tconst resolved: KeybindingsConfig = {};\n\t\tfor (const id of Object.keys(this.definitions)) {\n\t\t\tconst keys = this.keysById.get(id as Keybinding) ?? [];\n\t\t\tresolved[id] = keys.length === 1 ? keys[0]! : [...keys];\n\t\t}\n\t\treturn resolved;\n\t}\n}\n\nlet globalKeybindings: KeybindingsManager | null = null;\n\nexport function setKeybindings(keybindings: KeybindingsManager): void {\n\tglobalKeybindings = keybindings;\n}\n\nexport function getKeybindings(): KeybindingsManager {\n\tif (!globalKeybindings) {\n\t\tglobalKeybindings = new KeybindingsManager(TUI_KEYBINDINGS);\n\t}\n\treturn globalKeybindings;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Keyboard input handling for terminal applications.\n *\n * Supports both legacy terminal sequences and Kitty keyboard protocol.\n * See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/\n * Reference: https://github.com/sst/opentui/blob/7da92b4088aebfe27b9f691c04163a48821e49fd/packages/core/src/lib/parse.keypress.ts\n *\n * Symbol keys are also supported, however some ctrl+symbol combos\n * overlap with ASCII codes, e.g. ctrl+[ = ESC.\n * See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/#legacy-ctrl-mapping-of-ascii-keys\n * Those can still be * used for ctrl+shift combos\n *\n * API:\n * - matchesKey(data, keyId) - Check if input matches a key identifier\n * - parseKey(data) - Parse input and return the key identifier\n * - Key - Helper object for creating typed key identifiers\n * - setKittyProtocolActive(active) - Set global Kitty protocol state\n * - isKittyProtocolActive() - Query global Kitty protocol state\n */\n\n// =============================================================================\n// Global Kitty Protocol State\n// =============================================================================\n\nlet _kittyProtocolActive = false;\n\n/**\n * Set the global Kitty keyboard protocol state.\n * Called by ProcessTerminal after detecting protocol support.\n */\nexport function setKittyProtocolActive(active: boolean): void {\n\t_kittyProtocolActive = active;\n}\n\n/**\n * Query whether Kitty keyboard protocol is currently active.\n */\nexport function isKittyProtocolActive(): boolean {\n\treturn _kittyProtocolActive;\n}\n\n// =============================================================================\n// Type-Safe Key Identifiers\n// =============================================================================\n\ntype Letter =\n\t| \"a\"\n\t| \"b\"\n\t| \"c\"\n\t| \"d\"\n\t| \"e\"\n\t| \"f\"\n\t| \"g\"\n\t| \"h\"\n\t| \"i\"\n\t| \"j\"\n\t| \"k\"\n\t| \"l\"\n\t| \"m\"\n\t| \"n\"\n\t| \"o\"\n\t| \"p\"\n\t| \"q\"\n\t| \"r\"\n\t| \"s\"\n\t| \"t\"\n\t| \"u\"\n\t| \"v\"\n\t| \"w\"\n\t| \"x\"\n\t| \"y\"\n\t| \"z\";\n\ntype Digit = \"0\" | \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\" | \"7\" | \"8\" | \"9\";\n\ntype SymbolKey =\n\t| \"`\"\n\t| \"-\"\n\t| \"=\"\n\t| \"[\"\n\t| \"]\"\n\t| \"\\\\\"\n\t| \";\"\n\t| \"'\"\n\t| \",\"\n\t| \".\"\n\t| \"/\"\n\t| \"!\"\n\t| \"@\"\n\t| \"#\"\n\t| \"$\"\n\t| \"%\"\n\t| \"^\"\n\t| \"&\"\n\t| \"*\"\n\t| \"(\"\n\t| \")\"\n\t| \"_\"\n\t| \"+\"\n\t| \"|\"\n\t| \"~\"\n\t| \"{\"\n\t| \"}\"\n\t| \":\"\n\t| \"<\"\n\t| \">\"\n\t| \"?\";\n\ntype SpecialKey =\n\t| \"escape\"\n\t| \"esc\"\n\t| \"enter\"\n\t| \"return\"\n\t| \"tab\"\n\t| \"space\"\n\t| \"backspace\"\n\t| \"delete\"\n\t| \"insert\"\n\t| \"clear\"\n\t| \"home\"\n\t| \"end\"\n\t| \"pageUp\"\n\t| \"pageDown\"\n\t| \"up\"\n\t| \"down\"\n\t| \"left\"\n\t| \"right\"\n\t| \"f1\"\n\t| \"f2\"\n\t| \"f3\"\n\t| \"f4\"\n\t| \"f5\"\n\t| \"f6\"\n\t| \"f7\"\n\t| \"f8\"\n\t| \"f9\"\n\t| \"f10\"\n\t| \"f11\"\n\t| \"f12\";\n\ntype BaseKey = Letter | Digit | SymbolKey | SpecialKey;\n\n/**\n * Union type of all valid key identifiers.\n * Provides autocomplete and catches typos at compile time.\n */\nexport type KeyId =\n\t| BaseKey\n\t| `ctrl+${BaseKey}`\n\t| `shift+${BaseKey}`\n\t| `alt+${BaseKey}`\n\t| `ctrl+shift+${BaseKey}`\n\t| `shift+ctrl+${BaseKey}`\n\t| `ctrl+alt+${BaseKey}`\n\t| `alt+ctrl+${BaseKey}`\n\t| `shift+alt+${BaseKey}`\n\t| `alt+shift+${BaseKey}`\n\t| `ctrl+shift+alt+${BaseKey}`\n\t| `ctrl+alt+shift+${BaseKey}`\n\t| `shift+ctrl+alt+${BaseKey}`\n\t| `shift+alt+ctrl+${BaseKey}`\n\t| `alt+ctrl+shift+${BaseKey}`\n\t| `alt+shift+ctrl+${BaseKey}`;\n\n/**\n * Helper object for creating typed key identifiers with autocomplete.\n *\n * Usage:\n * - Key.escape, Key.enter, Key.tab, etc. for special keys\n * - Key.backtick, Key.comma, Key.period, etc. for symbol keys\n * - Key.ctrl(\"c\"), Key.alt(\"x\") for single modifier\n * - Key.ctrlShift(\"p\"), Key.ctrlAlt(\"x\") for combined modifiers\n */\nexport const Key = {\n\t// Special keys\n\tescape: \"escape\" as const,\n\tesc: \"esc\" as const,\n\tenter: \"enter\" as const,\n\treturn: \"return\" as const,\n\ttab: \"tab\" as const,\n\tspace: \"space\" as const,\n\tbackspace: \"backspace\" as const,\n\tdelete: \"delete\" as const,\n\tinsert: \"insert\" as const,\n\tclear: \"clear\" as const,\n\thome: \"home\" as const,\n\tend: \"end\" as const,\n\tpageUp: \"pageUp\" as const,\n\tpageDown: \"pageDown\" as const,\n\tup: \"up\" as const,\n\tdown: \"down\" as const,\n\tleft: \"left\" as const,\n\tright: \"right\" as const,\n\tf1: \"f1\" as const,\n\tf2: \"f2\" as const,\n\tf3: \"f3\" as const,\n\tf4: \"f4\" as const,\n\tf5: \"f5\" as const,\n\tf6: \"f6\" as const,\n\tf7: \"f7\" as const,\n\tf8: \"f8\" as const,\n\tf9: \"f9\" as const,\n\tf10: \"f10\" as const,\n\tf11: \"f11\" as const,\n\tf12: \"f12\" as const,\n\n\t// Symbol keys\n\tbacktick: \"`\" as const,\n\thyphen: \"-\" as const,\n\tequals: \"=\" as const,\n\tleftbracket: \"[\" as const,\n\trightbracket: \"]\" as const,\n\tbackslash: \"\\\\\" as const,\n\tsemicolon: \";\" as const,\n\tquote: \"'\" as const,\n\tcomma: \",\" as const,\n\tperiod: \".\" as const,\n\tslash: \"/\" as const,\n\texclamation: \"!\" as const,\n\tat: \"@\" as const,\n\thash: \"#\" as const,\n\tdollar: \"$\" as const,\n\tpercent: \"%\" as const,\n\tcaret: \"^\" as const,\n\tampersand: \"&\" as const,\n\tasterisk: \"*\" as const,\n\tleftparen: \"(\" as const,\n\trightparen: \")\" as const,\n\tunderscore: \"_\" as const,\n\tplus: \"+\" as const,\n\tpipe: \"|\" as const,\n\ttilde: \"~\" as const,\n\tleftbrace: \"{\" as const,\n\trightbrace: \"}\" as const,\n\tcolon: \":\" as const,\n\tlessthan: \"<\" as const,\n\tgreaterthan: \">\" as const,\n\tquestion: \"?\" as const,\n\n\t// Single modifiers\n\tctrl: <K extends BaseKey>(key: K): `ctrl+${K}` => `ctrl+${key}`,\n\tshift: <K extends BaseKey>(key: K): `shift+${K}` => `shift+${key}`,\n\talt: <K extends BaseKey>(key: K): `alt+${K}` => `alt+${key}`,\n\n\t// Combined modifiers\n\tctrlShift: <K extends BaseKey>(key: K): `ctrl+shift+${K}` => `ctrl+shift+${key}`,\n\tshiftCtrl: <K extends BaseKey>(key: K): `shift+ctrl+${K}` => `shift+ctrl+${key}`,\n\tctrlAlt: <K extends BaseKey>(key: K): `ctrl+alt+${K}` => `ctrl+alt+${key}`,\n\taltCtrl: <K extends BaseKey>(key: K): `alt+ctrl+${K}` => `alt+ctrl+${key}`,\n\tshiftAlt: <K extends BaseKey>(key: K): `shift+alt+${K}` => `shift+alt+${key}`,\n\taltShift: <K extends BaseKey>(key: K): `alt+shift+${K}` => `alt+shift+${key}`,\n\n\t// Triple modifiers\n\tctrlShiftAlt: <K extends BaseKey>(key: K): `ctrl+shift+alt+${K}` => `ctrl+shift+alt+${key}`,\n} as const;\n\n// =============================================================================\n// Constants\n// =============================================================================\n\nconst SYMBOL_KEYS = new Set([\n\t\"`\",\n\t\"-\",\n\t\"=\",\n\t\"[\",\n\t\"]\",\n\t\"\\\\\",\n\t\";\",\n\t\"'\",\n\t\",\",\n\t\".\",\n\t\"/\",\n\t\"!\",\n\t\"@\",\n\t\"#\",\n\t\"$\",\n\t\"%\",\n\t\"^\",\n\t\"&\",\n\t\"*\",\n\t\"(\",\n\t\")\",\n\t\"_\",\n\t\"+\",\n\t\"|\",\n\t\"~\",\n\t\"{\",\n\t\"}\",\n\t\":\",\n\t\"<\",\n\t\">\",\n\t\"?\",\n]);\n\nconst MODIFIERS = {\n\tshift: 1,\n\talt: 2,\n\tctrl: 4,\n} as const;\n\nconst LOCK_MASK = 64 + 128; // Caps Lock + Num Lock\n\nconst CODEPOINTS = {\n\tescape: 27,\n\ttab: 9,\n\tenter: 13,\n\tspace: 32,\n\tbackspace: 127,\n\tkpEnter: 57414, // Numpad Enter (Kitty protocol)\n} as const;\n\nconst ARROW_CODEPOINTS = {\n\tup: -1,\n\tdown: -2,\n\tright: -3,\n\tleft: -4,\n} as const;\n\nconst FUNCTIONAL_CODEPOINTS = {\n\tdelete: -10,\n\tinsert: -11,\n\tpageUp: -12,\n\tpageDown: -13,\n\thome: -14,\n\tend: -15,\n} as const;\n\nconst KITTY_FUNCTIONAL_KEY_EQUIVALENTS = new Map<number, number>([\n\t[57399, 48], // KP_0 -> 0\n\t[57400, 49], // KP_1 -> 1\n\t[57401, 50], // KP_2 -> 2\n\t[57402, 51], // KP_3 -> 3\n\t[57403, 52], // KP_4 -> 4\n\t[57404, 53], // KP_5 -> 5\n\t[57405, 54], // KP_6 -> 6\n\t[57406, 55], // KP_7 -> 7\n\t[57407, 56], // KP_8 -> 8\n\t[57408, 57], // KP_9 -> 9\n\t[57409, 46], // KP_DECIMAL -> .\n\t[57410, 47], // KP_DIVIDE -> /\n\t[57411, 42], // KP_MULTIPLY -> *\n\t[57412, 45], // KP_SUBTRACT -> -\n\t[57413, 43], // KP_ADD -> +\n\t[57415, 61], // KP_EQUAL -> =\n\t[57416, 44], // KP_SEPARATOR -> ,\n\t[57417, ARROW_CODEPOINTS.left],\n\t[57418, ARROW_CODEPOINTS.right],\n\t[57419, ARROW_CODEPOINTS.up],\n\t[57420, ARROW_CODEPOINTS.down],\n\t[57421, FUNCTIONAL_CODEPOINTS.pageUp],\n\t[57422, FUNCTIONAL_CODEPOINTS.pageDown],\n\t[57423, FUNCTIONAL_CODEPOINTS.home],\n\t[57424, FUNCTIONAL_CODEPOINTS.end],\n\t[57425, FUNCTIONAL_CODEPOINTS.insert],\n\t[57426, FUNCTIONAL_CODEPOINTS.delete],\n]);\n\nfunction normalizeKittyFunctionalCodepoint(codepoint: number): number {\n\treturn KITTY_FUNCTIONAL_KEY_EQUIVALENTS.get(codepoint) ?? codepoint;\n}\n\nconst LEGACY_KEY_SEQUENCES = {\n\tup: [\"\\x1b[A\", \"\\x1bOA\"],\n\tdown: [\"\\x1b[B\", \"\\x1bOB\"],\n\tright: [\"\\x1b[C\", \"\\x1bOC\"],\n\tleft: [\"\\x1b[D\", \"\\x1bOD\"],\n\thome: [\"\\x1b[H\", \"\\x1bOH\", \"\\x1b[1~\", \"\\x1b[7~\"],\n\tend: [\"\\x1b[F\", \"\\x1bOF\", \"\\x1b[4~\", \"\\x1b[8~\"],\n\tinsert: [\"\\x1b[2~\"],\n\tdelete: [\"\\x1b[3~\"],\n\tpageUp: [\"\\x1b[5~\", \"\\x1b[[5~\"],\n\tpageDown: [\"\\x1b[6~\", \"\\x1b[[6~\"],\n\tclear: [\"\\x1b[E\", \"\\x1bOE\"],\n\tf1: [\"\\x1bOP\", \"\\x1b[11~\", \"\\x1b[[A\"],\n\tf2: [\"\\x1bOQ\", \"\\x1b[12~\", \"\\x1b[[B\"],\n\tf3: [\"\\x1bOR\", \"\\x1b[13~\", \"\\x1b[[C\"],\n\tf4: [\"\\x1bOS\", \"\\x1b[14~\", \"\\x1b[[D\"],\n\tf5: [\"\\x1b[15~\", \"\\x1b[[E\"],\n\tf6: [\"\\x1b[17~\"],\n\tf7: [\"\\x1b[18~\"],\n\tf8: [\"\\x1b[19~\"],\n\tf9: [\"\\x1b[20~\"],\n\tf10: [\"\\x1b[21~\"],\n\tf11: [\"\\x1b[23~\"],\n\tf12: [\"\\x1b[24~\"],\n} as const;\n\nconst LEGACY_SHIFT_SEQUENCES = {\n\tup: [\"\\x1b[a\"],\n\tdown: [\"\\x1b[b\"],\n\tright: [\"\\x1b[c\"],\n\tleft: [\"\\x1b[d\"],\n\tclear: [\"\\x1b[e\"],\n\tinsert: [\"\\x1b[2$\"],\n\tdelete: [\"\\x1b[3$\"],\n\tpageUp: [\"\\x1b[5$\"],\n\tpageDown: [\"\\x1b[6$\"],\n\thome: [\"\\x1b[7$\"],\n\tend: [\"\\x1b[8$\"],\n} as const;\n\nconst LEGACY_CTRL_SEQUENCES = {\n\tup: [\"\\x1bOa\"],\n\tdown: [\"\\x1bOb\"],\n\tright: [\"\\x1bOc\"],\n\tleft: [\"\\x1bOd\"],\n\tclear: [\"\\x1bOe\"],\n\tinsert: [\"\\x1b[2^\"],\n\tdelete: [\"\\x1b[3^\"],\n\tpageUp: [\"\\x1b[5^\"],\n\tpageDown: [\"\\x1b[6^\"],\n\thome: [\"\\x1b[7^\"],\n\tend: [\"\\x1b[8^\"],\n} as const;\n\nconst LEGACY_SEQUENCE_KEY_IDS: Record<string, KeyId> = {\n\t\"\\x1bOA\": \"up\",\n\t\"\\x1bOB\": \"down\",\n\t\"\\x1bOC\": \"right\",\n\t\"\\x1bOD\": \"left\",\n\t\"\\x1bOH\": \"home\",\n\t\"\\x1bOF\": \"end\",\n\t\"\\x1b[E\": \"clear\",\n\t\"\\x1bOE\": \"clear\",\n\t\"\\x1bOe\": \"ctrl+clear\",\n\t\"\\x1b[e\": \"shift+clear\",\n\t\"\\x1b[2~\": \"insert\",\n\t\"\\x1b[2$\": \"shift+insert\",\n\t\"\\x1b[2^\": \"ctrl+insert\",\n\t\"\\x1b[3$\": \"shift+delete\",\n\t\"\\x1b[3^\": \"ctrl+delete\",\n\t\"\\x1b[[5~\": \"pageUp\",\n\t\"\\x1b[[6~\": \"pageDown\",\n\t\"\\x1b[a\": \"shift+up\",\n\t\"\\x1b[b\": \"shift+down\",\n\t\"\\x1b[c\": \"shift+right\",\n\t\"\\x1b[d\": \"shift+left\",\n\t\"\\x1bOa\": \"ctrl+up\",\n\t\"\\x1bOb\": \"ctrl+down\",\n\t\"\\x1bOc\": \"ctrl+right\",\n\t\"\\x1bOd\": \"ctrl+left\",\n\t\"\\x1b[5$\": \"shift+pageUp\",\n\t\"\\x1b[6$\": \"shift+pageDown\",\n\t\"\\x1b[7$\": \"shift+home\",\n\t\"\\x1b[8$\": \"shift+end\",\n\t\"\\x1b[5^\": \"ctrl+pageUp\",\n\t\"\\x1b[6^\": \"ctrl+pageDown\",\n\t\"\\x1b[7^\": \"ctrl+home\",\n\t\"\\x1b[8^\": \"ctrl+end\",\n\t\"\\x1bOP\": \"f1\",\n\t\"\\x1bOQ\": \"f2\",\n\t\"\\x1bOR\": \"f3\",\n\t\"\\x1bOS\": \"f4\",\n\t\"\\x1b[11~\": \"f1\",\n\t\"\\x1b[12~\": \"f2\",\n\t\"\\x1b[13~\": \"f3\",\n\t\"\\x1b[14~\": \"f4\",\n\t\"\\x1b[[A\": \"f1\",\n\t\"\\x1b[[B\": \"f2\",\n\t\"\\x1b[[C\": \"f3\",\n\t\"\\x1b[[D\": \"f4\",\n\t\"\\x1b[[E\": \"f5\",\n\t\"\\x1b[15~\": \"f5\",\n\t\"\\x1b[17~\": \"f6\",\n\t\"\\x1b[18~\": \"f7\",\n\t\"\\x1b[19~\": \"f8\",\n\t\"\\x1b[20~\": \"f9\",\n\t\"\\x1b[21~\": \"f10\",\n\t\"\\x1b[23~\": \"f11\",\n\t\"\\x1b[24~\": \"f12\",\n\t\"\\x1bb\": \"alt+left\",\n\t\"\\x1bf\": \"alt+right\",\n\t\"\\x1bp\": \"alt+up\",\n\t\"\\x1bn\": \"alt+down\",\n} as const;\n\ntype LegacyModifierKey = keyof typeof LEGACY_SHIFT_SEQUENCES;\n\nconst matchesLegacySequence = (data: string, sequences: readonly string[]): boolean => sequences.includes(data);\n\nconst matchesLegacyModifierSequence = (data: string, key: LegacyModifierKey, modifier: number): boolean => {\n\tif (modifier === MODIFIERS.shift) {\n\t\treturn matchesLegacySequence(data, LEGACY_SHIFT_SEQUENCES[key]);\n\t}\n\tif (modifier === MODIFIERS.ctrl) {\n\t\treturn matchesLegacySequence(data, LEGACY_CTRL_SEQUENCES[key]);\n\t}\n\treturn false;\n};\n\n// =============================================================================\n// Kitty Protocol Parsing\n// =============================================================================\n\n/**\n * Event types from Kitty keyboard protocol (flag 2)\n * 1 = key press, 2 = key repeat, 3 = key release\n */\nexport type KeyEventType = \"press\" | \"repeat\" | \"release\";\n\ninterface ParsedKittySequence {\n\tcodepoint: number;\n\tshiftedKey?: number; // Shifted version of the key (when shift is pressed)\n\tbaseLayoutKey?: number; // Key in standard PC-101 layout (for non-Latin layouts)\n\tmodifier: number;\n\teventType: KeyEventType;\n}\n\ninterface ParsedModifyOtherKeysSequence {\n\tcodepoint: number;\n\tmodifier: number;\n}\n\n// Store the last parsed event type for isKeyRelease() to query\nlet _lastEventType: KeyEventType = \"press\";\n\n/**\n * Check if the last parsed key event was a key release.\n * Only meaningful when Kitty keyboard protocol with flag 2 is active.\n */\nexport function isKeyRelease(data: string): boolean {\n\t// Don't treat bracketed paste content as key release, even if it contains\n\t// patterns like \":3F\" (e.g., bluetooth MAC addresses like \"90:62:3F:A5\").\n\t// Terminal.ts re-wraps paste content with bracketed paste markers before\n\t// passing to TUI, so pasted data will always contain \\x1b[200~.\n\tif (data.includes(\"\\x1b[200~\")) {\n\t\treturn false;\n\t}\n\n\t// Quick check: release events with flag 2 contain \":3\"\n\t// Format: \\x1b[<codepoint>;<modifier>:3u\n\tif (\n\t\tdata.includes(\":3u\") ||\n\t\tdata.includes(\":3~\") ||\n\t\tdata.includes(\":3A\") ||\n\t\tdata.includes(\":3B\") ||\n\t\tdata.includes(\":3C\") ||\n\t\tdata.includes(\":3D\") ||\n\t\tdata.includes(\":3H\") ||\n\t\tdata.includes(\":3F\")\n\t) {\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Check if the last parsed key event was a key repeat.\n * Only meaningful when Kitty keyboard protocol with flag 2 is active.\n */\nexport function isKeyRepeat(data: string): boolean {\n\t// Don't treat bracketed paste content as key repeat, even if it contains\n\t// patterns like \":2F\". See isKeyRelease() for details.\n\tif (data.includes(\"\\x1b[200~\")) {\n\t\treturn false;\n\t}\n\n\tif (\n\t\tdata.includes(\":2u\") ||\n\t\tdata.includes(\":2~\") ||\n\t\tdata.includes(\":2A\") ||\n\t\tdata.includes(\":2B\") ||\n\t\tdata.includes(\":2C\") ||\n\t\tdata.includes(\":2D\") ||\n\t\tdata.includes(\":2H\") ||\n\t\tdata.includes(\":2F\")\n\t) {\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nfunction parseEventType(eventTypeStr: string | undefined): KeyEventType {\n\tif (!eventTypeStr) return \"press\";\n\tconst eventType = parseInt(eventTypeStr, 10);\n\tif (eventType === 2) return \"repeat\";\n\tif (eventType === 3) return \"release\";\n\treturn \"press\";\n}\n\nfunction parseKittySequence(data: string): ParsedKittySequence | null {\n\t// CSI u format with alternate keys (flag 4):\n\t// \\x1b[<codepoint>u\n\t// \\x1b[<codepoint>;<mod>u\n\t// \\x1b[<codepoint>;<mod>:<event>u\n\t// \\x1b[<codepoint>:<shifted>;<mod>u\n\t// \\x1b[<codepoint>:<shifted>:<base>;<mod>u\n\t// \\x1b[<codepoint>::<base>;<mod>u (no shifted key, only base)\n\t//\n\t// With flag 2, event type is appended after modifier colon: 1=press, 2=repeat, 3=release\n\t// With flag 4, alternate keys are appended after codepoint with colons\n\tconst csiUMatch = data.match(/^\\x1b\\[(\\d+)(?::(\\d*))?(?::(\\d+))?(?:;(\\d+))?(?::(\\d+))?u$/);\n\tif (csiUMatch) {\n\t\tconst codepoint = parseInt(csiUMatch[1]!, 10);\n\t\tconst shiftedKey = csiUMatch[2] && csiUMatch[2].length > 0 ? parseInt(csiUMatch[2], 10) : undefined;\n\t\tconst baseLayoutKey = csiUMatch[3] ? parseInt(csiUMatch[3], 10) : undefined;\n\t\tconst modValue = csiUMatch[4] ? parseInt(csiUMatch[4], 10) : 1;\n\t\tconst eventType = parseEventType(csiUMatch[5]);\n\t\t_lastEventType = eventType;\n\t\treturn { codepoint, shiftedKey, baseLayoutKey, modifier: modValue - 1, eventType };\n\t}\n\n\t// Arrow keys with modifier: \\x1b[1;<mod>A/B/C/D or \\x1b[1;<mod>:<event>A/B/C/D\n\tconst arrowMatch = data.match(/^\\x1b\\[1;(\\d+)(?::(\\d+))?([ABCD])$/);\n\tif (arrowMatch) {\n\t\tconst modValue = parseInt(arrowMatch[1]!, 10);\n\t\tconst eventType = parseEventType(arrowMatch[2]);\n\t\tconst arrowCodes: Record<string, number> = { A: -1, B: -2, C: -3, D: -4 };\n\t\t_lastEventType = eventType;\n\t\treturn { codepoint: arrowCodes[arrowMatch[3]!]!, modifier: modValue - 1, eventType };\n\t}\n\n\t// Functional keys: \\x1b[<num>~ or \\x1b[<num>;<mod>~ or \\x1b[<num>;<mod>:<event>~\n\tconst funcMatch = data.match(/^\\x1b\\[(\\d+)(?:;(\\d+))?(?::(\\d+))?~$/);\n\tif (funcMatch) {\n\t\tconst keyNum = parseInt(funcMatch[1]!, 10);\n\t\tconst modValue = funcMatch[2] ? parseInt(funcMatch[2], 10) : 1;\n\t\tconst eventType = parseEventType(funcMatch[3]);\n\t\tconst funcCodes: Record<number, number> = {\n\t\t\t2: FUNCTIONAL_CODEPOINTS.insert,\n\t\t\t3: FUNCTIONAL_CODEPOINTS.delete,\n\t\t\t5: FUNCTIONAL_CODEPOINTS.pageUp,\n\t\t\t6: FUNCTIONAL_CODEPOINTS.pageDown,\n\t\t\t7: FUNCTIONAL_CODEPOINTS.home,\n\t\t\t8: FUNCTIONAL_CODEPOINTS.end,\n\t\t};\n\t\tconst codepoint = funcCodes[keyNum];\n\t\tif (codepoint !== undefined) {\n\t\t\t_lastEventType = eventType;\n\t\t\treturn { codepoint, modifier: modValue - 1, eventType };\n\t\t}\n\t}\n\n\t// Home/End with modifier: \\x1b[1;<mod>H/F or \\x1b[1;<mod>:<event>H/F\n\tconst homeEndMatch = data.match(/^\\x1b\\[1;(\\d+)(?::(\\d+))?([HF])$/);\n\tif (homeEndMatch) {\n\t\tconst modValue = parseInt(homeEndMatch[1]!, 10);\n\t\tconst eventType = parseEventType(homeEndMatch[2]);\n\t\tconst codepoint = homeEndMatch[3] === \"H\" ? FUNCTIONAL_CODEPOINTS.home : FUNCTIONAL_CODEPOINTS.end;\n\t\t_lastEventType = eventType;\n\t\treturn { codepoint, modifier: modValue - 1, eventType };\n\t}\n\n\treturn null;\n}\n\nfunction matchesKittySequence(data: string, expectedCodepoint: number, expectedModifier: number): boolean {\n\tconst parsed = parseKittySequence(data);\n\tif (!parsed) return false;\n\tconst actualMod = parsed.modifier & ~LOCK_MASK;\n\tconst expectedMod = expectedModifier & ~LOCK_MASK;\n\n\t// Check if modifiers match\n\tif (actualMod !== expectedMod) return false;\n\n\tconst normalizedCodepoint = normalizeKittyFunctionalCodepoint(parsed.codepoint);\n\tconst normalizedExpectedCodepoint = normalizeKittyFunctionalCodepoint(expectedCodepoint);\n\n\t// Primary match: codepoint matches directly after normalizing functional keys\n\tif (normalizedCodepoint === normalizedExpectedCodepoint) return true;\n\n\t// Alternate match: use base layout key for non-Latin keyboard layouts.\n\t// This allows Ctrl+С (Cyrillic) to match Ctrl+c (Latin) when terminal reports\n\t// the base layout key (the key in standard PC-101 layout).\n\t//\n\t// Only fall back to base layout key when the codepoint is NOT already a\n\t// recognized Latin letter (a-z) or symbol (e.g., /, -, [, ;, etc.).\n\t// When the codepoint is a recognized key, it is authoritative regardless\n\t// of physical key position. This prevents remapped layouts (Dvorak, Colemak,\n\t// xremap, etc.) from causing false matches: both letters and symbols move\n\t// to different physical positions, so Ctrl+K could falsely match Ctrl+V\n\t// (letter remapping) and Ctrl+/ could falsely match Ctrl+[ (symbol remapping)\n\t// if the base layout key were always considered.\n\tif (parsed.baseLayoutKey !== undefined && parsed.baseLayoutKey === expectedCodepoint) {\n\t\tconst cp = normalizedCodepoint;\n\t\tconst isLatinLetter = cp >= 97 && cp <= 122; // a-z\n\t\tconst isKnownSymbol = SYMBOL_KEYS.has(String.fromCharCode(cp));\n\t\tif (!isLatinLetter && !isKnownSymbol) return true;\n\t}\n\n\treturn false;\n}\n\nfunction parseModifyOtherKeysSequence(data: string): ParsedModifyOtherKeysSequence | null {\n\tconst match = data.match(/^\\x1b\\[27;(\\d+);(\\d+)~$/);\n\tif (!match) return null;\n\tconst modValue = parseInt(match[1]!, 10);\n\tconst codepoint = parseInt(match[2]!, 10);\n\treturn { codepoint, modifier: modValue - 1 };\n}\n\n/**\n * Match xterm modifyOtherKeys format: CSI 27 ; modifiers ; keycode ~\n * This is used by terminals when Kitty protocol is not enabled.\n * Modifier values are 1-indexed: 2=shift, 3=alt, 5=ctrl, etc.\n */\nfunction matchesModifyOtherKeys(data: string, expectedKeycode: number, expectedModifier: number): boolean {\n\tconst parsed = parseModifyOtherKeysSequence(data);\n\tif (!parsed) return false;\n\treturn parsed.codepoint === expectedKeycode && parsed.modifier === expectedModifier;\n}\n\nfunction isWindowsTerminalSession(): boolean {\n\treturn (\n\t\tBoolean(process.env.WT_SESSION) && !process.env.SSH_CONNECTION && !process.env.SSH_CLIENT && !process.env.SSH_TTY\n\t);\n}\n\n/**\n * Raw 0x08 (BS) is ambiguous in legacy terminals.\n *\n * - Windows Terminal uses it for Ctrl+Backspace.\n * - Some legacy terminals and tmux setups send it for plain Backspace.\n *\n * Prefer explicit Kitty / CSI-u / modifyOtherKeys sequences whenever they are\n * available. Fall back to a Windows Terminal heuristic only for raw BS bytes.\n */\nfunction matchesRawBackspace(data: string, expectedModifier: number): boolean {\n\tif (data === \"\\x7f\") return expectedModifier === 0;\n\tif (data !== \"\\x08\") return false;\n\treturn isWindowsTerminalSession() ? expectedModifier === MODIFIERS.ctrl : expectedModifier === 0;\n}\n\n// =============================================================================\n// Generic Key Matching\n// =============================================================================\n\n/**\n * Get the control character for a key.\n * Uses the universal formula: code & 0x1f (mask to lower 5 bits)\n *\n * Works for:\n * - Letters a-z → 1-26\n * - Symbols [\\]_ → 27, 28, 29, 31\n * - Also maps - to same as _ (same physical key on US keyboards)\n */\nfunction rawCtrlChar(key: string): string | null {\n\tconst char = key.toLowerCase();\n\tconst code = char.charCodeAt(0);\n\tif ((code >= 97 && code <= 122) || char === \"[\" || char === \"\\\\\" || char === \"]\" || char === \"_\") {\n\t\treturn String.fromCharCode(code & 0x1f);\n\t}\n\t// Handle - as _ (same physical key on US keyboards)\n\tif (char === \"-\") {\n\t\treturn String.fromCharCode(31); // Same as Ctrl+_\n\t}\n\treturn null;\n}\n\nfunction isDigitKey(key: string): boolean {\n\treturn key >= \"0\" && key <= \"9\";\n}\n\nfunction matchesPrintableModifyOtherKeys(data: string, expectedKeycode: number, expectedModifier: number): boolean {\n\tif (expectedModifier === 0) return false;\n\treturn matchesModifyOtherKeys(data, expectedKeycode, expectedModifier);\n}\n\nfunction formatKeyNameWithModifiers(keyName: string, modifier: number): string | undefined {\n\tconst mods: string[] = [];\n\tconst effectiveMod = modifier & ~LOCK_MASK;\n\tconst supportedModifierMask = MODIFIERS.shift | MODIFIERS.ctrl | MODIFIERS.alt;\n\tif ((effectiveMod & ~supportedModifierMask) !== 0) return undefined;\n\tif (effectiveMod & MODIFIERS.shift) mods.push(\"shift\");\n\tif (effectiveMod & MODIFIERS.ctrl) mods.push(\"ctrl\");\n\tif (effectiveMod & MODIFIERS.alt) mods.push(\"alt\");\n\treturn mods.length > 0 ? `${mods.join(\"+\")}+${keyName}` : keyName;\n}\n\nfunction parseKeyId(keyId: string): { key: string; ctrl: boolean; shift: boolean; alt: boolean } | null {\n\tconst parts = keyId.toLowerCase().split(\"+\");\n\tconst key = parts[parts.length - 1];\n\tif (!key) return null;\n\treturn {\n\t\tkey,\n\t\tctrl: parts.includes(\"ctrl\"),\n\t\tshift: parts.includes(\"shift\"),\n\t\talt: parts.includes(\"alt\"),\n\t};\n}\n\n/**\n * Match input data against a key identifier string.\n *\n * Supported key identifiers:\n * - Single keys: \"escape\", \"tab\", \"enter\", \"backspace\", \"delete\", \"home\", \"end\", \"space\"\n * - Arrow keys: \"up\", \"down\", \"left\", \"right\"\n * - Ctrl combinations: \"ctrl+c\", \"ctrl+z\", etc.\n * - Shift combinations: \"shift+tab\", \"shift+enter\"\n * - Alt combinations: \"alt+enter\", \"alt+backspace\"\n * - Combined modifiers: \"shift+ctrl+p\", \"ctrl+alt+x\"\n *\n * Use the Key helper for autocomplete: Key.ctrl(\"c\"), Key.escape, Key.ctrlShift(\"p\")\n *\n * @param data - Raw input data from terminal\n * @param keyId - Key identifier (e.g., \"ctrl+c\", \"escape\", Key.ctrl(\"c\"))\n */\nexport function matchesKey(data: string, keyId: KeyId): boolean {\n\tconst parsed = parseKeyId(keyId);\n\tif (!parsed) return false;\n\n\tconst { key, ctrl, shift, alt } = parsed;\n\tlet modifier = 0;\n\tif (shift) modifier |= MODIFIERS.shift;\n\tif (alt) modifier |= MODIFIERS.alt;\n\tif (ctrl) modifier |= MODIFIERS.ctrl;\n\n\tswitch (key) {\n\t\tcase \"escape\":\n\t\tcase \"esc\":\n\t\t\tif (modifier !== 0) return false;\n\t\t\treturn (\n\t\t\t\tdata === \"\\x1b\" ||\n\t\t\t\tmatchesKittySequence(data, CODEPOINTS.escape, 0) ||\n\t\t\t\tmatchesModifyOtherKeys(data, CODEPOINTS.escape, 0)\n\t\t\t);\n\n\t\tcase \"space\":\n\t\t\tif (!_kittyProtocolActive) {\n\t\t\t\tif (ctrl && !alt && !shift && data === \"\\x00\") {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (alt && !ctrl && !shift && data === \"\\x1b \") {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \" \" ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.space, 0) ||\n\t\t\t\t\tmatchesModifyOtherKeys(data, CODEPOINTS.space, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn (\n\t\t\t\tmatchesKittySequence(data, CODEPOINTS.space, modifier) ||\n\t\t\t\tmatchesModifyOtherKeys(data, CODEPOINTS.space, modifier)\n\t\t\t);\n\n\t\tcase \"tab\":\n\t\t\tif (shift && !ctrl && !alt) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[Z\" ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.tab, MODIFIERS.shift) ||\n\t\t\t\t\tmatchesModifyOtherKeys(data, CODEPOINTS.tab, MODIFIERS.shift)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn data === \"\\t\" || matchesKittySequence(data, CODEPOINTS.tab, 0);\n\t\t\t}\n\t\t\treturn (\n\t\t\t\tmatchesKittySequence(data, CODEPOINTS.tab, modifier) ||\n\t\t\t\tmatchesModifyOtherKeys(data, CODEPOINTS.tab, modifier)\n\t\t\t);\n\n\t\tcase \"enter\":\n\t\tcase \"return\":\n\t\t\tif (shift && !ctrl && !alt) {\n\t\t\t\t// CSI u sequences (standard Kitty protocol)\n\t\t\t\tif (\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, MODIFIERS.shift) ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, MODIFIERS.shift)\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\t// xterm modifyOtherKeys format (fallback when Kitty protocol not enabled)\n\t\t\t\tif (matchesModifyOtherKeys(data, CODEPOINTS.enter, MODIFIERS.shift)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\t// When Kitty protocol is active, legacy sequences are custom terminal mappings\n\t\t\t\t// \\x1b\\r = Kitty's \"map shift+enter send_text all \\e\\r\"\n\t\t\t\t// \\n = Ghostty's \"keybind = shift+enter=text:\\n\"\n\t\t\t\tif (_kittyProtocolActive) {\n\t\t\t\t\treturn data === \"\\x1b\\r\" || data === \"\\n\";\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\t// CSI u sequences (standard Kitty protocol)\n\t\t\t\tif (\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, MODIFIERS.alt) ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, MODIFIERS.alt)\n\t\t\t\t) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\t// xterm modifyOtherKeys format (fallback when Kitty protocol not enabled)\n\t\t\t\tif (matchesModifyOtherKeys(data, CODEPOINTS.enter, MODIFIERS.alt)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\t// \\x1b\\r is alt+enter only in legacy mode (no Kitty protocol)\n\t\t\t\t// When Kitty protocol is active, alt+enter comes as CSI u sequence\n\t\t\t\tif (!_kittyProtocolActive) {\n\t\t\t\t\treturn data === \"\\x1b\\r\";\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\r\" ||\n\t\t\t\t\t(!_kittyProtocolActive && data === \"\\n\") ||\n\t\t\t\t\tdata === \"\\x1bOM\" || // SS3 M (numpad enter in some terminals)\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, 0) ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn (\n\t\t\t\tmatchesKittySequence(data, CODEPOINTS.enter, modifier) ||\n\t\t\t\tmatchesKittySequence(data, CODEPOINTS.kpEnter, modifier) ||\n\t\t\t\tmatchesModifyOtherKeys(data, CODEPOINTS.enter, modifier)\n\t\t\t);\n\n\t\tcase \"backspace\":\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\tif (data === \"\\x1b\\x7f\" || data === \"\\x1b\\b\") {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn (\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.backspace, MODIFIERS.alt) ||\n\t\t\t\t\tmatchesModifyOtherKeys(data, CODEPOINTS.backspace, MODIFIERS.alt)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (ctrl && !alt && !shift) {\n\t\t\t\t// Legacy raw 0x08 is ambiguous: it can be Ctrl+Backspace on Windows\n\t\t\t\t// Terminal or plain Backspace on other terminals, while also\n\t\t\t\t// overlapping with Ctrl+H.\n\t\t\t\tif (matchesRawBackspace(data, MODIFIERS.ctrl)) return true;\n\t\t\t\treturn (\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.backspace, MODIFIERS.ctrl) ||\n\t\t\t\t\tmatchesModifyOtherKeys(data, CODEPOINTS.backspace, MODIFIERS.ctrl)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tmatchesRawBackspace(data, 0) ||\n\t\t\t\t\tmatchesKittySequence(data, CODEPOINTS.backspace, 0) ||\n\t\t\t\t\tmatchesModifyOtherKeys(data, CODEPOINTS.backspace, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn (\n\t\t\t\tmatchesKittySequence(data, CODEPOINTS.backspace, modifier) ||\n\t\t\t\tmatchesModifyOtherKeys(data, CODEPOINTS.backspace, modifier)\n\t\t\t);\n\n\t\tcase \"insert\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tmatchesLegacySequence(data, LEGACY_KEY_SEQUENCES.insert) ||\n\t\t\t\t\tmatchesKittySequence(data, FUNCTIONAL_CODEPOINTS.insert, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (matchesLegacyModifierSequence(data, \"insert\", modifier)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.insert, modifier);\n\n\t\tcase \"delete\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tmatchesLegacySequence(data, LEGACY_KEY_SEQUENCES.delete) ||\n\t\t\t\t\tmatchesKittySequence(data, FUNCTIONAL_CODEPOINTS.delete, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (matchesLegacyModifierSequence(data, \"delete\", modifier)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.delete, modifier);\n\n\t\tcase \"clear\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn matchesLegacySequence(data, LEGACY_KEY_SEQUENCES.clear);\n\t\t\t}\n\t\t\treturn matchesLegacyModifierSequence(data, \"clear\", modifier);\n\n\t\tcase \"home\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tmatchesLegacySequence(data, LEGACY_KEY_SEQUENCES.home) ||\n\t\t\t\t\tmatchesKittySequence(data, FUNCTIONAL_CODEPOINTS.home, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (matchesLegacyModifierSequence(data, \"home\", modifier)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.home, modifier);\n\n\t\tcase \"end\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tmatchesLegacySequence(data, LEGACY_KEY_SEQUENCES.end) ||\n\t\t\t\t\tmatchesKittySequence(data, FUNCTIONAL_CODEPOINTS.end, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (matchesLegacyModifierSequence(data, \"end\", modifier)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.end, modifier);\n\n\t\tcase \"pageup\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tmatchesLegacySequence(data, LEGACY_KEY_SEQUENCES.pageUp) ||\n\t\t\t\t\tmatchesKittySequence(data, FUNCTIONAL_CODEPOINTS.pageUp, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (matchesLegacyModifierSequence(data, \"pageUp\", modifier)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.pageUp, modifier);\n\n\t\tcase \"pagedown\":\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tmatchesLegacySequence(data, LEGACY_KEY_SEQUENCES.pageDown) ||\n\t\t\t\t\tmatchesKittySequence(data, FUNCTIONAL_CODEPOINTS.pageDown, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (matchesLegacyModifierSequence(data, \"pageDown\", modifier)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.pageDown, modifier);\n\n\t\tcase \"up\":\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn data === \"\\x1bp\" || matchesKittySequence(data, ARROW_CODEPOINTS.up, MODIFIERS.alt);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tmatchesLegacySequence(data, LEGACY_KEY_SEQUENCES.up) ||\n\t\t\t\t\tmatchesKittySequence(data, ARROW_CODEPOINTS.up, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (matchesLegacyModifierSequence(data, \"up\", modifier)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.up, modifier);\n\n\t\tcase \"down\":\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn data === \"\\x1bn\" || matchesKittySequence(data, ARROW_CODEPOINTS.down, MODIFIERS.alt);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tmatchesLegacySequence(data, LEGACY_KEY_SEQUENCES.down) ||\n\t\t\t\t\tmatchesKittySequence(data, ARROW_CODEPOINTS.down, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (matchesLegacyModifierSequence(data, \"down\", modifier)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.down, modifier);\n\n\t\tcase \"left\":\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[1;3D\" ||\n\t\t\t\t\t(!_kittyProtocolActive && data === \"\\x1bB\") ||\n\t\t\t\t\tdata === \"\\x1bb\" ||\n\t\t\t\t\tmatchesKittySequence(data, ARROW_CODEPOINTS.left, MODIFIERS.alt)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (ctrl && !alt && !shift) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[1;5D\" ||\n\t\t\t\t\tmatchesLegacyModifierSequence(data, \"left\", MODIFIERS.ctrl) ||\n\t\t\t\t\tmatchesKittySequence(data, ARROW_CODEPOINTS.left, MODIFIERS.ctrl)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tmatchesLegacySequence(data, LEGACY_KEY_SEQUENCES.left) ||\n\t\t\t\t\tmatchesKittySequence(data, ARROW_CODEPOINTS.left, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (matchesLegacyModifierSequence(data, \"left\", modifier)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.left, modifier);\n\n\t\tcase \"right\":\n\t\t\tif (alt && !ctrl && !shift) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[1;3C\" ||\n\t\t\t\t\t(!_kittyProtocolActive && data === \"\\x1bF\") ||\n\t\t\t\t\tdata === \"\\x1bf\" ||\n\t\t\t\t\tmatchesKittySequence(data, ARROW_CODEPOINTS.right, MODIFIERS.alt)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (ctrl && !alt && !shift) {\n\t\t\t\treturn (\n\t\t\t\t\tdata === \"\\x1b[1;5C\" ||\n\t\t\t\t\tmatchesLegacyModifierSequence(data, \"right\", MODIFIERS.ctrl) ||\n\t\t\t\t\tmatchesKittySequence(data, ARROW_CODEPOINTS.right, MODIFIERS.ctrl)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (modifier === 0) {\n\t\t\t\treturn (\n\t\t\t\t\tmatchesLegacySequence(data, LEGACY_KEY_SEQUENCES.right) ||\n\t\t\t\t\tmatchesKittySequence(data, ARROW_CODEPOINTS.right, 0)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (matchesLegacyModifierSequence(data, \"right\", modifier)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn matchesKittySequence(data, ARROW_CODEPOINTS.right, modifier);\n\n\t\tcase \"f1\":\n\t\tcase \"f2\":\n\t\tcase \"f3\":\n\t\tcase \"f4\":\n\t\tcase \"f5\":\n\t\tcase \"f6\":\n\t\tcase \"f7\":\n\t\tcase \"f8\":\n\t\tcase \"f9\":\n\t\tcase \"f10\":\n\t\tcase \"f11\":\n\t\tcase \"f12\": {\n\t\t\tif (modifier !== 0) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tconst functionKey = key as keyof typeof LEGACY_KEY_SEQUENCES;\n\t\t\treturn matchesLegacySequence(data, LEGACY_KEY_SEQUENCES[functionKey]);\n\t\t}\n\t}\n\n\t// Handle single letter/digit keys and symbols\n\tif (key.length === 1 && ((key >= \"a\" && key <= \"z\") || isDigitKey(key) || SYMBOL_KEYS.has(key))) {\n\t\tconst codepoint = key.charCodeAt(0);\n\t\tconst rawCtrl = rawCtrlChar(key);\n\t\tconst isLetter = key >= \"a\" && key <= \"z\";\n\t\tconst isDigit = isDigitKey(key);\n\n\t\tif (ctrl && alt && !shift && !_kittyProtocolActive && rawCtrl) {\n\t\t\t// Legacy: ctrl+alt+key is ESC followed by the control character\n\t\t\treturn data === `\\x1b${rawCtrl}`;\n\t\t}\n\n\t\tif (alt && !ctrl && !shift && !_kittyProtocolActive && (isLetter || isDigit)) {\n\t\t\t// Legacy: alt+letter/digit is ESC followed by the key\n\t\t\tif (data === `\\x1b${key}`) return true;\n\t\t}\n\n\t\tif (ctrl && !shift && !alt) {\n\t\t\t// Legacy: ctrl+key sends the control character\n\t\t\tif (rawCtrl && data === rawCtrl) return true;\n\t\t\treturn (\n\t\t\t\tmatchesKittySequence(data, codepoint, MODIFIERS.ctrl) ||\n\t\t\t\tmatchesPrintableModifyOtherKeys(data, codepoint, MODIFIERS.ctrl)\n\t\t\t);\n\t\t}\n\n\t\tif (ctrl && shift && !alt) {\n\t\t\treturn (\n\t\t\t\tmatchesKittySequence(data, codepoint, MODIFIERS.shift + MODIFIERS.ctrl) ||\n\t\t\t\tmatchesPrintableModifyOtherKeys(data, codepoint, MODIFIERS.shift + MODIFIERS.ctrl)\n\t\t\t);\n\t\t}\n\n\t\tif (shift && !ctrl && !alt) {\n\t\t\t// Legacy: shift+letter produces uppercase\n\t\t\tif (isLetter && data === key.toUpperCase()) return true;\n\t\t\treturn (\n\t\t\t\tmatchesKittySequence(data, codepoint, MODIFIERS.shift) ||\n\t\t\t\tmatchesPrintableModifyOtherKeys(data, codepoint, MODIFIERS.shift)\n\t\t\t);\n\t\t}\n\n\t\tif (modifier !== 0) {\n\t\t\treturn (\n\t\t\t\tmatchesKittySequence(data, codepoint, modifier) ||\n\t\t\t\tmatchesPrintableModifyOtherKeys(data, codepoint, modifier)\n\t\t\t);\n\t\t}\n\n\t\t// Check both raw char and Kitty sequence (needed for release events)\n\t\treturn data === key || matchesKittySequence(data, codepoint, 0);\n\t}\n\n\treturn false;\n}\n\n/**\n * Parse input data and return the key identifier if recognized.\n *\n * @param data - Raw input data from terminal\n * @returns Key identifier string (e.g., \"ctrl+c\") or undefined\n */\nfunction formatParsedKey(codepoint: number, modifier: number, baseLayoutKey?: number): string | undefined {\n\tconst normalizedCodepoint = normalizeKittyFunctionalCodepoint(codepoint);\n\n\t// Use base layout key only when codepoint is not a recognized Latin\n\t// letter (a-z), digit (0-9), or symbol (/, -, [, ;, etc.). For those,\n\t// the codepoint is authoritative regardless of physical key position.\n\t// This prevents remapped layouts (Dvorak, Colemak, xremap, etc.) from\n\t// reporting the wrong key name based on the QWERTY physical position.\n\tconst isLatinLetter = normalizedCodepoint >= 97 && normalizedCodepoint <= 122; // a-z\n\tconst isDigit = normalizedCodepoint >= 48 && normalizedCodepoint <= 57; // 0-9\n\tconst isKnownSymbol = SYMBOL_KEYS.has(String.fromCharCode(normalizedCodepoint));\n\tconst effectiveCodepoint =\n\t\tisLatinLetter || isDigit || isKnownSymbol ? normalizedCodepoint : (baseLayoutKey ?? normalizedCodepoint);\n\n\tlet keyName: string | undefined;\n\tif (effectiveCodepoint === CODEPOINTS.escape) keyName = \"escape\";\n\telse if (effectiveCodepoint === CODEPOINTS.tab) keyName = \"tab\";\n\telse if (effectiveCodepoint === CODEPOINTS.enter || effectiveCodepoint === CODEPOINTS.kpEnter) keyName = \"enter\";\n\telse if (effectiveCodepoint === CODEPOINTS.space) keyName = \"space\";\n\telse if (effectiveCodepoint === CODEPOINTS.backspace) keyName = \"backspace\";\n\telse if (effectiveCodepoint === FUNCTIONAL_CODEPOINTS.delete) keyName = \"delete\";\n\telse if (effectiveCodepoint === FUNCTIONAL_CODEPOINTS.insert) keyName = \"insert\";\n\telse if (effectiveCodepoint === FUNCTIONAL_CODEPOINTS.home) keyName = \"home\";\n\telse if (effectiveCodepoint === FUNCTIONAL_CODEPOINTS.end) keyName = \"end\";\n\telse if (effectiveCodepoint === FUNCTIONAL_CODEPOINTS.pageUp) keyName = \"pageUp\";\n\telse if (effectiveCodepoint === FUNCTIONAL_CODEPOINTS.pageDown) keyName = \"pageDown\";\n\telse if (effectiveCodepoint === ARROW_CODEPOINTS.up) keyName = \"up\";\n\telse if (effectiveCodepoint === ARROW_CODEPOINTS.down) keyName = \"down\";\n\telse if (effectiveCodepoint === ARROW_CODEPOINTS.left) keyName = \"left\";\n\telse if (effectiveCodepoint === ARROW_CODEPOINTS.right) keyName = \"right\";\n\telse if (effectiveCodepoint >= 48 && effectiveCodepoint <= 57) keyName = String.fromCharCode(effectiveCodepoint);\n\telse if (effectiveCodepoint >= 97 && effectiveCodepoint <= 122) keyName = String.fromCharCode(effectiveCodepoint);\n\telse if (SYMBOL_KEYS.has(String.fromCharCode(effectiveCodepoint))) keyName = String.fromCharCode(effectiveCodepoint);\n\n\tif (!keyName) return undefined;\n\treturn formatKeyNameWithModifiers(keyName, modifier);\n}\n\nexport function parseKey(data: string): string | undefined {\n\tconst kitty = parseKittySequence(data);\n\tif (kitty) {\n\t\treturn formatParsedKey(kitty.codepoint, kitty.modifier, kitty.baseLayoutKey);\n\t}\n\n\tconst modifyOtherKeys = parseModifyOtherKeysSequence(data);\n\tif (modifyOtherKeys) {\n\t\treturn formatParsedKey(modifyOtherKeys.codepoint, modifyOtherKeys.modifier);\n\t}\n\n\t// Mode-aware legacy sequences\n\t// When Kitty protocol is active, ambiguous sequences are interpreted as custom terminal mappings:\n\t// - \\x1b\\r = shift+enter (Kitty mapping), not alt+enter\n\t// - \\n = shift+enter (Ghostty mapping)\n\tif (_kittyProtocolActive) {\n\t\tif (data === \"\\x1b\\r\" || data === \"\\n\") return \"shift+enter\";\n\t}\n\n\tconst legacySequenceKeyId = LEGACY_SEQUENCE_KEY_IDS[data];\n\tif (legacySequenceKeyId) return legacySequenceKeyId;\n\n\t// Legacy sequences (used when Kitty protocol is not active, or for unambiguous sequences)\n\tif (data === \"\\x1b\") return \"escape\";\n\tif (data === \"\\x1c\") return \"ctrl+\\\\\";\n\tif (data === \"\\x1d\") return \"ctrl+]\";\n\tif (data === \"\\x1f\") return \"ctrl+-\";\n\tif (data === \"\\x1b\\x1b\") return \"ctrl+alt+[\";\n\tif (data === \"\\x1b\\x1c\") return \"ctrl+alt+\\\\\";\n\tif (data === \"\\x1b\\x1d\") return \"ctrl+alt+]\";\n\tif (data === \"\\x1b\\x1f\") return \"ctrl+alt+-\";\n\tif (data === \"\\t\") return \"tab\";\n\tif (data === \"\\r\" || (!_kittyProtocolActive && data === \"\\n\") || data === \"\\x1bOM\") return \"enter\";\n\tif (data === \"\\x00\") return \"ctrl+space\";\n\tif (data === \" \") return \"space\";\n\tif (data === \"\\x7f\") return \"backspace\";\n\tif (data === \"\\x08\") return isWindowsTerminalSession() ? \"ctrl+backspace\" : \"backspace\";\n\tif (data === \"\\x1b[Z\") return \"shift+tab\";\n\tif (!_kittyProtocolActive && data === \"\\x1b\\r\") return \"alt+enter\";\n\tif (!_kittyProtocolActive && data === \"\\x1b \") return \"alt+space\";\n\tif (data === \"\\x1b\\x7f\" || data === \"\\x1b\\b\") return \"alt+backspace\";\n\tif (!_kittyProtocolActive && data === \"\\x1bB\") return \"alt+left\";\n\tif (!_kittyProtocolActive && data === \"\\x1bF\") return \"alt+right\";\n\tif (!_kittyProtocolActive && data.length === 2 && data[0] === \"\\x1b\") {\n\t\tconst code = data.charCodeAt(1);\n\t\tif (code >= 1 && code <= 26) {\n\t\t\treturn `ctrl+alt+${String.fromCharCode(code + 96)}`;\n\t\t}\n\t\t// Legacy alt+letter/digit (ESC followed by the key)\n\t\tif ((code >= 97 && code <= 122) || (code >= 48 && code <= 57)) {\n\t\t\treturn `alt+${String.fromCharCode(code)}`;\n\t\t}\n\t}\n\tif (data === \"\\x1b[A\") return \"up\";\n\tif (data === \"\\x1b[B\") return \"down\";\n\tif (data === \"\\x1b[C\") return \"right\";\n\tif (data === \"\\x1b[D\") return \"left\";\n\tif (data === \"\\x1b[H\" || data === \"\\x1bOH\") return \"home\";\n\tif (data === \"\\x1b[F\" || data === \"\\x1bOF\") return \"end\";\n\tif (data === \"\\x1b[3~\") return \"delete\";\n\tif (data === \"\\x1b[5~\") return \"pageUp\";\n\tif (data === \"\\x1b[6~\") return \"pageDown\";\n\n\t// Raw Ctrl+letter\n\tif (data.length === 1) {\n\t\tconst code = data.charCodeAt(0);\n\t\tif (code >= 1 && code <= 26) {\n\t\t\treturn `ctrl+${String.fromCharCode(code + 96)}`;\n\t\t}\n\t\tif (code >= 32 && code <= 126) {\n\t\t\treturn data;\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\n// =============================================================================\n// Kitty CSI-u Printable Decoding\n// =============================================================================\n\nconst KITTY_CSI_U_REGEX = /^\\x1b\\[(\\d+)(?::(\\d*))?(?::(\\d+))?(?:;(\\d+))?(?::(\\d+))?u$/;\nconst KITTY_PRINTABLE_ALLOWED_MODIFIERS = MODIFIERS.shift | LOCK_MASK;\n\n/**\n * Decode a Kitty CSI-u sequence into a printable character, if applicable.\n *\n * When Kitty keyboard protocol flag 1 (disambiguate) is active, terminals send\n * CSI-u sequences for all keys, including plain printable characters. This\n * function extracts the printable character from such sequences.\n *\n * Only accepts plain or Shift-modified keys. Rejects Ctrl, Alt, and unsupported\n * modifier combinations (those are handled by keybinding matching instead).\n * Prefers the shifted keycode when Shift is held and a shifted key is reported.\n *\n * @param data - Raw input data from terminal\n * @returns The printable character, or undefined if not a printable CSI-u sequence\n */\nexport function decodeKittyPrintable(data: string): string | undefined {\n\tconst match = data.match(KITTY_CSI_U_REGEX);\n\tif (!match) return undefined;\n\n\t// CSI-u groups: <codepoint>[:<shifted>[:<base>]];<mod>[:<event>]u\n\tconst codepoint = Number.parseInt(match[1] ?? \"\", 10);\n\tif (!Number.isFinite(codepoint)) return undefined;\n\n\tconst shiftedKey = match[2] && match[2].length > 0 ? Number.parseInt(match[2], 10) : undefined;\n\tconst modValue = match[4] ? Number.parseInt(match[4], 10) : 1;\n\t// Modifiers are 1-indexed in CSI-u; normalize to our bitmask.\n\tconst modifier = Number.isFinite(modValue) ? modValue - 1 : 0;\n\n\t// Only accept printable CSI-u input for plain or Shift-modified text keys.\n\t// Reject unsupported modifier bits (e.g. Super/Meta) to avoid inserting\n\t// characters from modifier-only terminal events.\n\tif ((modifier & ~KITTY_PRINTABLE_ALLOWED_MODIFIERS) !== 0) return undefined;\n\tif (modifier & (MODIFIERS.alt | MODIFIERS.ctrl)) return undefined;\n\n\t// Prefer the shifted keycode when Shift is held.\n\tlet effectiveCodepoint = codepoint;\n\tif (modifier & MODIFIERS.shift && typeof shiftedKey === \"number\") {\n\t\teffectiveCodepoint = shiftedKey;\n\t}\n\teffectiveCodepoint = normalizeKittyFunctionalCodepoint(effectiveCodepoint);\n\t// Drop control characters or invalid codepoints.\n\tif (!Number.isFinite(effectiveCodepoint) || effectiveCodepoint < 32) return undefined;\n\n\ttry {\n\t\treturn String.fromCodePoint(effectiveCodepoint);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"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"}
|