@mariozechner/pi-tui 0.25.3 → 0.25.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"editor.js","sourceRoot":"","sources":["../../src/components/editor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AutocompleteProvider, CombinedAutocompleteProvider } from \"../autocomplete.js\";\nimport {\n\tisAltBackspace,\n\tisAltEnter,\n\tisAltLeft,\n\tisAltRight,\n\tisArrowDown,\n\tisArrowLeft,\n\tisArrowRight,\n\tisArrowUp,\n\tisBackspace,\n\tisCtrlA,\n\tisCtrlC,\n\tisCtrlE,\n\tisCtrlK,\n\tisCtrlLeft,\n\tisCtrlRight,\n\tisCtrlU,\n\tisCtrlW,\n\tisDelete,\n\tisEnd,\n\tisEnter,\n\tisEscape,\n\tisHome,\n\tisShiftEnter,\n\tisTab,\n} from \"../keys.js\";\nimport type { Component } from \"../tui.js\";\nimport { visibleWidth } from \"../utils.js\";\nimport { SelectList, type SelectListTheme } from \"./select-list.js\";\n\n// Grapheme segmenter for proper Unicode iteration (handles emojis, etc.)\nconst segmenter = new Intl.Segmenter();\n\ninterface EditorState {\n\tlines: string[];\n\tcursorLine: number;\n\tcursorCol: number;\n}\n\ninterface LayoutLine {\n\ttext: string;\n\thasCursor: boolean;\n\tcursorPos?: number;\n}\n\nexport interface EditorTheme {\n\tborderColor: (str: string) => string;\n\tselectList: SelectListTheme;\n}\n\nexport class Editor implements Component {\n\tprivate state: EditorState = {\n\t\tlines: [\"\"],\n\t\tcursorLine: 0,\n\t\tcursorCol: 0,\n\t};\n\n\tprivate theme: EditorTheme;\n\n\t// Store last render width for cursor navigation\n\tprivate lastWidth: number = 80;\n\n\t// Border color (can be changed dynamically)\n\tpublic borderColor: (str: string) => string;\n\n\t// Autocomplete support\n\tprivate autocompleteProvider?: AutocompleteProvider;\n\tprivate autocompleteList?: SelectList;\n\tprivate isAutocompleting: boolean = false;\n\tprivate autocompletePrefix: string = \"\";\n\n\t// Paste tracking for large pastes\n\tprivate pastes: Map<number, string> = new Map();\n\tprivate pasteCounter: number = 0;\n\n\t// Bracketed paste mode buffering\n\tprivate pasteBuffer: string = \"\";\n\tprivate isInPaste: boolean = false;\n\n\t// Prompt history for up/down navigation\n\tprivate history: string[] = [];\n\tprivate historyIndex: number = -1; // -1 = not browsing, 0 = most recent, 1 = older, etc.\n\n\tpublic onSubmit?: (text: string) => void;\n\tpublic onChange?: (text: string) => void;\n\tpublic disableSubmit: boolean = false;\n\n\tconstructor(theme: EditorTheme) {\n\t\tthis.theme = theme;\n\t\tthis.borderColor = theme.borderColor;\n\t}\n\n\tsetAutocompleteProvider(provider: AutocompleteProvider): void {\n\t\tthis.autocompleteProvider = provider;\n\t}\n\n\t/**\n\t * Add a prompt to history for up/down arrow navigation.\n\t * Called after successful submission.\n\t */\n\taddToHistory(text: string): void {\n\t\tconst trimmed = text.trim();\n\t\tif (!trimmed) return;\n\t\t// Don't add consecutive duplicates\n\t\tif (this.history.length > 0 && this.history[0] === trimmed) return;\n\t\tthis.history.unshift(trimmed);\n\t\t// Limit history size\n\t\tif (this.history.length > 100) {\n\t\t\tthis.history.pop();\n\t\t}\n\t}\n\n\tprivate isEditorEmpty(): boolean {\n\t\treturn this.state.lines.length === 1 && this.state.lines[0] === \"\";\n\t}\n\n\tprivate isOnFirstVisualLine(): boolean {\n\t\tconst visualLines = this.buildVisualLineMap(this.lastWidth);\n\t\tconst currentVisualLine = this.findCurrentVisualLine(visualLines);\n\t\treturn currentVisualLine === 0;\n\t}\n\n\tprivate isOnLastVisualLine(): boolean {\n\t\tconst visualLines = this.buildVisualLineMap(this.lastWidth);\n\t\tconst currentVisualLine = this.findCurrentVisualLine(visualLines);\n\t\treturn currentVisualLine === visualLines.length - 1;\n\t}\n\n\tprivate navigateHistory(direction: 1 | -1): void {\n\t\tif (this.history.length === 0) return;\n\n\t\tconst newIndex = this.historyIndex - direction; // Up(-1) increases index, Down(1) decreases\n\t\tif (newIndex < -1 || newIndex >= this.history.length) return;\n\n\t\tthis.historyIndex = newIndex;\n\n\t\tif (this.historyIndex === -1) {\n\t\t\t// Returned to \"current\" state - clear editor\n\t\t\tthis.setTextInternal(\"\");\n\t\t} else {\n\t\t\tthis.setTextInternal(this.history[this.historyIndex] || \"\");\n\t\t}\n\t}\n\n\t/** Internal setText that doesn't reset history state - used by navigateHistory */\n\tprivate setTextInternal(text: string): void {\n\t\tconst lines = text.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\").split(\"\\n\");\n\t\tthis.state.lines = lines.length === 0 ? [\"\"] : lines;\n\t\tthis.state.cursorLine = this.state.lines.length - 1;\n\t\tthis.state.cursorCol = this.state.lines[this.state.cursorLine]?.length || 0;\n\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\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\t// Store width for cursor navigation\n\t\tthis.lastWidth = width;\n\n\t\tconst horizontal = this.borderColor(\"─\");\n\n\t\t// Layout the text - use full width\n\t\tconst layoutLines = this.layoutText(width);\n\n\t\tconst result: string[] = [];\n\n\t\t// Render top border\n\t\tresult.push(horizontal.repeat(width));\n\n\t\t// Render each layout line\n\t\tfor (const layoutLine of layoutLines) {\n\t\t\tlet displayText = layoutLine.text;\n\t\t\tlet lineVisibleWidth = visibleWidth(layoutLine.text);\n\n\t\t\t// Add cursor if this line has it\n\t\t\tif (layoutLine.hasCursor && layoutLine.cursorPos !== undefined) {\n\t\t\t\tconst before = displayText.slice(0, layoutLine.cursorPos);\n\t\t\t\tconst after = displayText.slice(layoutLine.cursorPos);\n\n\t\t\t\tif (after.length > 0) {\n\t\t\t\t\t// Cursor is on a character (grapheme) - replace it with highlighted version\n\t\t\t\t\t// Get the first grapheme from 'after'\n\t\t\t\t\tconst afterGraphemes = [...segmenter.segment(after)];\n\t\t\t\t\tconst firstGrapheme = afterGraphemes[0]?.segment || \"\";\n\t\t\t\t\tconst restAfter = after.slice(firstGrapheme.length);\n\t\t\t\t\tconst cursor = `\\x1b[7m${firstGrapheme}\\x1b[0m`;\n\t\t\t\t\tdisplayText = before + cursor + restAfter;\n\t\t\t\t\t// lineVisibleWidth stays the same - we're replacing, not adding\n\t\t\t\t} else {\n\t\t\t\t\t// Cursor is at the end - check if we have room for the space\n\t\t\t\t\tif (lineVisibleWidth < width) {\n\t\t\t\t\t\t// We have room - add highlighted space\n\t\t\t\t\t\tconst cursor = \"\\x1b[7m \\x1b[0m\";\n\t\t\t\t\t\tdisplayText = before + cursor;\n\t\t\t\t\t\t// lineVisibleWidth increases by 1 - we're adding a space\n\t\t\t\t\t\tlineVisibleWidth = lineVisibleWidth + 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Line is at full width - use reverse video on last grapheme if possible\n\t\t\t\t\t\t// or just show cursor at the end without adding space\n\t\t\t\t\t\tconst beforeGraphemes = [...segmenter.segment(before)];\n\t\t\t\t\t\tif (beforeGraphemes.length > 0) {\n\t\t\t\t\t\t\tconst lastGrapheme = beforeGraphemes[beforeGraphemes.length - 1]?.segment || \"\";\n\t\t\t\t\t\t\tconst cursor = `\\x1b[7m${lastGrapheme}\\x1b[0m`;\n\t\t\t\t\t\t\t// Rebuild 'before' without the last grapheme\n\t\t\t\t\t\t\tconst beforeWithoutLast = beforeGraphemes\n\t\t\t\t\t\t\t\t.slice(0, -1)\n\t\t\t\t\t\t\t\t.map((g) => g.segment)\n\t\t\t\t\t\t\t\t.join(\"\");\n\t\t\t\t\t\t\tdisplayText = beforeWithoutLast + cursor;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// lineVisibleWidth stays the same\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Calculate padding based on actual visible width\n\t\t\tconst padding = \" \".repeat(Math.max(0, width - lineVisibleWidth));\n\n\t\t\t// Render the line (no side borders, just horizontal lines above and below)\n\t\t\tresult.push(displayText + padding);\n\t\t}\n\n\t\t// Render bottom border\n\t\tresult.push(horizontal.repeat(width));\n\n\t\t// Add autocomplete list if active\n\t\tif (this.isAutocompleting && this.autocompleteList) {\n\t\t\tconst autocompleteResult = this.autocompleteList.render(width);\n\t\t\tresult.push(...autocompleteResult);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\thandleInput(data: string): void {\n\t\t// Handle bracketed paste mode\n\t\t// Start of paste: \\x1b[200~\n\t\t// End of paste: \\x1b[201~\n\n\t\t// Check if we're starting a bracketed paste\n\t\tif (data.includes(\"\\x1b[200~\")) {\n\t\t\tthis.isInPaste = true;\n\t\t\tthis.pasteBuffer = \"\";\n\t\t\t// Remove the start marker and keep the rest\n\t\t\tdata = data.replace(\"\\x1b[200~\", \"\");\n\t\t}\n\n\t\t// If we're in a paste, buffer the data\n\t\tif (this.isInPaste) {\n\t\t\t// Append data to buffer first (end marker could be split across chunks)\n\t\t\tthis.pasteBuffer += data;\n\n\t\t\t// Check if the accumulated buffer contains the end marker\n\t\t\tconst endIndex = this.pasteBuffer.indexOf(\"\\x1b[201~\");\n\t\t\tif (endIndex !== -1) {\n\t\t\t\t// Extract content before the end marker\n\t\t\t\tconst pasteContent = this.pasteBuffer.substring(0, endIndex);\n\n\t\t\t\t// Process the complete paste\n\t\t\t\tthis.handlePaste(pasteContent);\n\n\t\t\t\t// Reset paste state\n\t\t\t\tthis.isInPaste = false;\n\n\t\t\t\t// Process any remaining data after the end marker\n\t\t\t\tconst remaining = this.pasteBuffer.substring(endIndex + 6); // 6 = length of \\x1b[201~\n\t\t\t\tthis.pasteBuffer = \"\";\n\n\t\t\t\tif (remaining.length > 0) {\n\t\t\t\t\tthis.handleInput(remaining);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\t// Still accumulating, wait for more data\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Handle special key combinations first\n\n\t\t// Ctrl+C - Exit (let parent handle this)\n\t\tif (isCtrlC(data)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle autocomplete special keys first (but don't block other input)\n\t\tif (this.isAutocompleting && this.autocompleteList) {\n\t\t\t// Escape - cancel autocomplete\n\t\t\tif (isEscape(data)) {\n\t\t\t\tthis.cancelAutocomplete();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Let the autocomplete list handle navigation and selection\n\t\t\telse if (isArrowUp(data) || isArrowDown(data) || isEnter(data) || isTab(data)) {\n\t\t\t\t// Only pass arrow keys to the list, not Enter/Tab (we handle those directly)\n\t\t\t\tif (isArrowUp(data) || isArrowDown(data)) {\n\t\t\t\t\tthis.autocompleteList.handleInput(data);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// If Tab was pressed, always apply the selection\n\t\t\t\tif (isTab(data)) {\n\t\t\t\t\tconst selected = this.autocompleteList.getSelectedItem();\n\t\t\t\t\tif (selected && this.autocompleteProvider) {\n\t\t\t\t\t\tconst result = this.autocompleteProvider.applyCompletion(\n\t\t\t\t\t\t\tthis.state.lines,\n\t\t\t\t\t\t\tthis.state.cursorLine,\n\t\t\t\t\t\t\tthis.state.cursorCol,\n\t\t\t\t\t\t\tselected,\n\t\t\t\t\t\t\tthis.autocompletePrefix,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tthis.state.lines = result.lines;\n\t\t\t\t\t\tthis.state.cursorLine = result.cursorLine;\n\t\t\t\t\t\tthis.state.cursorCol = result.cursorCol;\n\n\t\t\t\t\t\tthis.cancelAutocomplete();\n\n\t\t\t\t\t\tif (this.onChange) {\n\t\t\t\t\t\t\tthis.onChange(this.getText());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// If Enter was pressed on a slash command, apply completion and submit\n\t\t\t\tif (isEnter(data) && this.autocompletePrefix.startsWith(\"/\")) {\n\t\t\t\t\tconst selected = this.autocompleteList.getSelectedItem();\n\t\t\t\t\tif (selected && this.autocompleteProvider) {\n\t\t\t\t\t\tconst result = this.autocompleteProvider.applyCompletion(\n\t\t\t\t\t\t\tthis.state.lines,\n\t\t\t\t\t\t\tthis.state.cursorLine,\n\t\t\t\t\t\t\tthis.state.cursorCol,\n\t\t\t\t\t\t\tselected,\n\t\t\t\t\t\t\tthis.autocompletePrefix,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tthis.state.lines = result.lines;\n\t\t\t\t\t\tthis.state.cursorLine = result.cursorLine;\n\t\t\t\t\t\tthis.state.cursorCol = result.cursorCol;\n\t\t\t\t\t}\n\t\t\t\t\tthis.cancelAutocomplete();\n\t\t\t\t\t// Don't return - fall through to submission logic\n\t\t\t\t}\n\t\t\t\t// If Enter was pressed on a file path, apply completion\n\t\t\t\telse if (isEnter(data)) {\n\t\t\t\t\tconst selected = this.autocompleteList.getSelectedItem();\n\t\t\t\t\tif (selected && this.autocompleteProvider) {\n\t\t\t\t\t\tconst result = this.autocompleteProvider.applyCompletion(\n\t\t\t\t\t\t\tthis.state.lines,\n\t\t\t\t\t\t\tthis.state.cursorLine,\n\t\t\t\t\t\t\tthis.state.cursorCol,\n\t\t\t\t\t\t\tselected,\n\t\t\t\t\t\t\tthis.autocompletePrefix,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tthis.state.lines = result.lines;\n\t\t\t\t\t\tthis.state.cursorLine = result.cursorLine;\n\t\t\t\t\t\tthis.state.cursorCol = result.cursorCol;\n\n\t\t\t\t\t\tthis.cancelAutocomplete();\n\n\t\t\t\t\t\tif (this.onChange) {\n\t\t\t\t\t\t\tthis.onChange(this.getText());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// For other keys (like regular typing), DON'T return here\n\t\t\t// Let them fall through to normal character handling\n\t\t}\n\n\t\t// Tab key - context-aware completion (but not when already autocompleting)\n\t\tif (isTab(data) && !this.isAutocompleting) {\n\t\t\tthis.handleTabCompletion();\n\t\t\treturn;\n\t\t}\n\n\t\t// Continue with rest of input handling\n\t\t// Ctrl+K - Delete to end of line\n\t\tif (isCtrlK(data)) {\n\t\t\tthis.deleteToEndOfLine();\n\t\t}\n\t\t// Ctrl+U - Delete to start of line\n\t\telse if (isCtrlU(data)) {\n\t\t\tthis.deleteToStartOfLine();\n\t\t}\n\t\t// Ctrl+W - Delete word backwards\n\t\telse if (isCtrlW(data)) {\n\t\t\tthis.deleteWordBackwards();\n\t\t}\n\t\t// Option/Alt+Backspace - Delete word backwards\n\t\telse if (isAltBackspace(data)) {\n\t\t\tthis.deleteWordBackwards();\n\t\t}\n\t\t// Ctrl+A - Move to start of line\n\t\telse if (isCtrlA(data)) {\n\t\t\tthis.moveToLineStart();\n\t\t}\n\t\t// Ctrl+E - Move to end of line\n\t\telse if (isCtrlE(data)) {\n\t\t\tthis.moveToLineEnd();\n\t\t}\n\t\t// New line shortcuts (but not plain LF/CR which should be submit)\n\t\telse if (\n\t\t\t(data.charCodeAt(0) === 10 && data.length > 1) || // Ctrl+Enter with modifiers\n\t\t\tdata === \"\\x1b\\r\" || // Option+Enter in some terminals (legacy)\n\t\t\tdata === \"\\x1b[13;2~\" || // Shift+Enter in some terminals (legacy format)\n\t\t\tisShiftEnter(data) || // Shift+Enter (Kitty protocol, handles lock bits)\n\t\t\tisAltEnter(data) || // Alt+Enter (Kitty protocol, handles lock bits)\n\t\t\t(data.length > 1 && data.includes(\"\\x1b\") && data.includes(\"\\r\")) ||\n\t\t\t(data === \"\\n\" && data.length === 1) || // Shift+Enter from iTerm2 mapping\n\t\t\tdata === \"\\\\\\r\" // Shift+Enter in VS Code terminal\n\t\t) {\n\t\t\t// Modifier + Enter = new line\n\t\t\tthis.addNewLine();\n\t\t}\n\t\t// Plain Enter - submit (handles both legacy \\r and Kitty protocol with lock bits)\n\t\telse if (isEnter(data)) {\n\t\t\t// If submit is disabled, do nothing\n\t\t\tif (this.disableSubmit) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Get text and substitute paste markers with actual content\n\t\t\tlet result = this.state.lines.join(\"\\n\").trim();\n\n\t\t\t// Replace all [paste #N +xxx lines] or [paste #N xxx chars] markers with actual paste content\n\t\t\tfor (const [pasteId, pasteContent] of this.pastes) {\n\t\t\t\t// Match formats: [paste #N], [paste #N +xxx lines], or [paste #N xxx chars]\n\t\t\t\tconst markerRegex = new RegExp(`\\\\[paste #${pasteId}( (\\\\+\\\\d+ lines|\\\\d+ chars))?\\\\]`, \"g\");\n\t\t\t\tresult = result.replace(markerRegex, pasteContent);\n\t\t\t}\n\n\t\t\t// Reset editor and clear pastes\n\t\t\tthis.state = {\n\t\t\t\tlines: [\"\"],\n\t\t\t\tcursorLine: 0,\n\t\t\t\tcursorCol: 0,\n\t\t\t};\n\t\t\tthis.pastes.clear();\n\t\t\tthis.pasteCounter = 0;\n\t\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\t\t// Notify that editor is now empty\n\t\t\tif (this.onChange) {\n\t\t\t\tthis.onChange(\"\");\n\t\t\t}\n\n\t\t\tif (this.onSubmit) {\n\t\t\t\tthis.onSubmit(result);\n\t\t\t}\n\t\t}\n\t\t// Backspace\n\t\telse if (isBackspace(data)) {\n\t\t\tthis.handleBackspace();\n\t\t}\n\t\t// Line navigation shortcuts (Home/End keys)\n\t\telse if (isHome(data)) {\n\t\t\tthis.moveToLineStart();\n\t\t} else if (isEnd(data)) {\n\t\t\tthis.moveToLineEnd();\n\t\t}\n\t\t// Forward delete (Fn+Backspace or Delete key)\n\t\telse if (isDelete(data)) {\n\t\t\tthis.handleForwardDelete();\n\t\t}\n\t\t// Word navigation (Option/Alt + Arrow or Ctrl + Arrow)\n\t\telse if (isAltLeft(data) || isCtrlLeft(data)) {\n\t\t\t// Word left\n\t\t\tthis.moveWordBackwards();\n\t\t} else if (isAltRight(data) || isCtrlRight(data)) {\n\t\t\t// Word right\n\t\t\tthis.moveWordForwards();\n\t\t}\n\t\t// Arrow keys\n\t\telse if (isArrowUp(data)) {\n\t\t\t// Up - history navigation or cursor movement\n\t\t\tif (this.isEditorEmpty()) {\n\t\t\t\tthis.navigateHistory(-1); // Start browsing history\n\t\t\t} else if (this.historyIndex > -1 && this.isOnFirstVisualLine()) {\n\t\t\t\tthis.navigateHistory(-1); // Navigate to older history entry\n\t\t\t} else {\n\t\t\t\tthis.moveCursor(-1, 0); // Cursor movement (within text or history entry)\n\t\t\t}\n\t\t} else if (isArrowDown(data)) {\n\t\t\t// Down - history navigation or cursor movement\n\t\t\tif (this.historyIndex > -1 && this.isOnLastVisualLine()) {\n\t\t\t\tthis.navigateHistory(1); // Navigate to newer history entry or clear\n\t\t\t} else {\n\t\t\t\tthis.moveCursor(1, 0); // Cursor movement (within text or history entry)\n\t\t\t}\n\t\t} else if (isArrowRight(data)) {\n\t\t\t// Right\n\t\t\tthis.moveCursor(0, 1);\n\t\t} else if (isArrowLeft(data)) {\n\t\t\t// Left\n\t\t\tthis.moveCursor(0, -1);\n\t\t}\n\t\t// Regular characters (printable characters and unicode, but not control characters)\n\t\telse if (data.charCodeAt(0) >= 32) {\n\t\t\tthis.insertCharacter(data);\n\t\t}\n\t}\n\n\tprivate layoutText(contentWidth: number): LayoutLine[] {\n\t\tconst layoutLines: LayoutLine[] = [];\n\n\t\tif (this.state.lines.length === 0 || (this.state.lines.length === 1 && this.state.lines[0] === \"\")) {\n\t\t\t// Empty editor\n\t\t\tlayoutLines.push({\n\t\t\t\ttext: \"\",\n\t\t\t\thasCursor: true,\n\t\t\t\tcursorPos: 0,\n\t\t\t});\n\t\t\treturn layoutLines;\n\t\t}\n\n\t\t// Process each logical line\n\t\tfor (let i = 0; i < this.state.lines.length; i++) {\n\t\t\tconst line = this.state.lines[i] || \"\";\n\t\t\tconst isCurrentLine = i === this.state.cursorLine;\n\t\t\tconst lineVisibleWidth = visibleWidth(line);\n\n\t\t\tif (lineVisibleWidth <= contentWidth) {\n\t\t\t\t// Line fits in one layout line\n\t\t\t\tif (isCurrentLine) {\n\t\t\t\t\tlayoutLines.push({\n\t\t\t\t\t\ttext: line,\n\t\t\t\t\t\thasCursor: true,\n\t\t\t\t\t\tcursorPos: this.state.cursorCol,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tlayoutLines.push({\n\t\t\t\t\t\ttext: line,\n\t\t\t\t\t\thasCursor: false,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Line needs wrapping - use grapheme-aware chunking\n\t\t\t\tconst chunks: { text: string; startIndex: number; endIndex: number }[] = [];\n\t\t\t\tlet currentChunk = \"\";\n\t\t\t\tlet currentWidth = 0;\n\t\t\t\tlet chunkStartIndex = 0;\n\t\t\t\tlet currentIndex = 0;\n\n\t\t\t\tfor (const seg of segmenter.segment(line)) {\n\t\t\t\t\tconst grapheme = seg.segment;\n\t\t\t\t\tconst graphemeWidth = visibleWidth(grapheme);\n\n\t\t\t\t\tif (currentWidth + graphemeWidth > contentWidth && currentChunk !== \"\") {\n\t\t\t\t\t\t// Start a new chunk\n\t\t\t\t\t\tchunks.push({\n\t\t\t\t\t\t\ttext: currentChunk,\n\t\t\t\t\t\t\tstartIndex: chunkStartIndex,\n\t\t\t\t\t\t\tendIndex: currentIndex,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcurrentChunk = grapheme;\n\t\t\t\t\t\tcurrentWidth = graphemeWidth;\n\t\t\t\t\t\tchunkStartIndex = currentIndex;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcurrentChunk += grapheme;\n\t\t\t\t\t\tcurrentWidth += graphemeWidth;\n\t\t\t\t\t}\n\t\t\t\t\tcurrentIndex += grapheme.length;\n\t\t\t\t}\n\n\t\t\t\t// Push the last chunk\n\t\t\t\tif (currentChunk !== \"\") {\n\t\t\t\t\tchunks.push({\n\t\t\t\t\t\ttext: currentChunk,\n\t\t\t\t\t\tstartIndex: chunkStartIndex,\n\t\t\t\t\t\tendIndex: currentIndex,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tfor (let chunkIndex = 0; chunkIndex < chunks.length; chunkIndex++) {\n\t\t\t\t\tconst chunk = chunks[chunkIndex];\n\t\t\t\t\tif (!chunk) continue;\n\n\t\t\t\t\tconst cursorPos = this.state.cursorCol;\n\t\t\t\t\tconst isLastChunk = chunkIndex === chunks.length - 1;\n\t\t\t\t\t// For non-last chunks, cursor at endIndex belongs to the next chunk\n\t\t\t\t\tconst hasCursorInChunk =\n\t\t\t\t\t\tisCurrentLine &&\n\t\t\t\t\t\tcursorPos >= chunk.startIndex &&\n\t\t\t\t\t\t(isLastChunk ? cursorPos <= chunk.endIndex : cursorPos < chunk.endIndex);\n\n\t\t\t\t\tif (hasCursorInChunk) {\n\t\t\t\t\t\tlayoutLines.push({\n\t\t\t\t\t\t\ttext: chunk.text,\n\t\t\t\t\t\t\thasCursor: true,\n\t\t\t\t\t\t\tcursorPos: cursorPos - chunk.startIndex,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlayoutLines.push({\n\t\t\t\t\t\t\ttext: chunk.text,\n\t\t\t\t\t\t\thasCursor: false,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn layoutLines;\n\t}\n\n\tgetText(): string {\n\t\treturn this.state.lines.join(\"\\n\");\n\t}\n\n\tgetLines(): string[] {\n\t\treturn [...this.state.lines];\n\t}\n\n\tgetCursor(): { line: number; col: number } {\n\t\treturn { line: this.state.cursorLine, col: this.state.cursorCol };\n\t}\n\n\tsetText(text: string): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\t\tthis.setTextInternal(text);\n\t}\n\n\t// All the editor methods from before...\n\tprivate insertCharacter(char: string): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\tconst line = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\tconst before = line.slice(0, this.state.cursorCol);\n\t\tconst after = line.slice(this.state.cursorCol);\n\n\t\tthis.state.lines[this.state.cursorLine] = before + char + after;\n\t\tthis.state.cursorCol += char.length; // Fix: increment by the length of the inserted string\n\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\n\n\t\t// Check if we should trigger or update autocomplete\n\t\tif (!this.isAutocompleting) {\n\t\t\t// Auto-trigger for \"/\" at the start of a line (slash commands)\n\t\t\tif (char === \"/\" && this.isAtStartOfMessage()) {\n\t\t\t\tthis.tryTriggerAutocomplete();\n\t\t\t}\n\t\t\t// Auto-trigger for \"@\" file reference (fuzzy search)\n\t\t\telse if (char === \"@\") {\n\t\t\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\t\t\tconst textBeforeCursor = currentLine.slice(0, this.state.cursorCol);\n\t\t\t\t// Only trigger if @ is after whitespace or at start of line\n\t\t\t\tconst charBeforeAt = textBeforeCursor[textBeforeCursor.length - 2];\n\t\t\t\tif (textBeforeCursor.length === 1 || charBeforeAt === \" \" || charBeforeAt === \"\\t\") {\n\t\t\t\t\tthis.tryTriggerAutocomplete();\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Also auto-trigger when typing letters in a slash command context\n\t\t\telse if (/[a-zA-Z0-9]/.test(char)) {\n\t\t\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\t\t\tconst textBeforeCursor = currentLine.slice(0, this.state.cursorCol);\n\t\t\t\t// Check if we're in a slash command (with or without space for arguments)\n\t\t\t\tif (textBeforeCursor.trimStart().startsWith(\"/\")) {\n\t\t\t\t\tthis.tryTriggerAutocomplete();\n\t\t\t\t}\n\t\t\t\t// Check if we're in an @ file reference context\n\t\t\t\telse if (textBeforeCursor.match(/(?:^|[\\s])@[^\\s]*$/)) {\n\t\t\t\t\tthis.tryTriggerAutocomplete();\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.updateAutocomplete();\n\t\t}\n\t}\n\n\tprivate handlePaste(pastedText: string): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\t// Clean the pasted text\n\t\tconst cleanText = pastedText.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\n\t\t// Convert tabs to spaces (4 spaces per tab)\n\t\tconst tabExpandedText = cleanText.replace(/\\t/g, \" \");\n\n\t\t// Filter out non-printable characters except newlines\n\t\tconst filteredText = tabExpandedText\n\t\t\t.split(\"\")\n\t\t\t.filter((char) => char === \"\\n\" || char.charCodeAt(0) >= 32)\n\t\t\t.join(\"\");\n\n\t\t// Split into lines\n\t\tconst pastedLines = filteredText.split(\"\\n\");\n\n\t\t// Check if this is a large paste (> 10 lines or > 1000 characters)\n\t\tconst totalChars = filteredText.length;\n\t\tif (pastedLines.length > 10 || totalChars > 1000) {\n\t\t\t// Store the paste and insert a marker\n\t\t\tthis.pasteCounter++;\n\t\t\tconst pasteId = this.pasteCounter;\n\t\t\tthis.pastes.set(pasteId, filteredText);\n\n\t\t\t// Insert marker like \"[paste #1 +123 lines]\" or \"[paste #1 1234 chars]\"\n\t\t\tconst marker =\n\t\t\t\tpastedLines.length > 10\n\t\t\t\t\t? `[paste #${pasteId} +${pastedLines.length} lines]`\n\t\t\t\t\t: `[paste #${pasteId} ${totalChars} chars]`;\n\t\t\tfor (const char of marker) {\n\t\t\t\tthis.insertCharacter(char);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tif (pastedLines.length === 1) {\n\t\t\t// Single line - just insert each character\n\t\t\tconst text = pastedLines[0] || \"\";\n\t\t\tfor (const char of text) {\n\t\t\t\tthis.insertCharacter(char);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Multi-line paste - be very careful with array manipulation\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\tconst beforeCursor = currentLine.slice(0, this.state.cursorCol);\n\t\tconst afterCursor = currentLine.slice(this.state.cursorCol);\n\n\t\t// Build the new lines array step by step\n\t\tconst newLines: string[] = [];\n\n\t\t// Add all lines before current line\n\t\tfor (let i = 0; i < this.state.cursorLine; i++) {\n\t\t\tnewLines.push(this.state.lines[i] || \"\");\n\t\t}\n\n\t\t// Add the first pasted line merged with before cursor text\n\t\tnewLines.push(beforeCursor + (pastedLines[0] || \"\"));\n\n\t\t// Add all middle pasted lines\n\t\tfor (let i = 1; i < pastedLines.length - 1; i++) {\n\t\t\tnewLines.push(pastedLines[i] || \"\");\n\t\t}\n\n\t\t// Add the last pasted line with after cursor text\n\t\tnewLines.push((pastedLines[pastedLines.length - 1] || \"\") + afterCursor);\n\n\t\t// Add all lines after current line\n\t\tfor (let i = this.state.cursorLine + 1; i < this.state.lines.length; i++) {\n\t\t\tnewLines.push(this.state.lines[i] || \"\");\n\t\t}\n\n\t\t// Replace the entire lines array\n\t\tthis.state.lines = newLines;\n\n\t\t// Update cursor position to end of pasted content\n\t\tthis.state.cursorLine += pastedLines.length - 1;\n\t\tthis.state.cursorCol = (pastedLines[pastedLines.length - 1] || \"\").length;\n\n\t\t// Notify of change\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\n\t}\n\n\tprivate addNewLine(): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\tconst before = currentLine.slice(0, this.state.cursorCol);\n\t\tconst after = currentLine.slice(this.state.cursorCol);\n\n\t\t// Split current line\n\t\tthis.state.lines[this.state.cursorLine] = before;\n\t\tthis.state.lines.splice(this.state.cursorLine + 1, 0, after);\n\n\t\t// Move cursor to start of new line\n\t\tthis.state.cursorLine++;\n\t\tthis.state.cursorCol = 0;\n\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\n\t}\n\n\tprivate handleBackspace(): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\tif (this.state.cursorCol > 0) {\n\t\t\t// Delete grapheme before cursor (handles emojis, combining characters, etc.)\n\t\t\tconst line = this.state.lines[this.state.cursorLine] || \"\";\n\t\t\tconst beforeCursor = line.slice(0, this.state.cursorCol);\n\n\t\t\t// Find the last grapheme in the text before cursor\n\t\t\tconst graphemes = [...segmenter.segment(beforeCursor)];\n\t\t\tconst lastGrapheme = graphemes[graphemes.length - 1];\n\t\t\tconst graphemeLength = lastGrapheme ? lastGrapheme.segment.length : 1;\n\n\t\t\tconst before = line.slice(0, this.state.cursorCol - graphemeLength);\n\t\t\tconst after = line.slice(this.state.cursorCol);\n\n\t\t\tthis.state.lines[this.state.cursorLine] = before + after;\n\t\t\tthis.state.cursorCol -= graphemeLength;\n\t\t} else if (this.state.cursorLine > 0) {\n\t\t\t// Merge with previous line\n\t\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\t\tconst previousLine = this.state.lines[this.state.cursorLine - 1] || \"\";\n\n\t\t\tthis.state.lines[this.state.cursorLine - 1] = previousLine + currentLine;\n\t\t\tthis.state.lines.splice(this.state.cursorLine, 1);\n\n\t\t\tthis.state.cursorLine--;\n\t\t\tthis.state.cursorCol = previousLine.length;\n\t\t}\n\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\n\n\t\t// Update or re-trigger autocomplete after backspace\n\t\tif (this.isAutocompleting) {\n\t\t\tthis.updateAutocomplete();\n\t\t} else {\n\t\t\t// If autocomplete was cancelled (no matches), re-trigger if we're in a completable context\n\t\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\t\tconst textBeforeCursor = currentLine.slice(0, this.state.cursorCol);\n\t\t\t// Slash command context\n\t\t\tif (textBeforeCursor.trimStart().startsWith(\"/\")) {\n\t\t\t\tthis.tryTriggerAutocomplete();\n\t\t\t}\n\t\t\t// @ file reference context\n\t\t\telse if (textBeforeCursor.match(/(?:^|[\\s])@[^\\s]*$/)) {\n\t\t\t\tthis.tryTriggerAutocomplete();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate moveToLineStart(): void {\n\t\tthis.state.cursorCol = 0;\n\t}\n\n\tprivate moveToLineEnd(): void {\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\tthis.state.cursorCol = currentLine.length;\n\t}\n\n\tprivate deleteToStartOfLine(): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\tif (this.state.cursorCol > 0) {\n\t\t\t// Delete from start of line up to cursor\n\t\t\tthis.state.lines[this.state.cursorLine] = currentLine.slice(this.state.cursorCol);\n\t\t\tthis.state.cursorCol = 0;\n\t\t} else if (this.state.cursorLine > 0) {\n\t\t\t// At start of line - merge with previous line\n\t\t\tconst previousLine = this.state.lines[this.state.cursorLine - 1] || \"\";\n\t\t\tthis.state.lines[this.state.cursorLine - 1] = previousLine + currentLine;\n\t\t\tthis.state.lines.splice(this.state.cursorLine, 1);\n\t\t\tthis.state.cursorLine--;\n\t\t\tthis.state.cursorCol = previousLine.length;\n\t\t}\n\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\n\t}\n\n\tprivate deleteToEndOfLine(): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\tif (this.state.cursorCol < currentLine.length) {\n\t\t\t// Delete from cursor to end of line\n\t\t\tthis.state.lines[this.state.cursorLine] = currentLine.slice(0, this.state.cursorCol);\n\t\t} else if (this.state.cursorLine < this.state.lines.length - 1) {\n\t\t\t// At end of line - merge with next line\n\t\t\tconst nextLine = this.state.lines[this.state.cursorLine + 1] || \"\";\n\t\t\tthis.state.lines[this.state.cursorLine] = currentLine + nextLine;\n\t\t\tthis.state.lines.splice(this.state.cursorLine + 1, 1);\n\t\t}\n\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\n\t}\n\n\tprivate deleteWordBackwards(): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\t// If at start of line, behave like backspace at column 0 (merge with previous line)\n\t\tif (this.state.cursorCol === 0) {\n\t\t\tif (this.state.cursorLine > 0) {\n\t\t\t\tconst previousLine = this.state.lines[this.state.cursorLine - 1] || \"\";\n\t\t\t\tthis.state.lines[this.state.cursorLine - 1] = previousLine + currentLine;\n\t\t\t\tthis.state.lines.splice(this.state.cursorLine, 1);\n\t\t\t\tthis.state.cursorLine--;\n\t\t\t\tthis.state.cursorCol = previousLine.length;\n\t\t\t}\n\t\t} else {\n\t\t\tconst textBeforeCursor = currentLine.slice(0, this.state.cursorCol);\n\n\t\t\tconst isWhitespace = (char: string): boolean => /\\s/.test(char);\n\t\t\tconst isPunctuation = (char: string): boolean => {\n\t\t\t\t// Treat obvious code punctuation as boundaries\n\t\t\t\treturn /[(){}[\\]<>.,;:'\"!?+\\-=*/\\\\|&%^$#@~`]/.test(char);\n\t\t\t};\n\n\t\t\tlet deleteFrom = this.state.cursorCol;\n\t\t\tconst lastChar = textBeforeCursor[deleteFrom - 1] ?? \"\";\n\n\t\t\t// If immediately on whitespace or punctuation, delete that single boundary char\n\t\t\tif (isWhitespace(lastChar) || isPunctuation(lastChar)) {\n\t\t\t\tdeleteFrom -= 1;\n\t\t\t} else {\n\t\t\t\t// Otherwise, delete a run of non-boundary characters (the \"word\")\n\t\t\t\twhile (deleteFrom > 0) {\n\t\t\t\t\tconst ch = textBeforeCursor[deleteFrom - 1] ?? \"\";\n\t\t\t\t\tif (isWhitespace(ch) || isPunctuation(ch)) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdeleteFrom -= 1;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.state.lines[this.state.cursorLine] =\n\t\t\t\tcurrentLine.slice(0, deleteFrom) + currentLine.slice(this.state.cursorCol);\n\t\t\tthis.state.cursorCol = deleteFrom;\n\t\t}\n\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\n\t}\n\n\tprivate handleForwardDelete(): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\tif (this.state.cursorCol < currentLine.length) {\n\t\t\t// Delete grapheme at cursor position (handles emojis, combining characters, etc.)\n\t\t\tconst afterCursor = currentLine.slice(this.state.cursorCol);\n\n\t\t\t// Find the first grapheme at cursor\n\t\t\tconst graphemes = [...segmenter.segment(afterCursor)];\n\t\t\tconst firstGrapheme = graphemes[0];\n\t\t\tconst graphemeLength = firstGrapheme ? firstGrapheme.segment.length : 1;\n\n\t\t\tconst before = currentLine.slice(0, this.state.cursorCol);\n\t\t\tconst after = currentLine.slice(this.state.cursorCol + graphemeLength);\n\t\t\tthis.state.lines[this.state.cursorLine] = before + after;\n\t\t} else if (this.state.cursorLine < this.state.lines.length - 1) {\n\t\t\t// At end of line - merge with next line\n\t\t\tconst nextLine = this.state.lines[this.state.cursorLine + 1] || \"\";\n\t\t\tthis.state.lines[this.state.cursorLine] = currentLine + nextLine;\n\t\t\tthis.state.lines.splice(this.state.cursorLine + 1, 1);\n\t\t}\n\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\n\n\t\t// Update or re-trigger autocomplete after forward delete\n\t\tif (this.isAutocompleting) {\n\t\t\tthis.updateAutocomplete();\n\t\t} else {\n\t\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\t\tconst textBeforeCursor = currentLine.slice(0, this.state.cursorCol);\n\t\t\t// Slash command context\n\t\t\tif (textBeforeCursor.trimStart().startsWith(\"/\")) {\n\t\t\t\tthis.tryTriggerAutocomplete();\n\t\t\t}\n\t\t\t// @ file reference context\n\t\t\telse if (textBeforeCursor.match(/(?:^|[\\s])@[^\\s]*$/)) {\n\t\t\t\tthis.tryTriggerAutocomplete();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Build a mapping from visual lines to logical positions.\n\t * Returns an array where each element represents a visual line with:\n\t * - logicalLine: index into this.state.lines\n\t * - startCol: starting column in the logical line\n\t * - length: length of this visual line segment\n\t */\n\tprivate buildVisualLineMap(width: number): Array<{ logicalLine: number; startCol: number; length: number }> {\n\t\tconst visualLines: Array<{ logicalLine: number; startCol: number; length: number }> = [];\n\n\t\tfor (let i = 0; i < this.state.lines.length; i++) {\n\t\t\tconst line = this.state.lines[i] || \"\";\n\t\t\tconst lineVisWidth = visibleWidth(line);\n\t\t\tif (line.length === 0) {\n\t\t\t\t// Empty line still takes one visual line\n\t\t\t\tvisualLines.push({ logicalLine: i, startCol: 0, length: 0 });\n\t\t\t} else if (lineVisWidth <= width) {\n\t\t\t\tvisualLines.push({ logicalLine: i, startCol: 0, length: line.length });\n\t\t\t} else {\n\t\t\t\t// Line needs wrapping - use grapheme-aware chunking\n\t\t\t\tlet currentWidth = 0;\n\t\t\t\tlet chunkStartIndex = 0;\n\t\t\t\tlet currentIndex = 0;\n\n\t\t\t\tfor (const seg of segmenter.segment(line)) {\n\t\t\t\t\tconst grapheme = seg.segment;\n\t\t\t\t\tconst graphemeWidth = visibleWidth(grapheme);\n\n\t\t\t\t\tif (currentWidth + graphemeWidth > width && currentIndex > chunkStartIndex) {\n\t\t\t\t\t\t// Start a new chunk\n\t\t\t\t\t\tvisualLines.push({\n\t\t\t\t\t\t\tlogicalLine: i,\n\t\t\t\t\t\t\tstartCol: chunkStartIndex,\n\t\t\t\t\t\t\tlength: currentIndex - chunkStartIndex,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tchunkStartIndex = currentIndex;\n\t\t\t\t\t\tcurrentWidth = graphemeWidth;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcurrentWidth += graphemeWidth;\n\t\t\t\t\t}\n\t\t\t\t\tcurrentIndex += grapheme.length;\n\t\t\t\t}\n\n\t\t\t\t// Push the last chunk\n\t\t\t\tif (currentIndex > chunkStartIndex) {\n\t\t\t\t\tvisualLines.push({\n\t\t\t\t\t\tlogicalLine: i,\n\t\t\t\t\t\tstartCol: chunkStartIndex,\n\t\t\t\t\t\tlength: currentIndex - chunkStartIndex,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn visualLines;\n\t}\n\n\t/**\n\t * Find the visual line index for the current cursor position.\n\t */\n\tprivate findCurrentVisualLine(\n\t\tvisualLines: Array<{ logicalLine: number; startCol: number; length: number }>,\n\t): number {\n\t\tfor (let i = 0; i < visualLines.length; i++) {\n\t\t\tconst vl = visualLines[i];\n\t\t\tif (!vl) continue;\n\t\t\tif (vl.logicalLine === this.state.cursorLine) {\n\t\t\t\tconst colInSegment = this.state.cursorCol - vl.startCol;\n\t\t\t\t// Cursor is in this segment if it's within range\n\t\t\t\t// For the last segment of a logical line, cursor can be at length (end position)\n\t\t\t\tconst isLastSegmentOfLine =\n\t\t\t\t\ti === visualLines.length - 1 || visualLines[i + 1]?.logicalLine !== vl.logicalLine;\n\t\t\t\tif (colInSegment >= 0 && (colInSegment < vl.length || (isLastSegmentOfLine && colInSegment <= vl.length))) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Fallback: return last visual line\n\t\treturn visualLines.length - 1;\n\t}\n\n\tprivate moveCursor(deltaLine: number, deltaCol: number): void {\n\t\tconst width = this.lastWidth;\n\n\t\tif (deltaLine !== 0) {\n\t\t\t// Build visual line map for navigation\n\t\t\tconst visualLines = this.buildVisualLineMap(width);\n\t\t\tconst currentVisualLine = this.findCurrentVisualLine(visualLines);\n\n\t\t\t// Calculate column position within current visual line\n\t\t\tconst currentVL = visualLines[currentVisualLine];\n\t\t\tconst visualCol = currentVL ? this.state.cursorCol - currentVL.startCol : 0;\n\n\t\t\t// Move to target visual line\n\t\t\tconst targetVisualLine = currentVisualLine + deltaLine;\n\n\t\t\tif (targetVisualLine >= 0 && targetVisualLine < visualLines.length) {\n\t\t\t\tconst targetVL = visualLines[targetVisualLine];\n\t\t\t\tif (targetVL) {\n\t\t\t\t\tthis.state.cursorLine = targetVL.logicalLine;\n\t\t\t\t\t// Try to maintain visual column position, clamped to line length\n\t\t\t\t\tconst targetCol = targetVL.startCol + Math.min(visualCol, targetVL.length);\n\t\t\t\t\tconst logicalLine = this.state.lines[targetVL.logicalLine] || \"\";\n\t\t\t\t\tthis.state.cursorCol = Math.min(targetCol, logicalLine.length);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (deltaCol !== 0) {\n\t\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\t\tif (deltaCol > 0) {\n\t\t\t\t// Moving right - move by one grapheme (handles emojis, combining characters, etc.)\n\t\t\t\tif (this.state.cursorCol < currentLine.length) {\n\t\t\t\t\tconst afterCursor = currentLine.slice(this.state.cursorCol);\n\t\t\t\t\tconst graphemes = [...segmenter.segment(afterCursor)];\n\t\t\t\t\tconst firstGrapheme = graphemes[0];\n\t\t\t\t\tthis.state.cursorCol += firstGrapheme ? firstGrapheme.segment.length : 1;\n\t\t\t\t} else if (this.state.cursorLine < this.state.lines.length - 1) {\n\t\t\t\t\t// Wrap to start of next logical line\n\t\t\t\t\tthis.state.cursorLine++;\n\t\t\t\t\tthis.state.cursorCol = 0;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Moving left - move by one grapheme (handles emojis, combining characters, etc.)\n\t\t\t\tif (this.state.cursorCol > 0) {\n\t\t\t\t\tconst beforeCursor = currentLine.slice(0, this.state.cursorCol);\n\t\t\t\t\tconst graphemes = [...segmenter.segment(beforeCursor)];\n\t\t\t\t\tconst lastGrapheme = graphemes[graphemes.length - 1];\n\t\t\t\t\tthis.state.cursorCol -= lastGrapheme ? lastGrapheme.segment.length : 1;\n\t\t\t\t} else if (this.state.cursorLine > 0) {\n\t\t\t\t\t// Wrap to end of previous logical line\n\t\t\t\t\tthis.state.cursorLine--;\n\t\t\t\t\tconst prevLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\t\t\t\tthis.state.cursorCol = prevLine.length;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isWordBoundary(char: string): boolean {\n\t\treturn /\\s/.test(char) || /[(){}[\\]<>.,;:'\"!?+\\-=*/\\\\|&%^$#@~`]/.test(char);\n\t}\n\n\tprivate moveWordBackwards(): void {\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\t// If at start of line, move to end of previous line\n\t\tif (this.state.cursorCol === 0) {\n\t\t\tif (this.state.cursorLine > 0) {\n\t\t\t\tthis.state.cursorLine--;\n\t\t\t\tconst prevLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\t\t\tthis.state.cursorCol = prevLine.length;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst textBeforeCursor = currentLine.slice(0, this.state.cursorCol);\n\t\tlet newCol = this.state.cursorCol;\n\t\tconst lastChar = textBeforeCursor[newCol - 1] ?? \"\";\n\n\t\t// If immediately on whitespace or punctuation, skip that single boundary char\n\t\tif (this.isWordBoundary(lastChar)) {\n\t\t\tnewCol -= 1;\n\t\t}\n\n\t\t// Now skip the \"word\" (non-boundary characters)\n\t\twhile (newCol > 0) {\n\t\t\tconst ch = textBeforeCursor[newCol - 1] ?? \"\";\n\t\t\tif (this.isWordBoundary(ch)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tnewCol -= 1;\n\t\t}\n\n\t\tthis.state.cursorCol = newCol;\n\t}\n\n\tprivate moveWordForwards(): void {\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\t// If at end of line, move to start of next line\n\t\tif (this.state.cursorCol >= currentLine.length) {\n\t\t\tif (this.state.cursorLine < this.state.lines.length - 1) {\n\t\t\t\tthis.state.cursorLine++;\n\t\t\t\tthis.state.cursorCol = 0;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet newCol = this.state.cursorCol;\n\t\tconst charAtCursor = currentLine[newCol] ?? \"\";\n\n\t\t// If on whitespace or punctuation, skip it\n\t\tif (this.isWordBoundary(charAtCursor)) {\n\t\t\tnewCol += 1;\n\t\t}\n\n\t\t// Skip the \"word\" (non-boundary characters)\n\t\twhile (newCol < currentLine.length) {\n\t\t\tconst ch = currentLine[newCol] ?? \"\";\n\t\t\tif (this.isWordBoundary(ch)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tnewCol += 1;\n\t\t}\n\n\t\tthis.state.cursorCol = newCol;\n\t}\n\n\t// Helper method to check if cursor is at start of message (for slash command detection)\n\tprivate isAtStartOfMessage(): boolean {\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\tconst beforeCursor = currentLine.slice(0, this.state.cursorCol);\n\n\t\t// At start if line is empty, only contains whitespace, or is just \"/\"\n\t\treturn beforeCursor.trim() === \"\" || beforeCursor.trim() === \"/\";\n\t}\n\n\t// Autocomplete methods\n\tprivate tryTriggerAutocomplete(explicitTab: boolean = false): void {\n\t\tif (!this.autocompleteProvider) return;\n\n\t\t// Check if we should trigger file completion on Tab\n\t\tif (explicitTab) {\n\t\t\tconst provider = this.autocompleteProvider as CombinedAutocompleteProvider;\n\t\t\tconst shouldTrigger =\n\t\t\t\t!provider.shouldTriggerFileCompletion ||\n\t\t\t\tprovider.shouldTriggerFileCompletion(this.state.lines, this.state.cursorLine, this.state.cursorCol);\n\t\t\tif (!shouldTrigger) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tconst suggestions = this.autocompleteProvider.getSuggestions(\n\t\t\tthis.state.lines,\n\t\t\tthis.state.cursorLine,\n\t\t\tthis.state.cursorCol,\n\t\t);\n\n\t\tif (suggestions && suggestions.items.length > 0) {\n\t\t\tthis.autocompletePrefix = suggestions.prefix;\n\t\t\tthis.autocompleteList = new SelectList(suggestions.items, 5, this.theme.selectList);\n\t\t\tthis.isAutocompleting = true;\n\t\t} else {\n\t\t\tthis.cancelAutocomplete();\n\t\t}\n\t}\n\n\tprivate handleTabCompletion(): void {\n\t\tif (!this.autocompleteProvider) return;\n\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\tconst beforeCursor = currentLine.slice(0, this.state.cursorCol);\n\n\t\t// Check if we're in a slash command context\n\t\tif (beforeCursor.trimStart().startsWith(\"/\") && !beforeCursor.trimStart().includes(\" \")) {\n\t\t\tthis.handleSlashCommandCompletion();\n\t\t} else {\n\t\t\tthis.forceFileAutocomplete();\n\t\t}\n\t}\n\n\tprivate handleSlashCommandCompletion(): void {\n\t\tthis.tryTriggerAutocomplete(true);\n\t}\n\n\t/*\nhttps://github.com/EsotericSoftware/spine-runtimes/actions/runs/19536643416/job/559322883\n17 this job fails with https://github.com/EsotericSoftware/spine-runtimes/actions/runs/19\n536643416/job/55932288317 havea look at .gi\n\t */\n\tprivate forceFileAutocomplete(): void {\n\t\tif (!this.autocompleteProvider) return;\n\n\t\t// Check if provider has the force method\n\t\tconst provider = this.autocompleteProvider as any;\n\t\tif (!provider.getForceFileSuggestions) {\n\t\t\tthis.tryTriggerAutocomplete(true);\n\t\t\treturn;\n\t\t}\n\n\t\tconst suggestions = provider.getForceFileSuggestions(\n\t\t\tthis.state.lines,\n\t\t\tthis.state.cursorLine,\n\t\t\tthis.state.cursorCol,\n\t\t);\n\n\t\tif (suggestions && suggestions.items.length > 0) {\n\t\t\tthis.autocompletePrefix = suggestions.prefix;\n\t\t\tthis.autocompleteList = new SelectList(suggestions.items, 5, this.theme.selectList);\n\t\t\tthis.isAutocompleting = true;\n\t\t} else {\n\t\t\tthis.cancelAutocomplete();\n\t\t}\n\t}\n\n\tprivate cancelAutocomplete(): void {\n\t\tthis.isAutocompleting = false;\n\t\tthis.autocompleteList = undefined as any;\n\t\tthis.autocompletePrefix = \"\";\n\t}\n\n\tpublic isShowingAutocomplete(): boolean {\n\t\treturn this.isAutocompleting;\n\t}\n\n\tprivate updateAutocomplete(): void {\n\t\tif (!this.isAutocompleting || !this.autocompleteProvider) return;\n\n\t\tconst suggestions = this.autocompleteProvider.getSuggestions(\n\t\t\tthis.state.lines,\n\t\t\tthis.state.cursorLine,\n\t\t\tthis.state.cursorCol,\n\t\t);\n\n\t\tif (suggestions && suggestions.items.length > 0) {\n\t\t\tthis.autocompletePrefix = suggestions.prefix;\n\t\t\t// Always create new SelectList to ensure update\n\t\t\tthis.autocompleteList = new SelectList(suggestions.items, 5, this.theme.selectList);\n\t\t} else {\n\t\t\t// No matches - check if we're still in a valid context before cancelling\n\t\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\t\tconst textBeforeCursor = currentLine.slice(0, this.state.cursorCol);\n\n\t\t\tthis.cancelAutocomplete();\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"editor.js","sourceRoot":"","sources":["../../src/components/editor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AutocompleteProvider, CombinedAutocompleteProvider } from \"../autocomplete.js\";\nimport {\n\tisAltBackspace,\n\tisAltEnter,\n\tisAltLeft,\n\tisAltRight,\n\tisArrowDown,\n\tisArrowLeft,\n\tisArrowRight,\n\tisArrowUp,\n\tisBackspace,\n\tisCtrlA,\n\tisCtrlC,\n\tisCtrlE,\n\tisCtrlK,\n\tisCtrlLeft,\n\tisCtrlRight,\n\tisCtrlU,\n\tisCtrlW,\n\tisDelete,\n\tisEnd,\n\tisEnter,\n\tisEscape,\n\tisHome,\n\tisShiftEnter,\n\tisTab,\n} from \"../keys.js\";\nimport type { Component } from \"../tui.js\";\nimport { visibleWidth } from \"../utils.js\";\nimport { SelectList, type SelectListTheme } from \"./select-list.js\";\n\n// Grapheme segmenter for proper Unicode iteration (handles emojis, etc.)\nconst segmenter = new Intl.Segmenter();\n\ninterface EditorState {\n\tlines: string[];\n\tcursorLine: number;\n\tcursorCol: number;\n}\n\ninterface LayoutLine {\n\ttext: string;\n\thasCursor: boolean;\n\tcursorPos?: number;\n}\n\nexport interface EditorTheme {\n\tborderColor: (str: string) => string;\n\tselectList: SelectListTheme;\n}\n\nexport class Editor implements Component {\n\tprivate state: EditorState = {\n\t\tlines: [\"\"],\n\t\tcursorLine: 0,\n\t\tcursorCol: 0,\n\t};\n\n\tprivate theme: EditorTheme;\n\n\t// Store last render width for cursor navigation\n\tprivate lastWidth: number = 80;\n\n\t// Border color (can be changed dynamically)\n\tpublic borderColor: (str: string) => string;\n\n\t// Autocomplete support\n\tprivate autocompleteProvider?: AutocompleteProvider;\n\tprivate autocompleteList?: SelectList;\n\tprivate isAutocompleting: boolean = false;\n\tprivate autocompletePrefix: string = \"\";\n\n\t// Paste tracking for large pastes\n\tprivate pastes: Map<number, string> = new Map();\n\tprivate pasteCounter: number = 0;\n\n\t// Bracketed paste mode buffering\n\tprivate pasteBuffer: string = \"\";\n\tprivate isInPaste: boolean = false;\n\n\t// Prompt history for up/down navigation\n\tprivate history: string[] = [];\n\tprivate historyIndex: number = -1; // -1 = not browsing, 0 = most recent, 1 = older, etc.\n\n\tpublic onSubmit?: (text: string) => void;\n\tpublic onChange?: (text: string) => void;\n\tpublic disableSubmit: boolean = false;\n\n\tconstructor(theme: EditorTheme) {\n\t\tthis.theme = theme;\n\t\tthis.borderColor = theme.borderColor;\n\t}\n\n\tsetAutocompleteProvider(provider: AutocompleteProvider): void {\n\t\tthis.autocompleteProvider = provider;\n\t}\n\n\t/**\n\t * Add a prompt to history for up/down arrow navigation.\n\t * Called after successful submission.\n\t */\n\taddToHistory(text: string): void {\n\t\tconst trimmed = text.trim();\n\t\tif (!trimmed) return;\n\t\t// Don't add consecutive duplicates\n\t\tif (this.history.length > 0 && this.history[0] === trimmed) return;\n\t\tthis.history.unshift(trimmed);\n\t\t// Limit history size\n\t\tif (this.history.length > 100) {\n\t\t\tthis.history.pop();\n\t\t}\n\t}\n\n\tprivate isEditorEmpty(): boolean {\n\t\treturn this.state.lines.length === 1 && this.state.lines[0] === \"\";\n\t}\n\n\tprivate isOnFirstVisualLine(): boolean {\n\t\tconst visualLines = this.buildVisualLineMap(this.lastWidth);\n\t\tconst currentVisualLine = this.findCurrentVisualLine(visualLines);\n\t\treturn currentVisualLine === 0;\n\t}\n\n\tprivate isOnLastVisualLine(): boolean {\n\t\tconst visualLines = this.buildVisualLineMap(this.lastWidth);\n\t\tconst currentVisualLine = this.findCurrentVisualLine(visualLines);\n\t\treturn currentVisualLine === visualLines.length - 1;\n\t}\n\n\tprivate navigateHistory(direction: 1 | -1): void {\n\t\tif (this.history.length === 0) return;\n\n\t\tconst newIndex = this.historyIndex - direction; // Up(-1) increases index, Down(1) decreases\n\t\tif (newIndex < -1 || newIndex >= this.history.length) return;\n\n\t\tthis.historyIndex = newIndex;\n\n\t\tif (this.historyIndex === -1) {\n\t\t\t// Returned to \"current\" state - clear editor\n\t\t\tthis.setTextInternal(\"\");\n\t\t} else {\n\t\t\tthis.setTextInternal(this.history[this.historyIndex] || \"\");\n\t\t}\n\t}\n\n\t/** Internal setText that doesn't reset history state - used by navigateHistory */\n\tprivate setTextInternal(text: string): void {\n\t\tconst lines = text.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\").split(\"\\n\");\n\t\tthis.state.lines = lines.length === 0 ? [\"\"] : lines;\n\t\tthis.state.cursorLine = this.state.lines.length - 1;\n\t\tthis.state.cursorCol = this.state.lines[this.state.cursorLine]?.length || 0;\n\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\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\t// Store width for cursor navigation\n\t\tthis.lastWidth = width;\n\n\t\tconst horizontal = this.borderColor(\"─\");\n\n\t\t// Layout the text - use full width\n\t\tconst layoutLines = this.layoutText(width);\n\n\t\tconst result: string[] = [];\n\n\t\t// Render top border\n\t\tresult.push(horizontal.repeat(width));\n\n\t\t// Render each layout line\n\t\tfor (const layoutLine of layoutLines) {\n\t\t\tlet displayText = layoutLine.text;\n\t\t\tlet lineVisibleWidth = visibleWidth(layoutLine.text);\n\n\t\t\t// Add cursor if this line has it\n\t\t\tif (layoutLine.hasCursor && layoutLine.cursorPos !== undefined) {\n\t\t\t\tconst before = displayText.slice(0, layoutLine.cursorPos);\n\t\t\t\tconst after = displayText.slice(layoutLine.cursorPos);\n\n\t\t\t\tif (after.length > 0) {\n\t\t\t\t\t// Cursor is on a character (grapheme) - replace it with highlighted version\n\t\t\t\t\t// Get the first grapheme from 'after'\n\t\t\t\t\tconst afterGraphemes = [...segmenter.segment(after)];\n\t\t\t\t\tconst firstGrapheme = afterGraphemes[0]?.segment || \"\";\n\t\t\t\t\tconst restAfter = after.slice(firstGrapheme.length);\n\t\t\t\t\tconst cursor = `\\x1b[7m${firstGrapheme}\\x1b[0m`;\n\t\t\t\t\tdisplayText = before + cursor + restAfter;\n\t\t\t\t\t// lineVisibleWidth stays the same - we're replacing, not adding\n\t\t\t\t} else {\n\t\t\t\t\t// Cursor is at the end - check if we have room for the space\n\t\t\t\t\tif (lineVisibleWidth < width) {\n\t\t\t\t\t\t// We have room - add highlighted space\n\t\t\t\t\t\tconst cursor = \"\\x1b[7m \\x1b[0m\";\n\t\t\t\t\t\tdisplayText = before + cursor;\n\t\t\t\t\t\t// lineVisibleWidth increases by 1 - we're adding a space\n\t\t\t\t\t\tlineVisibleWidth = lineVisibleWidth + 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Line is at full width - use reverse video on last grapheme if possible\n\t\t\t\t\t\t// or just show cursor at the end without adding space\n\t\t\t\t\t\tconst beforeGraphemes = [...segmenter.segment(before)];\n\t\t\t\t\t\tif (beforeGraphemes.length > 0) {\n\t\t\t\t\t\t\tconst lastGrapheme = beforeGraphemes[beforeGraphemes.length - 1]?.segment || \"\";\n\t\t\t\t\t\t\tconst cursor = `\\x1b[7m${lastGrapheme}\\x1b[0m`;\n\t\t\t\t\t\t\t// Rebuild 'before' without the last grapheme\n\t\t\t\t\t\t\tconst beforeWithoutLast = beforeGraphemes\n\t\t\t\t\t\t\t\t.slice(0, -1)\n\t\t\t\t\t\t\t\t.map((g) => g.segment)\n\t\t\t\t\t\t\t\t.join(\"\");\n\t\t\t\t\t\t\tdisplayText = beforeWithoutLast + cursor;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// lineVisibleWidth stays the same\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Calculate padding based on actual visible width\n\t\t\tconst padding = \" \".repeat(Math.max(0, width - lineVisibleWidth));\n\n\t\t\t// Render the line (no side borders, just horizontal lines above and below)\n\t\t\tresult.push(displayText + padding);\n\t\t}\n\n\t\t// Render bottom border\n\t\tresult.push(horizontal.repeat(width));\n\n\t\t// Add autocomplete list if active\n\t\tif (this.isAutocompleting && this.autocompleteList) {\n\t\t\tconst autocompleteResult = this.autocompleteList.render(width);\n\t\t\tresult.push(...autocompleteResult);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\thandleInput(data: string): void {\n\t\t// Handle bracketed paste mode\n\t\t// Start of paste: \\x1b[200~\n\t\t// End of paste: \\x1b[201~\n\n\t\t// Check if we're starting a bracketed paste\n\t\tif (data.includes(\"\\x1b[200~\")) {\n\t\t\tthis.isInPaste = true;\n\t\t\tthis.pasteBuffer = \"\";\n\t\t\t// Remove the start marker and keep the rest\n\t\t\tdata = data.replace(\"\\x1b[200~\", \"\");\n\t\t}\n\n\t\t// If we're in a paste, buffer the data\n\t\tif (this.isInPaste) {\n\t\t\t// Append data to buffer first (end marker could be split across chunks)\n\t\t\tthis.pasteBuffer += data;\n\n\t\t\t// Check if the accumulated buffer contains the end marker\n\t\t\tconst endIndex = this.pasteBuffer.indexOf(\"\\x1b[201~\");\n\t\t\tif (endIndex !== -1) {\n\t\t\t\t// Extract content before the end marker\n\t\t\t\tconst pasteContent = this.pasteBuffer.substring(0, endIndex);\n\n\t\t\t\t// Process the complete paste\n\t\t\t\tthis.handlePaste(pasteContent);\n\n\t\t\t\t// Reset paste state\n\t\t\t\tthis.isInPaste = false;\n\n\t\t\t\t// Process any remaining data after the end marker\n\t\t\t\tconst remaining = this.pasteBuffer.substring(endIndex + 6); // 6 = length of \\x1b[201~\n\t\t\t\tthis.pasteBuffer = \"\";\n\n\t\t\t\tif (remaining.length > 0) {\n\t\t\t\t\tthis.handleInput(remaining);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\t// Still accumulating, wait for more data\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Handle special key combinations first\n\n\t\t// Ctrl+C - Exit (let parent handle this)\n\t\tif (isCtrlC(data)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle autocomplete special keys first (but don't block other input)\n\t\tif (this.isAutocompleting && this.autocompleteList) {\n\t\t\t// Escape - cancel autocomplete\n\t\t\tif (isEscape(data)) {\n\t\t\t\tthis.cancelAutocomplete();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Let the autocomplete list handle navigation and selection\n\t\t\telse if (isArrowUp(data) || isArrowDown(data) || isEnter(data) || isTab(data)) {\n\t\t\t\t// Only pass arrow keys to the list, not Enter/Tab (we handle those directly)\n\t\t\t\tif (isArrowUp(data) || isArrowDown(data)) {\n\t\t\t\t\tthis.autocompleteList.handleInput(data);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// If Tab was pressed, always apply the selection\n\t\t\t\tif (isTab(data)) {\n\t\t\t\t\tconst selected = this.autocompleteList.getSelectedItem();\n\t\t\t\t\tif (selected && this.autocompleteProvider) {\n\t\t\t\t\t\tconst result = this.autocompleteProvider.applyCompletion(\n\t\t\t\t\t\t\tthis.state.lines,\n\t\t\t\t\t\t\tthis.state.cursorLine,\n\t\t\t\t\t\t\tthis.state.cursorCol,\n\t\t\t\t\t\t\tselected,\n\t\t\t\t\t\t\tthis.autocompletePrefix,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tthis.state.lines = result.lines;\n\t\t\t\t\t\tthis.state.cursorLine = result.cursorLine;\n\t\t\t\t\t\tthis.state.cursorCol = result.cursorCol;\n\n\t\t\t\t\t\tthis.cancelAutocomplete();\n\n\t\t\t\t\t\tif (this.onChange) {\n\t\t\t\t\t\t\tthis.onChange(this.getText());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// If Enter was pressed on a slash command, apply completion and submit\n\t\t\t\tif (isEnter(data) && this.autocompletePrefix.startsWith(\"/\")) {\n\t\t\t\t\tconst selected = this.autocompleteList.getSelectedItem();\n\t\t\t\t\tif (selected && this.autocompleteProvider) {\n\t\t\t\t\t\tconst result = this.autocompleteProvider.applyCompletion(\n\t\t\t\t\t\t\tthis.state.lines,\n\t\t\t\t\t\t\tthis.state.cursorLine,\n\t\t\t\t\t\t\tthis.state.cursorCol,\n\t\t\t\t\t\t\tselected,\n\t\t\t\t\t\t\tthis.autocompletePrefix,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tthis.state.lines = result.lines;\n\t\t\t\t\t\tthis.state.cursorLine = result.cursorLine;\n\t\t\t\t\t\tthis.state.cursorCol = result.cursorCol;\n\t\t\t\t\t}\n\t\t\t\t\tthis.cancelAutocomplete();\n\t\t\t\t\t// Don't return - fall through to submission logic\n\t\t\t\t}\n\t\t\t\t// If Enter was pressed on a file path, apply completion\n\t\t\t\telse if (isEnter(data)) {\n\t\t\t\t\tconst selected = this.autocompleteList.getSelectedItem();\n\t\t\t\t\tif (selected && this.autocompleteProvider) {\n\t\t\t\t\t\tconst result = this.autocompleteProvider.applyCompletion(\n\t\t\t\t\t\t\tthis.state.lines,\n\t\t\t\t\t\t\tthis.state.cursorLine,\n\t\t\t\t\t\t\tthis.state.cursorCol,\n\t\t\t\t\t\t\tselected,\n\t\t\t\t\t\t\tthis.autocompletePrefix,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tthis.state.lines = result.lines;\n\t\t\t\t\t\tthis.state.cursorLine = result.cursorLine;\n\t\t\t\t\t\tthis.state.cursorCol = result.cursorCol;\n\n\t\t\t\t\t\tthis.cancelAutocomplete();\n\n\t\t\t\t\t\tif (this.onChange) {\n\t\t\t\t\t\t\tthis.onChange(this.getText());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// For other keys (like regular typing), DON'T return here\n\t\t\t// Let them fall through to normal character handling\n\t\t}\n\n\t\t// Tab key - context-aware completion (but not when already autocompleting)\n\t\tif (isTab(data) && !this.isAutocompleting) {\n\t\t\tthis.handleTabCompletion();\n\t\t\treturn;\n\t\t}\n\n\t\t// Continue with rest of input handling\n\t\t// Ctrl+K - Delete to end of line\n\t\tif (isCtrlK(data)) {\n\t\t\tthis.deleteToEndOfLine();\n\t\t}\n\t\t// Ctrl+U - Delete to start of line\n\t\telse if (isCtrlU(data)) {\n\t\t\tthis.deleteToStartOfLine();\n\t\t}\n\t\t// Ctrl+W - Delete word backwards\n\t\telse if (isCtrlW(data)) {\n\t\t\tthis.deleteWordBackwards();\n\t\t}\n\t\t// Option/Alt+Backspace - Delete word backwards\n\t\telse if (isAltBackspace(data)) {\n\t\t\tthis.deleteWordBackwards();\n\t\t}\n\t\t// Ctrl+A - Move to start of line\n\t\telse if (isCtrlA(data)) {\n\t\t\tthis.moveToLineStart();\n\t\t}\n\t\t// Ctrl+E - Move to end of line\n\t\telse if (isCtrlE(data)) {\n\t\t\tthis.moveToLineEnd();\n\t\t}\n\t\t// New line shortcuts (but not plain LF/CR which should be submit)\n\t\telse if (\n\t\t\t(data.charCodeAt(0) === 10 && data.length > 1) || // Ctrl+Enter with modifiers\n\t\t\tdata === \"\\x1b\\r\" || // Option+Enter in some terminals (legacy)\n\t\t\tdata === \"\\x1b[13;2~\" || // Shift+Enter in some terminals (legacy format)\n\t\t\tisShiftEnter(data) || // Shift+Enter (Kitty protocol, handles lock bits)\n\t\t\tisAltEnter(data) || // Alt+Enter (Kitty protocol, handles lock bits)\n\t\t\t(data.length > 1 && data.includes(\"\\x1b\") && data.includes(\"\\r\")) ||\n\t\t\t(data === \"\\n\" && data.length === 1) || // Shift+Enter from iTerm2 mapping\n\t\t\tdata === \"\\\\\\r\" // Shift+Enter in VS Code terminal\n\t\t) {\n\t\t\t// Modifier + Enter = new line\n\t\t\tthis.addNewLine();\n\t\t}\n\t\t// Plain Enter - submit (handles both legacy \\r and Kitty protocol with lock bits)\n\t\telse if (isEnter(data)) {\n\t\t\t// If submit is disabled, do nothing\n\t\t\tif (this.disableSubmit) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Get text and substitute paste markers with actual content\n\t\t\tlet result = this.state.lines.join(\"\\n\").trim();\n\n\t\t\t// Replace all [paste #N +xxx lines] or [paste #N xxx chars] markers with actual paste content\n\t\t\tfor (const [pasteId, pasteContent] of this.pastes) {\n\t\t\t\t// Match formats: [paste #N], [paste #N +xxx lines], or [paste #N xxx chars]\n\t\t\t\tconst markerRegex = new RegExp(`\\\\[paste #${pasteId}( (\\\\+\\\\d+ lines|\\\\d+ chars))?\\\\]`, \"g\");\n\t\t\t\tresult = result.replace(markerRegex, pasteContent);\n\t\t\t}\n\n\t\t\t// Reset editor and clear pastes\n\t\t\tthis.state = {\n\t\t\t\tlines: [\"\"],\n\t\t\t\tcursorLine: 0,\n\t\t\t\tcursorCol: 0,\n\t\t\t};\n\t\t\tthis.pastes.clear();\n\t\t\tthis.pasteCounter = 0;\n\t\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\t\t// Notify that editor is now empty\n\t\t\tif (this.onChange) {\n\t\t\t\tthis.onChange(\"\");\n\t\t\t}\n\n\t\t\tif (this.onSubmit) {\n\t\t\t\tthis.onSubmit(result);\n\t\t\t}\n\t\t}\n\t\t// Backspace\n\t\telse if (isBackspace(data)) {\n\t\t\tthis.handleBackspace();\n\t\t}\n\t\t// Line navigation shortcuts (Home/End keys)\n\t\telse if (isHome(data)) {\n\t\t\tthis.moveToLineStart();\n\t\t} else if (isEnd(data)) {\n\t\t\tthis.moveToLineEnd();\n\t\t}\n\t\t// Forward delete (Fn+Backspace or Delete key)\n\t\telse if (isDelete(data)) {\n\t\t\tthis.handleForwardDelete();\n\t\t}\n\t\t// Word navigation (Option/Alt + Arrow or Ctrl + Arrow)\n\t\telse if (isAltLeft(data) || isCtrlLeft(data)) {\n\t\t\t// Word left\n\t\t\tthis.moveWordBackwards();\n\t\t} else if (isAltRight(data) || isCtrlRight(data)) {\n\t\t\t// Word right\n\t\t\tthis.moveWordForwards();\n\t\t}\n\t\t// Arrow keys\n\t\telse if (isArrowUp(data)) {\n\t\t\t// Up - history navigation or cursor movement\n\t\t\tif (this.isEditorEmpty()) {\n\t\t\t\tthis.navigateHistory(-1); // Start browsing history\n\t\t\t} else if (this.historyIndex > -1 && this.isOnFirstVisualLine()) {\n\t\t\t\tthis.navigateHistory(-1); // Navigate to older history entry\n\t\t\t} else {\n\t\t\t\tthis.moveCursor(-1, 0); // Cursor movement (within text or history entry)\n\t\t\t}\n\t\t} else if (isArrowDown(data)) {\n\t\t\t// Down - history navigation or cursor movement\n\t\t\tif (this.historyIndex > -1 && this.isOnLastVisualLine()) {\n\t\t\t\tthis.navigateHistory(1); // Navigate to newer history entry or clear\n\t\t\t} else {\n\t\t\t\tthis.moveCursor(1, 0); // Cursor movement (within text or history entry)\n\t\t\t}\n\t\t} else if (isArrowRight(data)) {\n\t\t\t// Right\n\t\t\tthis.moveCursor(0, 1);\n\t\t} else if (isArrowLeft(data)) {\n\t\t\t// Left\n\t\t\tthis.moveCursor(0, -1);\n\t\t}\n\t\t// Regular characters (printable characters and unicode, but not control characters)\n\t\telse if (data.charCodeAt(0) >= 32) {\n\t\t\tthis.insertCharacter(data);\n\t\t}\n\t}\n\n\tprivate layoutText(contentWidth: number): LayoutLine[] {\n\t\tconst layoutLines: LayoutLine[] = [];\n\n\t\tif (this.state.lines.length === 0 || (this.state.lines.length === 1 && this.state.lines[0] === \"\")) {\n\t\t\t// Empty editor\n\t\t\tlayoutLines.push({\n\t\t\t\ttext: \"\",\n\t\t\t\thasCursor: true,\n\t\t\t\tcursorPos: 0,\n\t\t\t});\n\t\t\treturn layoutLines;\n\t\t}\n\n\t\t// Process each logical line\n\t\tfor (let i = 0; i < this.state.lines.length; i++) {\n\t\t\tconst line = this.state.lines[i] || \"\";\n\t\t\tconst isCurrentLine = i === this.state.cursorLine;\n\t\t\tconst lineVisibleWidth = visibleWidth(line);\n\n\t\t\tif (lineVisibleWidth <= contentWidth) {\n\t\t\t\t// Line fits in one layout line\n\t\t\t\tif (isCurrentLine) {\n\t\t\t\t\tlayoutLines.push({\n\t\t\t\t\t\ttext: line,\n\t\t\t\t\t\thasCursor: true,\n\t\t\t\t\t\tcursorPos: this.state.cursorCol,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tlayoutLines.push({\n\t\t\t\t\t\ttext: line,\n\t\t\t\t\t\thasCursor: false,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Line needs wrapping - use grapheme-aware chunking\n\t\t\t\tconst chunks: { text: string; startIndex: number; endIndex: number }[] = [];\n\t\t\t\tlet currentChunk = \"\";\n\t\t\t\tlet currentWidth = 0;\n\t\t\t\tlet chunkStartIndex = 0;\n\t\t\t\tlet currentIndex = 0;\n\n\t\t\t\tfor (const seg of segmenter.segment(line)) {\n\t\t\t\t\tconst grapheme = seg.segment;\n\t\t\t\t\tconst graphemeWidth = visibleWidth(grapheme);\n\n\t\t\t\t\tif (currentWidth + graphemeWidth > contentWidth && currentChunk !== \"\") {\n\t\t\t\t\t\t// Start a new chunk\n\t\t\t\t\t\tchunks.push({\n\t\t\t\t\t\t\ttext: currentChunk,\n\t\t\t\t\t\t\tstartIndex: chunkStartIndex,\n\t\t\t\t\t\t\tendIndex: currentIndex,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcurrentChunk = grapheme;\n\t\t\t\t\t\tcurrentWidth = graphemeWidth;\n\t\t\t\t\t\tchunkStartIndex = currentIndex;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcurrentChunk += grapheme;\n\t\t\t\t\t\tcurrentWidth += graphemeWidth;\n\t\t\t\t\t}\n\t\t\t\t\tcurrentIndex += grapheme.length;\n\t\t\t\t}\n\n\t\t\t\t// Push the last chunk\n\t\t\t\tif (currentChunk !== \"\") {\n\t\t\t\t\tchunks.push({\n\t\t\t\t\t\ttext: currentChunk,\n\t\t\t\t\t\tstartIndex: chunkStartIndex,\n\t\t\t\t\t\tendIndex: currentIndex,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tfor (let chunkIndex = 0; chunkIndex < chunks.length; chunkIndex++) {\n\t\t\t\t\tconst chunk = chunks[chunkIndex];\n\t\t\t\t\tif (!chunk) continue;\n\n\t\t\t\t\tconst cursorPos = this.state.cursorCol;\n\t\t\t\t\tconst isLastChunk = chunkIndex === chunks.length - 1;\n\t\t\t\t\t// For non-last chunks, cursor at endIndex belongs to the next chunk\n\t\t\t\t\tconst hasCursorInChunk =\n\t\t\t\t\t\tisCurrentLine &&\n\t\t\t\t\t\tcursorPos >= chunk.startIndex &&\n\t\t\t\t\t\t(isLastChunk ? cursorPos <= chunk.endIndex : cursorPos < chunk.endIndex);\n\n\t\t\t\t\tif (hasCursorInChunk) {\n\t\t\t\t\t\tlayoutLines.push({\n\t\t\t\t\t\t\ttext: chunk.text,\n\t\t\t\t\t\t\thasCursor: true,\n\t\t\t\t\t\t\tcursorPos: cursorPos - chunk.startIndex,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlayoutLines.push({\n\t\t\t\t\t\t\ttext: chunk.text,\n\t\t\t\t\t\t\thasCursor: false,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn layoutLines;\n\t}\n\n\tgetText(): string {\n\t\treturn this.state.lines.join(\"\\n\");\n\t}\n\n\tgetLines(): string[] {\n\t\treturn [...this.state.lines];\n\t}\n\n\tgetCursor(): { line: number; col: number } {\n\t\treturn { line: this.state.cursorLine, col: this.state.cursorCol };\n\t}\n\n\tsetText(text: string): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\t\tthis.setTextInternal(text);\n\t}\n\n\t// All the editor methods from before...\n\tprivate insertCharacter(char: string): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\tconst line = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\tconst before = line.slice(0, this.state.cursorCol);\n\t\tconst after = line.slice(this.state.cursorCol);\n\n\t\tthis.state.lines[this.state.cursorLine] = before + char + after;\n\t\tthis.state.cursorCol += char.length; // Fix: increment by the length of the inserted string\n\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\n\n\t\t// Check if we should trigger or update autocomplete\n\t\tif (!this.isAutocompleting) {\n\t\t\t// Auto-trigger for \"/\" at the start of a line (slash commands)\n\t\t\tif (char === \"/\" && this.isAtStartOfMessage()) {\n\t\t\t\tthis.tryTriggerAutocomplete();\n\t\t\t}\n\t\t\t// Auto-trigger for \"@\" file reference (fuzzy search)\n\t\t\telse if (char === \"@\") {\n\t\t\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\t\t\tconst textBeforeCursor = currentLine.slice(0, this.state.cursorCol);\n\t\t\t\t// Only trigger if @ is after whitespace or at start of line\n\t\t\t\tconst charBeforeAt = textBeforeCursor[textBeforeCursor.length - 2];\n\t\t\t\tif (textBeforeCursor.length === 1 || charBeforeAt === \" \" || charBeforeAt === \"\\t\") {\n\t\t\t\t\tthis.tryTriggerAutocomplete();\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Also auto-trigger when typing letters in a slash command context\n\t\t\telse if (/[a-zA-Z0-9]/.test(char)) {\n\t\t\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\t\t\tconst textBeforeCursor = currentLine.slice(0, this.state.cursorCol);\n\t\t\t\t// Check if we're in a slash command (with or without space for arguments)\n\t\t\t\tif (textBeforeCursor.trimStart().startsWith(\"/\")) {\n\t\t\t\t\tthis.tryTriggerAutocomplete();\n\t\t\t\t}\n\t\t\t\t// Check if we're in an @ file reference context\n\t\t\t\telse if (textBeforeCursor.match(/(?:^|[\\s])@[^\\s]*$/)) {\n\t\t\t\t\tthis.tryTriggerAutocomplete();\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.updateAutocomplete();\n\t\t}\n\t}\n\n\tprivate handlePaste(pastedText: string): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\t// Clean the pasted text\n\t\tconst cleanText = pastedText.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\n\t\t// Convert tabs to spaces (4 spaces per tab)\n\t\tconst tabExpandedText = cleanText.replace(/\\t/g, \" \");\n\n\t\t// Filter out non-printable characters except newlines\n\t\tconst filteredText = tabExpandedText\n\t\t\t.split(\"\")\n\t\t\t.filter((char) => char === \"\\n\" || char.charCodeAt(0) >= 32)\n\t\t\t.join(\"\");\n\n\t\t// Split into lines\n\t\tconst pastedLines = filteredText.split(\"\\n\");\n\n\t\t// Check if this is a large paste (> 10 lines or > 1000 characters)\n\t\tconst totalChars = filteredText.length;\n\t\tif (pastedLines.length > 10 || totalChars > 1000) {\n\t\t\t// Store the paste and insert a marker\n\t\t\tthis.pasteCounter++;\n\t\t\tconst pasteId = this.pasteCounter;\n\t\t\tthis.pastes.set(pasteId, filteredText);\n\n\t\t\t// Insert marker like \"[paste #1 +123 lines]\" or \"[paste #1 1234 chars]\"\n\t\t\tconst marker =\n\t\t\t\tpastedLines.length > 10\n\t\t\t\t\t? `[paste #${pasteId} +${pastedLines.length} lines]`\n\t\t\t\t\t: `[paste #${pasteId} ${totalChars} chars]`;\n\t\t\tfor (const char of marker) {\n\t\t\t\tthis.insertCharacter(char);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tif (pastedLines.length === 1) {\n\t\t\t// Single line - just insert each character\n\t\t\tconst text = pastedLines[0] || \"\";\n\t\t\tfor (const char of text) {\n\t\t\t\tthis.insertCharacter(char);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Multi-line paste - be very careful with array manipulation\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\tconst beforeCursor = currentLine.slice(0, this.state.cursorCol);\n\t\tconst afterCursor = currentLine.slice(this.state.cursorCol);\n\n\t\t// Build the new lines array step by step\n\t\tconst newLines: string[] = [];\n\n\t\t// Add all lines before current line\n\t\tfor (let i = 0; i < this.state.cursorLine; i++) {\n\t\t\tnewLines.push(this.state.lines[i] || \"\");\n\t\t}\n\n\t\t// Add the first pasted line merged with before cursor text\n\t\tnewLines.push(beforeCursor + (pastedLines[0] || \"\"));\n\n\t\t// Add all middle pasted lines\n\t\tfor (let i = 1; i < pastedLines.length - 1; i++) {\n\t\t\tnewLines.push(pastedLines[i] || \"\");\n\t\t}\n\n\t\t// Add the last pasted line with after cursor text\n\t\tnewLines.push((pastedLines[pastedLines.length - 1] || \"\") + afterCursor);\n\n\t\t// Add all lines after current line\n\t\tfor (let i = this.state.cursorLine + 1; i < this.state.lines.length; i++) {\n\t\t\tnewLines.push(this.state.lines[i] || \"\");\n\t\t}\n\n\t\t// Replace the entire lines array\n\t\tthis.state.lines = newLines;\n\n\t\t// Update cursor position to end of pasted content\n\t\tthis.state.cursorLine += pastedLines.length - 1;\n\t\tthis.state.cursorCol = (pastedLines[pastedLines.length - 1] || \"\").length;\n\n\t\t// Notify of change\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\n\t}\n\n\tprivate addNewLine(): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\tconst before = currentLine.slice(0, this.state.cursorCol);\n\t\tconst after = currentLine.slice(this.state.cursorCol);\n\n\t\t// Split current line\n\t\tthis.state.lines[this.state.cursorLine] = before;\n\t\tthis.state.lines.splice(this.state.cursorLine + 1, 0, after);\n\n\t\t// Move cursor to start of new line\n\t\tthis.state.cursorLine++;\n\t\tthis.state.cursorCol = 0;\n\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\n\t}\n\n\tprivate handleBackspace(): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\tif (this.state.cursorCol > 0) {\n\t\t\t// Delete grapheme before cursor (handles emojis, combining characters, etc.)\n\t\t\tconst line = this.state.lines[this.state.cursorLine] || \"\";\n\t\t\tconst beforeCursor = line.slice(0, this.state.cursorCol);\n\n\t\t\t// Find the last grapheme in the text before cursor\n\t\t\tconst graphemes = [...segmenter.segment(beforeCursor)];\n\t\t\tconst lastGrapheme = graphemes[graphemes.length - 1];\n\t\t\tconst graphemeLength = lastGrapheme ? lastGrapheme.segment.length : 1;\n\n\t\t\tconst before = line.slice(0, this.state.cursorCol - graphemeLength);\n\t\t\tconst after = line.slice(this.state.cursorCol);\n\n\t\t\tthis.state.lines[this.state.cursorLine] = before + after;\n\t\t\tthis.state.cursorCol -= graphemeLength;\n\t\t} else if (this.state.cursorLine > 0) {\n\t\t\t// Merge with previous line\n\t\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\t\tconst previousLine = this.state.lines[this.state.cursorLine - 1] || \"\";\n\n\t\t\tthis.state.lines[this.state.cursorLine - 1] = previousLine + currentLine;\n\t\t\tthis.state.lines.splice(this.state.cursorLine, 1);\n\n\t\t\tthis.state.cursorLine--;\n\t\t\tthis.state.cursorCol = previousLine.length;\n\t\t}\n\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\n\n\t\t// Update or re-trigger autocomplete after backspace\n\t\tif (this.isAutocompleting) {\n\t\t\tthis.updateAutocomplete();\n\t\t} else {\n\t\t\t// If autocomplete was cancelled (no matches), re-trigger if we're in a completable context\n\t\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\t\tconst textBeforeCursor = currentLine.slice(0, this.state.cursorCol);\n\t\t\t// Slash command context\n\t\t\tif (textBeforeCursor.trimStart().startsWith(\"/\")) {\n\t\t\t\tthis.tryTriggerAutocomplete();\n\t\t\t}\n\t\t\t// @ file reference context\n\t\t\telse if (textBeforeCursor.match(/(?:^|[\\s])@[^\\s]*$/)) {\n\t\t\t\tthis.tryTriggerAutocomplete();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate moveToLineStart(): void {\n\t\tthis.state.cursorCol = 0;\n\t}\n\n\tprivate moveToLineEnd(): void {\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\tthis.state.cursorCol = currentLine.length;\n\t}\n\n\tprivate deleteToStartOfLine(): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\tif (this.state.cursorCol > 0) {\n\t\t\t// Delete from start of line up to cursor\n\t\t\tthis.state.lines[this.state.cursorLine] = currentLine.slice(this.state.cursorCol);\n\t\t\tthis.state.cursorCol = 0;\n\t\t} else if (this.state.cursorLine > 0) {\n\t\t\t// At start of line - merge with previous line\n\t\t\tconst previousLine = this.state.lines[this.state.cursorLine - 1] || \"\";\n\t\t\tthis.state.lines[this.state.cursorLine - 1] = previousLine + currentLine;\n\t\t\tthis.state.lines.splice(this.state.cursorLine, 1);\n\t\t\tthis.state.cursorLine--;\n\t\t\tthis.state.cursorCol = previousLine.length;\n\t\t}\n\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\n\t}\n\n\tprivate deleteToEndOfLine(): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\tif (this.state.cursorCol < currentLine.length) {\n\t\t\t// Delete from cursor to end of line\n\t\t\tthis.state.lines[this.state.cursorLine] = currentLine.slice(0, this.state.cursorCol);\n\t\t} else if (this.state.cursorLine < this.state.lines.length - 1) {\n\t\t\t// At end of line - merge with next line\n\t\t\tconst nextLine = this.state.lines[this.state.cursorLine + 1] || \"\";\n\t\t\tthis.state.lines[this.state.cursorLine] = currentLine + nextLine;\n\t\t\tthis.state.lines.splice(this.state.cursorLine + 1, 1);\n\t\t}\n\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\n\t}\n\n\tprivate deleteWordBackwards(): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\t// If at start of line, behave like backspace at column 0 (merge with previous line)\n\t\tif (this.state.cursorCol === 0) {\n\t\t\tif (this.state.cursorLine > 0) {\n\t\t\t\tconst previousLine = this.state.lines[this.state.cursorLine - 1] || \"\";\n\t\t\t\tthis.state.lines[this.state.cursorLine - 1] = previousLine + currentLine;\n\t\t\t\tthis.state.lines.splice(this.state.cursorLine, 1);\n\t\t\t\tthis.state.cursorLine--;\n\t\t\t\tthis.state.cursorCol = previousLine.length;\n\t\t\t}\n\t\t} else {\n\t\t\tconst textBeforeCursor = currentLine.slice(0, this.state.cursorCol);\n\n\t\t\tconst isWhitespace = (char: string): boolean => /\\s/.test(char);\n\t\t\tconst isPunctuation = (char: string): boolean => {\n\t\t\t\t// Treat obvious code punctuation as boundaries\n\t\t\t\treturn /[(){}[\\]<>.,;:'\"!?+\\-=*/\\\\|&%^$#@~`]/.test(char);\n\t\t\t};\n\n\t\t\tlet deleteFrom = this.state.cursorCol;\n\t\t\tconst lastChar = textBeforeCursor[deleteFrom - 1] ?? \"\";\n\n\t\t\t// If immediately on whitespace or punctuation, delete that single boundary char\n\t\t\tif (isWhitespace(lastChar) || isPunctuation(lastChar)) {\n\t\t\t\tdeleteFrom -= 1;\n\t\t\t} else {\n\t\t\t\t// Otherwise, delete a run of non-boundary characters (the \"word\")\n\t\t\t\twhile (deleteFrom > 0) {\n\t\t\t\t\tconst ch = textBeforeCursor[deleteFrom - 1] ?? \"\";\n\t\t\t\t\tif (isWhitespace(ch) || isPunctuation(ch)) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdeleteFrom -= 1;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.state.lines[this.state.cursorLine] =\n\t\t\t\tcurrentLine.slice(0, deleteFrom) + currentLine.slice(this.state.cursorCol);\n\t\t\tthis.state.cursorCol = deleteFrom;\n\t\t}\n\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\n\t}\n\n\tprivate handleForwardDelete(): void {\n\t\tthis.historyIndex = -1; // Exit history browsing mode\n\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\tif (this.state.cursorCol < currentLine.length) {\n\t\t\t// Delete grapheme at cursor position (handles emojis, combining characters, etc.)\n\t\t\tconst afterCursor = currentLine.slice(this.state.cursorCol);\n\n\t\t\t// Find the first grapheme at cursor\n\t\t\tconst graphemes = [...segmenter.segment(afterCursor)];\n\t\t\tconst firstGrapheme = graphemes[0];\n\t\t\tconst graphemeLength = firstGrapheme ? firstGrapheme.segment.length : 1;\n\n\t\t\tconst before = currentLine.slice(0, this.state.cursorCol);\n\t\t\tconst after = currentLine.slice(this.state.cursorCol + graphemeLength);\n\t\t\tthis.state.lines[this.state.cursorLine] = before + after;\n\t\t} else if (this.state.cursorLine < this.state.lines.length - 1) {\n\t\t\t// At end of line - merge with next line\n\t\t\tconst nextLine = this.state.lines[this.state.cursorLine + 1] || \"\";\n\t\t\tthis.state.lines[this.state.cursorLine] = currentLine + nextLine;\n\t\t\tthis.state.lines.splice(this.state.cursorLine + 1, 1);\n\t\t}\n\n\t\tif (this.onChange) {\n\t\t\tthis.onChange(this.getText());\n\t\t}\n\n\t\t// Update or re-trigger autocomplete after forward delete\n\t\tif (this.isAutocompleting) {\n\t\t\tthis.updateAutocomplete();\n\t\t} else {\n\t\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\t\tconst textBeforeCursor = currentLine.slice(0, this.state.cursorCol);\n\t\t\t// Slash command context\n\t\t\tif (textBeforeCursor.trimStart().startsWith(\"/\")) {\n\t\t\t\tthis.tryTriggerAutocomplete();\n\t\t\t}\n\t\t\t// @ file reference context\n\t\t\telse if (textBeforeCursor.match(/(?:^|[\\s])@[^\\s]*$/)) {\n\t\t\t\tthis.tryTriggerAutocomplete();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Build a mapping from visual lines to logical positions.\n\t * Returns an array where each element represents a visual line with:\n\t * - logicalLine: index into this.state.lines\n\t * - startCol: starting column in the logical line\n\t * - length: length of this visual line segment\n\t */\n\tprivate buildVisualLineMap(width: number): Array<{ logicalLine: number; startCol: number; length: number }> {\n\t\tconst visualLines: Array<{ logicalLine: number; startCol: number; length: number }> = [];\n\n\t\tfor (let i = 0; i < this.state.lines.length; i++) {\n\t\t\tconst line = this.state.lines[i] || \"\";\n\t\t\tconst lineVisWidth = visibleWidth(line);\n\t\t\tif (line.length === 0) {\n\t\t\t\t// Empty line still takes one visual line\n\t\t\t\tvisualLines.push({ logicalLine: i, startCol: 0, length: 0 });\n\t\t\t} else if (lineVisWidth <= width) {\n\t\t\t\tvisualLines.push({ logicalLine: i, startCol: 0, length: line.length });\n\t\t\t} else {\n\t\t\t\t// Line needs wrapping - use grapheme-aware chunking\n\t\t\t\tlet currentWidth = 0;\n\t\t\t\tlet chunkStartIndex = 0;\n\t\t\t\tlet currentIndex = 0;\n\n\t\t\t\tfor (const seg of segmenter.segment(line)) {\n\t\t\t\t\tconst grapheme = seg.segment;\n\t\t\t\t\tconst graphemeWidth = visibleWidth(grapheme);\n\n\t\t\t\t\tif (currentWidth + graphemeWidth > width && currentIndex > chunkStartIndex) {\n\t\t\t\t\t\t// Start a new chunk\n\t\t\t\t\t\tvisualLines.push({\n\t\t\t\t\t\t\tlogicalLine: i,\n\t\t\t\t\t\t\tstartCol: chunkStartIndex,\n\t\t\t\t\t\t\tlength: currentIndex - chunkStartIndex,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tchunkStartIndex = currentIndex;\n\t\t\t\t\t\tcurrentWidth = graphemeWidth;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcurrentWidth += graphemeWidth;\n\t\t\t\t\t}\n\t\t\t\t\tcurrentIndex += grapheme.length;\n\t\t\t\t}\n\n\t\t\t\t// Push the last chunk\n\t\t\t\tif (currentIndex > chunkStartIndex) {\n\t\t\t\t\tvisualLines.push({\n\t\t\t\t\t\tlogicalLine: i,\n\t\t\t\t\t\tstartCol: chunkStartIndex,\n\t\t\t\t\t\tlength: currentIndex - chunkStartIndex,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn visualLines;\n\t}\n\n\t/**\n\t * Find the visual line index for the current cursor position.\n\t */\n\tprivate findCurrentVisualLine(\n\t\tvisualLines: Array<{ logicalLine: number; startCol: number; length: number }>,\n\t): number {\n\t\tfor (let i = 0; i < visualLines.length; i++) {\n\t\t\tconst vl = visualLines[i];\n\t\t\tif (!vl) continue;\n\t\t\tif (vl.logicalLine === this.state.cursorLine) {\n\t\t\t\tconst colInSegment = this.state.cursorCol - vl.startCol;\n\t\t\t\t// Cursor is in this segment if it's within range\n\t\t\t\t// For the last segment of a logical line, cursor can be at length (end position)\n\t\t\t\tconst isLastSegmentOfLine =\n\t\t\t\t\ti === visualLines.length - 1 || visualLines[i + 1]?.logicalLine !== vl.logicalLine;\n\t\t\t\tif (colInSegment >= 0 && (colInSegment < vl.length || (isLastSegmentOfLine && colInSegment <= vl.length))) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Fallback: return last visual line\n\t\treturn visualLines.length - 1;\n\t}\n\n\tprivate moveCursor(deltaLine: number, deltaCol: number): void {\n\t\tconst width = this.lastWidth;\n\n\t\tif (deltaLine !== 0) {\n\t\t\t// Build visual line map for navigation\n\t\t\tconst visualLines = this.buildVisualLineMap(width);\n\t\t\tconst currentVisualLine = this.findCurrentVisualLine(visualLines);\n\n\t\t\t// Calculate column position within current visual line\n\t\t\tconst currentVL = visualLines[currentVisualLine];\n\t\t\tconst visualCol = currentVL ? this.state.cursorCol - currentVL.startCol : 0;\n\n\t\t\t// Move to target visual line\n\t\t\tconst targetVisualLine = currentVisualLine + deltaLine;\n\n\t\t\tif (targetVisualLine >= 0 && targetVisualLine < visualLines.length) {\n\t\t\t\tconst targetVL = visualLines[targetVisualLine];\n\t\t\t\tif (targetVL) {\n\t\t\t\t\tthis.state.cursorLine = targetVL.logicalLine;\n\t\t\t\t\t// Try to maintain visual column position, clamped to line length\n\t\t\t\t\tconst targetCol = targetVL.startCol + Math.min(visualCol, targetVL.length);\n\t\t\t\t\tconst logicalLine = this.state.lines[targetVL.logicalLine] || \"\";\n\t\t\t\t\tthis.state.cursorCol = Math.min(targetCol, logicalLine.length);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (deltaCol !== 0) {\n\t\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\t\tif (deltaCol > 0) {\n\t\t\t\t// Moving right - move by one grapheme (handles emojis, combining characters, etc.)\n\t\t\t\tif (this.state.cursorCol < currentLine.length) {\n\t\t\t\t\tconst afterCursor = currentLine.slice(this.state.cursorCol);\n\t\t\t\t\tconst graphemes = [...segmenter.segment(afterCursor)];\n\t\t\t\t\tconst firstGrapheme = graphemes[0];\n\t\t\t\t\tthis.state.cursorCol += firstGrapheme ? firstGrapheme.segment.length : 1;\n\t\t\t\t} else if (this.state.cursorLine < this.state.lines.length - 1) {\n\t\t\t\t\t// Wrap to start of next logical line\n\t\t\t\t\tthis.state.cursorLine++;\n\t\t\t\t\tthis.state.cursorCol = 0;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Moving left - move by one grapheme (handles emojis, combining characters, etc.)\n\t\t\t\tif (this.state.cursorCol > 0) {\n\t\t\t\t\tconst beforeCursor = currentLine.slice(0, this.state.cursorCol);\n\t\t\t\t\tconst graphemes = [...segmenter.segment(beforeCursor)];\n\t\t\t\t\tconst lastGrapheme = graphemes[graphemes.length - 1];\n\t\t\t\t\tthis.state.cursorCol -= lastGrapheme ? lastGrapheme.segment.length : 1;\n\t\t\t\t} else if (this.state.cursorLine > 0) {\n\t\t\t\t\t// Wrap to end of previous logical line\n\t\t\t\t\tthis.state.cursorLine--;\n\t\t\t\t\tconst prevLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\t\t\t\tthis.state.cursorCol = prevLine.length;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isWordBoundary(char: string): boolean {\n\t\treturn /\\s/.test(char) || /[(){}[\\]<>.,;:'\"!?+\\-=*/\\\\|&%^$#@~`]/.test(char);\n\t}\n\n\tprivate moveWordBackwards(): void {\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\t// If at start of line, move to end of previous line\n\t\tif (this.state.cursorCol === 0) {\n\t\t\tif (this.state.cursorLine > 0) {\n\t\t\t\tthis.state.cursorLine--;\n\t\t\t\tconst prevLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\t\t\tthis.state.cursorCol = prevLine.length;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst textBeforeCursor = currentLine.slice(0, this.state.cursorCol);\n\t\tlet newCol = this.state.cursorCol;\n\t\tconst lastChar = textBeforeCursor[newCol - 1] ?? \"\";\n\n\t\t// If immediately on whitespace or punctuation, skip that single boundary char\n\t\tif (this.isWordBoundary(lastChar)) {\n\t\t\tnewCol -= 1;\n\t\t}\n\n\t\t// Now skip the \"word\" (non-boundary characters)\n\t\twhile (newCol > 0) {\n\t\t\tconst ch = textBeforeCursor[newCol - 1] ?? \"\";\n\t\t\tif (this.isWordBoundary(ch)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tnewCol -= 1;\n\t\t}\n\n\t\tthis.state.cursorCol = newCol;\n\t}\n\n\tprivate moveWordForwards(): void {\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\n\t\t// If at end of line, move to start of next line\n\t\tif (this.state.cursorCol >= currentLine.length) {\n\t\t\tif (this.state.cursorLine < this.state.lines.length - 1) {\n\t\t\t\tthis.state.cursorLine++;\n\t\t\t\tthis.state.cursorCol = 0;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet newCol = this.state.cursorCol;\n\t\tconst charAtCursor = currentLine[newCol] ?? \"\";\n\n\t\t// If on whitespace or punctuation, skip it\n\t\tif (this.isWordBoundary(charAtCursor)) {\n\t\t\tnewCol += 1;\n\t\t}\n\n\t\t// Skip the \"word\" (non-boundary characters)\n\t\twhile (newCol < currentLine.length) {\n\t\t\tconst ch = currentLine[newCol] ?? \"\";\n\t\t\tif (this.isWordBoundary(ch)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tnewCol += 1;\n\t\t}\n\n\t\tthis.state.cursorCol = newCol;\n\t}\n\n\t// Helper method to check if cursor is at start of message (for slash command detection)\n\tprivate isAtStartOfMessage(): boolean {\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\tconst beforeCursor = currentLine.slice(0, this.state.cursorCol);\n\n\t\t// At start if line is empty, only contains whitespace, or is just \"/\"\n\t\treturn beforeCursor.trim() === \"\" || beforeCursor.trim() === \"/\";\n\t}\n\n\t// Autocomplete methods\n\tprivate tryTriggerAutocomplete(explicitTab: boolean = false): void {\n\t\tif (!this.autocompleteProvider) return;\n\n\t\t// Check if we should trigger file completion on Tab\n\t\tif (explicitTab) {\n\t\t\tconst provider = this.autocompleteProvider as CombinedAutocompleteProvider;\n\t\t\tconst shouldTrigger =\n\t\t\t\t!provider.shouldTriggerFileCompletion ||\n\t\t\t\tprovider.shouldTriggerFileCompletion(this.state.lines, this.state.cursorLine, this.state.cursorCol);\n\t\t\tif (!shouldTrigger) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tconst suggestions = this.autocompleteProvider.getSuggestions(\n\t\t\tthis.state.lines,\n\t\t\tthis.state.cursorLine,\n\t\t\tthis.state.cursorCol,\n\t\t);\n\n\t\tif (suggestions && suggestions.items.length > 0) {\n\t\t\tthis.autocompletePrefix = suggestions.prefix;\n\t\t\tthis.autocompleteList = new SelectList(suggestions.items, 5, this.theme.selectList);\n\t\t\tthis.isAutocompleting = true;\n\t\t} else {\n\t\t\tthis.cancelAutocomplete();\n\t\t}\n\t}\n\n\tprivate handleTabCompletion(): void {\n\t\tif (!this.autocompleteProvider) return;\n\n\t\tconst currentLine = this.state.lines[this.state.cursorLine] || \"\";\n\t\tconst beforeCursor = currentLine.slice(0, this.state.cursorCol);\n\n\t\t// Check if we're in a slash command context\n\t\tif (beforeCursor.trimStart().startsWith(\"/\") && !beforeCursor.trimStart().includes(\" \")) {\n\t\t\tthis.handleSlashCommandCompletion();\n\t\t} else {\n\t\t\tthis.forceFileAutocomplete();\n\t\t}\n\t}\n\n\tprivate handleSlashCommandCompletion(): void {\n\t\tthis.tryTriggerAutocomplete(true);\n\t}\n\n\t/*\nhttps://github.com/EsotericSoftware/spine-runtimes/actions/runs/19536643416/job/559322883\n17 this job fails with https://github.com/EsotericSoftware/spine-runtimes/actions/runs/19\n536643416/job/55932288317 havea look at .gi\n\t */\n\tprivate forceFileAutocomplete(): void {\n\t\tif (!this.autocompleteProvider) return;\n\n\t\t// Check if provider has the force method\n\t\tconst provider = this.autocompleteProvider as any;\n\t\tif (!provider.getForceFileSuggestions) {\n\t\t\tthis.tryTriggerAutocomplete(true);\n\t\t\treturn;\n\t\t}\n\n\t\tconst suggestions = provider.getForceFileSuggestions(\n\t\t\tthis.state.lines,\n\t\t\tthis.state.cursorLine,\n\t\t\tthis.state.cursorCol,\n\t\t);\n\n\t\tif (suggestions && suggestions.items.length > 0) {\n\t\t\tthis.autocompletePrefix = suggestions.prefix;\n\t\t\tthis.autocompleteList = new SelectList(suggestions.items, 5, this.theme.selectList);\n\t\t\tthis.isAutocompleting = true;\n\t\t} else {\n\t\t\tthis.cancelAutocomplete();\n\t\t}\n\t}\n\n\tprivate cancelAutocomplete(): void {\n\t\tthis.isAutocompleting = false;\n\t\tthis.autocompleteList = undefined as any;\n\t\tthis.autocompletePrefix = \"\";\n\t}\n\n\tpublic isShowingAutocomplete(): boolean {\n\t\treturn this.isAutocompleting;\n\t}\n\n\tprivate updateAutocomplete(): void {\n\t\tif (!this.isAutocompleting || !this.autocompleteProvider) return;\n\n\t\tconst suggestions = this.autocompleteProvider.getSuggestions(\n\t\t\tthis.state.lines,\n\t\t\tthis.state.cursorLine,\n\t\t\tthis.state.cursorCol,\n\t\t);\n\n\t\tif (suggestions && suggestions.items.length > 0) {\n\t\t\tthis.autocompletePrefix = suggestions.prefix;\n\t\t\t// Always create new SelectList to ensure update\n\t\t\tthis.autocompleteList = new SelectList(suggestions.items, 5, this.theme.selectList);\n\t\t} else {\n\t\t\tthis.cancelAutocomplete();\n\t\t}\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/components/markdown.ts"],"names":[],"mappings":"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","sourcesContent":["import { marked, type Token } from \"marked\";\nimport type { Component } from \"../tui.js\";\nimport { applyBackgroundToLine, visibleWidth, wrapTextWithAnsi } from \"../utils.js\";\n\n/**\n * Default text styling for markdown content.\n * Applied to all text unless overridden by markdown formatting.\n */\nexport interface DefaultTextStyle {\n\t/** Foreground color function */\n\tcolor?: (text: string) => string;\n\t/** Background color function */\n\tbgColor?: (text: string) => string;\n\t/** Bold text */\n\tbold?: boolean;\n\t/** Italic text */\n\titalic?: boolean;\n\t/** Strikethrough text */\n\tstrikethrough?: boolean;\n\t/** Underline text */\n\tunderline?: boolean;\n}\n\n/**\n * Theme functions for markdown elements.\n * Each function takes text and returns styled text with ANSI codes.\n */\nexport interface MarkdownTheme {\n\theading: (text: string) => string;\n\tlink: (text: string) => string;\n\tlinkUrl: (text: string) => string;\n\tcode: (text: string) => string;\n\tcodeBlock: (text: string) => string;\n\tcodeBlockBorder: (text: string) => string;\n\tquote: (text: string) => string;\n\tquoteBorder: (text: string) => string;\n\thr: (text: string) => string;\n\tlistBullet: (text: string) => string;\n\tbold: (text: string) => string;\n\titalic: (text: string) => string;\n\tstrikethrough: (text: string) => string;\n\tunderline: (text: string) => string;\n\thighlightCode?: (code: string, lang?: string) => string[];\n}\n\nexport class Markdown implements Component {\n\tprivate text: string;\n\tprivate paddingX: number; // Left/right padding\n\tprivate paddingY: number; // Top/bottom padding\n\tprivate defaultTextStyle?: DefaultTextStyle;\n\tprivate theme: MarkdownTheme;\n\tprivate defaultStylePrefix?: string;\n\n\t// Cache for rendered output\n\tprivate cachedText?: string;\n\tprivate cachedWidth?: number;\n\tprivate cachedLines?: string[];\n\n\tconstructor(\n\t\ttext: string,\n\t\tpaddingX: number,\n\t\tpaddingY: number,\n\t\ttheme: MarkdownTheme,\n\t\tdefaultTextStyle?: DefaultTextStyle,\n\t) {\n\t\tthis.text = text;\n\t\tthis.paddingX = paddingX;\n\t\tthis.paddingY = paddingY;\n\t\tthis.theme = theme;\n\t\tthis.defaultTextStyle = defaultTextStyle;\n\t}\n\n\tsetText(text: string): void {\n\t\tthis.text = text;\n\t\tthis.invalidate();\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// Calculate available width for content (subtract horizontal padding)\n\t\tconst contentWidth = Math.max(1, width - this.paddingX * 2);\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\t// Update cache\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 for consistent rendering\n\t\tconst normalizedText = this.text.replace(/\\t/g, \" \");\n\n\t\t// Parse markdown to HTML-like tokens\n\t\tconst tokens = marked.lexer(normalizedText);\n\n\t\t// Convert tokens to styled terminal output\n\t\tconst renderedLines: string[] = [];\n\n\t\tfor (let i = 0; i < tokens.length; i++) {\n\t\t\tconst token = tokens[i];\n\t\t\tconst nextToken = tokens[i + 1];\n\t\t\tconst tokenLines = this.renderToken(token, contentWidth, nextToken?.type);\n\t\t\trenderedLines.push(...tokenLines);\n\t\t}\n\n\t\t// Wrap lines (NO padding, NO background yet)\n\t\tconst wrappedLines: string[] = [];\n\t\tfor (const line of renderedLines) {\n\t\t\twrappedLines.push(...wrapTextWithAnsi(line, contentWidth));\n\t\t}\n\n\t\t// Add margins and background to each wrapped line\n\t\tconst leftMargin = \" \".repeat(this.paddingX);\n\t\tconst rightMargin = \" \".repeat(this.paddingX);\n\t\tconst bgFn = this.defaultTextStyle?.bgColor;\n\t\tconst contentLines: string[] = [];\n\n\t\tfor (const line of wrappedLines) {\n\t\t\tconst lineWithMargins = leftMargin + line + rightMargin;\n\n\t\t\tif (bgFn) {\n\t\t\t\tcontentLines.push(applyBackgroundToLine(lineWithMargins, width, bgFn));\n\t\t\t} else {\n\t\t\t\t// No background - just pad to width\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 = bgFn ? applyBackgroundToLine(emptyLine, width, bgFn) : emptyLine;\n\t\t\temptyLines.push(line);\n\t\t}\n\n\t\t// Combine top padding, content, and bottom padding\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\t/**\n\t * Apply default text style to a string.\n\t * This is the base styling applied to all text content.\n\t * NOTE: Background color is NOT applied here - it's applied at the padding stage\n\t * to ensure it extends to the full line width.\n\t */\n\tprivate applyDefaultStyle(text: string): string {\n\t\tif (!this.defaultTextStyle) {\n\t\t\treturn text;\n\t\t}\n\n\t\tlet styled = text;\n\n\t\t// Apply foreground color (NOT background - that's applied at padding stage)\n\t\tif (this.defaultTextStyle.color) {\n\t\t\tstyled = this.defaultTextStyle.color(styled);\n\t\t}\n\n\t\t// Apply text decorations using this.theme\n\t\tif (this.defaultTextStyle.bold) {\n\t\t\tstyled = this.theme.bold(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.italic) {\n\t\t\tstyled = this.theme.italic(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.strikethrough) {\n\t\t\tstyled = this.theme.strikethrough(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.underline) {\n\t\t\tstyled = this.theme.underline(styled);\n\t\t}\n\n\t\treturn styled;\n\t}\n\n\tprivate getDefaultStylePrefix(): string {\n\t\tif (!this.defaultTextStyle) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (this.defaultStylePrefix !== undefined) {\n\t\t\treturn this.defaultStylePrefix;\n\t\t}\n\n\t\tconst sentinel = \"\\u0000\";\n\t\tlet styled = sentinel;\n\n\t\tif (this.defaultTextStyle.color) {\n\t\t\tstyled = this.defaultTextStyle.color(styled);\n\t\t}\n\n\t\tif (this.defaultTextStyle.bold) {\n\t\t\tstyled = this.theme.bold(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.italic) {\n\t\t\tstyled = this.theme.italic(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.strikethrough) {\n\t\t\tstyled = this.theme.strikethrough(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.underline) {\n\t\t\tstyled = this.theme.underline(styled);\n\t\t}\n\n\t\tconst sentinelIndex = styled.indexOf(sentinel);\n\t\tthis.defaultStylePrefix = sentinelIndex >= 0 ? styled.slice(0, sentinelIndex) : \"\";\n\t\treturn this.defaultStylePrefix;\n\t}\n\n\tprivate renderToken(token: Token, width: number, nextTokenType?: string): string[] {\n\t\tconst lines: string[] = [];\n\n\t\tswitch (token.type) {\n\t\t\tcase \"heading\": {\n\t\t\t\tconst headingLevel = token.depth;\n\t\t\t\tconst headingPrefix = \"#\".repeat(headingLevel) + \" \";\n\t\t\t\tconst headingText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tlet styledHeading: string;\n\t\t\t\tif (headingLevel === 1) {\n\t\t\t\t\tstyledHeading = this.theme.heading(this.theme.bold(this.theme.underline(headingText)));\n\t\t\t\t} else if (headingLevel === 2) {\n\t\t\t\t\tstyledHeading = this.theme.heading(this.theme.bold(headingText));\n\t\t\t\t} else {\n\t\t\t\t\tstyledHeading = this.theme.heading(this.theme.bold(headingPrefix + headingText));\n\t\t\t\t}\n\t\t\t\tlines.push(styledHeading);\n\t\t\t\tif (nextTokenType !== \"space\") {\n\t\t\t\t\tlines.push(\"\"); // Add spacing after headings (unless space token follows)\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"paragraph\": {\n\t\t\t\tconst paragraphText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tlines.push(paragraphText);\n\t\t\t\t// Don't add spacing if next token is space or list\n\t\t\t\tif (nextTokenType && nextTokenType !== \"list\" && nextTokenType !== \"space\") {\n\t\t\t\t\tlines.push(\"\");\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"code\": {\n\t\t\t\tlines.push(this.theme.codeBlockBorder(\"```\" + (token.lang || \"\")));\n\t\t\t\tif (this.theme.highlightCode) {\n\t\t\t\t\tconst highlightedLines = this.theme.highlightCode(token.text, token.lang);\n\t\t\t\t\tfor (const hlLine of highlightedLines) {\n\t\t\t\t\t\tlines.push(\" \" + hlLine);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Split code by newlines and style each line\n\t\t\t\t\tconst codeLines = token.text.split(\"\\n\");\n\t\t\t\t\tfor (const codeLine of codeLines) {\n\t\t\t\t\t\tlines.push(\" \" + this.theme.codeBlock(codeLine));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlines.push(this.theme.codeBlockBorder(\"```\"));\n\t\t\t\tif (nextTokenType !== \"space\") {\n\t\t\t\t\tlines.push(\"\"); // Add spacing after code blocks (unless space token follows)\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"list\": {\n\t\t\t\tconst listLines = this.renderList(token as any, 0);\n\t\t\t\tlines.push(...listLines);\n\t\t\t\t// Don't add spacing after lists if a space token follows\n\t\t\t\t// (the space token will handle it)\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"table\": {\n\t\t\t\tconst tableLines = this.renderTable(token as any, width);\n\t\t\t\tlines.push(...tableLines);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"blockquote\": {\n\t\t\t\tconst quoteText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tconst quoteLines = quoteText.split(\"\\n\");\n\t\t\t\tfor (const quoteLine of quoteLines) {\n\t\t\t\t\tlines.push(this.theme.quoteBorder(\"│ \") + this.theme.quote(this.theme.italic(quoteLine)));\n\t\t\t\t}\n\t\t\t\tif (nextTokenType !== \"space\") {\n\t\t\t\t\tlines.push(\"\"); // Add spacing after blockquotes (unless space token follows)\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"hr\":\n\t\t\t\tlines.push(this.theme.hr(\"─\".repeat(Math.min(width, 80))));\n\t\t\t\tif (nextTokenType !== \"space\") {\n\t\t\t\t\tlines.push(\"\"); // Add spacing after horizontal rules (unless space token follows)\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase \"html\":\n\t\t\t\t// Skip HTML for terminal output\n\t\t\t\tbreak;\n\n\t\t\tcase \"space\":\n\t\t\t\t// Space tokens represent blank lines in markdown\n\t\t\t\tlines.push(\"\");\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\t// Handle any other token types as plain text\n\t\t\t\tif (\"text\" in token && typeof token.text === \"string\") {\n\t\t\t\t\tlines.push(token.text);\n\t\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\tprivate renderInlineTokens(tokens: Token[]): string {\n\t\tlet result = \"\";\n\n\t\tfor (const token of tokens) {\n\t\t\tswitch (token.type) {\n\t\t\t\tcase \"text\":\n\t\t\t\t\t// Text tokens in list items can have nested tokens for inline formatting\n\t\t\t\t\tif (token.tokens && token.tokens.length > 0) {\n\t\t\t\t\t\tresult += this.renderInlineTokens(token.tokens);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Apply default style to plain text\n\t\t\t\t\t\tresult += this.applyDefaultStyle(token.text);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"strong\": {\n\t\t\t\t\t// Apply bold, then reapply default style after\n\t\t\t\t\tconst boldContent = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\tresult += this.theme.bold(boldContent) + this.getDefaultStylePrefix();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"em\": {\n\t\t\t\t\t// Apply italic, then reapply default style after\n\t\t\t\t\tconst italicContent = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\tresult += this.theme.italic(italicContent) + this.getDefaultStylePrefix();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"codespan\":\n\t\t\t\t\t// Apply code styling without backticks\n\t\t\t\t\tresult += this.theme.code(token.text) + this.getDefaultStylePrefix();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"link\": {\n\t\t\t\t\tconst linkText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\t// If link text matches href, only show the link once\n\t\t\t\t\t// Compare raw text (token.text) not styled text (linkText) since linkText has ANSI codes\n\t\t\t\t\tif (token.text === token.href) {\n\t\t\t\t\t\tresult += this.theme.link(this.theme.underline(linkText)) + this.getDefaultStylePrefix();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult +=\n\t\t\t\t\t\t\tthis.theme.link(this.theme.underline(linkText)) +\n\t\t\t\t\t\t\tthis.theme.linkUrl(` (${token.href})`) +\n\t\t\t\t\t\t\tthis.getDefaultStylePrefix();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"br\":\n\t\t\t\t\tresult += \"\\n\";\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"del\": {\n\t\t\t\t\tconst delContent = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\tresult += this.theme.strikethrough(delContent) + this.getDefaultStylePrefix();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\t// Handle any other inline token types as plain text\n\t\t\t\t\tif (\"text\" in token && typeof token.text === \"string\") {\n\t\t\t\t\t\tresult += this.applyDefaultStyle(token.text);\n\t\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Render a list with proper nesting support\n\t */\n\tprivate renderList(token: Token & { items: any[]; ordered: boolean }, depth: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst indent = \" \".repeat(depth);\n\n\t\tfor (let i = 0; i < token.items.length; i++) {\n\t\t\tconst item = token.items[i];\n\t\t\tconst bullet = token.ordered ? `${i + 1}. ` : \"- \";\n\n\t\t\t// Process item tokens to handle nested lists\n\t\t\tconst itemLines = this.renderListItem(item.tokens || [], depth);\n\n\t\t\tif (itemLines.length > 0) {\n\t\t\t\t// First line - check if it's a nested list\n\t\t\t\t// A nested list will start with indent (spaces) followed by cyan bullet\n\t\t\t\tconst firstLine = itemLines[0];\n\t\t\t\tconst isNestedList = /^\\s+\\x1b\\[36m[-\\d]/.test(firstLine); // starts with spaces + cyan + bullet char\n\n\t\t\t\tif (isNestedList) {\n\t\t\t\t\t// This is a nested list, just add it as-is (already has full indent)\n\t\t\t\t\tlines.push(firstLine);\n\t\t\t\t} else {\n\t\t\t\t\t// Regular text content - add indent and bullet\n\t\t\t\t\tlines.push(indent + this.theme.listBullet(bullet) + firstLine);\n\t\t\t\t}\n\n\t\t\t\t// Rest of the lines\n\t\t\t\tfor (let j = 1; j < itemLines.length; j++) {\n\t\t\t\t\tconst line = itemLines[j];\n\t\t\t\t\tconst isNestedListLine = /^\\s+\\x1b\\[36m[-\\d]/.test(line); // starts with spaces + cyan + bullet char\n\n\t\t\t\t\tif (isNestedListLine) {\n\t\t\t\t\t\t// Nested list line - already has full indent\n\t\t\t\t\t\tlines.push(line);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Regular content - add parent indent + 2 spaces for continuation\n\t\t\t\t\t\tlines.push(indent + \" \" + line);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlines.push(indent + this.theme.listBullet(bullet));\n\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\t/**\n\t * Render list item tokens, handling nested lists\n\t * Returns lines WITHOUT the parent indent (renderList will add it)\n\t */\n\tprivate renderListItem(tokens: Token[], parentDepth: number): string[] {\n\t\tconst lines: string[] = [];\n\n\t\tfor (const token of tokens) {\n\t\t\tif (token.type === \"list\") {\n\t\t\t\t// Nested list - render with one additional indent level\n\t\t\t\t// These lines will have their own indent, so we just add them as-is\n\t\t\t\tconst nestedLines = this.renderList(token as any, parentDepth + 1);\n\t\t\t\tlines.push(...nestedLines);\n\t\t\t} else if (token.type === \"text\") {\n\t\t\t\t// Text content (may have inline tokens)\n\t\t\t\tconst text =\n\t\t\t\t\ttoken.tokens && token.tokens.length > 0 ? this.renderInlineTokens(token.tokens) : token.text || \"\";\n\t\t\t\tlines.push(text);\n\t\t\t} else if (token.type === \"paragraph\") {\n\t\t\t\t// Paragraph in list item\n\t\t\t\tconst text = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tlines.push(text);\n\t\t\t} else if (token.type === \"code\") {\n\t\t\t\t// Code block in list item\n\t\t\t\tlines.push(this.theme.codeBlockBorder(\"```\" + (token.lang || \"\")));\n\t\t\t\tif (this.theme.highlightCode) {\n\t\t\t\t\tconst highlightedLines = this.theme.highlightCode(token.text, token.lang);\n\t\t\t\t\tfor (const hlLine of highlightedLines) {\n\t\t\t\t\t\tlines.push(\" \" + hlLine);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tconst codeLines = token.text.split(\"\\n\");\n\t\t\t\t\tfor (const codeLine of codeLines) {\n\t\t\t\t\t\tlines.push(\" \" + this.theme.codeBlock(codeLine));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlines.push(this.theme.codeBlockBorder(\"```\"));\n\t\t\t} else {\n\t\t\t\t// Other token types - try to render as inline\n\t\t\t\tconst text = this.renderInlineTokens([token]);\n\t\t\t\tif (text) {\n\t\t\t\t\tlines.push(text);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\t/**\n\t * Wrap a table cell to fit into a column.\n\t *\n\t * Delegates to wrapTextWithAnsi() so ANSI codes + long tokens are handled\n\t * consistently with the rest of the renderer.\n\t */\n\tprivate wrapCellText(text: string, maxWidth: number): string[] {\n\t\treturn wrapTextWithAnsi(text, Math.max(1, maxWidth));\n\t}\n\n\t/**\n\t * Render a table with width-aware cell wrapping.\n\t * Cells that don't fit are wrapped to multiple lines.\n\t */\n\tprivate renderTable(\n\t\ttoken: Token & { header: any[]; rows: any[][]; raw?: string },\n\t\tavailableWidth: number,\n\t): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst numCols = token.header.length;\n\n\t\tif (numCols === 0) {\n\t\t\treturn lines;\n\t\t}\n\n\t\t// Calculate border overhead: \"│ \" + (n-1) * \" │ \" + \" │\"\n\t\t// = 2 + (n-1) * 3 + 2 = 3n + 1\n\t\tconst borderOverhead = 3 * numCols + 1;\n\n\t\t// Minimum width for a bordered table with at least 1 char per column.\n\t\tconst minTableWidth = borderOverhead + numCols;\n\t\tif (availableWidth < minTableWidth) {\n\t\t\t// Too narrow to render a stable table. Fall back to raw markdown.\n\t\t\tconst fallbackLines = token.raw ? wrapTextWithAnsi(token.raw, availableWidth) : [];\n\t\t\tfallbackLines.push(\"\");\n\t\t\treturn fallbackLines;\n\t\t}\n\n\t\t// Calculate natural column widths (what each column needs without constraints)\n\t\tconst naturalWidths: number[] = [];\n\t\tfor (let i = 0; i < numCols; i++) {\n\t\t\tconst headerText = this.renderInlineTokens(token.header[i].tokens || []);\n\t\t\tnaturalWidths[i] = visibleWidth(headerText);\n\t\t}\n\t\tfor (const row of token.rows) {\n\t\t\tfor (let i = 0; i < row.length; i++) {\n\t\t\t\tconst cellText = this.renderInlineTokens(row[i].tokens || []);\n\t\t\t\tnaturalWidths[i] = Math.max(naturalWidths[i] || 0, visibleWidth(cellText));\n\t\t\t}\n\t\t}\n\n\t\t// Calculate column widths that fit within available width\n\t\tconst totalNaturalWidth = naturalWidths.reduce((a, b) => a + b, 0) + borderOverhead;\n\t\tlet columnWidths: number[];\n\n\t\tif (totalNaturalWidth <= availableWidth) {\n\t\t\t// Everything fits naturally\n\t\t\tcolumnWidths = naturalWidths;\n\t\t} else {\n\t\t\t// Need to shrink columns to fit\n\t\t\tconst availableForCells = availableWidth - borderOverhead;\n\t\t\tif (availableForCells <= numCols) {\n\t\t\t\t// Extremely narrow - give each column at least 1 char\n\t\t\t\tcolumnWidths = naturalWidths.map(() => Math.max(1, Math.floor(availableForCells / numCols)));\n\t\t\t} else {\n\t\t\t\t// Distribute space proportionally based on natural widths\n\t\t\t\tconst totalNatural = naturalWidths.reduce((a, b) => a + b, 0);\n\t\t\t\tcolumnWidths = naturalWidths.map((w) => {\n\t\t\t\t\tconst proportion = w / totalNatural;\n\t\t\t\t\treturn Math.max(1, Math.floor(proportion * availableForCells));\n\t\t\t\t});\n\n\t\t\t\t// Adjust for rounding errors - distribute remaining space\n\t\t\t\tconst allocated = columnWidths.reduce((a, b) => a + b, 0);\n\t\t\t\tlet remaining = availableForCells - allocated;\n\t\t\t\tfor (let i = 0; remaining > 0 && i < numCols; i++) {\n\t\t\t\t\tcolumnWidths[i]++;\n\t\t\t\t\tremaining--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Render top border\n\t\tconst topBorderCells = columnWidths.map((w) => \"─\".repeat(w));\n\t\tlines.push(\"┌─\" + topBorderCells.join(\"─┬─\") + \"─┐\");\n\n\t\t// Render header with wrapping\n\t\tconst headerCellLines: string[][] = token.header.map((cell, i) => {\n\t\t\tconst text = this.renderInlineTokens(cell.tokens || []);\n\t\t\treturn this.wrapCellText(text, columnWidths[i]);\n\t\t});\n\t\tconst headerLineCount = Math.max(...headerCellLines.map((c) => c.length));\n\n\t\tfor (let lineIdx = 0; lineIdx < headerLineCount; lineIdx++) {\n\t\t\tconst rowParts = headerCellLines.map((cellLines, colIdx) => {\n\t\t\t\tconst text = cellLines[lineIdx] || \"\";\n\t\t\t\tconst padded = text + \" \".repeat(Math.max(0, columnWidths[colIdx] - visibleWidth(text)));\n\t\t\t\treturn this.theme.bold(padded);\n\t\t\t});\n\t\t\tlines.push(\"│ \" + rowParts.join(\" │ \") + \" │\");\n\t\t}\n\n\t\t// Render separator\n\t\tconst separatorCells = columnWidths.map((w) => \"─\".repeat(w));\n\t\tlines.push(\"├─\" + separatorCells.join(\"─┼─\") + \"─┤\");\n\n\t\t// Render rows with wrapping\n\t\tfor (const row of token.rows) {\n\t\t\tconst rowCellLines: string[][] = row.map((cell, i) => {\n\t\t\t\tconst text = this.renderInlineTokens(cell.tokens || []);\n\t\t\t\treturn this.wrapCellText(text, columnWidths[i]);\n\t\t\t});\n\t\t\tconst rowLineCount = Math.max(...rowCellLines.map((c) => c.length));\n\n\t\t\tfor (let lineIdx = 0; lineIdx < rowLineCount; lineIdx++) {\n\t\t\t\tconst rowParts = rowCellLines.map((cellLines, colIdx) => {\n\t\t\t\t\tconst text = cellLines[lineIdx] || \"\";\n\t\t\t\t\treturn text + \" \".repeat(Math.max(0, columnWidths[colIdx] - visibleWidth(text)));\n\t\t\t\t});\n\t\t\t\tlines.push(\"│ \" + rowParts.join(\" │ \") + \" │\");\n\t\t\t}\n\t\t}\n\n\t\t// Render bottom border\n\t\tconst bottomBorderCells = columnWidths.map((w) => \"─\".repeat(w));\n\t\tlines.push(\"└─\" + bottomBorderCells.join(\"─┴─\") + \"─┘\");\n\n\t\tlines.push(\"\"); // Add spacing after table\n\t\treturn lines;\n\t}\n}\n"]}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/components/markdown.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAChC,gCAAgC;IAChC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACjC,gCAAgC;IAChC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,gBAAgB;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,kBAAkB;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,yBAAyB;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qBAAqB;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAClC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAClC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1C,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAChC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7B,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACjC,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;CAC1D;AAED,qBAAa,QAAS,YAAW,SAAS;IACzC,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,gBAAgB,CAAC,CAAmB;IAC5C,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,kBAAkB,CAAC,CAAS;IAGpC,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAC,CAAW;IAE/B,YACC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,aAAa,EACpB,gBAAgB,CAAC,EAAE,gBAAgB,EAOnC;IAED,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAG1B;IAED,UAAU,IAAI,IAAI,CAIjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA6E9B;IAED;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IA6BzB,OAAO,CAAC,qBAAqB;IAkC7B,OAAO,CAAC,WAAW;IA0GnB,OAAO,CAAC,kBAAkB;IAsE1B;;OAEG;IACH,OAAO,CAAC,UAAU;IA8ClB;;;OAGG;IACH,OAAO,CAAC,cAAc;IA6CtB;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IAIpB;;;OAGG;IACH,OAAO,CAAC,WAAW;CAoHnB","sourcesContent":["import { marked, type Token } from \"marked\";\nimport type { Component } from \"../tui.js\";\nimport { applyBackgroundToLine, visibleWidth, wrapTextWithAnsi } from \"../utils.js\";\n\n/**\n * Default text styling for markdown content.\n * Applied to all text unless overridden by markdown formatting.\n */\nexport interface DefaultTextStyle {\n\t/** Foreground color function */\n\tcolor?: (text: string) => string;\n\t/** Background color function */\n\tbgColor?: (text: string) => string;\n\t/** Bold text */\n\tbold?: boolean;\n\t/** Italic text */\n\titalic?: boolean;\n\t/** Strikethrough text */\n\tstrikethrough?: boolean;\n\t/** Underline text */\n\tunderline?: boolean;\n}\n\n/**\n * Theme functions for markdown elements.\n * Each function takes text and returns styled text with ANSI codes.\n */\nexport interface MarkdownTheme {\n\theading: (text: string) => string;\n\tlink: (text: string) => string;\n\tlinkUrl: (text: string) => string;\n\tcode: (text: string) => string;\n\tcodeBlock: (text: string) => string;\n\tcodeBlockBorder: (text: string) => string;\n\tquote: (text: string) => string;\n\tquoteBorder: (text: string) => string;\n\thr: (text: string) => string;\n\tlistBullet: (text: string) => string;\n\tbold: (text: string) => string;\n\titalic: (text: string) => string;\n\tstrikethrough: (text: string) => string;\n\tunderline: (text: string) => string;\n\thighlightCode?: (code: string, lang?: string) => string[];\n}\n\nexport class Markdown implements Component {\n\tprivate text: string;\n\tprivate paddingX: number; // Left/right padding\n\tprivate paddingY: number; // Top/bottom padding\n\tprivate defaultTextStyle?: DefaultTextStyle;\n\tprivate theme: MarkdownTheme;\n\tprivate defaultStylePrefix?: string;\n\n\t// Cache for rendered output\n\tprivate cachedText?: string;\n\tprivate cachedWidth?: number;\n\tprivate cachedLines?: string[];\n\n\tconstructor(\n\t\ttext: string,\n\t\tpaddingX: number,\n\t\tpaddingY: number,\n\t\ttheme: MarkdownTheme,\n\t\tdefaultTextStyle?: DefaultTextStyle,\n\t) {\n\t\tthis.text = text;\n\t\tthis.paddingX = paddingX;\n\t\tthis.paddingY = paddingY;\n\t\tthis.theme = theme;\n\t\tthis.defaultTextStyle = defaultTextStyle;\n\t}\n\n\tsetText(text: string): void {\n\t\tthis.text = text;\n\t\tthis.invalidate();\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// Calculate available width for content (subtract horizontal padding)\n\t\tconst contentWidth = Math.max(1, width - this.paddingX * 2);\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\t// Update cache\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 for consistent rendering\n\t\tconst normalizedText = this.text.replace(/\\t/g, \" \");\n\n\t\t// Parse markdown to HTML-like tokens\n\t\tconst tokens = marked.lexer(normalizedText);\n\n\t\t// Convert tokens to styled terminal output\n\t\tconst renderedLines: string[] = [];\n\n\t\tfor (let i = 0; i < tokens.length; i++) {\n\t\t\tconst token = tokens[i];\n\t\t\tconst nextToken = tokens[i + 1];\n\t\t\tconst tokenLines = this.renderToken(token, contentWidth, nextToken?.type);\n\t\t\trenderedLines.push(...tokenLines);\n\t\t}\n\n\t\t// Wrap lines (NO padding, NO background yet)\n\t\tconst wrappedLines: string[] = [];\n\t\tfor (const line of renderedLines) {\n\t\t\twrappedLines.push(...wrapTextWithAnsi(line, contentWidth));\n\t\t}\n\n\t\t// Add margins and background to each wrapped line\n\t\tconst leftMargin = \" \".repeat(this.paddingX);\n\t\tconst rightMargin = \" \".repeat(this.paddingX);\n\t\tconst bgFn = this.defaultTextStyle?.bgColor;\n\t\tconst contentLines: string[] = [];\n\n\t\tfor (const line of wrappedLines) {\n\t\t\tconst lineWithMargins = leftMargin + line + rightMargin;\n\n\t\t\tif (bgFn) {\n\t\t\t\tcontentLines.push(applyBackgroundToLine(lineWithMargins, width, bgFn));\n\t\t\t} else {\n\t\t\t\t// No background - just pad to width\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 = bgFn ? applyBackgroundToLine(emptyLine, width, bgFn) : emptyLine;\n\t\t\temptyLines.push(line);\n\t\t}\n\n\t\t// Combine top padding, content, and bottom padding\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\t/**\n\t * Apply default text style to a string.\n\t * This is the base styling applied to all text content.\n\t * NOTE: Background color is NOT applied here - it's applied at the padding stage\n\t * to ensure it extends to the full line width.\n\t */\n\tprivate applyDefaultStyle(text: string): string {\n\t\tif (!this.defaultTextStyle) {\n\t\t\treturn text;\n\t\t}\n\n\t\tlet styled = text;\n\n\t\t// Apply foreground color (NOT background - that's applied at padding stage)\n\t\tif (this.defaultTextStyle.color) {\n\t\t\tstyled = this.defaultTextStyle.color(styled);\n\t\t}\n\n\t\t// Apply text decorations using this.theme\n\t\tif (this.defaultTextStyle.bold) {\n\t\t\tstyled = this.theme.bold(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.italic) {\n\t\t\tstyled = this.theme.italic(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.strikethrough) {\n\t\t\tstyled = this.theme.strikethrough(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.underline) {\n\t\t\tstyled = this.theme.underline(styled);\n\t\t}\n\n\t\treturn styled;\n\t}\n\n\tprivate getDefaultStylePrefix(): string {\n\t\tif (!this.defaultTextStyle) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (this.defaultStylePrefix !== undefined) {\n\t\t\treturn this.defaultStylePrefix;\n\t\t}\n\n\t\tconst sentinel = \"\\u0000\";\n\t\tlet styled = sentinel;\n\n\t\tif (this.defaultTextStyle.color) {\n\t\t\tstyled = this.defaultTextStyle.color(styled);\n\t\t}\n\n\t\tif (this.defaultTextStyle.bold) {\n\t\t\tstyled = this.theme.bold(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.italic) {\n\t\t\tstyled = this.theme.italic(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.strikethrough) {\n\t\t\tstyled = this.theme.strikethrough(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.underline) {\n\t\t\tstyled = this.theme.underline(styled);\n\t\t}\n\n\t\tconst sentinelIndex = styled.indexOf(sentinel);\n\t\tthis.defaultStylePrefix = sentinelIndex >= 0 ? styled.slice(0, sentinelIndex) : \"\";\n\t\treturn this.defaultStylePrefix;\n\t}\n\n\tprivate renderToken(token: Token, width: number, nextTokenType?: string): string[] {\n\t\tconst lines: string[] = [];\n\n\t\tswitch (token.type) {\n\t\t\tcase \"heading\": {\n\t\t\t\tconst headingLevel = token.depth;\n\t\t\t\tconst headingPrefix = `${\"#\".repeat(headingLevel)} `;\n\t\t\t\tconst headingText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tlet styledHeading: string;\n\t\t\t\tif (headingLevel === 1) {\n\t\t\t\t\tstyledHeading = this.theme.heading(this.theme.bold(this.theme.underline(headingText)));\n\t\t\t\t} else if (headingLevel === 2) {\n\t\t\t\t\tstyledHeading = this.theme.heading(this.theme.bold(headingText));\n\t\t\t\t} else {\n\t\t\t\t\tstyledHeading = this.theme.heading(this.theme.bold(headingPrefix + headingText));\n\t\t\t\t}\n\t\t\t\tlines.push(styledHeading);\n\t\t\t\tif (nextTokenType !== \"space\") {\n\t\t\t\t\tlines.push(\"\"); // Add spacing after headings (unless space token follows)\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"paragraph\": {\n\t\t\t\tconst paragraphText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tlines.push(paragraphText);\n\t\t\t\t// Don't add spacing if next token is space or list\n\t\t\t\tif (nextTokenType && nextTokenType !== \"list\" && nextTokenType !== \"space\") {\n\t\t\t\t\tlines.push(\"\");\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"code\": {\n\t\t\t\tlines.push(this.theme.codeBlockBorder(`\\`\\`\\`${token.lang || \"\"}`));\n\t\t\t\tif (this.theme.highlightCode) {\n\t\t\t\t\tconst highlightedLines = this.theme.highlightCode(token.text, token.lang);\n\t\t\t\t\tfor (const hlLine of highlightedLines) {\n\t\t\t\t\t\tlines.push(` ${hlLine}`);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Split code by newlines and style each line\n\t\t\t\t\tconst codeLines = token.text.split(\"\\n\");\n\t\t\t\t\tfor (const codeLine of codeLines) {\n\t\t\t\t\t\tlines.push(` ${this.theme.codeBlock(codeLine)}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlines.push(this.theme.codeBlockBorder(\"```\"));\n\t\t\t\tif (nextTokenType !== \"space\") {\n\t\t\t\t\tlines.push(\"\"); // Add spacing after code blocks (unless space token follows)\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"list\": {\n\t\t\t\tconst listLines = this.renderList(token as any, 0);\n\t\t\t\tlines.push(...listLines);\n\t\t\t\t// Don't add spacing after lists if a space token follows\n\t\t\t\t// (the space token will handle it)\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"table\": {\n\t\t\t\tconst tableLines = this.renderTable(token as any, width);\n\t\t\t\tlines.push(...tableLines);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"blockquote\": {\n\t\t\t\tconst quoteText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tconst quoteLines = quoteText.split(\"\\n\");\n\t\t\t\tfor (const quoteLine of quoteLines) {\n\t\t\t\t\tlines.push(this.theme.quoteBorder(\"│ \") + this.theme.quote(this.theme.italic(quoteLine)));\n\t\t\t\t}\n\t\t\t\tif (nextTokenType !== \"space\") {\n\t\t\t\t\tlines.push(\"\"); // Add spacing after blockquotes (unless space token follows)\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"hr\":\n\t\t\t\tlines.push(this.theme.hr(\"─\".repeat(Math.min(width, 80))));\n\t\t\t\tif (nextTokenType !== \"space\") {\n\t\t\t\t\tlines.push(\"\"); // Add spacing after horizontal rules (unless space token follows)\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase \"html\":\n\t\t\t\t// Skip HTML for terminal output\n\t\t\t\tbreak;\n\n\t\t\tcase \"space\":\n\t\t\t\t// Space tokens represent blank lines in markdown\n\t\t\t\tlines.push(\"\");\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\t// Handle any other token types as plain text\n\t\t\t\tif (\"text\" in token && typeof token.text === \"string\") {\n\t\t\t\t\tlines.push(token.text);\n\t\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\tprivate renderInlineTokens(tokens: Token[]): string {\n\t\tlet result = \"\";\n\n\t\tfor (const token of tokens) {\n\t\t\tswitch (token.type) {\n\t\t\t\tcase \"text\":\n\t\t\t\t\t// Text tokens in list items can have nested tokens for inline formatting\n\t\t\t\t\tif (token.tokens && token.tokens.length > 0) {\n\t\t\t\t\t\tresult += this.renderInlineTokens(token.tokens);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Apply default style to plain text\n\t\t\t\t\t\tresult += this.applyDefaultStyle(token.text);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"strong\": {\n\t\t\t\t\t// Apply bold, then reapply default style after\n\t\t\t\t\tconst boldContent = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\tresult += this.theme.bold(boldContent) + this.getDefaultStylePrefix();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"em\": {\n\t\t\t\t\t// Apply italic, then reapply default style after\n\t\t\t\t\tconst italicContent = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\tresult += this.theme.italic(italicContent) + this.getDefaultStylePrefix();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"codespan\":\n\t\t\t\t\t// Apply code styling without backticks\n\t\t\t\t\tresult += this.theme.code(token.text) + this.getDefaultStylePrefix();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"link\": {\n\t\t\t\t\tconst linkText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\t// If link text matches href, only show the link once\n\t\t\t\t\t// Compare raw text (token.text) not styled text (linkText) since linkText has ANSI codes\n\t\t\t\t\tif (token.text === token.href) {\n\t\t\t\t\t\tresult += this.theme.link(this.theme.underline(linkText)) + this.getDefaultStylePrefix();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult +=\n\t\t\t\t\t\t\tthis.theme.link(this.theme.underline(linkText)) +\n\t\t\t\t\t\t\tthis.theme.linkUrl(` (${token.href})`) +\n\t\t\t\t\t\t\tthis.getDefaultStylePrefix();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"br\":\n\t\t\t\t\tresult += \"\\n\";\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"del\": {\n\t\t\t\t\tconst delContent = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\tresult += this.theme.strikethrough(delContent) + this.getDefaultStylePrefix();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\t// Handle any other inline token types as plain text\n\t\t\t\t\tif (\"text\" in token && typeof token.text === \"string\") {\n\t\t\t\t\t\tresult += this.applyDefaultStyle(token.text);\n\t\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Render a list with proper nesting support\n\t */\n\tprivate renderList(token: Token & { items: any[]; ordered: boolean }, depth: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst indent = \" \".repeat(depth);\n\n\t\tfor (let i = 0; i < token.items.length; i++) {\n\t\t\tconst item = token.items[i];\n\t\t\tconst bullet = token.ordered ? `${i + 1}. ` : \"- \";\n\n\t\t\t// Process item tokens to handle nested lists\n\t\t\tconst itemLines = this.renderListItem(item.tokens || [], depth);\n\n\t\t\tif (itemLines.length > 0) {\n\t\t\t\t// First line - check if it's a nested list\n\t\t\t\t// A nested list will start with indent (spaces) followed by cyan bullet\n\t\t\t\tconst firstLine = itemLines[0];\n\t\t\t\tconst isNestedList = /^\\s+\\x1b\\[36m[-\\d]/.test(firstLine); // starts with spaces + cyan + bullet char\n\n\t\t\t\tif (isNestedList) {\n\t\t\t\t\t// This is a nested list, just add it as-is (already has full indent)\n\t\t\t\t\tlines.push(firstLine);\n\t\t\t\t} else {\n\t\t\t\t\t// Regular text content - add indent and bullet\n\t\t\t\t\tlines.push(indent + this.theme.listBullet(bullet) + firstLine);\n\t\t\t\t}\n\n\t\t\t\t// Rest of the lines\n\t\t\t\tfor (let j = 1; j < itemLines.length; j++) {\n\t\t\t\t\tconst line = itemLines[j];\n\t\t\t\t\tconst isNestedListLine = /^\\s+\\x1b\\[36m[-\\d]/.test(line); // starts with spaces + cyan + bullet char\n\n\t\t\t\t\tif (isNestedListLine) {\n\t\t\t\t\t\t// Nested list line - already has full indent\n\t\t\t\t\t\tlines.push(line);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Regular content - add parent indent + 2 spaces for continuation\n\t\t\t\t\t\tlines.push(`${indent} ${line}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlines.push(indent + this.theme.listBullet(bullet));\n\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\t/**\n\t * Render list item tokens, handling nested lists\n\t * Returns lines WITHOUT the parent indent (renderList will add it)\n\t */\n\tprivate renderListItem(tokens: Token[], parentDepth: number): string[] {\n\t\tconst lines: string[] = [];\n\n\t\tfor (const token of tokens) {\n\t\t\tif (token.type === \"list\") {\n\t\t\t\t// Nested list - render with one additional indent level\n\t\t\t\t// These lines will have their own indent, so we just add them as-is\n\t\t\t\tconst nestedLines = this.renderList(token as any, parentDepth + 1);\n\t\t\t\tlines.push(...nestedLines);\n\t\t\t} else if (token.type === \"text\") {\n\t\t\t\t// Text content (may have inline tokens)\n\t\t\t\tconst text =\n\t\t\t\t\ttoken.tokens && token.tokens.length > 0 ? this.renderInlineTokens(token.tokens) : token.text || \"\";\n\t\t\t\tlines.push(text);\n\t\t\t} else if (token.type === \"paragraph\") {\n\t\t\t\t// Paragraph in list item\n\t\t\t\tconst text = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tlines.push(text);\n\t\t\t} else if (token.type === \"code\") {\n\t\t\t\t// Code block in list item\n\t\t\t\tlines.push(this.theme.codeBlockBorder(`\\`\\`\\`${token.lang || \"\"}`));\n\t\t\t\tif (this.theme.highlightCode) {\n\t\t\t\t\tconst highlightedLines = this.theme.highlightCode(token.text, token.lang);\n\t\t\t\t\tfor (const hlLine of highlightedLines) {\n\t\t\t\t\t\tlines.push(` ${hlLine}`);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tconst codeLines = token.text.split(\"\\n\");\n\t\t\t\t\tfor (const codeLine of codeLines) {\n\t\t\t\t\t\tlines.push(` ${this.theme.codeBlock(codeLine)}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlines.push(this.theme.codeBlockBorder(\"```\"));\n\t\t\t} else {\n\t\t\t\t// Other token types - try to render as inline\n\t\t\t\tconst text = this.renderInlineTokens([token]);\n\t\t\t\tif (text) {\n\t\t\t\t\tlines.push(text);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\t/**\n\t * Wrap a table cell to fit into a column.\n\t *\n\t * Delegates to wrapTextWithAnsi() so ANSI codes + long tokens are handled\n\t * consistently with the rest of the renderer.\n\t */\n\tprivate wrapCellText(text: string, maxWidth: number): string[] {\n\t\treturn wrapTextWithAnsi(text, Math.max(1, maxWidth));\n\t}\n\n\t/**\n\t * Render a table with width-aware cell wrapping.\n\t * Cells that don't fit are wrapped to multiple lines.\n\t */\n\tprivate renderTable(\n\t\ttoken: Token & { header: any[]; rows: any[][]; raw?: string },\n\t\tavailableWidth: number,\n\t): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst numCols = token.header.length;\n\n\t\tif (numCols === 0) {\n\t\t\treturn lines;\n\t\t}\n\n\t\t// Calculate border overhead: \"│ \" + (n-1) * \" │ \" + \" │\"\n\t\t// = 2 + (n-1) * 3 + 2 = 3n + 1\n\t\tconst borderOverhead = 3 * numCols + 1;\n\n\t\t// Minimum width for a bordered table with at least 1 char per column.\n\t\tconst minTableWidth = borderOverhead + numCols;\n\t\tif (availableWidth < minTableWidth) {\n\t\t\t// Too narrow to render a stable table. Fall back to raw markdown.\n\t\t\tconst fallbackLines = token.raw ? wrapTextWithAnsi(token.raw, availableWidth) : [];\n\t\t\tfallbackLines.push(\"\");\n\t\t\treturn fallbackLines;\n\t\t}\n\n\t\t// Calculate natural column widths (what each column needs without constraints)\n\t\tconst naturalWidths: number[] = [];\n\t\tfor (let i = 0; i < numCols; i++) {\n\t\t\tconst headerText = this.renderInlineTokens(token.header[i].tokens || []);\n\t\t\tnaturalWidths[i] = visibleWidth(headerText);\n\t\t}\n\t\tfor (const row of token.rows) {\n\t\t\tfor (let i = 0; i < row.length; i++) {\n\t\t\t\tconst cellText = this.renderInlineTokens(row[i].tokens || []);\n\t\t\t\tnaturalWidths[i] = Math.max(naturalWidths[i] || 0, visibleWidth(cellText));\n\t\t\t}\n\t\t}\n\n\t\t// Calculate column widths that fit within available width\n\t\tconst totalNaturalWidth = naturalWidths.reduce((a, b) => a + b, 0) + borderOverhead;\n\t\tlet columnWidths: number[];\n\n\t\tif (totalNaturalWidth <= availableWidth) {\n\t\t\t// Everything fits naturally\n\t\t\tcolumnWidths = naturalWidths;\n\t\t} else {\n\t\t\t// Need to shrink columns to fit\n\t\t\tconst availableForCells = availableWidth - borderOverhead;\n\t\t\tif (availableForCells <= numCols) {\n\t\t\t\t// Extremely narrow - give each column at least 1 char\n\t\t\t\tcolumnWidths = naturalWidths.map(() => Math.max(1, Math.floor(availableForCells / numCols)));\n\t\t\t} else {\n\t\t\t\t// Distribute space proportionally based on natural widths\n\t\t\t\tconst totalNatural = naturalWidths.reduce((a, b) => a + b, 0);\n\t\t\t\tcolumnWidths = naturalWidths.map((w) => {\n\t\t\t\t\tconst proportion = w / totalNatural;\n\t\t\t\t\treturn Math.max(1, Math.floor(proportion * availableForCells));\n\t\t\t\t});\n\n\t\t\t\t// Adjust for rounding errors - distribute remaining space\n\t\t\t\tconst allocated = columnWidths.reduce((a, b) => a + b, 0);\n\t\t\t\tlet remaining = availableForCells - allocated;\n\t\t\t\tfor (let i = 0; remaining > 0 && i < numCols; i++) {\n\t\t\t\t\tcolumnWidths[i]++;\n\t\t\t\t\tremaining--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Render top border\n\t\tconst topBorderCells = columnWidths.map((w) => \"─\".repeat(w));\n\t\tlines.push(`┌─${topBorderCells.join(\"─┬─\")}─┐`);\n\n\t\t// Render header with wrapping\n\t\tconst headerCellLines: string[][] = token.header.map((cell, i) => {\n\t\t\tconst text = this.renderInlineTokens(cell.tokens || []);\n\t\t\treturn this.wrapCellText(text, columnWidths[i]);\n\t\t});\n\t\tconst headerLineCount = Math.max(...headerCellLines.map((c) => c.length));\n\n\t\tfor (let lineIdx = 0; lineIdx < headerLineCount; lineIdx++) {\n\t\t\tconst rowParts = headerCellLines.map((cellLines, colIdx) => {\n\t\t\t\tconst text = cellLines[lineIdx] || \"\";\n\t\t\t\tconst padded = text + \" \".repeat(Math.max(0, columnWidths[colIdx] - visibleWidth(text)));\n\t\t\t\treturn this.theme.bold(padded);\n\t\t\t});\n\t\t\tlines.push(`│ ${rowParts.join(\" │ \")} │`);\n\t\t}\n\n\t\t// Render separator\n\t\tconst separatorCells = columnWidths.map((w) => \"─\".repeat(w));\n\t\tlines.push(`├─${separatorCells.join(\"─┼─\")}─┤`);\n\n\t\t// Render rows with wrapping\n\t\tfor (const row of token.rows) {\n\t\t\tconst rowCellLines: string[][] = row.map((cell, i) => {\n\t\t\t\tconst text = this.renderInlineTokens(cell.tokens || []);\n\t\t\t\treturn this.wrapCellText(text, columnWidths[i]);\n\t\t\t});\n\t\t\tconst rowLineCount = Math.max(...rowCellLines.map((c) => c.length));\n\n\t\t\tfor (let lineIdx = 0; lineIdx < rowLineCount; lineIdx++) {\n\t\t\t\tconst rowParts = rowCellLines.map((cellLines, colIdx) => {\n\t\t\t\t\tconst text = cellLines[lineIdx] || \"\";\n\t\t\t\t\treturn text + \" \".repeat(Math.max(0, columnWidths[colIdx] - visibleWidth(text)));\n\t\t\t\t});\n\t\t\t\tlines.push(`│ ${rowParts.join(\" │ \")} │`);\n\t\t\t}\n\t\t}\n\n\t\t// Render bottom border\n\t\tconst bottomBorderCells = columnWidths.map((w) => \"─\".repeat(w));\n\t\tlines.push(`└─${bottomBorderCells.join(\"─┴─\")}─┘`);\n\n\t\tlines.push(\"\"); // Add spacing after table\n\t\treturn lines;\n\t}\n}\n"]}