tui

package
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 1, 2026 License: MIT Imports: 53 Imported by: 0

Documentation

Overview

Package tui provides Pi-compatible terminal rendering, input, components, keybindings, and screen lifecycle management.

Ports packages/coding-agent/src/modes/interactive/theme/theme.ts.

Index

Constants

View Source
const (
	// Scoped SGR resets mirror upstream Pi's theme helpers:
	// foreground styles close with 39m and background styles close with 49m.
	// Avoid using SGRResetAll inside bg-painted content because it also clears
	// background color and creates visual gaps/stripes.
	SGRResetAll       = "\x1b[0m"
	SGRFgReset        = "\x1b[39m"
	SGRBgReset        = "\x1b[49m"
	SGRBoldDimReset   = "\x1b[22m"
	SGRItalicReset    = "\x1b[23m"
	SGRUnderlineReset = "\x1b[24m"
	SGRInverseReset   = "\x1b[27m"
	SGRStrikeReset    = "\x1b[29m"
)
View Source
const TUICrashLogName = "pi-tui-crash.log"

TUICrashLogName is the upstream crash-log filename for over-wide rows that reach the main-screen differential renderer.

Variables

View Source
var DefaultSpinnerFrames = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}

DefaultSpinnerFrames is the Braille spinner used by upstream.

KeybindingPlatforms lists every platform column in inventory order.

Functions

func ActionKeyDisplayText

func ActionKeyDisplayText(action string) string

ActionKeyDisplayText formats every key the registry binds to action, capitalized and joined by "/", or "" when none is bound. Mirrors upstream keyDisplayText (coding-agent keybinding-hints.ts).

func ActionKeyDisplayTextOr

func ActionKeyDisplayTextOr(action, fallback string) string

ActionKeyDisplayTextOr is ActionKeyDisplayText for an action that may not be registered (app actions outside the interactive mode, such as in component tests), falling back to the upstream default keys.

func AllocateImageID

func AllocateImageID() int

func AppKeyText

func AppKeyText(action, fallback string) string

AppKeyText formats the resolved keys for an app-level keybinding, falling back to the provided default raw key text when no resolver is installed.

func BgClose

func BgClose() string

func BgSeq

func BgSeq(c color.RGBA, trueColor bool) string

BgSeq returns the SGR background sequence for c (see FgSeq).

func BuildTerminalTitle

func BuildTerminalTitle(sessionName, cwd string) string

BuildTerminalTitle formats the pig terminal title from a session name (may be empty) and a cwd path. Matches upstream interactive-mode.ts pattern using APP_TITLE semantics.

func CalculateImageRows

func CalculateImageRows(imageDimensions ImageDimensions, targetWidthCells int, dims CellDimensions) int

func CropKittyImageLine

func CropKittyImageLine(line string, hiddenRows, visibleRows int) string

CropKittyImageLine rewrites a Kitty image line to show only rows [hiddenRows, hiddenRows+visibleRows) of the source image, adjusting the y/h/r controls. Returns the line unchanged when it carries no registered image or the crop is a no-op. Mirrors upstream cropKittyImageLine.

func CustomMessageText

func CustomMessageText(cm *CustomMessage) string

CustomMessageText extracts text from a CustomMessage's Content field the way upstream CustomMessageComponent does: a string is shown as is, and an array's text blocks are joined with newlines. Content from an extension is JSON-decoded ([]any of map[string]any); typed block slices from Go callers are read through the same JSON shape.

func DecodeKittyPrintable

func DecodeKittyPrintable(data string) (string, bool)

DecodeKittyPrintable decodes a printable Kitty CSI-u sequence into the corresponding character. Mirrors upstream decodeKittyPrintable().

func DecodePrintableKey

func DecodePrintableKey(data string) (string, bool)

DecodePrintableKey decodes printable terminal sequences from either Kitty CSI-u or xterm modifyOtherKeys formats.

func DeleteAllKittyImages

func DeleteAllKittyImages() string

func DeleteAllKittyPlacements

func DeleteAllKittyPlacements() string

DeleteAllKittyPlacements removes every Kitty image placement (visible renderings) while leaving the transmitted image data intact. Mirrors upstream deleteAllKittyPlacements.

func DeleteKittyImage

func DeleteKittyImage(imageID int) string

func DetectTheme

func DetectTheme()

DetectTheme auto-detects dark/light mode and sets the active theme. Uses COLORFGBG env var (same heuristic as upstream theme.ts). Falls back to dark if detection fails.

func EncodeITerm2

func EncodeITerm2(base64Data string, width any, height any, name string, preserveAspect bool) string

EncodeITerm2 includes the decoded payload byte length in OSC 1337 metadata.

func EncodeKitty

func EncodeKitty(base64Data string, columns, rows, imageID int, moveCursor ...bool) string

func EnterRawMode

func EnterRawMode() (restore func(), err error)

EnterRawMode puts stdin into raw mode and returns a restore function.

This preserves pig's main-buffer rendering model from `tui.go`: no alternate screen, no hidden terminal reader, and callers continue to own the input loop.

func EnterRawModeForHandoff

func EnterRawModeForHandoff() (restore func(), err error)

EnterRawModeForHandoff enters raw mode with a restore closure that leaves unread input for the next terminal owner. The caller must join its reader before restoring and drain late releases separately on final shutdown.

func EnterRawModeWithDrain

func EnterRawModeWithDrain() (restore func(), drain func(), err error)

EnterRawModeWithDrain separates process-shutdown input draining from cooked-mode restoration. A renderer drains first, stops while output is still raw, then restores cooked mode. Temporary terminal handoffs call only restore.

func FgSeq

func FgSeq(c color.RGBA, trueColor bool) string

FgSeq returns the SGR foreground sequence for c: 24-bit (38;2) when trueColor, else the nearest 256-color (38;5). BgSeq is the background equivalent.

func FindWordBackward

func FindWordBackward(text string, cursor int, options ...WordNavigationOptions) int

FindWordBackward skips trailing whitespace, then one word-like or atomic segment or a non-word run. Offsets count UTF-16 units.

func FindWordForward

func FindWordForward(text string, cursor int, options ...WordNavigationOptions) int

FindWordForward skips leading whitespace, then one word-like or atomic segment or a non-word run. Offsets count UTF-16 units.

func FormatAuthSelectorProviderType

func FormatAuthSelectorProviderType(authType string) string

FormatAuthSelectorProviderType mirrors upstream formatAuthSelectorProviderType.

func FormatBashHeader

func FormatBashHeader(raw json.RawMessage) string

FormatBashHeader returns the styled `$ command` header for bash tool calls.

func FormatBuiltinToolHeader

func FormatBuiltinToolHeader(toolName string, args json.RawMessage, cwd string) string

FormatBuiltinToolHeader dispatches to the per-tool header formatter matching upstream's renderCall functions. cwd resolves relative paths to absolute file:// URLs for the OSC-8 hyperlink. Returns "" if the tool has no custom header format (falls back to FormatToolArgs).

func FormatCompactReadHeader

func FormatCompactReadHeader(raw json.RawMessage, cwd string) string

FormatCompactReadHeader is upstream read.ts formatCompactReadCall for the collapsed read card, or "" when the path has no compact classification.

func FormatEditHeader

func FormatEditHeader(raw json.RawMessage, cwd string) string

FormatEditHeader returns the styled `edit <path>` header for edit tool calls. Mirrors upstream edit.ts formatEditCall.

func FormatFindHeader

func FormatFindHeader(raw json.RawMessage) string

FormatFindHeader returns the styled find call. Mirrors upstream renderers/find.ts formatFindCall.

func FormatGrepHeader

func FormatGrepHeader(raw json.RawMessage) string

FormatGrepHeader returns the styled grep call. Mirrors upstream renderers/grep.ts formatGrepCall: bold toolTitle `grep`, accent `/pattern/`, toolOutput ` in <path>` ($HOME shortened, "." by default), then optional ` (glob)` and ` limit N` suffixes. Non-string pattern or path arguments render as the invalid-arg marker.

func FormatKeyText

func FormatKeyText(key string, capitalize bool) string

FormatKeyText formats a raw key string for UI display. It mirrors upstream formatKeyText by splitting alternate combos on "/" and combo parts on "+", mapping alt → option on macOS, and optionally capitalizing each part.

func FormatLsHeader

func FormatLsHeader(raw json.RawMessage, cwd string) string

FormatLsHeader returns the styled ls call. Mirrors upstream renderers/ls.ts formatLsCall: renderToolPath with emptyFallback ".".

func FormatReadHeader

func FormatReadHeader(raw json.RawMessage, cwd string) string

FormatReadHeader returns the styled `read <path>` header for read tool calls. Mirrors upstream read.ts formatReadCall: bold toolTitle `read`, the path via renderToolPath (accent + ~/ + OSC-8 link), and a warning- colored `:start-end` line range.

func FormatShellHeader

func FormatShellHeader(raw json.RawMessage, prompt string) string

FormatShellHeader renders a shell tool call. Mirrors upstream formatShellCall: the whole `<prompt> <command>` is toolTitle-colored and bold, followed by a muted ` (timeout Ns)` suffix when the timeout argument is truthy. A non-string command renders as the error-colored invalid-arg marker; an empty or missing command renders as a toolOutput "...".

func FormatToolArgs

func FormatToolArgs(raw json.RawMessage) string

FormatToolArgs renders a JSON object as a compact `key:val, key:val` preview suitable for the tool-call header. Falls back to the raw JSON for non-object inputs. Long string values are truncated with "\u2026" so the header never overflows the terminal width.

Examples:

{"path":"x","limit":10}                \u2192  path:"x", limit:10
{"command":"git status --porcelain"}    \u2192  command:"git status \u2026"
[]                                      \u2192  []

func FormatToolDuration

func FormatToolDuration(d time.Duration) string

FormatToolDuration mirrors upstream renderers/bash.ts formatDuration over the integer milliseconds Date.now() differences produce: seconds with one decimal under a minute, then "Xm Ys", then "Xh Ym Zs".

func FormatWriteHeader

func FormatWriteHeader(raw json.RawMessage, cwd string) string

FormatWriteHeader returns the styled `write <path>` header for write tool calls. Mirrors upstream write.ts formatWriteCall.

func FuzzyFilter

func FuzzyFilter[T any](items []T, query string, getText func(T) string) []T

FuzzyFilter sorts items best-match-first and drops non-matchers. Tokens (separated by whitespace or `/`, upstream `split(/[\s/]+/)`) AND together: each token must match, so "openai-codex/gpt-5.5" matches the reordered text "gpt-5.5 openai-codex". Empty/whitespace-only query returns items unchanged.

func GetAltScreenSearchMatchKey

func GetAltScreenSearchMatchKey(match AltScreenSearchMatch) string

GetAltScreenSearchMatchKey identifies a match by its first and last cells. Mirrors upstream getAltScreenSearchMatchKey.

func GetDefaultTheme

func GetDefaultTheme() string

func GetModelSearchText

func GetModelSearchText(item ModelSearchItem) string

GetModelSearchText mirrors upstream getModelSearchText: the bare id leads, followed by the provider, the provider/id pair, provider and id again, and the name when present.

func GetModelSelectorSearchText

func GetModelSelectorSearchText(item ModelSearchItem) string

GetModelSelectorSearchText mirrors upstream getModelSelectorSearchText. The /model selector search should rank exact provider-prefixed queries before proxy-provider IDs like openrouter/openai/gpt-5, so the bare model ID stays out of the leading position.

func HasBuiltInToolRenderers

func HasBuiltInToolRenderers(toolName string) bool

HasBuiltInToolRenderers reports whether upstream createAllToolRenderers has an entry for toolName. withBuiltInRenderers falls back to that entry for a registered definition (for example an extension override of a built-in name) that supplies no renderCall or renderResult of its own.

func HeaderForTool

func HeaderForTool(name string, args json.RawMessage, cwd string) string

HeaderForTool returns the fully styled call header for any tool: the builtin per-tool formatter when one matches, otherwise the upstream default of a bold toolTitle tool name followed by its compact args (tool-execution.ts:136 / formatToolExecution). The returned string is self-styled; renderHeaderInner emits it verbatim.

func HighlightCode

func HighlightCode(code, lang string) []string

HighlightCode highlights code with the language's syntax, diff, and metadata theme colors and returns one styled line per source line. An empty or unrecognized language uses the code-block color.

func Hyperlink(text, url string) string

func ImageFallback

func ImageFallback(mimeType string, dimensions *ImageDimensions, filename string) string

ImageFallback shortens home-prefixed paths and links absolute paths when the terminal supports hyperlinks.

func IsAppleTerminalSession

func IsAppleTerminalSession() bool

IsAppleTerminalSession mirrors terminal.ts isAppleTerminalSession.

func IsImageLine

func IsImageLine(line string) bool

IsImageLine reports whether the line contains Kitty or iTerm2 image protocol bytes. Mirrors upstream terminal-image.ts isImageLine().

func IsKeyRelease

func IsKeyRelease(data string) bool

IsKeyRelease reports whether a raw input chunk is a Kitty key-release event (flag 2, ":3" variants). Bracketed-paste content is never treated as a release even when it contains ":3" byte patterns. Mirrors upstream isKeyRelease.

Prefer ShouldDeliverKey when routing input to a focused component; call this directly only from a raw-input consumer.

func IsKittyProtocolActive

func IsKittyProtocolActive() bool

IsKittyProtocolActive reports whether a Kitty protocol response was seen during the current raw-mode session.

func IsNativeModifierPressed

func IsNativeModifierPressed(key ModifierKey) bool

IsNativeModifierPressed mirrors upstream native-modifiers.ts isNativeModifierPressed: it asks the operating system whether a modifier key is held right now, and reports false when no helper is available.

func IsOsc11BackgroundColorResponse

func IsOsc11BackgroundColorResponse(data string) bool

IsOsc11BackgroundColorResponse recognizes a complete OSC 11 reply, even when its color payload cannot be parsed.

func IsShellTool

func IsShellTool(toolName string) bool

IsShellTool reports whether toolName uses the shared shell renderers.

func JSNumberString

func JSNumberString(v float64) string

JSNumberString mirrors JavaScript Number.prototype.toString() for finite values: the shortest round-trip digits, in plain notation for magnitudes in [1e-6, 1e21) and exponent notation (e.g. "1e-7", "1e+21") outside it.

func JSToFixed

func JSToFixed(v float64, digits int) string

JSToFixed mirrors JavaScript Number.prototype.toFixed(digits) for values below 1e21: it rounds the exact binary magnitude and an exact tie rounds away from zero, unlike Go's round-half-even "%.*f".

func JSToFixed1

func JSToFixed1(v float64) string

JSToFixed1 mirrors JavaScript Number.prototype.toFixed(1) for a finite, non-negative value: it rounds the exact binary value to one decimal, and an exact tie rounds up (0.25 → "0.3"), unlike Go's round-half-even "%.1f".

func KeyDisplayText

func KeyDisplayText(key string) string

KeyDisplayText formats a raw key string in display form.

func KeyHint

func KeyHint(key, description string) string

KeyHint formats a display key and description with foreground-only resets, preserving enclosing text styles.

func LanguageFromPath

func LanguageFromPath(path string) string

LanguageFromPath returns a language identifier for the given file path, or empty if no mapping exists. Mirrors upstream getLanguageFromPath in theme.ts:1015-1077. The extension table is kept in lock-step with upstream so a file rendered through `read` displays identically in both implementations.

func LoadThemeDir

func LoadThemeDir(dir string) (map[string]*Theme, error)

LoadThemeDir scans a directory for .json theme files and returns a map of name → *Theme. Mirrors upstream theme discovery.

func MatchesKeyID

func MatchesKeyID(data, keyID string) bool

MatchesKeyID checks if raw terminal data matches a key identifier string like "ctrl+c", "ctrl+shift+z", "enter", etc. Exported for use by extension shortcut dispatch in interactive mode.

func NormalizeAppleTerminalInput

func NormalizeAppleTerminalInput(data string, isAppleTerminal, isShiftPressed bool) string

NormalizeAppleTerminalInput mirrors terminal.ts normalizeAppleTerminalInput.

func NormalizeNativeShiftEnterInput

func NormalizeNativeShiftEnterInput(data string, shouldDetectNativeShiftEnter, isShiftPressed bool) string

NormalizeNativeShiftEnterInput mirrors terminal.ts normalizeNativeShiftEnterInput: a plain Return read while the native Shift key is held becomes the enhanced Shift+Enter sequence.

func NormalizeProcessInputSequence

func NormalizeProcessInputSequence(sequence string) string

NormalizeProcessInputSequence applies the input normalization of upstream ProcessTerminal.forwardInputSequence to one complete StdinBuffer sequence. Apple Terminal (and the Windows console) can send plain Return for Shift+Enter even with enhanced key reporting requested, so Pi asks the local OS whether Shift is held. Pig's input loops split sequences outside ProcessTerminal, so each loop calls this before dispatch.

func ParseAutoThemeSetting

func ParseAutoThemeSetting(themeSetting string) (lightTheme, darkTheme string, ok bool)

ParseAutoThemeSetting parses "lightTheme/darkTheme", trimming ECMAScript whitespace around each name. Empty or malformed values are not automatic.

func ParseKey

func ParseKey(data string) (string, bool)

ParseKey parses terminal input into Pi's canonical key identifier. The bool is false when the input is not one recognized key.

func RGBTo256

func RGBTo256(c color.RGBA) uint8

RGBTo256 maps a 24-bit color to the nearest xterm-256 palette index, choosing between the 6x6x6 color cube (16-231) and the 24-step grayscale ramp (232-255) by squared RGB distance, so near-gray colors use the finer gray ramp rather than a coarse cube step.

func RawKeyHint

func RawKeyHint(key, description string) string

RawKeyHint formats a raw key string without going through a keybinding registry. Mirrors upstream's rawKeyHint which skips the keybinding lookup.

func ReadInputChunk

func ReadInputChunk(r io.Reader) ([]byte, error)

ReadInputChunk reads one unframed terminal chunk. The input-loop owner passes it to TerminalInput so negotiation is handled after sequence framing.

func ReadInputStream

func ReadInputStream(ctx context.Context, source io.Reader, onInput func([]byte)) error

ReadInputStream delivers raw reads synchronously until EOF, a read error, or cancellation. The callback must return when ctx is cancelled. Files stay open for the next terminal owner. Other ReadClosers are closed on cancellation to interrupt Read; non-closable readers must complete each Read without waiting for external input.

func RedactSecretInput

func RedactSecretInput(text, value string) string

RedactSecretInput removes a submitted input and its trimmed credential form from an authentication diagnostic. It does not modify credentials or persist the input.

func RefreshActiveThemeColorMode

func RefreshActiveThemeColorMode()

RefreshActiveThemeColorMode re-activates the active theme in the color mode the terminal supports now. Upstream re-creates the theme from settings after applying capability overrides on reload.

func RegisterKittyImageMetadata

func RegisterKittyImageMetadata(metadata KittyImageMetadata)

RegisterKittyImageMetadata records metadata for a transmitted Kitty image, evicting the oldest entry past the cap. Mirrors upstream registerKittyImageMetadata.

func RenderDiff

func RenderDiff(diffText string) string

RenderDiff renders a diff string with colored lines and intra-line highlighting. Uses theme colors for added/removed/context lines.

func RenderImage

func RenderImage(base64Data string, imageDimensions ImageDimensions, options ImageRenderOptions) *renderedImage

RenderImage preserves aspect ratio and permits Kitty cursor movement unless explicitly disabled in options.

func RenderIntraLineDiff

func RenderIntraLineDiff(oldContent, newContent string) (removedLine, addedLine string)

RenderIntraLineDiff produces word-level diff with inverse highlighting on changes. Matches upstream's renderIntraLineDiff behavior.

func ResetCapabilitiesCache

func ResetCapabilitiesCache()

func ResolveEscapeTimeoutMs

func ResolveEscapeTimeoutMs(getenv func(string) string) float64

ResolveEscapeTimeoutMs returns how long, in milliseconds, input handling waits for the rest of an escape sequence before dispatching a lone ESC as the Escape key. PI_TUI_ESC_TIMEOUT wins when it is a finite positive number; SSH sessions default to 100ms because legacy Alt+key input is ESC plus another byte and high-latency transports split them. Mirrors upstream resolveEscapeTimeoutMs (terminal.ts).

func ResolveThemeSetting deprecated

func ResolveThemeSetting(themeSetting string, terminalTheme TerminalTheme) (string, bool)

ResolveThemeSetting resolves a stored theme setting to the concrete theme name for the detected terminal appearance.

Deprecated: use ResolveThemeSettingPresence; an empty string means no setting.

func ResolveThemeSettingPresence

func ResolveThemeSettingPresence(themeSetting *string, terminalTheme TerminalTheme) (string, bool)

ResolveThemeSettingPresence resolves a theme setting to the concrete theme name for the detected terminal appearance. A nil setting and a malformed slash value resolve to nothing; any other string, including an empty one, is a fixed name that resolves to itself.

func RestoreTerminalFromSignal

func RestoreTerminalFromSignal() bool

RestoreTerminalFromSignal returns the terminal to the mode it had before pig took it over, and reports whether there was anything to restore.

This is the subset of raw-mode teardown that is safe to run from a signal goroutine: it disables the extended-key protocols in a single write and then runs one tcsetattr against a state captured at startup. It deliberately skips the rest of the normal teardown, which drains stdin for up to a second, because that would race the input reader and the render loop.

Without the tcsetattr, exiting on a signal leaves the terminal raw: ISIG stays off, so the user's shell has no working Ctrl+C until they run `reset`. Without the protocol disable, the Kitty flags pig pushed stay on the terminal's stack after pig is gone, so the shell that inherits the terminal receives CSI-u encoded keys it does not understand.

func SecretInputPreview

func SecretInputPreview(value string) (string, int)

SecretInputPreview returns a bounded masked preview and the number of user-perceived characters. Inputs shorter than five characters reveal no suffix.

func SetAppKeyTextResolver

func SetAppKeyTextResolver(resolver func(action string) string)

SetAppKeyTextResolver installs a resolver for app-level keybinding IDs (for example, `app.tree.foldOrUp`) used by TUI components that can't import the codingagent package directly.

func SetCapabilities

func SetCapabilities(caps TerminalCapabilities)

SetCapabilities overrides the cached capabilities. Mirrors upstream setCapabilities.

func SetCapabilityOverrides

func SetCapabilityOverrides(overrides CapabilityOverrides)

SetCapabilityOverrides mirrors upstream setCapabilityOverrides: it replaces the overrides and drops the cache only when a field changed.

func SetCellDimensions

func SetCellDimensions(dims CellDimensions)

func SetCompactReadClassifier

func SetCompactReadClassifier(classify func(rawPath, cwd string) (CompactReadClassification, bool))

SetCompactReadClassifier installs the classifier FormatCompactReadHeader uses. Nil turns compact read headers off.

func SetKeybindings

func SetKeybindings(kb *TUIKeybindingsManager)

SetKeybindings mirrors upstream setKeybindings().

func SetKittyProtocolActive

func SetKittyProtocolActive(active bool)

SetKittyProtocolActive mirrors upstream keys.ts global Kitty state.

func SetTUIKeybindings

func SetTUIKeybindings(kb *TUIKeybindingsManager)

SetTUIKeybindings sets the global TUI keybinding manager.

func SetTerminalProgress

func SetTerminalProgress(active bool)

SetTerminalProgress toggles the OSC 9;4 terminal progress indicator.

func SetTerminalTitle

func SetTerminalTitle(title string)

SetTerminalTitle writes an OSC 0 sequence to stdout to update the terminal window title. An empty title clears back to terminal default.

func SetTheme

func SetTheme(name string, enableWatcher ...bool)

SetTheme switches the active built-in theme. enableWatcher restarts the owned watcher; previews leave the current watch registration unchanged.

func SetThemeByName

func SetThemeByName(name string, enableWatcher ...bool)

SetThemeByName activates a registered theme, or falls back to dark when absent. enableWatcher restarts the interactive owner's watch after a successful selection; it defaults to false for previews.

func SetThemeRegistry

func SetThemeRegistry(r *ThemeRegistry)

SetThemeRegistry sets the global theme registry.

func SetThemeSetting deprecated

func SetThemeSetting(themeSetting string)

SetThemeSetting applies a stored theme setting.

Deprecated: use SetThemeSettingPresence; an empty string means no setting.

func SetThemeSettingPresence

func SetThemeSettingPresence(themeSetting *string)

SetThemeSettingPresence applies a theme setting before the terminal answers. A nil or malformed setting selects the environment-detected built-in theme; a fixed name that is not registered, including an empty one, falls back to dark.

func ShellToolPrompt

func ShellToolPrompt(toolName string) (prompt string, ok bool)

ShellToolPrompt returns the prompt upstream createAllToolRenderers assigns to a built-in shell tool: createShellRenderers("$") for bash and createShellRenderers("PS>") for powershell. ok is false for other tools.

func ShouldDeliverKey

func ShouldDeliverKey(component Component, data string) bool

ShouldDeliverKey reports whether a raw input chunk may be handed to a focused component's HandleInput. Kitty key releases are dropped unless the component implements KeyReleaseReceiver and opts in.

This is the single decision point for focused-component key delivery, and every such handoff must route through it. A component that acts on a release fires each keystroke twice, because extendedKeyInit pushes \x1b[>7u, whose flag 2 makes the terminal report press, repeat, and release. Scattering the check across dispatch sites is what let extension dialogs move a selector cursor two rows per arrow press: the filter existed, but an earlier return bypassed it.

Raw-input consumers are a different contract and must not use this: terminal input listeners, alt-screen viewport handling, and extension shortcut listeners all see unfiltered input by design, matching upstream's addInputListener and handleViewportInput.

Mirrors upstream tui.ts:887 (isKeyRelease(data) && !wantsKeyRelease -> drop).

func SupportsTrueColor

func SupportsTrueColor() bool

SupportsTrueColor reports whether the terminal advertises 24-bit color via the COLORTERM hint (truecolor/24bit) or Windows Terminal, matching the probe in DetectTerminalCapabilities. Terminals without the hint (Apple Terminal.app, plain xterm-256color) are treated as 256-color so callers downsample instead of emitting 24-bit SGR the terminal ignores, which would otherwise render the half-block art as a single default color.

func TUIKeybindingDefinitionsFor

func TUIKeybindingDefinitionsFor(platform KeybindingPlatform) map[string]TUIKeybindingDef

TUIKeybindingDefinitionsFor returns the tui.* definition table for a platform: upstream TUI_KEYBINDINGS (packages/tui/src/keybindings.ts) with the per-platform tui.* defaults that coding-agent's KEYBINDINGS applies on top (core/keybindings.ts). Every call returns a fresh map.

func ThemeHexBg

func ThemeHexBg(hex string) string

ThemeHexBg returns the active theme's background escape for a fixed hex color, in the theme's color mode.

func ThemeHexFg

func ThemeHexFg(hex string) string

ThemeHexFg returns the active theme's foreground escape for a fixed hex color, in the theme's color mode.

func ToolErrorBgOpen

func ToolErrorBgOpen() string

func ToolPendingBgOpen

func ToolPendingBgOpen() string

func ToolSuccessBgOpen

func ToolSuccessBgOpen() string

func TreeVisibleLines

func TreeVisibleLines(terminalHeight int) int

NewTreeSelect builds the flattened view from the given root. Root itself is not rendered; only its children.

Indent + connector rules mirror upstream tree-selector.ts:143-260 (flattenTree) and :631-666 (per-row prefix construction). Single-child chains stay at the same indent and skip the connector glyph; only branch points (parent with > 1 children) bump indent and draw `├─`/`└─`. TreeVisibleLines is upstream TreeSelectorComponent's row budget for a terminal of the given height.

func UseWindowsKeybindings

func UseWindowsKeybindings(goos string, getenv func(string) string) bool

UseWindowsKeybindings reports whether Windows default keys apply: native Windows, or Linux under WSL. WT_SESSION alone does not count, because Windows Terminal also hosts SSH sessions to other machines. Mirrors upstream useWindowsKeybindings(platform, env) in core/keybindings.ts; goos uses Go's runtime.GOOS names.

func UserMessageBgOpen

func UserMessageBgOpen() string

Convenience accessors for component code that paints backgrounds. These read from the active theme so dark/light mode works automatically.

func ValidateThemeJSON

func ValidateThemeJSON(label string, data []byte) error

ValidateThemeJSON validates one theme document (JSON text without a BOM) and returns an error naming the offending tokens, or nil. Mirrors upstream validateThemeJson.

func WrapText

func WrapText(s string, width int) []string

WrapText wraps text at width, preserving ANSI escape codes across line breaks. Exported for use by tool renderers.

Types

type AltScreenFlashContainer

type AltScreenFlashContainer struct {
	// contains filtered or unexported fields
}

AltScreenFlashContainer holds transient reverse-video messages composited by the alternate-screen renderer. Ports pi-tui's AltScreenFlashContainer.

Forced Go mechanic: upstream's single-loop setTimeout(...).unref() removal is an owned time.AfterFunc guarded by a mutex, because each timer fires on its own goroutine and races Render/Flash/Dispose. The per-entry id is the identity guard: a fired-but-already-removed callback finds its id gone and no-ops. The requestRender callback runs after the lock is released so slow render work never holds the mutex. Go timers never keep the process alive, so unref() has no Go counterpart; Dispose stops every timer to avoid a goroutine leak.

func NewAltScreenFlashContainer

func NewAltScreenFlashContainer(requestRender func()) *AltScreenFlashContainer

NewAltScreenFlashContainer constructs a flash container that calls requestRender whenever the visible set changes.

func (*AltScreenFlashContainer) Dispose

func (c *AltScreenFlashContainer) Dispose()

Dispose stops all pending timers and clears the visible set.

func (*AltScreenFlashContainer) Flash

func (c *AltScreenFlashContainer) Flash(message string, durationMs int)

Flash shows message in reverse video for durationMs, then removes it. The caller supplies altScreenFlashDefaultDurationMS for the optional upstream default; an explicit zero or negative duration is clamped to zero like Math.max(0, durationMs).

func (*AltScreenFlashContainer) Invalidate

func (i *AltScreenFlashContainer) Invalidate()

func (*AltScreenFlashContainer) IsDirty

func (i *AltScreenFlashContainer) IsDirty() bool

func (*AltScreenFlashContainer) NeedsRedraw

func (i *AltScreenFlashContainer) NeedsRedraw() bool

func (*AltScreenFlashContainer) Render

func (c *AltScreenFlashContainer) Render(width int) []string

Render returns one reverse-video line per active flash, each padded-spaced and truncated to width. Mirrors upstream render.

type AltScreenSearchComponent

type AltScreenSearchComponent struct {
	// contains filtered or unexported fields
}

AltScreenSearchComponent is the transcript search box: an input, a result counter, and previous/next buttons in its bottom border. Mirrors upstream AltScreenSearchComponent. Navigation directions are -1 (previous), 1 (next), and 0 (none, upstream undefined).

func NewAltScreenSearchComponent

func NewAltScreenSearchComponent(onQueryChange func(query string), navigationButtonStyle func(text string, hovered bool) string) *AltScreenSearchComponent

NewAltScreenSearchComponent creates the search box. A nil navigationButtonStyle leaves the buttons unstyled.

func (*AltScreenSearchComponent) Focused

func (c *AltScreenSearchComponent) Focused() bool

Focused reports the Focusable state. Mirrors upstream get focused.

func (*AltScreenSearchComponent) GetNavigationDirectionAt

func (c *AltScreenSearchComponent) GetNavigationDirectionAt(row, column int) int

GetNavigationDirectionAt returns the button under a component-local cell.

func (*AltScreenSearchComponent) HandleInput

func (c *AltScreenSearchComponent) HandleInput(data string)

HandleInput edits the query and reports a changed query.

func (*AltScreenSearchComponent) Invalidate

func (c *AltScreenSearchComponent) Invalidate()

Invalidate invalidates the input.

func (*AltScreenSearchComponent) Render

func (c *AltScreenSearchComponent) Render(width int) []string

Render draws the box: top border, input row, and a bottom border carrying the navigation buttons. Mirrors upstream AltScreenSearchComponent.render.

func (*AltScreenSearchComponent) SetFocused

func (c *AltScreenSearchComponent) SetFocused(value bool)

SetFocused updates the Focusable state and forwards it to the input.

func (*AltScreenSearchComponent) SetHoveredNavigationDirection

func (c *AltScreenSearchComponent) SetHoveredNavigationDirection(direction int) bool

SetHoveredNavigationDirection records the hovered button and reports whether it changed.

func (*AltScreenSearchComponent) SetResult

func (c *AltScreenSearchComponent) SetResult(index, count int)

SetResult sets the displayed match index (-1 for none) and count.

type AltScreenSearchIndex

type AltScreenSearchIndex struct {
	// contains filtered or unexported fields
}

AltScreenSearchIndex caches the searchable corpus and matches while the rendered transcript lines remain unchanged. Mirrors upstream AltScreenSearchIndex.

func (*AltScreenSearchIndex) Search

func (i *AltScreenSearchIndex) Search(lines []string, query string) (matches []AltScreenSearchMatch, changed bool)

Search returns the matches for query over lines and whether they changed since the previous call. Mirrors upstream AltScreenSearchIndex.search.

type AltScreenSearchMatch

type AltScreenSearchMatch struct {
	Segments []AltScreenSearchSegment
}

AltScreenSearchMatch is one match, possibly spanning rows. Mirrors upstream AltScreenSearchMatch.

func FindAltScreenSearchMatches

func FindAltScreenSearchMatches(lines []string, query string) []AltScreenSearchMatch

FindAltScreenSearchMatches searches lines for query without caching. Mirrors upstream findAltScreenSearchMatches.

type AltScreenSearchSegment

type AltScreenSearchSegment struct {
	Row      int
	StartCol int
	EndCol   int
}

AltScreenSearchSegment is one row-local cell range of a match. Mirrors upstream AltScreenSearchSegment.

type AssistantMessageBlock

type AssistantMessageBlock struct {
	// contains filtered or unexported fields
}

AssistantMessageBlock renders ordered text/thinking content, terminal diagnostics, and OSC 133 zones for one assistant turn. Ports packages/coding-agent/src/modes/interactive/components/assistant-message.ts.

func NewAssistantMessageBlock

func NewAssistantMessageBlock(hiddenThinking bool) *AssistantMessageBlock

NewAssistantMessageBlock creates an empty block. Pass hiddenThinking=true when the user has toggled thinking visibility off (Ctrl+T).

func (*AssistantMessageBlock) Dispose

func (b *AssistantMessageBlock) Dispose()

Dispose releases this block's Markdown generations without allowing a late publication.

func (*AssistantMessageBlock) HandleMouse

HandleMouse toggles only the rendered thinking run under a left click. Hit testing uses the last frame's row ranges without rendering or copying the message.

func (*AssistantMessageBlock) Invalidate

func (i *AssistantMessageBlock) Invalidate()

func (*AssistantMessageBlock) IsDirty

func (i *AssistantMessageBlock) IsDirty() bool

func (*AssistantMessageBlock) NeedsRedraw

func (i *AssistantMessageBlock) NeedsRedraw() bool

func (*AssistantMessageBlock) Render

func (b *AssistantMessageBlock) Render(width int) []string

Render applies both horizontal margins and fills remaining cells. Image rows pass through unchanged. Non-tool-call messages carry OSC 133 zone boundaries. Empty content with no terminal diagnostic has no rows.

func (*AssistantMessageBlock) SetAsyncMarkdownTransforms

func (b *AssistantMessageBlock) SetAsyncMarkdownTransforms(text, thinking *AsyncMarkdownTransform)

SetAsyncMarkdownTransforms installs separately contextualized text and thinking rewrites. Each retained segment owns its replaceable worker generation.

func (*AssistantMessageBlock) SetContent

func (b *AssistantMessageBlock) SetContent(content []AssistantSegment)

SetContent replaces text/thinking content in message order for streaming or redraw. Blocks are trimmed, empty ones skipped, and consecutive thinking blocks form one run joined by a blank line. An empty text segment preserves an invisible boundary such as a tool call.

func (*AssistantMessageBlock) SetHasToolCalls

func (b *AssistantMessageBlock) SetHasToolCalls(v bool)

SetHasToolCalls records that the assistant message contains tool calls. When true, the abort/error section is suppressed: tool execution components show their own error state. Mirrors upstream assistant-message.ts:128: `if (!hasToolCalls) { ... }`.

func (*AssistantMessageBlock) SetHiddenThinking

func (b *AssistantMessageBlock) SetHiddenThinking(hidden bool)

SetHiddenThinking controls all thinking runs and clears individual click overrides, as upstream setHideThinkingBlock does.

func (*AssistantMessageBlock) SetMarkdownTransform

func (b *AssistantMessageBlock) SetMarkdownTransform(fn func(markdown string, width int) string)

SetMarkdownTransform installs a display-only rewrite applied to the text section at its render width, before markdown parsing. Mirrors upstream MarkdownOptions.transform threaded through createMarkdownTransform in assistant-message.ts:112. Used for the built-in Mermaid transformer.

func (*AssistantMessageBlock) SetMarkdownTransformState

func (b *AssistantMessageBlock) SetMarkdownTransformState(fn func() string)

SetMarkdownTransformState declares the external state the installed transform reads, so a change to it re-renders instead of serving the cached lines. Required whenever the transform is not a pure function of (markdown, width).

func (*AssistantMessageBlock) SetOutputPad

func (b *AssistantMessageBlock) SetOutputPad(padding int)

SetOutputPad changes the horizontal content padding.

func (*AssistantMessageBlock) SetTerminalError

func (b *AssistantMessageBlock) SetTerminalError(stopReason, errorMessage string)

SetTerminalError records length/error/abort state after partial assistant content. An empty error message renders "Unknown error"; tool calls suppress abort/error but not length diagnostics.

func (*AssistantMessageBlock) SetTextDelta

func (b *AssistantMessageBlock) SetTextDelta(delta string)

SetTextDelta appends to the current text block, or starts one after thinking.

func (*AssistantMessageBlock) SetThinkingDelta

func (b *AssistantMessageBlock) SetThinkingDelta(delta string)

SetThinkingDelta appends to the current thinking block, or starts one after text.

func (*AssistantMessageBlock) SetThinkingMarkdownTransform

func (b *AssistantMessageBlock) SetThinkingMarkdownTransform(fn func(markdown string, width int) string)

SetThinkingMarkdownTransform installs the display-only rewrite for visible thinking, separate from the assistant-text transform context. Hidden thinking does not invoke it.

func (*AssistantMessageBlock) Text

func (b *AssistantMessageBlock) Text() string

Text returns concatenated untrimmed text blocks, without display transformations.

func (*AssistantMessageBlock) Thinking

func (b *AssistantMessageBlock) Thinking() string

Thinking returns the accumulated thinking content.

type AssistantSegment

type AssistantSegment struct {
	Thinking bool
	Text     string
}

AssistantSegment is one text or thinking content block of a complete assistant message, in message order.

type AsyncAutocompleteProvider

type AsyncAutocompleteProvider struct {
	TriggerCharacters           []string
	GetSuggestions              func(context.Context, []string, int, int, bool) (*AutocompleteSuggestions, error)
	ApplyCompletion             func(context.Context, []string, int, int, AutocompleteItem, string) ([]string, int, int, error)
	ShouldTriggerFileCompletion func(context.Context, []string, int, int) (bool, error)
}

AsyncAutocompleteProvider runs a complete provider chain off the editor loop. Provider columns are byte offsets; the native editor converts its UTF-16 positions at this boundary.

type AsyncFileSearcher

type AsyncFileSearcher interface {
	FileSearchTask(lines []string, cursorLine, cursorCol int) (prefix string, run func(context.Context) []AutocompleteItem, ok bool)
}

AsyncFileSearcher is an optional capability of the local autocomplete provider: it returns a deferred fd-backed @-file search that the editor runs off the input thread with cancellation. Mirrors upstream's async getFuzzyFileSuggestions (autocomplete.ts:717) so a deep directory walk cannot block keystrokes. When ok is false the editor falls back to the synchronous GetSuggestions result.

type AsyncMarkdownTransform

type AsyncMarkdownTransform struct {
	Context    context.Context
	Start      func(func())
	Invalidate func()
	Prepare    func(markdown string, width int) func(context.Context) string
	// Queue preserves render admission order across components belonging to one owner. A nil queue keeps work local to the component.
	Queue *MarkdownTransformQueue
}

AsyncMarkdownTransform prepares an owned, cancellable display rewrite. Prepare runs on the UI loop and snapshots mutable inputs; its returned function runs off-loop. Start joins that work at owner shutdown. Invalidate requests a paint without mutating UI state. pig additive (D19): subprocess callbacks execute outside the host render loop.

type AsyncSuggestionPlanner

type AsyncSuggestionPlanner interface {
	SuggestionTask([]string, int, int, bool) (string, func(context.Context) ([]AutocompleteItem, error), bool)
}

AsyncSuggestionPlanner captures the awaited branch of a local provider without executing that branch on the owner loop.

type AuthInfoLink struct{ URL, Label string }

AuthInfoLink is a provider-owned documentation link shown in a login dialog.

type AutocompleteItem

type AutocompleteItem struct {
	Value       string // text inserted at cursor on accept
	Label       string // displayed primary text
	Description string // optional secondary text (dim)
}

AutocompleteItem is one popup row.

type AutocompleteProvider

type AutocompleteProvider interface {
	// GetSuggestions returns suggestions for the given buffer state.
	// Return nil when no popup should be shown (no match, wrong context).
	GetSuggestions(lines []string, cursorLine, cursorCol int) *AutocompleteSuggestions

	// ApplyCompletion edits the buffer to insert `item.Value` in place
	// of the trailing `prefix`. Returns the new buffer + cursor.
	ApplyCompletion(lines []string, cursorLine, cursorCol int, item AutocompleteItem, prefix string) (newLines []string, newLine, newCol int)
}

AutocompleteProvider supplies the local synchronous portion of a query. Deferred callbacks and filesystem searches are captured by AsyncSuggestionPlanner and AsyncFileSearcher; extension chains use AsyncAutocompleteProvider.

type AutocompleteSuggestions

type AutocompleteSuggestions struct {
	Items  []AutocompleteItem
	Prefix string
}

AutocompleteSuggestions is the provider return shape. Prefix is the buffer slice the popup is matching against: applyCompletion uses its length to know how many chars to replace.

type AutocompleteWork

type AutocompleteWork func(context.Context) (func(), error)

AutocompleteWork runs off-loop and returns a mutation to execute on the owner loop. The host holds subsequent input while input work is pending.

type BaseComponent

type BaseComponent struct {
	// contains filtered or unexported fields
}

BaseComponent is the exported equivalent of invalidatable for components living in other packages.

func (*BaseComponent) Invalidate

func (i *BaseComponent) Invalidate()

func (*BaseComponent) IsDirty

func (i *BaseComponent) IsDirty() bool

func (*BaseComponent) NeedsRedraw

func (i *BaseComponent) NeedsRedraw() bool

type BashExecutionBlock

type BashExecutionBlock struct {
	// contains filtered or unexported fields
}

BashExecutionBlock displays a `!cmd` invocation with streaming output, top/bottom borders, and expand/collapse support.

func NewBashExecutionBlock

func NewBashExecutionBlock(command string, excludeFromContext bool) *BashExecutionBlock

NewBashExecutionBlock returns a freshly-constructed bash-execution component in the running state.

func (*BashExecutionBlock) AppendOutput

func (b *BashExecutionBlock) AppendOutput(chunk string)

AppendOutput streams a sanitized chunk into the block.

func (*BashExecutionBlock) Invalidate

func (i *BashExecutionBlock) Invalidate()

func (*BashExecutionBlock) IsDirty

func (b *BashExecutionBlock) IsDirty() bool

IsDirty reports whether the block needs re-rendering. While running it embeds an animated Loader spinner advanced by the 100ms tick loop, but the tick ticks the loader without Invalidating this block. Reporting dirty while running keeps the per-child render cache from freezing the spinner.

func (*BashExecutionBlock) Loader

func (b *BashExecutionBlock) Loader() *Loader

Loader returns the embedded spinner when the block is still running, nil otherwise. The animation driver ticks it to advance the spinner.

func (*BashExecutionBlock) NeedsRedraw

func (i *BashExecutionBlock) NeedsRedraw() bool

func (*BashExecutionBlock) Render

func (b *BashExecutionBlock) Render(width int) []string

Render produces the block's lines. Commands and output wrap to the current terminal width, and collapsed previews retain the last previewLines visual rows.

func (*BashExecutionBlock) SetComplete

func (b *BashExecutionBlock) SetComplete(exitCode *int, cancelled, truncated bool)

SetComplete transitions the block out of the running state.

func (*BashExecutionBlock) SetCompleteWithOutput

func (b *BashExecutionBlock) SetCompleteWithOutput(exitCode *int, cancelled, truncated bool, output, fullOutputPath string)

SetCompleteWithOutput replaces the streaming preview with the durable truncated output and records its full-output path before completing the block.

func (*BashExecutionBlock) SetExpanded

func (b *BashExecutionBlock) SetExpanded(expanded bool)

SetExpanded forces the body open (true) or collapsed-to-preview (false). Driven by the global Ctrl+O toggle so all bash blocks land in the same state as their tool-execution peers.

type BorderedLoader

type BorderedLoader struct {
	// contains filtered or unexported fields
}

BorderedLoader renders a loader between two horizontal borders, optionally with an Esc cancel hint.

func NewBorderedLoader

func NewBorderedLoader(message string, cancellable bool) *BorderedLoader

NewBorderedLoader creates a bordered loader. When cancellable is true, an Esc cancel hint is shown and HandleInput cancels on Esc.

func (*BorderedLoader) CancellableContext

func (bl *BorderedLoader) CancellableContext() *CancellableLoader

CancellableContext returns the cancellable loader's context, or nil.

func (*BorderedLoader) Dispose

func (bl *BorderedLoader) Dispose()

Dispose stops the loader.

func (*BorderedLoader) HandleInput

func (bl *BorderedLoader) HandleInput(data string)

HandleInput delegates to the cancellable loader if present.

func (*BorderedLoader) Invalidate

func (i *BorderedLoader) Invalidate()

func (*BorderedLoader) IsDirty

func (i *BorderedLoader) IsDirty() bool

func (*BorderedLoader) NeedsRedraw

func (i *BorderedLoader) NeedsRedraw() bool

func (*BorderedLoader) NextFrame

func (bl *BorderedLoader) NextFrame()

NextFrame advances the spinner animation.

func (*BorderedLoader) Render

func (bl *BorderedLoader) Render(width int) []string

Render produces border + loader + optional hint + border.

type Box

type Box struct {
	PaddingX int
	PaddingY int
	BgFn     func(string) string
	// contains filtered or unexported fields
}

Box component - a container that applies padding and background to children.

func NewBox

func NewBox() *Box

func NewPaddedBox

func NewPaddedBox(paddingX, paddingY int, bgFn func(string) string) *Box

func (*Box) AddChild

func (b *Box) AddChild(component Component)

func (*Box) Clear

func (b *Box) Clear()

func (*Box) HandleMouse

func (b *Box) HandleMouse(event TuiMouseEvent) *TuiMouseDispatchResult

HandleMouse forwards an event inside the padded content area to the child under the pointer. Mirrors upstream Box.handleMouse.

func (*Box) Invalidate

func (b *Box) Invalidate()

func (*Box) IsDirty

func (i *Box) IsDirty() bool

func (*Box) NeedsRedraw

func (i *Box) NeedsRedraw() bool

func (*Box) RemoveChild

func (b *Box) RemoveChild(component Component)

func (*Box) Render

func (b *Box) Render(width int) []string

func (*Box) SetBgFn

func (b *Box) SetBgFn(bgFn func(string) string)

type BranchSummaryComponent

type BranchSummaryComponent struct {
	// contains filtered or unexported fields
}

BranchSummaryComponent renders a branch-summary boundary marker in the chat transcript. Replaces the single-row BranchSummaryChip.

Upstream: components/branch-summary-message.ts (BranchSummaryMessageComponent).

func NewBranchSummaryComponent

func NewBranchSummaryComponent(summary string) *BranchSummaryComponent

NewBranchSummaryComponent creates a branch summary component. summary is the LLM-generated markdown text summarising the abandoned branch.

func (*BranchSummaryComponent) HandleMouse

HandleMouse toggles the summary on a left click inside the box content, excluding its one-cell padding. Ports packages/coding-agent/src/modes/interactive/components/branch-summary-message.ts:59.

func (*BranchSummaryComponent) Invalidate

func (i *BranchSummaryComponent) Invalidate()

func (*BranchSummaryComponent) IsDirty

func (i *BranchSummaryComponent) IsDirty() bool

func (*BranchSummaryComponent) NeedsRedraw

func (i *BranchSummaryComponent) NeedsRedraw() bool

func (*BranchSummaryComponent) Render

func (c *BranchSummaryComponent) Render(width int) []string

Render returns the lines for this component at the given terminal width. All column measurements are delegated to paintBgWith (which uses lineDisplayWidth / runewidth.StringWidth internally).

func (*BranchSummaryComponent) SetExpanded

func (c *BranchSummaryComponent) SetExpanded(expanded bool)

SetExpanded opens or collapses the component body. InteractiveMode calls it from the global Ctrl+O toggle.

type CancellableLoader

type CancellableLoader struct {
	Loader

	OnAbort func()
	// contains filtered or unexported fields
}

CancellableLoader extends Loader with Esc-key cancellation.

func NewCancellableLoader

func NewCancellableLoader(spinnerColor, messageColor, message string, frames []string) *CancellableLoader

NewCancellableLoader creates a cancellable loader.

func (*CancellableLoader) Aborted

func (cl *CancellableLoader) Aborted() bool

Aborted returns true if cancelled.

func (*CancellableLoader) Context

func (cl *CancellableLoader) Context() context.Context

Context returns the cancellation context.

func (*CancellableLoader) Dispose

func (*CancellableLoader) Dispose()

Dispose stops loader animation ownership. Loader animation is host-driven in Pig, so there is no local timer to stop and cancellation state is unchanged.

func (*CancellableLoader) HandleInput

func (cl *CancellableLoader) HandleInput(data string)

HandleInput cancels on the registry-bound tui.select.cancel key.

func (*CancellableLoader) Invalidate

func (i *CancellableLoader) Invalidate()

func (*CancellableLoader) IsDirty

func (i *CancellableLoader) IsDirty() bool

func (*CancellableLoader) NeedsRedraw

func (i *CancellableLoader) NeedsRedraw() bool

func (*CancellableLoader) Signal

func (cl *CancellableLoader) Signal() context.Context

Signal returns the underlying cancellation context.

type CapabilityOverrides

type CapabilityOverrides struct {
	Images     *ImageProtocol
	TrueColor  *bool
	Hyperlinks *bool
}

CapabilityOverrides mirrors upstream Partial<TerminalCapabilities> as passed to setCapabilityOverrides. A nil field is absent. Images points at "" for upstream's null (no image protocol).

type CellDimensions

type CellDimensions struct {
	WidthPx  int
	HeightPx int
}

func GetCellDimensions

func GetCellDimensions() CellDimensions

type ColorMode

type ColorMode string

ColorMode mirrors theme.ts ColorMode.

const (
	ColorModeTrueColor ColorMode = "truecolor"
	ColorMode256       ColorMode = "256color"
)

type CombinedProvider

type CombinedProvider struct {
	// contains filtered or unexported fields
}

CombinedProvider handles both slash-command and @-file autocomplete. Mirrors upstream CombinedAutocompleteProvider (autocomplete.ts:238).

func NewCombinedProvider

func NewCombinedProvider(cmds []SlashCommand, baseDir, fdPath string) *CombinedProvider

NewCombinedProvider creates a provider for slash commands, attachment search, and direct paths. An empty fdPath disables attachment suggestions without affecting direct path completion.

func (*CombinedProvider) ApplyCompletion

func (p *CombinedProvider) ApplyCompletion(lines []string, cursorLine, cursorCol int, item AutocompleteItem, prefix string) ([]string, int, int)

ApplyCompletion preserves path prefixes and surrounding text, consumes an existing closing quote, and leaves directory cursors inside quotes. Only slash commands and file attachments append a space.

func (*CombinedProvider) FileSearchTask

func (p *CombinedProvider) FileSearchTask(lines []string, cursorLine, cursorCol int) (string, func(context.Context) []AutocompleteItem, bool)

FileSearchTask returns a deferred, cancellable fd-backed @-file search for the cursor's @-prefix, or ok=false when async file search is disabled, fd is unavailable, or the buffer-before-cursor is not an @ query. The returned run closure executes fd under the caller's context so the editor can abort it on the next keystroke, mirroring upstream's async getFuzzyFileSuggestions + AbortSignal (autocomplete.ts:717).

func (*CombinedProvider) GetSuggestions

func (p *CombinedProvider) GetSuggestions(lines []string, cursorLine, cursorCol int) *AutocompleteSuggestions

GetSuggestions implements upstream command, attachment and path matching. The Editor decides which contexts trigger queries automatically.

func (*CombinedProvider) GetSuggestionsForce

func (p *CombinedProvider) GetSuggestionsForce(lines []string, cursorLine, cursorCol int) *AutocompleteSuggestions

GetSuggestionsForce mirrors upstream getSuggestions(..., {force: true}). Triggered by Tab outside a slash-command-name context to force naked path completion even when the prefix doesn't look path-like yet.

func (*CombinedProvider) SetAsyncFileSearch

func (p *CombinedProvider) SetAsyncFileSearch(v bool)

SetAsyncFileSearch enables deferred, cancellable fd-backed @-file search. Interactive mode enables this so a slow tree walk cannot block keystrokes.

func (*CombinedProvider) SuggestionTask

func (p *CombinedProvider) SuggestionTask(lines []string, line, col int, force bool) (string, func(context.Context) ([]AutocompleteItem, error), bool)

SuggestionTask defers filesystem access and awaited command arguments while preserving the combined provider's branch precedence.

type CompactReadClassification

type CompactReadClassification struct {
	Kind  string // "docs", "resource" or "skill"
	Label string
}

CompactReadClassification is upstream read.ts CompactReadClassification: a read of a skill file, the agent's own docs, or a context file draws a short label while the card is collapsed.

type CompactionSummaryComponent

type CompactionSummaryComponent struct {
	// contains filtered or unexported fields
}

CompactionSummaryComponent renders a collapsible compaction marker. It preserves Pi's horizontal and vertical Box padding.

func NewCompactionSummaryComponent

func NewCompactionSummaryComponent(summary string, tokensBefore int) *CompactionSummaryComponent

NewCompactionSummaryComponent creates a compaction summary component. summary is the markdown text of the compaction context; tokensBefore is the LLM token count before compaction (shown in the header).

func (*CompactionSummaryComponent) HandleMouse

HandleMouse toggles the summary on a left click inside the box content, excluding its one-cell padding. Ports packages/coding-agent/src/modes/interactive/components/compaction-summary-message.ts:60.

func (*CompactionSummaryComponent) Invalidate

func (i *CompactionSummaryComponent) Invalidate()

func (*CompactionSummaryComponent) IsDirty

func (i *CompactionSummaryComponent) IsDirty() bool

func (*CompactionSummaryComponent) NeedsRedraw

func (i *CompactionSummaryComponent) NeedsRedraw() bool

func (*CompactionSummaryComponent) Render

func (c *CompactionSummaryComponent) Render(width int) []string

Render returns the lines for this component at the given terminal width. All column measurements are delegated to paintBgWith (which uses lineDisplayWidth / runewidth.StringWidth internally).

func (*CompactionSummaryComponent) SetExpanded

func (c *CompactionSummaryComponent) SetExpanded(expanded bool)

SetExpanded opens or collapses the component body. InteractiveMode calls it from the global Ctrl+O toggle.

type Component

type Component interface {
	Render(width int) []string
	// Invalidate marks the component as needing a redraw on the next tick.
	Invalidate()
}

Component is the base interface all TUI widgets implement. Render returns a slice of ANSI-annotated lines (no trailing newlines). Width is the available terminal columns.

type ConfigSelectorComponent

type ConfigSelectorComponent struct {
	OnCancel   func()
	OnExit     func()
	OnToggle   func(item *ResourceItem, enabled bool)
	OnOverride func(item *ResourceItem, state string) error
	// contains filtered or unexported fields
}

ConfigSelectorComponent manages the resource configuration overlay.

func NewConfigSelector

func NewConfigSelector(groups []*ResourceGroup, terminalRows int) *ConfigSelectorComponent

NewConfigSelector creates a config selector from resolved resource groups.

func NewScopedConfigSelector

func NewScopedConfigSelector(global, project []*ResourceGroup, terminalRows int, writeScope string, projectModeAvailable bool) *ConfigSelectorComponent

NewScopedConfigSelector creates the global/project selector used by pig config.

func (*ConfigSelectorComponent) HandleInput

func (cs *ConfigSelectorComponent) HandleInput(data string)

HandleInput processes keyboard input.

func (*ConfigSelectorComponent) Invalidate

func (i *ConfigSelectorComponent) Invalidate()

func (*ConfigSelectorComponent) IsDirty

func (i *ConfigSelectorComponent) IsDirty() bool

func (*ConfigSelectorComponent) NeedsRedraw

func (i *ConfigSelectorComponent) NeedsRedraw() bool

func (*ConfigSelectorComponent) Render

func (cs *ConfigSelectorComponent) Render(width int) []string

Render produces the config selector overlay.

func (*ConfigSelectorComponent) SetTerminalRows

func (cs *ConfigSelectorComponent) SetTerminalRows(rows int)

SetTerminalRows updates the selector's view budget to track terminal height.

type Container

type Container struct {
	// contains filtered or unexported fields
}

Container stacks child components vertically.

func NewContainer

func NewContainer(children ...Component) *Container

func (*Container) Add

func (c *Container) Add(comp Component)

func (*Container) ChildCount

func (c *Container) ChildCount() int

func (*Container) Children

func (c *Container) Children() []Component

Children returns a snapshot of the mounted child identities in insertion order. Callers can invoke child methods without holding the container lock. upstream: packages/tui/src/tui.ts:Container

func (*Container) Clear

func (c *Container) Clear()

Clear removes every child component. Used by /clear and /new.

func (*Container) HandleMouse

func (c *Container) HandleMouse(event TuiMouseEvent) *TuiMouseDispatchResult

HandleMouse forwards an event to the child under the pointer. Mirrors upstream Container.handleMouse. Upstream also rewrites a focus result's focusTarget to the container when a Container subclass handles keyboard input; Go embedding has no subclass identity, so a type that embeds Container and handles input must override HandleMouse to do the same.

func (*Container) Invalidate

func (i *Container) Invalidate()

func (*Container) IsDirty

func (i *Container) IsDirty() bool

func (*Container) IsEmpty

func (c *Container) IsEmpty() bool

IsEmpty reports whether the container currently has no children.

func (*Container) LastTwoChildren

func (c *Container) LastTwoChildren() (Component, Component)

func (*Container) NeedsRedraw

func (i *Container) NeedsRedraw() bool

func (*Container) Remove

func (c *Container) Remove(comp Component)

func (*Container) Render

func (c *Container) Render(width int) []string

Render returns a fresh slice, matching upstream Container.render's observable array ownership. Package renderers use renderBorrowed to read the immutable cached concatenation without copying settled transcript history every frame.

func (*Container) Replace

func (c *Container) Replace(oldComp, newComp Component) bool

Replace swaps oldComp with newComp at the same child index. Returns true if oldComp was found.

func (*Container) SetChildren

func (c *Container) SetChildren(children ...Component)

SetChildren atomically replaces all children.

func (*Container) SetMaxLines

func (c *Container) SetMaxLines(n int)

SetMaxLines caps how many lines Render() returns. When n>0, only the last n lines of all children's output are returned. When n==0 (default), all lines are returned. Used by the /tree selector to keep the chat scrolled to a minimum context window. pig-specific: upstream controls the full viewport; this cap is not needed there.

type ConvertedImage

type ConvertedImage struct {
	Data     string
	MimeType string
}

ConvertedImage is a base64 image and its MIME type, the result of upstream image-convert.ts convertToPng.

type CountdownTimer

type CountdownTimer struct {
	// contains filtered or unexported fields
}

CountdownTimer counts down from a duration, calling OnTick each second and OnExpire when it reaches zero.

func NewCountdownTimer

func NewCountdownTimer(timeout time.Duration, dispatch func(func()), onTick func(int), onExpire func()) *CountdownTimer

NewCountdownTimer creates a timer. It calls onTick immediately with the initial seconds value, then starts a 1-second ticker.

Upstream's interval callback runs on the event loop that owns the dialog, so dispatch runs each second's decrement, onTick and expiry together on the owner loop. A nil dispatch runs them on the ticker goroutine. Dispose stops every later second, including one already dispatched.

func (*CountdownTimer) Dispose

func (ct *CountdownTimer) Dispose()

Dispose stops the timer.

type CustomMessage

type CustomMessage struct {
	CustomType string
	Content    any // string or []ContentBlock
}

CustomMessage holds the data for a custom message entry. Mirrors the upstream CustomMessage<T> shape.

type CustomMessageComponent

type CustomMessageComponent struct {
	CustomType string
	Content    string // text content (may contain markdown)
	Expanded   bool
	// contains filtered or unexported fields
}

CustomMessageComponent renders a custom message entry from extensions.

func NewCustomMessageComponent

func NewCustomMessageComponent(customType, content string) *CustomMessageComponent

NewCustomMessageComponent creates a custom message renderer.

func (*CustomMessageComponent) Invalidate

func (i *CustomMessageComponent) Invalidate()

func (*CustomMessageComponent) IsDirty

func (i *CustomMessageComponent) IsDirty() bool

func (*CustomMessageComponent) NeedsRedraw

func (i *CustomMessageComponent) NeedsRedraw() bool

func (*CustomMessageComponent) Render

func (c *CustomMessageComponent) Render(width int) []string

Render produces the custom message lines. Mirrors upstream CustomMessageComponent which extends Container with a Box(1,1,bgFn). The Box adds paddingX=1 (space indent) and paddingY=1 (blank rows) with bg tint.

func (*CustomMessageComponent) SetExpanded

func (c *CustomMessageComponent) SetExpanded(expanded bool)

SetExpanded toggles between collapsed and expanded rendering.

func (*CustomMessageComponent) SetOutputPad

func (c *CustomMessageComponent) SetOutputPad(_ int)

SetOutputPad invalidates the default renderer, whose box keeps its fixed inset. Only registered custom renderers consume the configured horizontal padding.

type DefaultTextStyle

type DefaultTextStyle struct {
	Color, BgColor                         func(string) string
	Bold, Italic, Strikethrough, Underline bool
}

DefaultTextStyle decorates ordinary Markdown text; background is applied after layout and padding.

type DiffComponent

type DiffComponent struct {
	// contains filtered or unexported fields
}

DiffComponent renders a diff string as colored output. It wraps RenderDiff from diff_render.go into the Component interface.

func NewDiffComponent

func NewDiffComponent(diffText, filePath string) *DiffComponent

NewDiffComponent creates a diff display component.

func (*DiffComponent) Invalidate

func (i *DiffComponent) Invalidate()

func (*DiffComponent) IsDirty

func (i *DiffComponent) IsDirty() bool

func (*DiffComponent) NeedsRedraw

func (i *DiffComponent) NeedsRedraw() bool

func (*DiffComponent) Render

func (d *DiffComponent) Render(width int) []string

Render produces colored diff lines.

func (*DiffComponent) SetDiff

func (d *DiffComponent) SetDiff(text string)

SetDiff updates the diff text.

type Disposable

type Disposable interface {
	Dispose()
}

Disposable is implemented by components that need cleanup.

type DynamicBorder

type DynamicBorder struct {
	// contains filtered or unexported fields
}

DynamicBorder renders a full-width horizontal rule using "─".

func NewDynamicBorder

func NewDynamicBorder(color string) *DynamicBorder

NewDynamicBorder creates a border. If color is empty, the active theme's border color is used at render time.

func (*DynamicBorder) Invalidate

func (i *DynamicBorder) Invalidate()

func (*DynamicBorder) IsDirty

func (i *DynamicBorder) IsDirty() bool

func (*DynamicBorder) NeedsRedraw

func (i *DynamicBorder) NeedsRedraw() bool

func (*DynamicBorder) Render

func (d *DynamicBorder) Render(width int) []string

Render produces a full-width rule and resets only its foreground color.

type Editor

type Editor struct {

	// EmbedWorkingStatus opts into the coding-agent status border.
	EmbedWorkingStatus bool

	// BorderColor colors a complete border after layout and truncation. Nil selects the application-derived default.
	BorderColor func(string) string
	// Focused emits widthx.CursorMarker so the TUI can position the hardware cursor for IME candidate windows.
	Focused bool

	// Thinking-level border color.
	// Mirrors upstream `editor.ts::updateEditorBorderColor` which maps
	// the thinking level to a per-level theme color. "off" uses borderMuted.
	// Bash mode overrides this (bashHeaderColor takes precedence).
	ThinkingLevel string // "off" | "low" | "medium" | "high"

	// Mirrors upstream editor.ts public hooks / flags.
	OnSubmit      func(string)
	OnChange      func(string)
	DisableSubmit bool
	// contains filtered or unexported fields
}

Editor is a multi-line text input with undo/kill-ring support.

func NewEditor

func NewEditor() *Editor

func (*Editor) AcceptAutocomplete

func (e *Editor) AcceptAutocomplete(done func(bool))

AcceptAutocomplete reports whether an accepted slash-name completion submits. Remote completion waits off-loop and calls done only after applying on the owner loop.

func (*Editor) AddToHistory

func (e *Editor) AddToHistory(text string)

AddToHistory trims JavaScript whitespace and adds a submitted prompt for Up/Down navigation. It skips empty strings and consecutive duplicates and retains at most 100 entries.

func (*Editor) ApplyRemoteChange

func (e *Editor) ApplyRemoteChange(text, expanded string)

ApplyRemoteChange mirrors the remote's text (its onChange) and the same text with paste markers expanded.

func (*Editor) AutocompleteAccept

func (e *Editor) AutocompleteAccept() (submit bool)

AutocompleteAccept applies the currently-selected suggestion. Returns submit=true iff the host should now submit the editor (mirrors upstream editor.ts:644: Enter on a slash-name prefix inserts and falls through to submit).

func (*Editor) AutocompleteCancel

func (e *Editor) AutocompleteCancel()

AutocompleteCancel dismisses the popup without applying.

func (*Editor) AutocompleteMaxVisible

func (e *Editor) AutocompleteMaxVisible() int

AutocompleteMaxVisible returns the maximum number of autocomplete rows.

func (*Editor) AutocompleteMove

func (e *Editor) AutocompleteMove(delta int)

AutocompleteMove moves the selection with keyboard-style wraparound. Mouse callers clamp their target before invoking it.

func (*Editor) AutocompleteOpen

func (e *Editor) AutocompleteOpen() bool

AutocompleteOpen reports whether the popup is currently visible. Used by the host (interactive.go) to gate Esc/Enter handling.

func (*Editor) AutocompleteProvider

func (e *Editor) AutocompleteProvider() AutocompleteProvider

AutocompleteProvider returns the local base captured by extension wrapper factories.

func (*Editor) Clear

func (e *Editor) Clear()

Clear resets the editor.

func (*Editor) ClearPastes

func (e *Editor) ClearPastes()

ClearPastes drops the compact-paste store. Callers that consume the editor's text via GetExpandedText (e.g. submit) should call this after expanding so subsequent edits don't re-expand stale markers. Mirrors upstream submitValue() resetting pastes + pasteCounter.

func (*Editor) GetCursor

func (e *Editor) GetCursor() EditorCursor

GetCursor returns the logical cursor position in JavaScript string units.

func (*Editor) GetExpandedText

func (e *Editor) GetExpandedText() string

GetExpandedText returns the editor content with any compact paste markers (`[paste #N +K lines]` / `[paste #N M chars]`) expanded back to their stored content. Mirrors upstream editor.ts::getExpandedText (.upstream/v0.69.0/packages/tui/src/components/editor.ts:929).

func (*Editor) GetLines

func (e *Editor) GetLines() []string

GetLines returns a defensive copy of the editor's logical lines.

func (*Editor) HandleInput

func (e *Editor) HandleInput(data string)

func (*Editor) HandleMouse

func (e *Editor) HandleMouse(event TuiMouseEvent) *TuiMouseDispatchResult

HandleMouse activates autocomplete rows and positions the editor cursor on a synthesized left click. Press, drag, and release remain unhandled so the alternate-screen renderer can own text selection. Mirrors upstream Editor.handleMouse. Autocomplete clicks retain the pressed item across scrolling.

func (*Editor) InsertTextAtCursor

func (e *Editor) InsertTextAtCursor(text string)

InsertTextAtCursor inserts normalized single- or multi-line text as one undoable edit.

func (*Editor) Invalidate

func (i *Editor) Invalidate()

func (*Editor) IsBashMode

func (e *Editor) IsBashMode() bool

IsBashMode reports whether the buffer is in bash-prefix mode (first non-whitespace char is `!`). Used to switch the editor border color and to suppress slash-autocomplete in this state.

func (*Editor) IsDirty

func (e *Editor) IsDirty() bool

IsDirty reports whether the editor's rendered lines changed since the last consume. The embedded status indicator is animated and relabelled by its owner (spinner ticks, working message, retry countdown) without touching the editor, so its own dirty flag counts too; otherwise the per-child render cache would keep the old border row until a keystroke dirtied the editor.

func (*Editor) IsRemote

func (e *Editor) IsRemote() bool

IsRemote reports whether an extension's editor component stands in for the editor.

func (*Editor) MaxVisibleLines

func (e *Editor) MaxVisibleLines() int

MaxVisibleLines returns the current visible-line cap (mostly for tests).

func (*Editor) NeedsRedraw

func (e *Editor) NeedsRedraw() bool

NeedsRedraw consumes the editor's and the embedded indicator's dirty flags.

func (*Editor) PaddingX

func (e *Editor) PaddingX() int

PaddingX returns the editor's horizontal content padding.

func (*Editor) RefreshAutocomplete

func (e *Editor) RefreshAutocomplete()

RefreshAutocomplete queries the provider again for the current buffer, for a provider whose answer arrived after the keystroke that asked for it.

func (*Editor) Remote

func (e *Editor) Remote() EditorRemote

Remote returns the installed remote, or nil.

func (*Editor) Render

func (e *Editor) Render(width int) []string

func (*Editor) SetAsyncApply

func (e *Editor) SetAsyncApply(schedule func(func()))

SetAsyncApply installs a scheduler that runs the given closure on the host's main loop (single-threaded with keystroke handling). The editor uses it to apply async suggestion results without mutating its lock-free state from a worker goroutine. When unset, results are applied inline on the worker (single-threaded callers / tests only).

func (*Editor) SetAsyncAutocomplete

func (e *Editor) SetAsyncAutocomplete(provider *AsyncAutocompleteProvider, lifetime context.Context, start func(func()), input func(AutocompleteWork), report func(error))

SetAsyncAutocomplete selects a complete provider, not an additive suggestion source. start owns query workers; input owns ordered completion workers.

func (*Editor) SetAutocomplete

func (e *Editor) SetAutocomplete(p AutocompleteProvider)

SetAutocomplete replaces the provider and cancels pending completion without querying. The host rebuilds extension wrappers through its change callback.

func (*Editor) SetAutocompleteChanged

func (e *Editor) SetAutocompleteChanged(changed func(AutocompleteProvider))

SetAutocompleteChanged binds the owner's provider rebuild operation.

func (*Editor) SetAutocompleteMaxVisible

func (e *Editor) SetAutocompleteMaxVisible(maxVisible int)

SetAutocompleteMaxVisible changes the autocomplete row limit.

func (*Editor) SetAutocompleteTaskOwner

func (e *Editor) SetAutocompleteTaskOwner(ctx context.Context, start func(func()), report func(error))

SetAutocompleteTaskOwner binds the lifetime, joined worker launcher and owner-loop error reporter for native queries.

func (*Editor) SetFocused

func (e *Editor) SetFocused(focused bool)

SetFocused records whether the editor holds TUI focus; only a focused editor emits the hardware-cursor marker.

func (*Editor) SetMaxVisibleLines

func (e *Editor) SetMaxVisibleLines(n int)

SetMaxVisibleLines updates the editor's maximum visible visual-line count. Mirrors upstream editor.ts maxVisibleLines (set from `max(5, floor(terminalRows * 0.3))` on resize). Clamped to ≥ 1.

func (*Editor) SetPaddingX

func (e *Editor) SetPaddingX(padding int)

SetPaddingX changes the editor's horizontal content padding.

func (*Editor) SetRemote

func (e *Editor) SetRemote(remote EditorRemote)

SetRemote installs remote in place of the editor's own editing, or with nil restores it. The mirrored text becomes the editor's text.

func (*Editor) SetRemoteFrame

func (e *Editor) SetRemoteFrame(lines []string, width int, wantsKeyRelease bool)

SetRemoteFrame records the remote's latest render output for the terminal width it was laid out for.

func (*Editor) SetText

func (e *Editor) SetText(text string)

SetText normalizes and replaces the document, resets paste/typing state, records a changed document for undo, and cancels completion without querying.

func (*Editor) SetWorkingStatusIndicator

func (e *Editor) SetWorkingStatusIndicator(indicator *StatusIndicator)

SetWorkingStatusIndicator selects the status displayed by an opted-in editor.

func (*Editor) Text

func (e *Editor) Text() string

Text returns the editor content as a single string.

func (*Editor) WantsKeyRelease

func (e *Editor) WantsKeyRelease() bool

WantsKeyRelease reports the remote component's wantsKeyRelease; the editor's own editing takes no key releases.

type EditorCursor

type EditorCursor struct {
	Line int
	Col  int
}

EditorCursor is a logical line and UTF-16 column, not a terminal-cell position.

type EditorRemote

type EditorRemote interface {
	// Input delivers one keystroke to the component's handleInput.
	Input(data string)
	SetText(text string)
	InsertTextAtCursor(text string)
	AddToHistory(text string)
	// Mouse delivers a left click, its row relative to the component's
	// first row, to the component's handleMouse.
	Mouse(event TuiMouseEvent)
	// StateChanged reports that the editor's padding, autocomplete size,
	// focus or thinking level changed, which the component mirrors.
	StateChanged()
}

EditorRemote is an extension's editor component standing in for the editor (Pi's ctx.ui.setEditorComponent). Pi replaces its editor with the component and routes to it everything it routes to the editor; with a remote installed the editor does the same: it forwards keystrokes and the host's text operations to the remote, shows the remote's frames, and mirrors the remote's text so the host reads it as it would its own.

type ExtensionEditorComponent

type ExtensionEditorComponent struct {
	// contains filtered or unexported fields
}

Ports packages/coding-agent/src/modes/interactive/components/extension-editor.ts ExtensionEditorComponent wraps a fresh Editor with bordered extension-editor chrome, matching upstream's layout exactly.

func NewExtensionEditorComponent

func NewExtensionEditorComponent(title, prefill string) *ExtensionEditorComponent

NewExtensionEditorComponent creates the editor-slot extension editor. prefill pre-populates the editor content.

func (*ExtensionEditorComponent) Cancelled

func (c *ExtensionEditorComponent) Cancelled() bool

Cancelled reports whether the user pressed Esc/Ctrl+C.

func (*ExtensionEditorComponent) Done

func (c *ExtensionEditorComponent) Done() bool

Done reports whether the user submitted or cancelled.

func (*ExtensionEditorComponent) HandleInput

func (c *ExtensionEditorComponent) HandleInput(data string)

HandleInput processes key events. Esc/Ctrl+C cancels; everything else is forwarded to the underlying Editor (which calls OnSubmit on Enter, handles Shift+Enter/Ctrl+J as newline).

func (*ExtensionEditorComponent) Invalidate

func (i *ExtensionEditorComponent) Invalidate()

func (*ExtensionEditorComponent) IsDirty

func (i *ExtensionEditorComponent) IsDirty() bool

func (*ExtensionEditorComponent) NeedsRedraw

func (i *ExtensionEditorComponent) NeedsRedraw() bool

func (*ExtensionEditorComponent) Render

func (c *ExtensionEditorComponent) Render(width int) []string

Render mirrors upstream ExtensionEditorComponent layout:

DynamicBorder + Spacer + accent(title) indented 1 + Spacer +
Editor (with its own internal dashed borders) + Spacer +
hint line indented 1 + Spacer + DynamicBorder.

func (*ExtensionEditorComponent) SetDescription

func (c *ExtensionEditorComponent) SetDescription(description string)

SetDescription sets optional explanatory text shown between the title and the editor. Mirrors upstream ExtensionEditorOptions.description.

func (*ExtensionEditorComponent) SetExternalEditor

func (c *ExtensionEditorComponent) SetExternalEditor(open func(string, func(string)))

SetExternalEditor binds the terminal owner's asynchronous external-editor handoff. A successful completion updates the buffer without submitting the dialog.

func (*ExtensionEditorComponent) Value

func (c *ExtensionEditorComponent) Value() string

Value returns the submitted text (empty if cancelled).

type ExtensionInputComponent

type ExtensionInputComponent struct {
	// contains filtered or unexported fields
}

ExtensionInputComponent wraps a bare TextInput with extension-style chrome.

func NewExtensionInputComponent

func NewExtensionInputComponent(title, placeholder string) *ExtensionInputComponent

NewExtensionInputComponent creates the editor-slot extension input wrapper. Placeholder is accepted for API parity; upstream currently ignores it.

func (*ExtensionInputComponent) Cancel

func (e *ExtensionInputComponent) Cancel()

Cancel completes the input as cancelled, as upstream's countdown expiry calls onCancel.

func (*ExtensionInputComponent) Cancelled

func (e *ExtensionInputComponent) Cancelled() bool

Cancelled reports whether the user cancelled the input.

func (*ExtensionInputComponent) Done

func (e *ExtensionInputComponent) Done() bool

Done reports whether the user submitted or cancelled the input.

func (*ExtensionInputComponent) HandleInput

func (e *ExtensionInputComponent) HandleInput(data string)

HandleInput resolves selection actions before delegating text editing to Input. The inner input's submit action does not complete the dialog.

func (*ExtensionInputComponent) Invalidate

func (i *ExtensionInputComponent) Invalidate()

func (*ExtensionInputComponent) IsDirty

func (i *ExtensionInputComponent) IsDirty() bool

func (*ExtensionInputComponent) NeedsRedraw

func (i *ExtensionInputComponent) NeedsRedraw() bool

func (*ExtensionInputComponent) Render

func (e *ExtensionInputComponent) Render(width int) []string

Render mirrors upstream ExtensionInputComponent layout: the title and the key hints are Text(..., 1, 0) children, so they wrap within the width.

func (*ExtensionInputComponent) SetCountdown

func (e *ExtensionInputComponent) SetCountdown(seconds int)

SetCountdown shows the seconds left before the input times out, as upstream's countdown sets the title to `${baseTitle} (${s}s)`.

func (*ExtensionInputComponent) SetText

func (e *ExtensionInputComponent) SetText(s string)

SetText pre-fills the input.

func (*ExtensionInputComponent) Text

func (e *ExtensionInputComponent) Text() string

Text returns the current value.

type ExtensionSelectorComponent

type ExtensionSelectorComponent struct {
	// contains filtered or unexported fields
}

ExtensionSelectorComponent is the editor-slot overlay component extensions and built-in flows use to ask the user to pick from a list of string options.

func NewExtensionSelector

func NewExtensionSelector(title string, options []string, onToggleToolsExpanded ...func()) *ExtensionSelectorComponent

NewExtensionSelector creates a generic selector overlay. The first option is pre-selected. The component does not own its lifecycle - the caller (runEditorSlotExtensionSelector) drives input/render until Done() returns true.

func (*ExtensionSelectorComponent) Cancel

func (e *ExtensionSelectorComponent) Cancel()

Cancel completes the selector as cancelled, as upstream's countdown expiry calls onCancel.

func (*ExtensionSelectorComponent) Cancelled

func (e *ExtensionSelectorComponent) Cancelled() bool

Cancelled reports whether the cancellation action completed the selector.

func (*ExtensionSelectorComponent) Done

func (e *ExtensionSelectorComponent) Done() bool

Done reports whether the user picked an option (or cancelled).

func (*ExtensionSelectorComponent) HandleInput

func (e *ExtensionSelectorComponent) HandleInput(data string)

HandleInput resolves expansion, navigation, confirmation and cancellation in that order. Empty options do not complete the selector.

func (*ExtensionSelectorComponent) Invalidate

func (i *ExtensionSelectorComponent) Invalidate()

func (*ExtensionSelectorComponent) IsDirty

func (i *ExtensionSelectorComponent) IsDirty() bool

func (*ExtensionSelectorComponent) NeedsRedraw

func (i *ExtensionSelectorComponent) NeedsRedraw() bool

func (*ExtensionSelectorComponent) Render

func (e *ExtensionSelectorComponent) Render(width int) []string

Render mirrors upstream extension-selector.ts, whose rows are Text(…, 1, 0) children between Spacer(1) and DynamicBorder rows:

DynamicBorder + Spacer + accent(bold(title)) + [Spacer + description] +
Spacer + one Text per option ("→ " prefix on selected) + Spacer +
navigate/select/cancel hint + Spacer + DynamicBorder.

Every Text wraps within one cell of padding on each side and pads to width, so no row is wider than the render width.

func (*ExtensionSelectorComponent) SelectedIndex

func (e *ExtensionSelectorComponent) SelectedIndex() int

SelectedIndex returns the index of the selected option, or -1 if cancelled.

func (*ExtensionSelectorComponent) SelectedValue

func (e *ExtensionSelectorComponent) SelectedValue() string

SelectedValue returns the selected option string, or "" if cancelled.

func (*ExtensionSelectorComponent) SetCountdown

func (e *ExtensionSelectorComponent) SetCountdown(seconds int)

SetCountdown shows the seconds left before the selector times out, as upstream's countdown sets the title to `${baseTitle} (${s}s)`.

func (*ExtensionSelectorComponent) SetDescription

func (e *ExtensionSelectorComponent) SetDescription(description string)

SetDescription sets optional explanatory text shown between the title and the options. Mirrors upstream ExtensionSelectorOptions.description.

type FilterableList

type FilterableList struct {
	Title  string
	Labels []string // display label per item

	// EnableSearch controls whether the upstream-style search input row is
	// rendered and whether printable input edits the filter. Default: true.
	// Settings submenus use false to mirror upstream SelectList-based menus.
	EnableSearch bool

	// Descriptions, when non-nil and width allows, render in a second
	// column to the right of each label. Mirrors upstream
	// select-list.ts SelectItem.description handling. Length should
	// match Labels; missing entries render as empty.
	Descriptions []string

	// MinPrimaryColumnWidth / MaxPrimaryColumnWidth bound the
	// label column when descriptions render. Mirrors upstream
	// SelectListLayoutOptions. Defaults to upstream's 32 cells.
	MinPrimaryColumnWidth int
	MaxPrimaryColumnWidth int

	// TruncatePrimary overrides primary-column truncation. Its output is still
	// clipped to MaxWidth, matching upstream SelectListLayoutOptions.
	TruncatePrimary func(context SelectListTruncatePrimaryContext) string

	// MaxVisible bounds the visible window. Mirrors upstream
	// SelectList.maxVisible. Defaults to 20.
	MaxVisible int
	// contains filtered or unexported fields
}

FilterableList is a modal selector. After Done()==true callers inspect SelectedIndex (-1 on cancel) or Cancelled().

func NewFilterableList

func NewFilterableList(title string, labels []string) *FilterableList

NewFilterableList creates a list with the given labels and an optional title shown in the overlay border.

func (*FilterableList) Cancelled

func (f *FilterableList) Cancelled() bool

Cancelled reports whether the user pressed Esc.

func (*FilterableList) CursorIndex

func (f *FilterableList) CursorIndex() int

CursorIndex returns the current index within the filtered view.

func (*FilterableList) Done

func (f *FilterableList) Done() bool

Done reports whether the user has confirmed or cancelled.

func (*FilterableList) FilterText

func (f *FilterableList) FilterText() string

FilterText returns the current filter query typed by the user. Used by ShowExtensionEditor to retrieve free-text input.

func (*FilterableList) HandleInput

func (f *FilterableList) HandleInput(data string)

HandleInput updates the filter or moves the cursor.

func (*FilterableList) HandleMouse

func (f *FilterableList) HandleMouse(event TuiMouseEvent) *TuiMouseDispatchResult

HandleMouse selects visible rows on press, activates them on click, and moves selection one item per wheel report without changing selection on hover. Mirrors upstream SelectList.handleMouse.

func (*FilterableList) Invalidate

func (i *FilterableList) Invalidate()

func (*FilterableList) IsDirty

func (i *FilterableList) IsDirty() bool

func (*FilterableList) NeedsRedraw

func (i *FilterableList) NeedsRedraw() bool

func (*FilterableList) Render

func (f *FilterableList) Render(width int) []string

Render draws the optional filter input and SelectList rows, with unpadded muted status rows.

func (*FilterableList) SelectedIndex

func (f *FilterableList) SelectedIndex() int

SelectedIndex returns the chosen index into Labels, or -1 on cancel.

func (*FilterableList) SetCursor

func (f *FilterableList) SetCursor(idx int)

SetCursor positions the cursor on a specific filtered-view row.

type Focusable

type Focusable interface {
	SetFocused(focused bool)
}

Focusable is pi-tui's Focusable: a component that renders differently while it holds TUI focus, as a focused Editor or TextInput emits the hardware-cursor marker. Go interfaces carry no fields, so the TUI sets the flag through SetFocused instead of assigning `focused`.

type ForcefulAutocompleteProvider

type ForcefulAutocompleteProvider interface {
	GetSuggestionsForce(lines []string, cursorLine, cursorCol int) *AutocompleteSuggestions
}

ForcefulAutocompleteProvider is an optional extension implemented by providers that support "force" file-completion, triggered by Tab when the popup is closed and the buffer is not in a slash-command-name context. Mirrors upstream `AutocompleteProvider.getSuggestions` `{force: true}` branch (autocomplete.ts:281).

type FuzzyMatch

type FuzzyMatch struct {
	Matches bool
	Score   float64
}

FuzzyMatch is the result of matching a single query against a text. Matches=false means the query does not appear in text in order.

func FuzzyMatchScore

func FuzzyMatchScore(query, text string) FuzzyMatch

FuzzyMatchScore matches an ordered, case-insensitive UTF-16 subsequence and returns Pi's lower-is-better score.

type HStack

type HStack struct {
	*Stack
}

HStack ports pi-tui's HStack: children laid out left to right with flexbox widths and vertical alignment.

func NewHStack

func NewHStack(children []StackChild, options StackOptions) *HStack

NewHStack constructs a horizontal stack.

func (HStack) Invalidate

func (i HStack) Invalidate()

func (HStack) IsDirty

func (i HStack) IsDirty() bool

func (HStack) NeedsRedraw

func (i HStack) NeedsRedraw() bool

func (*HStack) Render

func (h *HStack) Render(width int) []string

Render ports upstream HStack.render.

type IdleStatus

type IdleStatus struct{}

IdleStatus reserves the standalone loader's two rows after clearing it.

func (*IdleStatus) Invalidate

func (*IdleStatus) Invalidate()

func (*IdleStatus) Render

func (*IdleStatus) Render(width int) []string

type Image

type Image struct {
	Base64Data string
	MIMEType   string
	Dimensions ImageDimensions
	Theme      ImageTheme
	Options    ImageOptions
	// contains filtered or unexported fields
}

func NewImage

func NewImage(base64Data, mimeType string, options ImageOptions, dimensions *ImageDimensions) *Image

func (*Image) GetImageID

func (i *Image) GetImageID() int

func (*Image) Invalidate

func (i *Image) Invalidate()

func (*Image) IsDirty

func (i *Image) IsDirty() bool

func (*Image) NeedsRedraw

func (i *Image) NeedsRedraw() bool

func (*Image) Render

func (i *Image) Render(width int) []string

Render returns image protocol rows or a width-bounded, styled fallback.

type ImageBlock

type ImageBlock struct {
	Data     string // base64-encoded image data
	MIMEType string
}

ImageBlock describes one image from a tool result for rendering.

type ImageCellSize

type ImageCellSize struct {
	Columns int
	Rows    int
}

func CalculateImageCellSize

func CalculateImageCellSize(imageDimensions ImageDimensions, maxWidthCells int, maxHeightCells int, dims CellDimensions) ImageCellSize

type ImageDimensions

type ImageDimensions struct {
	WidthPx  int
	HeightPx int
}

func GetGIFDimensions

func GetGIFDimensions(base64Data string) *ImageDimensions

func GetImageDimensions

func GetImageDimensions(base64Data, mimeType string) *ImageDimensions

func GetJPEGDimensions

func GetJPEGDimensions(base64Data string) *ImageDimensions

func GetPNGDimensions

func GetPNGDimensions(base64Data string) *ImageDimensions

func GetWebPDimensions

func GetWebPDimensions(base64Data string) *ImageDimensions

type ImageOptions

type ImageOptions struct {
	MaxWidthCells  int
	MaxHeightCells int
	Filename       string
	ImageID        int
}

type ImageProtocol

type ImageProtocol string
const (
	ImageProtocolKitty  ImageProtocol = "kitty"
	ImageProtocolITerm2 ImageProtocol = "iterm2"
)

type ImageRenderOptions

type ImageRenderOptions struct {
	MaxWidthCells       int
	MaxHeightCells      int
	PreserveAspectRatio *bool // nil preserves the aspect ratio
	ImageID             int
	Name                string
	MoveCursor          *bool // nil permits Kitty cursor movement; false emits C=1
}

type ImageTheme

type ImageTheme struct {
	FallbackColor func(string) string
}

type InputHandler

type InputHandler interface {
	HandleInput(data string)
}

InputHandler is implemented by components that want keyboard events.

type InputOptions

type InputOptions struct {
	Prompt           *string
	Placeholder      string
	PlaceholderStyle func(string) string
}

InputOptions mirrors InputOptions. Nil Prompt selects "> "; nil PlaceholderStyle leaves text unstyled.

type KeyReleaseReceiver

type KeyReleaseReceiver interface {
	WantsKeyRelease() bool
}

KeyReleaseReceiver is implemented by components that want Kitty key-release events delivered to HandleInput. Mirrors upstream's optional Component.wantsKeyRelease (tui.ts:40), which defaults to false. Upstream opts in only for games (the space-invaders and doom-overlay example extensions), which need key-up to stop movement.

type KeybindingPlatform

type KeybindingPlatform string

KeybindingPlatform selects a column of per-platform default keys. Upstream branches its default table on process.platform and on useWindowsKeybindings() (coding-agent core/keybindings.ts); these four values name every combination the table distinguishes. The values match the columns of the behavior-input inventory.

const (
	KeybindingPlatformDarwin   KeybindingPlatform = "darwin"
	KeybindingPlatformLinux    KeybindingPlatform = "linux"
	KeybindingPlatformLinuxWSL KeybindingPlatform = "linuxWsl"
	KeybindingPlatformWin32    KeybindingPlatform = "win32"
)

func HostKeybindingPlatform

func HostKeybindingPlatform() KeybindingPlatform

HostKeybindingPlatform returns the platform column for this process.

func KeybindingPlatformFor

func KeybindingPlatformFor(goos string, getenv func(string) string) KeybindingPlatform

KeybindingPlatformFor maps a runtime.GOOS value and an environment to the default-key column. Platforms upstream does not name (freebsd, etc.) take the Linux column, as process.platform comparisons fall through there.

func (KeybindingPlatform) UsesWindowsKeybindings

func (p KeybindingPlatform) UsesWindowsKeybindings() bool

UsesWindowsKeybindings reports whether the platform takes Windows defaults.

type KillRing

type KillRing struct {
	// contains filtered or unexported fields
}

KillRing is an Emacs-style kill/yank ring buffer.

Tracks killed (deleted) text entries. Consecutive kills accumulate into a single entry via Push(accumulate=true). Supports yank (paste most recent) and yank-pop (cycle through older entries via Rotate).

Mirrors upstream kill-ring.ts.

func (*KillRing) Len

func (k *KillRing) Len() int

Len returns the number of entries in the ring.

func (*KillRing) Length

func (k *KillRing) Length() int

Length mirrors upstream's `get length()` surface.

func (*KillRing) Peek

func (k *KillRing) Peek() string

Peek returns the most recent entry without modifying the ring. Returns "" if the ring is empty.

func (*KillRing) Push

func (k *KillRing) Push(text string, prepend bool, accumulate bool)

Push adds text to the kill ring.

  • prepend: when accumulating, prepend text (backward deletion) vs append (forward).
  • accumulate: merge with the most recent entry instead of creating a new one.

Empty text is a no-op.

func (*KillRing) Rotate

func (k *KillRing) Rotate()

Rotate moves the last entry to the front (for yank-pop cycling). No-op if the ring has fewer than 2 entries.

type KittyImageConversion

type KittyImageConversion struct {
	Index    int
	Data     string
	MimeType string
}

KittyImageConversion names one tool-result image that needs a PNG conversion before the Kitty graphics protocol can display it.

type KittyImageMetadata

type KittyImageMetadata struct {
	ImageID  int
	Columns  int
	Rows     int
	WidthPx  int
	HeightPx int
}

KittyImageMetadata is the public metadata for a registered Kitty image.

func GetKittyImageMetadata

func GetKittyImageMetadata(line string) *KittyImageMetadata

GetKittyImageMetadata returns the public metadata for the Kitty image on a rendered line, or nil if the line carries no registered image. Mirrors upstream getKittyImageMetadata.

type KittyImagePlacement

type KittyImagePlacement struct {
	ImageID                int
	TransmissionGeneration int
	TransmissionBytes      int
	EstimatedDecodedBytes  int
	Sequence               string
	ReplacementLine        string
}

KittyImagePlacement is a placement-only command derived from a transmitted Kitty image line. Mirrors upstream KittyImagePlacement.

func GetKittyImagePlacement

func GetKittyImagePlacement(line string) (KittyImagePlacement, bool)

GetKittyImagePlacement builds a placement-only command for an image line emitted by RenderImage, so the alt-screen renderer can re-place an already transmitted image without re-uploading its data. Returns ok=false for a line with no Kitty command or no registered metadata. Mirrors upstream getKittyImagePlacement.

type LayoutBox

type LayoutBox struct {
	Component          Component
	Rect               LayoutRect
	Clip               LayoutRect
	Children           []*LayoutBox
	Parent             *LayoutBox
	Lines              []string
	LineOffset         int
	ScrollView         *ScrollView
	ScrollContentLines []string
	Layer              int
}

LayoutBox is one node in the laid-out tree. Lines (non-nil) marks a leaf whose rendered lines paint directly; ScrollView/ScrollContentLines mark a scroll viewport. Optional upstream fields are zero values here.

func GetLayoutBoxesAt

func GetLayoutBoxesAt(frame LayoutFrame, x, y int) []*LayoutBox

GetLayoutBoxesAt returns the visual hit path at a point, from the deepest component to the layout root, highest layer first. Mirrors upstream getLayoutBoxesAt.

func GetScrollViewBox

func GetScrollViewBox(frame LayoutFrame, scrollView *ScrollView) *LayoutBox

GetScrollViewBox finds the layout box wrapping a given ScrollView, or nil. Mirrors upstream getScrollViewBox.

type LayoutComponent

type LayoutComponent interface {
	Component
	LayoutNode() LayoutNode
}

LayoutComponent is a Component that exposes a layout node. It ports upstream's LayoutComponent interface; the LAYOUT_NODE symbol method becomes LayoutNode().

type LayoutFrame

type LayoutFrame struct {
	Root              *LayoutBox
	Width             int
	Height            int
	Lines             []string
	PrimaryScrollView *ScrollView
}

LayoutFrame is a fully laid-out and painted viewport.

func RenderLayoutFrame

func RenderLayoutFrame(root Component, width, height int, requestRender func()) LayoutFrame

RenderLayoutFrame lays out a component tree into a width×height viewport and paints it. Mirrors upstream renderLayoutFrame.

type LayoutNode

type LayoutNode interface {
	// contains filtered or unexported methods
}

LayoutNode is the sealed union of layout node kinds (upstream's StackLayoutNode | ScrollLayoutNode discriminated union). Only the two node types in this package implement it.

type LayoutRect

type LayoutRect struct {
	X      int
	Y      int
	Width  int
	Height int
}

LayoutRect is an axis-aligned rectangle in terminal cells.

type LayoutViewport

type LayoutViewport struct {
	Width  int
	Height int
}

LayoutViewport is the available render area a stack entry's visibility predicate is evaluated against.

type Loader

type Loader struct {
	Message           string
	Frame             int
	Frames            []string
	SpinnerColor      string // ANSI fg escape for spinner (optional)
	MessageColor      string // ANSI fg escape for message (optional)
	IndicatorVerbatim bool   // extension frames include their own formatting
	// contains filtered or unexported fields
}

Loader shows an animated spinner with a message. Matches upstream Loader which extends Text(paddingX=1, paddingY=0).

func NewLoader

func NewLoader(message string) *Loader

func NewStyledLoader

func NewStyledLoader(spinnerColor, messageColor, message string, frames []string) *Loader

NewStyledLoader creates a Loader with ANSI color escapes.

func (*Loader) Invalidate

func (i *Loader) Invalidate()

func (*Loader) IsDirty

func (i *Loader) IsDirty() bool

func (*Loader) NeedsRedraw

func (i *Loader) NeedsRedraw() bool

func (*Loader) Render

func (l *Loader) Render(width int) []string

Render produces ["", paddedLine] matching upstream Loader.render(width) which returns ["", ...super.render(width)] where super is Text(paddingX=1).

func (*Loader) SetIndicator

func (l *Loader) SetIndicator(frames []string, verbatim bool)

SetIndicator replaces the animation frames, restarts at the first frame, and marks the loader for repaint. nil frames select DefaultSpinnerFrames and an empty slice hides the indicator. verbatim renders caller-formatted frames without the spinner color. Mirrors upstream Loader.setIndicator; the owner that ticks the loader applies the frame interval.

func (*Loader) SetMessage

func (l *Loader) SetMessage(message string)

SetMessage replaces the message and marks the loader for repaint. Mirrors upstream Loader.setMessage, which updates the text and requests a render.

func (*Loader) Tick

func (l *Loader) Tick()

Tick advances the spinner one frame.

type LoginDialog

type LoginDialog struct {
	// contains filtered or unexported fields
}

LoginDialog renders provider authentication in the editor slot. The caller owns I/O and feeds prompt, progress and completion events.

func NewLoginDialog

func NewLoginDialog(providerName string, onCancel func(), titleOverride ...string) *LoginDialog

NewLoginDialog creates a provider dialog with PiG's configurable input privacy default enabled.

func (*LoginDialog) Cancelled

func (d *LoginDialog) Cancelled() bool

func (*LoginDialog) Done

func (d *LoginDialog) Done() bool

func (*LoginDialog) HandleInput

func (d *LoginDialog) HandleInput(data string)

HandleInput routes editing to the active prompt and cancels with the configured selector binding.

func (*LoginDialog) Invalidate

func (i *LoginDialog) Invalidate()

func (*LoginDialog) IsDirty

func (i *LoginDialog) IsDirty() bool

func (*LoginDialog) NeedsRedraw

func (i *LoginDialog) NeedsRedraw() bool

func (*LoginDialog) Redact

func (d *LoginDialog) Redact(text string) string

Redact removes masked prompt values from authentication errors emitted after the dialog closes.

func (*LoginDialog) Render

func (d *LoginDialog) Render(width int) []string

Render returns Pi's dialog layout, adding the preview, count and hint only for masked prompts.

func (*LoginDialog) SetMaskSecretInput

func (d *LoginDialog) SetMaskSecretInput(enabled bool)

SetMaskSecretInput selects masking for subsequent secret prompts. Already masked history stays masked.

func (*LoginDialog) ShowAuth

func (d *LoginDialog) ShowAuth(url, instructions string)

ShowAuth replaces the dialog content with a URL and optional instructions.

func (*LoginDialog) ShowDetails

func (d *LoginDialog) ShowDetails(lines []string)

ShowDetails replaces the content with informational lines before a provider prompt.

func (*LoginDialog) ShowDeviceCode

func (d *LoginDialog) ShowDeviceCode(verificationURI, userCode string)

ShowDeviceCode replaces the dialog content with a verification URL and the user code, as Pi's showDeviceCode does.

func (*LoginDialog) ShowInfo

func (d *LoginDialog) ShowInfo(message string, links []AuthInfoLink, showCloseHint bool)

ShowInfo appends provider instructions and links before the next prompt.

func (*LoginDialog) ShowInput

func (d *LoginDialog) ShowInput(prompt, placeholder string) <-chan string

ShowInput appends a text prompt. Its returned channel delivers the original submitted value and closes on cancellation.

func (*LoginDialog) ShowManualInput

func (d *LoginDialog) ShowManualInput(prompt string) <-chan string

ShowManualInput appends a dim callback-code prompt with a cancel-only hint. Its returned channel delivers the submitted value and closes on cancellation.

func (*LoginDialog) ShowProgress

func (d *LoginDialog) ShowProgress(msg string)

ShowProgress appends an authentication diagnostic, redacting masked prompt values.

func (*LoginDialog) ShowSecretInput

func (d *LoginDialog) ShowSecretInput(prompt, placeholder string) <-chan string

ShowSecretInput honors the configured privacy setting; false uses Pi's ordinary prompt and submitted-text rendering.

func (*LoginDialog) ShowWaiting

func (d *LoginDialog) ShowWaiting(msg string)

ShowWaiting appends a waiting message and cancellation hint.

func (*LoginDialog) Success

func (d *LoginDialog) Success()

Success marks the provider operation complete; the caller restores the editor.

type Markdown

type Markdown struct {
	Content string

	// Transform is an optional display-only rewrite of Content applied at the
	// render width before parsing, mirroring upstream MarkdownOptions.transform
	// (markdown.ts). Used to replace Mermaid code blocks with rendered diagrams.
	// A Transform that reads state outside (Content, width) must report it through
	// TransformState, or the render cache will serve a stale result.
	Transform func(markdown string, width int) string
	// TransformState reports external transform inputs so a retained Markdown component invalidates cached lines when those inputs change without a Content or width change.
	TransformState func() string
	// AsyncTransform rewrites off-loop and withholds new content until the complete rewrite is ready. During replacement it retains only a previously completed frame at the current width.
	AsyncTransform *AsyncMarkdownTransform
	// contains filtered or unexported fields
}

Markdown renders themed text with terminal-cell wrapping, padding and cached display transforms. Ports packages/tui/src/components/markdown.ts.

func NewMarkdown

func NewMarkdown(content string) *Markdown

func NewMarkdownWithOptions

func NewMarkdownWithOptions(content string, paddingX, paddingY int, theme *MarkdownTheme, style *DefaultTextStyle, options *MarkdownOptions) *Markdown

NewMarkdownWithOptions maps the full upstream constructor. NewMarkdown supplies its normal unpadded, active-theme defaults without a Go overload.

func (*Markdown) Dispose

func (m *Markdown) Dispose()

Dispose revokes this component's pending publication and removes its queued transform.

func (*Markdown) Invalidate

func (m *Markdown) Invalidate()

Invalidate reruns the display transform and parser on the next render, even when the source text is unchanged.

func (*Markdown) IsDirty

func (i *Markdown) IsDirty() bool

func (*Markdown) NeedsRedraw

func (i *Markdown) NeedsRedraw() bool

func (*Markdown) Render

func (m *Markdown) Render(width int) []string

func (*Markdown) SetDefaultColor

func (m *Markdown) SetDefaultColor(open string)

SetDefaultColor sets the ANSI foreground applied to ordinary Markdown text tokens. Headings, code, list markers and blockquotes retain their own theme styles. Passing an empty string restores terminal-default foreground and invalidates the cache.

func (*Markdown) SetText

func (m *Markdown) SetText(text string)

SetText replaces source text and invalidates its rendered output.

type MarkdownOptions

type MarkdownOptions struct {
	PreserveOrderedListMarkers bool
	PreserveBackslashEscapes   bool
	Transform                  func(markdown string, availableWidth int) string
	RenderLatex                *bool
}

MarkdownOptions controls source preservation, display transforms and math rendering. Nil RenderLatex selects the upstream default, true.

type MarkdownTheme

type MarkdownTheme struct {
	Heading, Link, LinkUrl, Code, CodeBlock, CodeBlockBorder func(string) string
	Quote, QuoteBorder, Hr, ListBullet                       func(string) string
	Bold, Italic, Strikethrough, Underline                   func(string) string
	HighlightCode                                            func(code, lang string) []string
	CodeBlockIndent                                          *string
}

MarkdownTheme supplies the styling functions used by Markdown. It mirrors packages/tui/src/components/markdown.ts.

type MarkdownTransformQueue

type MarkdownTransformQueue struct {
	// contains filtered or unexported fields
}

MarkdownTransformQueue serializes individual transform generations in render admission order. Each component retains at most one queued replacement in addition to the owner's active callback.

type ModelItem

type ModelItem struct {
	FullID   string // "provider/model-id"
	Name     string // display name
	Provider string
}

ModelItem describes one model in the scoped-models list.

type ModelScope

type ModelScope int

ModelScope discriminates the two views of the picker.

const (
	ModelScopeScoped ModelScope = iota
	ModelScopeAll
)

type ModelSearchItem

type ModelSearchItem struct {
	ID       string
	Provider string
	Name     string
}

ModelSearchItem is the provider, bare id, and optional display name a model search text is built from. Mirrors upstream ModelSearchItem; an empty Name is upstream's absent (or empty) name.

type ModelSelector

type ModelSelector struct {
	Title string
	// contains filtered or unexported fields
}

ModelSelector renders a fuzzy-filtered list of models with a scope-toggle header.

func NewModelSelector

func NewModelSelector(title string, scoped, allReachable []ModelSelectorItem, current string) *ModelSelector

NewModelSelector constructs a picker. scoped contains the session's scoped models; allReachable contains all models with configured auth. current is the current provider-qualified model ID, or empty when none is selected. With no scoped models, the picker starts in all scope and shows the provider hint.

func (*ModelSelector) Cancelled

func (m *ModelSelector) Cancelled() bool

func (*ModelSelector) Done

func (m *ModelSelector) Done() bool

Done / Cancelled / SelectedFQ: modal contract.

func (*ModelSelector) HandleInput

func (m *ModelSelector) HandleInput(data string)

HandleInput mirrors upstream model-selector.ts handleInput: it checks tui.input.tab, tui.select.up, tui.select.down, tui.select.confirm, tui.select.cancel and app.models.save in that order, and passes every other key to the search input before it reapplies the query.

func (*ModelSelector) Invalidate

func (i *ModelSelector) Invalidate()

func (*ModelSelector) IsDirty

func (i *ModelSelector) IsDirty() bool

func (*ModelSelector) NeedsRedraw

func (i *ModelSelector) NeedsRedraw() bool

func (*ModelSelector) Render

func (m *ModelSelector) Render(width int) []string

Render lays out the upstream selector rows (model-selector.ts): top border, scope and hint (or the no-auth warning), search input, model list, scroll position, selected-model name, refresh status, selection hint, and bottom border. Every text row is a Text(..., 0, 0), so long rows wrap to the width.

func (*ModelSelector) Scope

func (m *ModelSelector) Scope() ModelScope

Scope returns the current scope (exposed for tests).

func (*ModelSelector) SelectedAsDefault

func (m *ModelSelector) SelectedAsDefault() bool

SelectedAsDefault reports whether the selection requested persistence via app.models.save.

func (*ModelSelector) SelectedFQ

func (m *ModelSelector) SelectedFQ() string

func (*ModelSelector) SetDefaultModel

func (m *ModelSelector) SetDefaultModel(fq string)

SetDefaultModel marks the settings default model ("<provider>/<id>"), which upstream badges with "· default", sorts after the current model, and matches for a "default" search.

func (*ModelSelector) SetError

func (m *ModelSelector) SetError(text string)

func (*ModelSelector) SetFilter

func (m *ModelSelector) SetFilter(query string)

func (*ModelSelector) SetRefreshSuccess

func (m *ModelSelector) SetRefreshSuccess(text string)

SetRefreshSuccess shows the upstream "Model catalogs refreshed." status in the success color.

func (*ModelSelector) SetStatus

func (m *ModelSelector) SetStatus(text string)

func (*ModelSelector) UpdateModels

func (m *ModelSelector) UpdateModels(models []ModelSelectorItem)

UpdateModels replaces the available snapshot and refreshes scoped model metadata without dropping unavailable scoped entries. It retains the scope and query, reanchors on the current model (or clamps the cursor), then selects the best match when a query is active, like upstream loadModelsFromSnapshot followed by filterModels.

func (*ModelSelector) VisibleCount

func (m *ModelSelector) VisibleCount() int

VisibleCount returns the number of items in the filtered view.

type ModelSelectorItem

type ModelSelectorItem struct {
	Provider string
	ID       string // bare model id (e.g. "gpt-4o")
	// Name is the raw model display name (upstream model.name), empty when
	// the source has none. Search text omits an empty name; the selected-model
	// footer falls back to ID.
	Name string
}

ModelSelectorItem is one row in the picker.

func (ModelSelectorItem) FQ

func (m ModelSelectorItem) FQ() string

FQ returns the "<provider>/<id>" form used for switch dispatch.

type ModifierKey

type ModifierKey string

ModifierKey mirrors upstream native-platform.ts ModifierKey.

const (
	ModifierShift   ModifierKey = "shift"
	ModifierCommand ModifierKey = "command"
	ModifierControl ModifierKey = "control"
	ModifierOption  ModifierKey = "option"
)

type MouseHandler

type MouseHandler interface {
	HandleMouse(event TuiMouseEvent) *TuiMouseDispatchResult
}

MouseHandler is implemented by components with a normalized mouse handler. Mirrors upstream Component.handleMouse.

type MouseRegion

type MouseRegion struct {
	// contains filtered or unexported fields
}

MouseRegion adds mouse handling to an existing component without changing its rendering. Ports pi-tui components/mouse-region.ts.

func NewMouseRegion

func NewMouseRegion(child Component, onMouse MouseRegionHandler) *MouseRegion

NewMouseRegion wraps child with onMouse. Mirrors upstream new MouseRegion.

func (*MouseRegion) HandleMouse

func (r *MouseRegion) HandleMouse(event TuiMouseEvent) *TuiMouseDispatchResult

HandleMouse gives nested mouse-aware children the first chance, then the region's own handler. Mirrors upstream MouseRegion.handleMouse.

func (*MouseRegion) Invalidate

func (r *MouseRegion) Invalidate()

Invalidate invalidates the wrapped child.

func (*MouseRegion) Render

func (r *MouseRegion) Render(width int) []string

Render renders the wrapped child unchanged.

type MouseRegionHandler

type MouseRegionHandler func(event TuiMouseEvent) *TuiMouseEventResult

MouseRegionHandler handles a mouse event that no nested child handled. Mirrors upstream MouseRegionHandler; nil means unhandled.

type NativeClipboard

type NativeClipboard = nativeplatform.NativeClipboard

NativeClipboard is the platform helper's clipboard and optional modifier capabilities. Read methods are blocking Go equivalents of the upstream promises; invoke them off the input/render loop. available=false represents undefined, while a nil value with available=true represents null.

func GetNativeClipboard

func GetNativeClipboard() *NativeClipboard

func GetNativePlatformHelper

func GetNativePlatformHelper() *NativeClipboard

type OAuthProvider

type OAuthProvider struct {
	ID         string // e.g. "github-copilot"
	Name       string // display name
	AuthType   string // "oauth" or "api_key"
	MethodName string
	LoginLabel string

	// Stored indicates auth.json contains a stored credential for this provider.
	Stored bool
	// StoredType is the type of the stored credential when Stored is true.
	StoredType string // "oauth" or "api_key"
	// AuthStatusSource/Label mirror ai.AuthStatus for API-key providers.
	AuthStatusSource string // "", "stored", "environment", "runtime", "fallback", "models_json_key", "models_json_command"
	AuthStatusLabel  string
}

OAuthProvider is one entry in the auth provider selector.

type OAuthSelector

type OAuthSelector struct {
	// contains filtered or unexported fields
}

OAuthSelector renders the bordered provider picker (port of OAuthSelectorComponent in oauth-selector.ts).

func NewOAuthSelector

func NewOAuthSelector(mode string, providers []OAuthProvider, initialSearch ...string) *OAuthSelector

NewOAuthSelector constructs the picker.

func (*OAuthSelector) Cancelled

func (s *OAuthSelector) Cancelled() bool

Cancelled reports whether Esc was pressed.

func (*OAuthSelector) Done

func (s *OAuthSelector) Done() bool

Done reports whether the user selected or cancelled.

func (*OAuthSelector) HandleInput

func (s *OAuthSelector) HandleInput(data string)

HandleInput processes navigation, select, and cancel keys.

func (*OAuthSelector) Invalidate

func (i *OAuthSelector) Invalidate()

func (*OAuthSelector) IsDirty

func (i *OAuthSelector) IsDirty() bool

func (*OAuthSelector) NeedsRedraw

func (i *OAuthSelector) NeedsRedraw() bool

func (*OAuthSelector) Render

func (s *OAuthSelector) Render(width int) []string

Render returns ANSI lines for the bordered overlay.

func (*OAuthSelector) SelectedID

func (s *OAuthSelector) SelectedID() string

SelectedID returns the selected provider ID, or "" on cancel.

func (*OAuthSelector) SelectedProvider

func (s *OAuthSelector) SelectedProvider() OAuthProvider

SelectedProvider returns the selected method, including its auth type in mixed lists.

type OverlayBounds

type OverlayBounds struct {
	Row    int
	Col    int
	Width  int
	Height int
}

OverlayBounds is an overlay's last rendered terminal-relative rectangle. Mirrors upstream OverlayBounds.

type OverlayGeometry

type OverlayGeometry struct {
	Width, Row, Col int
	MaxHeight       int
	HasMaxHeight    bool
}

OverlayGeometry is the resolved placement of an overlay.

func ResolveOverlayGeometry

func ResolveOverlayGeometry(opts OverlayOptions, overlayHeight, termWidth, termHeight int) OverlayGeometry

ResolveOverlayGeometry resolves opts for a component of overlayHeight lines on a termWidth x termHeight screen, using the same resolver the compositor uses. Width is the width the component is rendered at.

type OverlayHandle

type OverlayHandle struct {
	// contains filtered or unexported fields
}

OverlayHandle lets callers control an overlay.

func (*OverlayHandle) Close

func (h *OverlayHandle) Close()

Close permanently removes this overlay.

func (*OverlayHandle) Focus

func (h *OverlayHandle) Focus()

Focus gives an eligible visible overlay keyboard focus.

func (*OverlayHandle) GetBounds

func (h *OverlayHandle) GetBounds() (OverlayBounds, bool)

GetBounds returns the most recent rendered bounds of a visible overlay. Mirrors upstream OverlayHandle.getBounds.

func (*OverlayHandle) Hide

func (h *OverlayHandle) Hide()

Hide permanently removes this overlay, matching Pi's OverlayHandle.hide.

func (*OverlayHandle) IsFocused

func (h *OverlayHandle) IsFocused() bool

IsFocused reports whether this overlay currently has focus.

func (*OverlayHandle) IsHidden

func (h *OverlayHandle) IsHidden() bool

IsHidden reports the mounted overlay's explicit hidden state.

func (*OverlayHandle) SetHidden

func (h *OverlayHandle) SetHidden(hidden bool)

SetHidden changes visibility without removing the overlay.

func (*OverlayHandle) Unfocus

func (h *OverlayHandle) Unfocus()

Unfocus restores focus to the next eligible component. It keeps its zero-argument signature so that a value assigned to interface{ Unfocus() } keeps compiling; UnfocusWith is upstream OverlayHandle.unfocus(options).

func (*OverlayHandle) UnfocusWith

func (h *OverlayHandle) UnfocusWith(options OverlayUnfocusOptions)

UnfocusWith releases focus to options' explicit target, which may be nil, instead of the next visible capturing overlay or previous target. Mirrors upstream OverlayHandle.unfocus(options).

type OverlayMarginSpec

type OverlayMarginSpec struct {
	Top, Right, Bottom, Left int
}

OverlayMarginSpec mirrors upstream OverlayMargin.

type OverlayOptions

type OverlayOptions struct {

	// WidthFraction, HeightFraction, and Title configure the private built-in
	// modal wrapper.
	WidthFraction  float64
	HeightFraction float64
	Title          string
	// contains filtered or unexported fields
}

OverlayOptions controls the size/position of an overlay.

type OverlaySpec

type OverlaySpec struct {
	Width     *OverlayValue
	MinWidth  *int
	MaxHeight *OverlayValue
	Anchor    string
	OffsetX   int
	OffsetY   int
	Row       *OverlayValue
	Col       *OverlayValue
	// Margin is the per-edge form; MarginAll the upstream numeric form.
	Margin       *OverlayMarginSpec
	MarginAll    *int
	NonCapturing bool
}

OverlaySpec is the serialisable subset of upstream pi-tui OverlayOptions (everything except the visible callback). It lets callers outside this package, such as the subprocess extension bridge, open a component-framed overlay whose geometry resolves exactly like upstream showOverlay.

func (OverlaySpec) Options

func (s OverlaySpec) Options() OverlayOptions

Options converts the spec into OverlayOptions. The result carries no modal title or fractions, so OpenOverlay mounts the component without a frame.

type OverlayUnfocusOptions

type OverlayUnfocusOptions struct {
	Target Component
}

OverlayUnfocusOptions mirrors upstream OverlayUnfocusOptions: an explicit focus target, which may be nil, used after this overlay releases focus.

type OverlayValue

type OverlayValue struct {
	Value   float64
	Percent bool
	// Invalid preserves a supplied but malformed size, distinct from omission.
	Invalid bool
}

OverlayValue is a serialisable upstream SizeValue: an absolute cell count or, when Percent is set, a percentage of the terminal dimension.

type ParsedSkillBlock

type ParsedSkillBlock struct {
	Name    string
	Content string
}

ParsedSkillBlock holds the parsed skill invocation data. Mirrors upstream's ParsedSkillBlock.

type PlatformKeys

type PlatformKeys struct {
	Other    []string
	Darwin   []string
	Windows  []string
	Win32    []string
	LinuxWSL []string
}

PlatformKeys holds default keys that differ by platform. Other applies unless a narrower field is non-nil. Windows covers every platform that uses Windows keybindings (win32 and WSL); Win32, LinuxWSL, and Darwin override it for one platform. A non-nil empty slice means "no default key" on that platform, as upstream's `[]`.

func (PlatformKeys) For

func (k PlatformKeys) For(platform KeybindingPlatform) []string

For returns the default keys for platform.

type ProcessTerminal

type ProcessTerminal struct {
	// contains filtered or unexported fields
}

ProcessTerminal is the concrete terminal control implementation backed by process stdin/stdout (or test doubles).

func NewProcessTerminal

func NewProcessTerminal(stdin, stdout *os.File) *ProcessTerminal

NewProcessTerminal constructs a terminal helper around the provided stdin and stdout files.

func NewProcessTerminalWithOutput

func NewProcessTerminalWithOutput(stdin, stdout *os.File, out io.Writer) *ProcessTerminal

NewProcessTerminalWithOutput constructs a terminal helper whose control bytes are written to out. Used by tests that want stdout-like behavior without touching the real terminal.

func (*ProcessTerminal) ClearFromCursor

func (t *ProcessTerminal) ClearFromCursor()

ClearFromCursor clears from the cursor to the end of the screen.

func (*ProcessTerminal) ClearLine

func (t *ProcessTerminal) ClearLine()

ClearLine clears from the cursor to the end of the current line.

func (*ProcessTerminal) ClearScreen

func (t *ProcessTerminal) ClearScreen()

ClearScreen clears the screen and homes the cursor.

func (*ProcessTerminal) Columns

func (t *ProcessTerminal) Columns() int

Columns returns the terminal width, falling back to COLUMNS or 80 when unavailable.

func (*ProcessTerminal) DrainInput

func (t *ProcessTerminal) DrainInput(maxWait, idleWait time.Duration) error

DrainInput drains pending stdin bytes for up to maxWait, exiting early once no new bytes arrive within idleWait. This mirrors upstream's slow-SSH guard against key release sequences leaking into the parent shell on exit.

Disables the extended-key protocols first, as upstream's drainInput does: a drain that runs while the terminal is still reporting key events has no stable end, because releasing the keys pressed during the drain produces more input. Idempotent, so a caller that already disabled loses nothing.

func (*ProcessTerminal) EnterRawMode

func (t *ProcessTerminal) EnterRawMode() (restore func(), err error)

EnterRawMode puts this terminal into raw mode and returns a restore closure that drains late extended-key releases before restoring cooked mode.

func (*ProcessTerminal) HideCursor

func (t *ProcessTerminal) HideCursor()

HideCursor hides the terminal cursor.

func (*ProcessTerminal) KittyProtocolActive

func (*ProcessTerminal) KittyProtocolActive() bool

KittyProtocolActive reports whether this raw-mode session received non-zero Kitty keyboard protocol flags.

func (*ProcessTerminal) MoveBy

func (t *ProcessTerminal) MoveBy(lines int)

MoveBy moves the cursor relative to its current row.

func (*ProcessTerminal) NewTerminalInput

func (t *ProcessTerminal) NewTerminalInput(onInput func(string)) *TerminalInput

NewTerminalInput constructs an input decoder bound to this terminal's protocol control output.

func (*ProcessTerminal) Rows

func (t *ProcessTerminal) Rows() int

Rows returns the terminal height, falling back to LINES or 24 when unavailable.

func (*ProcessTerminal) SetProgress

func (t *ProcessTerminal) SetProgress(active bool)

SetProgress writes the OSC 9;4 progress indicator and keeps it alive during agent work. Clearing stops the keepalive and writes OSC 9;4;0 followed directly by BEL.

func (*ProcessTerminal) SetTitle

func (t *ProcessTerminal) SetTitle(title string)

SetTitle writes an OSC 0 title update sequence.

func (*ProcessTerminal) ShowCursor

func (t *ProcessTerminal) ShowCursor()

ShowCursor shows the terminal cursor.

func (*ProcessTerminal) Start

func (t *ProcessTerminal) Start(onInput func([]byte), onResize func()) error

Start enters raw mode and owns input and resize delivery. Each onInput callback receives one framed, normalized event after keyboard negotiation filtering. Callbacks run synchronously in input order.

Use ProcessTerminal.StartWithReadError to distinguish terminal closure from user input. Caller-owned loops use EnterRawMode, ReadInputStream and TerminalInput instead.

Calling Start twice without an intervening Stop is a no-op.

func (*ProcessTerminal) StartWithReadError

func (t *ProcessTerminal) StartWithReadError(onInput func([]byte), onResize func(), onReadError func(error)) error

StartWithReadError starts terminal input and reports the error that ends the input loop. Cancellation through ProcessTerminal.Stop does not report an error.

func (*ProcessTerminal) Stop

func (t *ProcessTerminal) Stop()

Stop mirrors upstream `ProcessTerminal.stop()`. It cancels and joins the input goroutine, removes the resize handler, and restores cooked mode without draining unread input. This lets a subsequent terminal owner receive bytes typed during focus handoff. Safe to call multiple times; a standalone protocol query is unwound even when no reader was started.

func (*ProcessTerminal) Write

func (t *ProcessTerminal) Write(data string)

Write emits data to the terminal output.

type RefreshStatusKind

type RefreshStatusKind string

RefreshStatusKind controls the refresh message emphasis.

const (
	RefreshStatusMuted   RefreshStatusKind = "muted"
	RefreshStatusSuccess RefreshStatusKind = "success"
	RefreshStatusWarning RefreshStatusKind = "warning"
)

type RemoteSuggestionQuery

type RemoteSuggestionQuery struct {
	// contains filtered or unexported fields
}

RemoteSuggestionQuery captures a local provider's synchronous answer and its awaited work without reading the editor again.

func NewAutocompleteQuery

func NewAutocompleteQuery(provider AutocompleteProvider, lines []string, cursorLine, cursorCol int, force bool) *RemoteSuggestionQuery

NewAutocompleteQuery captures the local provider's answer and deferred filesystem search on the owner loop. Run awaits filesystem work off-loop.

func (*RemoteSuggestionQuery) RunResult

RunResult awaits the query and preserves callback errors for its caller.

type RenderOverflowError

type RenderOverflowError struct {
	Line          int
	LineWidth     int
	TerminalWidth int
	LogPath       string
}

RenderOverflowError is the value doRender panics with when an over-wide non-image row reaches the differential-render loop. Its message is the Error thrown by upstream TuiMainScreen.doRender (tui-main-screen.ts:536-544).

func (*RenderOverflowError) Error

func (e *RenderOverflowError) Error() string

type Renderer

type Renderer interface {
	// Render performs a differential render pass now.
	Render()
	// RequestRender coalesces a render on the shared 16ms frame throttle.
	RequestRender()
	// RequestImmediateRender coalesces input updates onto the next owner-loop turn without throttle delay.
	RequestImmediateRender()
	// CancelPendingRender invalidates a throttled frame already queued for owner-loop delivery.
	CancelPendingRender()
	// ForceFullRender marks the next frame as a full (non-differential) redraw.
	ForceFullRender()
	// RepaintAll forces an immediate full repaint.
	RepaintAll()
	// RenderSnapshot returns the rendered document lines at the given width.
	RenderSnapshot(width int) []string
	// Add mounts a component in the render tree.
	Add(component Component)
	// Invalidate marks the render tree dirty.
	Invalidate()
	// OpenOverlay pushes an overlay and returns its handle.
	OpenOverlay(component Component, opts OverlayOptions) *OverlayHandle
	// SetFocus records the non-overlay target restored after overlay teardown.
	SetFocus(component Component)
	// ActiveOverlay prepares visibility and eligible focus restoration at the input boundary.
	ActiveOverlay() Component
	// FocusedComponent returns the current keyboard focus target.
	FocusedComponent() Component
	// SetOverlayCommandDispatcher binds remote overlay commands to the owner loop.
	SetOverlayCommandDispatcher(dispatch func(func()))
	// HasOverlay reports whether any overlay is currently open.
	HasOverlay() bool
	// Width and Height report the current terminal geometry.
	Width() int
	Height() int
	// QueryTerminalBackgroundColor asks for the default background and returns its one-shot completion.
	QueryTerminalBackgroundColor(options TerminalColorQueryOptions) <-chan TerminalBackgroundColorResult
	// ConsumeOsc11BackgroundResponse intercepts replies before input listeners, including late replies after timeout.
	ConsumeOsc11BackgroundResponse(data string) bool
	// QueryCellSize asks an image-capable terminal for its cell size.
	QueryCellSize()
	// ConsumeCellSizeResponse applies and consumes a cell-size response.
	ConsumeCellSizeResponse(data string) bool
	// ShowCursor and HideCursor toggle the terminal cursor directly.
	ShowCursor()
	HideCursor()
	// SetShowHardwareCursor toggles hardware-cursor positioning.
	SetShowHardwareCursor(enabled bool)
	// SetClearOnShrink records the clear-on-shrink preference.
	SetClearOnShrink(enabled bool)
	// SetOnWidthChange registers a terminal-width-change callback.
	SetOnWidthChange(fn func(width int))

	// SetOnHeightChange registers a terminal-height-change callback.
	SetOnHeightChange(fn func(height int))
	// SetRenderDispatcher marshals timer-scheduled renders onto the driver loop.
	SetRenderDispatcher(dispatch func(render func()))
	// Start resumes rendering after Stop. The driver owns terminal input and raw mode.
	Start()
	// Stop tears down the renderer.
	Stop()
	// StopWithOptions tears down the renderer; PreserveScreen leaves the current
	// screen intact for a live renderer swap (no end-of-session output).
	StopWithOptions(options StopOptions)
}

Renderer is the interactive-driver-facing rendering contract implemented by both the main-screen (TUI) and alternate-screen (TuiAltScreen) renderers. It is the Go equivalent of upstream's TUI interface (packages/tui/src/tui.ts), which both TuiMainScreen and TuiAltScreen implement; the driver holds one of these and does not care which renderer backs it.

The interface is named Renderer rather than TUI (upstream's name) because pig reuses the identifier TUI for the concrete main-screen renderer struct (the layer-6 tui-main-screen naming reconciliation). This is a forced Go naming divergence, not a behavioral one.

type RendererFallback

type RendererFallback interface {
	SetRendererFallback(func(width int) []string)
}

RendererFallback is implemented by a renderer component whose rendering can fail after it was returned, because an extension process renders it. The card supplies the fallback upstream shows for a renderer that throws.

type ResourceGroup

type ResourceGroup struct {
	Key       string
	Label     string
	Scope     string
	Origin    string
	Source    string
	Subgroups []*ResourceSubgroup
}

ResourceGroup is a top-level grouping (by origin + scope + source).

func BuildResourceGroups

func BuildResourceGroups(resources []ResourceItem) []*ResourceGroup

BuildResourceGroups constructs groups from resolved resource data. This is a helper for callers that have raw path lists.

type ResourceItem

type ResourceItem struct {
	Path             string
	Enabled          bool
	ResourceType     ResourceType
	DisplayName      string
	GroupKey         string
	SubgroupKey      string
	Scope            string // "user" or "project"
	Origin           string // "package" or "top-level"
	Source           string
	BaseDir          string // for package-relative pattern generation
	Pattern          string // authored Package-relative member path
	Health           string // empty or "missing"
	Override         string // "inherit", "load", or "unload" in project mode
	Inherited        bool
	InheritedEnabled bool
}

ResourceItem is a single toggleable resource.

type ResourceSubgroup

type ResourceSubgroup struct {
	Type  ResourceType
	Label string
	Items []*ResourceItem
}

ResourceSubgroup groups items by resource type within a group.

type ResourceType

type ResourceType string

ResourceType identifies the kind of package resource.

const (
	ResourceExtensions ResourceType = "extensions"
	ResourceSkills     ResourceType = "skills"
	ResourcePrompts    ResourceType = "prompts"
	ResourceThemes     ResourceType = "themes"
)

type RgbColor

type RgbColor struct {
	R float64
	G float64
	B float64
}

RgbColor preserves JavaScript numeric channels, including NaN when an overflowing channel is scaled by an infinite maximum.

func ParseOsc11BackgroundColor

func ParseOsc11BackgroundColor(data string) *RgbColor

ParseOsc11BackgroundColor uses JavaScript whitespace and numeric semantics for strict OSC 11 replies. Slash-separated colors use the first three channels; later channels do not change the RGB result.

type ScopedModelsConfig

type ScopedModelsConfig struct {
	AllModels       []ModelItem
	EnabledModelIDs []string // nil = all enabled
	RefreshStatus   string
}

ScopedModelsConfig configures the scoped-models list.

type ScopedModelsList

type ScopedModelsList struct {
	// contains filtered or unexported fields
}

ScopedModelsList is the /scoped-models selector component.

func NewScopedModelsList

func NewScopedModelsList(cfg ScopedModelsConfig) *ScopedModelsList

NewScopedModelsList creates a new scoped-models selector.

func (*ScopedModelsList) ConsumeSave

func (s *ScopedModelsList) ConsumeSave() ([]string, bool)

ConsumeSave returns the most recent Ctrl+S save request and clears it.

func (*ScopedModelsList) Done

func (s *ScopedModelsList) Done() bool

Done reports whether the user has confirmed, persisted, or cancelled.

func (*ScopedModelsList) EnabledIDs

func (s *ScopedModelsList) EnabledIDs() []string

EnabledIDs returns the current enabled model IDs (nil = all).

func (*ScopedModelsList) HandleInput

func (s *ScopedModelsList) HandleInput(data string)

HandleInput processes a keystroke.

func (*ScopedModelsList) Invalidate

func (i *ScopedModelsList) Invalidate()

func (*ScopedModelsList) IsDirty

func (i *ScopedModelsList) IsDirty() bool

func (*ScopedModelsList) NeedsRedraw

func (i *ScopedModelsList) NeedsRedraw() bool

func (*ScopedModelsList) Render

func (s *ScopedModelsList) Render(width int) []string

Render draws the component. Mirrors upstream ScopedModelsSelectorComponent: every text row is a Text(..., 0, 0) between two DynamicBorders.

func (*ScopedModelsList) Result

Result returns the outcome after Done()==true.

func (*ScopedModelsList) SetRefreshStatus

func (s *ScopedModelsList) SetRefreshStatus(message string, kind RefreshStatusKind)

SetRefreshStatus replaces the catalog refresh message rendered above the footer.

func (*ScopedModelsList) UpdateModels

func (s *ScopedModelsList) UpdateModels(models []ModelItem, enabledIDs ...[]string)

UpdateModels publishes a refreshed catalog while preserving the selected model. Supplying enabledIDs also replaces the selection; an explicit nil means all.

type ScopedModelsResult

type ScopedModelsResult struct {
	EnabledIDs []string // nil = all enabled
	Persisted  bool     // retained for compatibility; Ctrl+S no longer closes the selector
	Cancelled  bool
}

ScopedModelsResult describes the outcome after Done()==true.

type ScrollLayoutNode

type ScrollLayoutNode struct {
	Component Component
	State     ScrollLayoutState
}

ScrollLayoutNode is a scroll layout node. State holds the narrow interface, not the concrete ScrollView, preserving upstream's intentional narrowing.

type ScrollLayoutState

type ScrollLayoutState interface {
	ScrollTop() int
	Primary() bool
	Overscroll() string
	ViewportHeight() int
	GetContentWidth(width int) int
	UpdateLayout(contentHeight, viewportHeight int, requestRender func())
}

ScrollLayoutState is the narrow contract the layout engine sees for a scroll node; *ScrollView implements it and is passed as the node's State. Upstream's readonly fields (scrollTop, primary, overscroll, viewportHeight) are getter methods here because a Go interface cannot carry fields.

type ScrollView

type ScrollView struct {
	*Container
	// contains filtered or unexported fields
}

ScrollView ports pi-tui's ScrollView. It embeds pig's Container (holding the single child) and owns the transient-scrollbar timer.

func GetScrollViewsAt

func GetScrollViewsAt(frame LayoutFrame, x, y int) []*ScrollView

GetScrollViewsAt returns the scroll views under a point, deepest first. Mirrors upstream getScrollViewsAt.

func NewScrollView

func NewScrollView(component Component, options ScrollViewOptions) *ScrollView

NewScrollView constructs a ScrollView. It panics on an unsupported axis, mirroring upstream's constructor throw.

func (*ScrollView) Add

func (s *ScrollView) Add(Component)

Add panics: a ScrollView has exactly one child (upstream throw).

func (*ScrollView) Clear

func (s *ScrollView) Clear()

Clear panics: a ScrollView's child cannot be cleared (upstream throw).

func (*ScrollView) Dispose

func (s *ScrollView) Dispose()

Dispose stops the hide timer so no goroutine outlives the view.

func (*ScrollView) FollowEnd

func (s *ScrollView) FollowEnd() bool

FollowEnd reports whether the view was configured to follow its end.

func (*ScrollView) GetContentWidth

func (s *ScrollView) GetContentWidth(width int) int

GetContentWidth returns the child render width, reserving a column for an always-on scrollbar.

func (ScrollView) Invalidate

func (i ScrollView) Invalidate()

func (ScrollView) IsDirty

func (i ScrollView) IsDirty() bool

func (*ScrollView) IsFollowingEnd

func (s *ScrollView) IsFollowingEnd() bool

IsFollowingEnd reports whether the view is pinned to the end.

func (*ScrollView) IsScrollbarActive

func (s *ScrollView) IsScrollbarActive() bool

IsScrollbarActive reports whether the pointer is hovering or dragging the scrollbar.

func (*ScrollView) IsScrollbarVisible

func (s *ScrollView) IsScrollbarVisible() bool

IsScrollbarVisible reports whether the scrollbar should paint this frame.

func (*ScrollView) LayoutNode

func (s *ScrollView) LayoutNode() LayoutNode

LayoutNode ports upstream ScrollView[LAYOUT_NODE](): a scroll node whose state is this ScrollView narrowed to ScrollLayoutState.

func (ScrollView) NeedsRedraw

func (i ScrollView) NeedsRedraw() bool

func (*ScrollView) Overscroll

func (s *ScrollView) Overscroll() string

Overscroll reports the overscroll mode.

func (*ScrollView) Primary

func (s *ScrollView) Primary() bool

Primary reports whether this is the primary scroll view.

func (*ScrollView) Remove

func (s *ScrollView) Remove(Component)

Remove panics: a ScrollView's child cannot be removed (upstream throw).

func (*ScrollView) Render

func (s *ScrollView) Render(width int) []string

Render ports upstream ScrollView.render: render the child at the content width, padding each line by a column when a scrollbar column is reserved.

func (*ScrollView) ScrollBy

func (s *ScrollView) ScrollBy(lines int) int

ScrollBy scrolls by a relative number of lines and returns the leftover lines that could not be applied (for overscroll chaining).

func (*ScrollView) ScrollTo

func (s *ScrollView) ScrollTo(scrollTop int)

ScrollTo scrolls to an absolute offset, clamped to the scrollable range.

func (*ScrollView) ScrollToEnd

func (s *ScrollView) ScrollToEnd()

ScrollToEnd scrolls to the bottom.

func (*ScrollView) ScrollToStart

func (s *ScrollView) ScrollToStart()

ScrollToStart scrolls to the top.

func (*ScrollView) ScrollToWithOptions

func (s *ScrollView) ScrollToWithOptions(scrollTop int, options ScrollViewScrollToOptions)

ScrollToWithOptions scrolls to an absolute offset, clamped to the scrollable range. Mirrors upstream scrollTo(scrollTop, options).

func (*ScrollView) ScrollTop

func (s *ScrollView) ScrollTop() int

ScrollTop reports the current scroll offset.

func (*ScrollView) Scrollbar

func (s *ScrollView) Scrollbar() string

Scrollbar reports the current scrollbar mode.

func (*ScrollView) ScrollbarThumbStyle

func (s *ScrollView) ScrollbarThumbStyle() func(text string) string

ScrollbarThumbStyle returns the style function applied to scrollbar thumb cells.

func (*ScrollView) ScrollbarTrackStyle

func (s *ScrollView) ScrollbarTrackStyle() func(text string) string

ScrollbarTrackStyle returns the style function applied to scrollbar track cells.

func (*ScrollView) SetScrollbar

func (s *ScrollView) SetScrollbar(scrollbar string)

SetScrollbar changes the scrollbar mode.

func (*ScrollView) SetScrollbarActive

func (s *ScrollView) SetScrollbarActive(active bool)

SetScrollbarActive marks the scrollbar as actively dragged (keeping it shown).

func (*ScrollView) UpdateLayout

func (s *ScrollView) UpdateLayout(contentHeight, viewportHeight int, requestRender func())

UpdateLayout is called by the layout engine each pass with the measured content and viewport heights; it clamps the scroll offset and stores the render callback the hide timer will invoke.

func (*ScrollView) ViewportHeight

func (s *ScrollView) ViewportHeight() int

ViewportHeight reports the current viewport height.

type ScrollViewOptions

type ScrollViewOptions struct {
	Axis                 string // "" (unset) or "vertical"
	Follow               string // "none" | "end"
	Primary              bool
	Overscroll           string // "chain" | "contain"
	Scrollbar            string // "hidden" | "auto" | "always"
	ScrollbarTrackStyle  func(text string) string
	ScrollbarThumbStyle  func(text string) string
	ScrollbarHideDelayMs *int
}

ScrollViewOptions configure a ScrollView. Empty string fields take upstream's default; ScrollbarHideDelayMs nil defaults to 1000ms.

type ScrollViewScrollToOptions

type ScrollViewScrollToOptions struct {
	// DisableFollow keeps follow-end disabled even when the target is the
	// current content end.
	DisableFollow bool
}

ScrollViewScrollToOptions mirrors upstream ScrollViewScrollToOptions.

type ScrollbarGeometry

type ScrollbarGeometry struct {
	Column       int
	TrackTop     int
	TrackHeight  int
	ThumbTop     int
	ThumbHeight  int
	MaxScrollTop int
}

ScrollbarGeometry describes where a scroll viewport's scrollbar paints.

func GetScrollbarGeometry

func GetScrollbarGeometry(box *LayoutBox) *ScrollbarGeometry

GetScrollbarGeometry computes where a scroll box's scrollbar paints, or nil if it should not paint. Mirrors upstream getScrollbarGeometry(box).

type SegmentData

type SegmentData = wordsegmenter.SegmentData

type SelectItem

type SelectItem struct {
	Value       string
	Label       string
	Description string
}

SelectItem mirrors upstream pi-tui's SelectItem shape for submenu-style selectors (value + label + optional description).

type SelectListTruncatePrimaryContext

type SelectListTruncatePrimaryContext struct {
	Text        string
	MaxWidth    int
	ColumnWidth int
	Item        SelectItem
	IsSelected  bool
}

SelectListTruncatePrimaryContext describes one primary-column truncation. Mirrors upstream SelectListTruncatePrimaryContext.

type SelectSubmenuComponent

type SelectSubmenuComponent struct {
	// contains filtered or unexported fields
}

SelectSubmenuComponent shows a titled select list with optional fuzzy search.

func NewSelectSubmenu

func NewSelectSubmenu(title, description string, items []SelectItem, currentValue string, options ...SelectSubmenuOptions) *SelectSubmenuComponent

func (*SelectSubmenuComponent) Cancelled

func (s *SelectSubmenuComponent) Cancelled() bool

func (*SelectSubmenuComponent) CurrentValue

func (s *SelectSubmenuComponent) CurrentValue() string

func (*SelectSubmenuComponent) Done

func (s *SelectSubmenuComponent) Done() bool

func (*SelectSubmenuComponent) HandleInput

func (s *SelectSubmenuComponent) HandleInput(data string)

func (*SelectSubmenuComponent) Invalidate

func (i *SelectSubmenuComponent) Invalidate()

func (*SelectSubmenuComponent) IsDirty

func (i *SelectSubmenuComponent) IsDirty() bool

func (*SelectSubmenuComponent) NeedsRedraw

func (i *SelectSubmenuComponent) NeedsRedraw() bool

func (*SelectSubmenuComponent) Render

func (s *SelectSubmenuComponent) Render(width int) []string

func (*SelectSubmenuComponent) SelectedValue

func (s *SelectSubmenuComponent) SelectedValue() string

func (*SelectSubmenuComponent) String

func (s *SelectSubmenuComponent) String() string

type SelectSubmenuOptions

type SelectSubmenuOptions struct {
	Searchable            bool
	MinPrimaryColumnWidth int
	MaxPrimaryColumnWidth int
}

SelectSubmenuOptions enables fuzzy search and overrides the primary-column layout.

type SettingItem

type SettingItem struct {
	ID           string   // unique identifier
	Label        string   // display label (left column)
	Description  string   // shown below list when selected
	CurrentValue string   // right column
	Values       []string // Enter/Space cycles through these
	Submenu      func(currentValue string, done func(*string)) Component
}

SettingItem describes one toggle-able setting.

type SettingsList

type SettingsList struct {

	// Last change made (for the caller loop pattern).
	ChangedID    string
	ChangedValue string
	// contains filtered or unexported fields
}

SettingsList is a two-column selector that cycles setting values. After Done()==true, callers read ChangedID/ChangedValue for the last change, or Cancelled() if the user pressed Esc. A host that keeps the list open, as upstream's onChange does, applies the change and calls Reset.

func NewSettingsList

func NewSettingsList(items []SettingItem) *SettingsList

NewSettingsList creates the searchable settings list the /settings selector uses (upstream maxVisible 10, enableSearch true).

func NewSettingsListWithOptions

func NewSettingsListWithOptions(items []SettingItem, maxVisible int, enableSearch bool) *SettingsList

NewSettingsListWithOptions mirrors upstream's SettingsList constructor arguments: maxVisible rows and SettingsListOptions.enableSearch. Nested settings menus pass Math.min(items.length, 10) and no search.

func (*SettingsList) Cancelled

func (s *SettingsList) Cancelled() bool

Cancelled reports whether the user pressed Esc.

func (*SettingsList) Done

func (s *SettingsList) Done() bool

Done reports whether the user confirmed a change or cancelled.

func (*SettingsList) HandleInput

func (s *SettingsList) HandleInput(data string)

HandleInput processes keystrokes.

func (*SettingsList) HandleMouse

func (s *SettingsList) HandleMouse(event TuiMouseEvent) *TuiMouseDispatchResult

HandleMouse moves selection by wheel, selects a visible row on press, and activates the pressed row on click. Pointer motion does not change selection. Mirrors upstream SettingsList.handleMouse.

func (*SettingsList) Invalidate

func (i *SettingsList) Invalidate()

func (*SettingsList) IsDirty

func (i *SettingsList) IsDirty() bool

func (*SettingsList) NeedsRedraw

func (i *SettingsList) NeedsRedraw() bool

func (*SettingsList) Render

func (s *SettingsList) Render(width int) []string

Render draws the settings list. Matches upstream SettingsList.renderMainList.

func (*SettingsList) Reset

func (s *SettingsList) Reset()

Reset clears done/cancelled so the list can be reused in a loop.

func (*SettingsList) UpdateValue

func (s *SettingsList) UpdateValue(id, newValue string)

UpdateValue sets a new current value for the item with the given ID.

type ShowImagesSelectorComponent

type ShowImagesSelectorComponent struct {
	// contains filtered or unexported fields
}

ShowImagesSelectorComponent renders a yes/no selector for image display.

func NewShowImagesSelector

func NewShowImagesSelector(currentValue bool, onSelect func(bool), onCancel func()) *ShowImagesSelectorComponent

NewShowImagesSelector creates the selector. currentValue pre-selects the matching entry. Confirm invokes onSelect; cancellation invokes onCancel.

func (*ShowImagesSelectorComponent) HandleInput

func (s *ShowImagesSelectorComponent) HandleInput(data string)

HandleInput delegates to the list.

func (*ShowImagesSelectorComponent) Invalidate

func (i *ShowImagesSelectorComponent) Invalidate()

func (*ShowImagesSelectorComponent) IsDirty

func (i *ShowImagesSelectorComponent) IsDirty() bool

func (*ShowImagesSelectorComponent) List

List returns the underlying FilterableList for input handling.

func (*ShowImagesSelectorComponent) NeedsRedraw

func (i *ShowImagesSelectorComponent) NeedsRedraw() bool

func (*ShowImagesSelectorComponent) Render

func (s *ShowImagesSelectorComponent) Render(width int) []string

Render wraps the list with dynamic borders.

func (*ShowImagesSelectorComponent) SelectedShowImages

func (s *ShowImagesSelectorComponent) SelectedShowImages() (bool, bool)

SelectedShowImages returns the boolean result after selection. Returns (value, true) if a selection was made, (false, false) otherwise.

type SkillInvocationMessageComponent

type SkillInvocationMessageComponent struct {
	// contains filtered or unexported fields
}

SkillInvocationMessageComponent renders a skill invocation message.

func NewSkillInvocationMessage

func NewSkillInvocationMessage(block ParsedSkillBlock) *SkillInvocationMessageComponent

NewSkillInvocationMessage creates a skill invocation component.

func (*SkillInvocationMessageComponent) HandleMouse

HandleMouse toggles the skill on a left click inside the box content, excluding its one-cell padding. Ports packages/coding-agent/src/modes/interactive/components/skill-invocation-message.ts:56.

func (*SkillInvocationMessageComponent) Invalidate

func (i *SkillInvocationMessageComponent) Invalidate()

func (*SkillInvocationMessageComponent) IsDirty

func (i *SkillInvocationMessageComponent) IsDirty() bool

func (*SkillInvocationMessageComponent) NeedsRedraw

func (i *SkillInvocationMessageComponent) NeedsRedraw() bool

func (*SkillInvocationMessageComponent) Render

func (s *SkillInvocationMessageComponent) Render(width int) []string

Render produces the skill invocation lines. Mirrors upstream SkillInvocationMessageComponent which extends Box(paddingX=1, paddingY=1). In pig's line renderer, paddingY manifests as empty rows above and below content.

func (*SkillInvocationMessageComponent) SetExpanded

func (s *SkillInvocationMessageComponent) SetExpanded(expanded bool)

SetExpanded toggles expanded/collapsed rendering.

type SlashCommand

type SlashCommand struct {
	Name                   string
	Description            string
	ArgumentHint           string
	GetArgumentCompletions func(argPrefix string) []AutocompleteItem
	// AwaitArgumentCompletions is the Promise-returning form. The editor invokes it on its owned query worker, not while reading/rendering input.
	AwaitArgumentCompletions func(argPrefix string) ([]AutocompleteItem, error)
}

SlashCommand is the autocomplete-side view of a registered slash command. Matches upstream's `SlashCommand` interface in autocomplete.ts. GetArgumentCompletions is optional; nil means the command takes no completable arguments.

type SlashOnlyProvider

type SlashOnlyProvider struct {
	Commands []SlashCommand
}

SlashOnlyProvider serves command names and their immediate or awaited argument completions. It does not perform path or attachment completion.

func NewSlashOnlyProvider

func NewSlashOnlyProvider(cmds []SlashCommand) *SlashOnlyProvider

NewSlashOnlyProvider constructs a provider over the given command list.

func (*SlashOnlyProvider) ApplyCompletion

func (p *SlashOnlyProvider) ApplyCompletion(lines []string, cursorLine, cursorCol int, item AutocompleteItem, prefix string) ([]string, int, int)

ApplyCompletion replaces the trailing `prefix` chars of the current line with the completion text. Three behaviors:

  • Slash-name completion (prefix starts with `/`, no space, at line start): inserts `/<value> ` (note trailing space). Cursor lands after the space. Mirrors autocomplete.ts:368-385.
  • Argument completion (prefix is the arg text, line contains `/cmd `): inserts `value` at cursor. No trailing space.
  • Other (defensive fallthrough): same as argument completion.

func (*SlashOnlyProvider) GetSuggestions

func (p *SlashOnlyProvider) GetSuggestions(lines []string, cursorLine, cursorCol int) *AutocompleteSuggestions

GetSuggestions implements AutocompleteProvider. Three cases:

  1. Buffer doesn't start with `/` (after trim of leading line slice up to cursor) → return nil (popup off).
  2. `/<partial>` (no space) → fuzzy-filter command names.
  3. `/<cmd> <argPrefix>` (space present) → delegate to the matched command's GetArgumentCompletions.

Mirrors `CombinedAutocompleteProvider.getSuggestions` slash branch (autocomplete.ts:262-342): minus the `@`/path branches.

func (*SlashOnlyProvider) SuggestionTask

func (p *SlashOnlyProvider) SuggestionTask(lines []string, line, col int, _ bool) (string, func(context.Context) ([]AutocompleteItem, error), bool)

SuggestionTask captures a Promise-returning command callback without invoking it on the input loop.

type Spacer

type Spacer struct {
	Lines int
	// contains filtered or unexported fields
}

Spacer component that renders empty lines.

func NewSpacer

func NewSpacer(n int) *Spacer

func (*Spacer) Invalidate

func (i *Spacer) Invalidate()

func (*Spacer) IsDirty

func (i *Spacer) IsDirty() bool

func (*Spacer) NeedsRedraw

func (i *Spacer) NeedsRedraw() bool

func (*Spacer) Render

func (s *Spacer) Render(_ int) []string

func (*Spacer) SetLines

func (s *Spacer) SetLines(n int)

SetLines updates the number of blank lines.

type Stack

type Stack struct {
	*Container
	// contains filtered or unexported fields
}

Stack is the abstract base shared by HStack and VStack. It embeds pig's Container and maintains the parallel entries slice with flexbox metadata.

func (*Stack) Add

func (s *Stack) Add(component Component)

Add shadows the promoted Container.Add so an options-free add still records an entry (equivalent to addChild with no options), keeping entries consistent.

func (*Stack) AddChild

func (s *Stack) AddChild(component Component, options StackEntryOptions)

AddChild mirrors upstream Stack.addChild: it adds the component to the container and records its normalized flexbox entry. A provided option is normalized and stored; an omitted (nil) option is left unset so the allocator applies its default.

func (*Stack) Clear

func (s *Stack) Clear()

Clear mirrors upstream Stack.clear: clear the container and the entries.

func (Stack) Invalidate

func (i Stack) Invalidate()

func (Stack) IsDirty

func (i Stack) IsDirty() bool

func (*Stack) LayoutNode

func (s *Stack) LayoutNode() LayoutNode

LayoutNode mirrors upstream Stack[LAYOUT_NODE](): the stack's layout node.

func (Stack) NeedsRedraw

func (i Stack) NeedsRedraw() bool

func (*Stack) Remove

func (s *Stack) Remove(component Component)

Remove shadows the promoted Container.Remove to keep entries consistent.

func (*Stack) RemoveChild

func (s *Stack) RemoveChild(component Component)

RemoveChild mirrors upstream Stack.removeChild: remove the component and its first matching entry.

type StackChild

type StackChild struct {
	Component Component
	StackEntryOptions
}

StackChild is one child passed to a stack constructor. A bare component is StackChild{Component: c} with zero-value options (upstream's Component arm of the Component | StackEntry union); a configured child sets the options too.

type StackEntryOptions

type StackEntryOptions struct {
	Basis   *int // nil == "auto"/undefined -> intrinsic size
	Grow    *int
	Shrink  *int
	MinSize *int
	MaxSize *int
	Visible func(viewport LayoutViewport) bool
}

StackEntryOptions are the per-child flexbox options. A nil pointer field is upstream's "undefined": the allocator applies the default at read time (Basis nil == "auto" -> intrinsic, Grow 0, Shrink 1, MinSize 0, MaxSize maxSafeInteger).

type StackLayoutEntry

type StackLayoutEntry struct {
	Component Component
	Basis     *int
	Grow      *int
	Shrink    *int
	MinSize   *int
	MaxSize   *int
	Visible   func(viewport LayoutViewport) bool
}

StackLayoutEntry is one child in a stack with flexbox sizing. The pointer fields are upstream's optional properties: nil means "unset", and the allocator applies the upstream default (Basis nil == "auto" -> intrinsic size, Grow 0, Shrink 1, MinSize 0, MaxSize maxSafeInteger).

type StackLayoutNode

type StackLayoutNode struct {
	Type    string
	Entries []StackLayoutEntry
	Gap     int
	Align   string
}

StackLayoutNode is a vstack or hstack layout node. Type holds upstream's literal discriminant ("vstack" | "hstack"); Align holds "stretch" | "start" | "center" | "end".

type StackOptions

type StackOptions struct {
	Gap   *int
	Align string // "stretch" | "start" | "center" | "end"
}

StackOptions configure a stack. Gap nil defaults to 0; Align "" defaults to "stretch".

type StaticText

type StaticText struct {
	// contains filtered or unexported fields
}

StaticText is a Component that renders fixed pre-rendered lines. Used for content that never changes (e.g. login art/banner) but must survive full redraws because it's part of the TUI render buffer.

func NewStaticText

func NewStaticText(lines []string) *StaticText

NewStaticText creates a StaticText component from pre-rendered lines.

func (*StaticText) Invalidate

func (s *StaticText) Invalidate()

func (*StaticText) IsDirty

func (s *StaticText) IsDirty() bool

func (*StaticText) NeedsRedraw

func (s *StaticText) NeedsRedraw() bool

func (*StaticText) Render

func (s *StaticText) Render(_ int) []string

type StatusIndicator

type StatusIndicator struct {
	*Loader
	Kind string
}

StatusIndicator renders a loader either standalone or inside an editor border. Its owner advances animation and disposes operation timers on replacement.

func (StatusIndicator) Invalidate

func (i StatusIndicator) Invalidate()

func (StatusIndicator) IsDirty

func (i StatusIndicator) IsDirty() bool

func (StatusIndicator) NeedsRedraw

func (i StatusIndicator) NeedsRedraw() bool

func (*StatusIndicator) RenderInBorder

func (s *StatusIndicator) RenderInBorder(width int) string

func (*StatusIndicator) RenderSpinnerInBorder

func (s *StatusIndicator) RenderSpinnerInBorder(width int) string

type StdinBuffer

type StdinBuffer struct {
	// contains filtered or unexported fields
}

StdinBuffer accumulates partial escape sequences across reads and emits JavaScript UTF-16 units for ordinary text. Lone surrogate events use WTF-8. Bracketed pastes remain one framed payload. The zero value uses upstream's default timeouts.

func NewStdinBuffer

func NewStdinBuffer(options StdinBufferOptions) *StdinBuffer

NewStdinBuffer mirrors the upstream StdinBuffer constructor.

func (*StdinBuffer) Clear

func (b *StdinBuffer) Clear()

func (*StdinBuffer) Flush

func (b *StdinBuffer) Flush() []string

Flush returns an incomplete remainder as one chunk. An empty flush preserves pending Kitty printable deduplication; the input loop owns timeout cancellation.

func (*StdinBuffer) FlushTimeout

func (b *StdinBuffer) FlushTimeout() time.Duration

FlushTimeout is how long the buffered remainder waits for more input before Flush emits it: the escape timeout for a lone ESC, the sequence timeout for anything else. Mirrors the timeout StdinBuffer.process schedules upstream.

func (*StdinBuffer) GetBuffer

func (b *StdinBuffer) GetBuffer() string

GetBuffer returns the pending incomplete input, excluding paste content.

func (*StdinBuffer) HasPendingFlush

func (b *StdinBuffer) HasPendingFlush() bool

func (*StdinBuffer) ProcessBytes

func (b *StdinBuffer) ProcessBytes(data []byte) []string

ProcessBytes mirrors upstream process(Buffer): it feeds raw bytes and returns any complete keystroke chunks ready for dispatch. Terminal loops use ProcessTerminalBytes, which matches upstream's utf8-decoded stdin instead.

func (*StdinBuffer) ProcessString

func (b *StdinBuffer) ProcessString(s string) []string

ProcessString mirrors upstream process(string).

func (*StdinBuffer) ProcessTerminalBytes

func (b *StdinBuffer) ProcessTerminalBytes(data []byte) []string

ProcessTerminalBytes feeds one terminal read. It decodes UTF-8 across reads the way upstream ProcessTerminal's stdin.setEncoding("utf8") does, so a character split between reads is held until it is complete and a lone high byte is never rewritten as a Meta key; the decoded text then goes through ProcessString.

type StdinBufferOptions

type StdinBufferOptions struct {
	// Timeout is how long an incomplete escape sequence waits for more input.
	Timeout time.Duration
	// EscapeTimeout is how long a lone ESC waits before it is the Escape key.
	EscapeTimeout time.Duration
}

StdinBufferOptions mirrors upstream StdinBufferOptions. A zero field keeps the upstream default.

type StopOptions

type StopOptions struct {
	// PreserveScreen leaves the alternate screen contents visible on exit
	// instead of re-emitting the final frame into the main screen scrollback.
	PreserveScreen bool
}

StopOptions controls alt-screen teardown. Mirrors upstream TuiStopOptions.

type TUI

type TUI struct {
	// contains filtered or unexported fields
}

TUI is the main-screen renderer: differential rendering into the terminal's main screen + scrollback, overlays, cursor, raw input. It ports pi-tui's TuiMainScreen (the concrete-type name TUI is kept for pig-wide call-site stability; the base machinery lives in the embedded tuiBase).

func New

func New() *TUI

New creates and initialises a TUI instance.

func NewWithOutput

func NewWithOutput(out io.Writer, cols, rows int) *TUI

NewWithOutput creates a TUI that writes to a fixed io.Writer with fixed dimensions. Used only by tests; production code uses New().

func (*TUI) ActiveOverlay

func (t *TUI) ActiveOverlay() Component

ActiveOverlay refreshes overlay visibility and restores eligible focus before input dispatch. An active replacement keeps input until it changes focus, even if it is not mounted in the render tree.

func (*TUI) CancelPendingRender

func (t *TUI) CancelPendingRender()

CancelPendingRender invalidates a throttled frame, including one whose timer callback has already handed it to the owner loop. It maps the single-threaded JavaScript event-loop rule that a later state transition can consume a queued request before its callback runs.

func (*TUI) CaptureRenderState

func (t *TUI) CaptureRenderState() TUIRenderState

CaptureRenderState snapshots the current inline-flow render state so a renderer swap can restore it. Mirrors upstream TuiMainScreen.captureRenderState.

func (*TUI) ConsumeCellSizeResponse

func (t *TUI) ConsumeCellSizeResponse(data string) bool

ConsumeCellSizeResponse reports whether data is a complete cell-size response. A response with positive dimensions updates the cell dimensions, invalidates every mounted component so images re-render at the new size, and requests a render; a response with a zero dimension is still consumed. Any other input returns false so it reaches the focused component. Mirrors upstream tui.ts consumeCellSizeResponse.

func (*TUI) ConsumeOsc11BackgroundResponse

func (t *TUI) ConsumeOsc11BackgroundResponse(data string) bool

ConsumeOsc11BackgroundResponse consumes one strict OSC 11 reply only when a query still owns a reply slot. Call it before terminal-input listeners or focused-component dispatch, including after a query timeout.

func (*TUI) FocusedComponent

func (t *TUI) FocusedComponent() Component

FocusedComponent returns the current overlay or non-overlay focus target.

func (*TUI) ForceFullRender

func (t *TUI) ForceFullRender()

ForceFullRender marks the next Render() as a destructive full repaint. Use it when the physical buffer is invalid, including semantic transcript replacement, not for ordinary dynamic shrink or streaming updates.

func (*TUI) GetClearOnShrink

func (t *TUI) GetClearOnShrink() bool

GetClearOnShrink reports whether shrinking content triggers a full redraw to clear empty rows. Mirrors upstream TUI.getClearOnShrink().

func (*TUI) GetShowHardwareCursor

func (t *TUI) GetShowHardwareCursor() bool

GetShowHardwareCursor reports whether the real terminal cursor is shown. Mirrors upstream TUI.getShowHardwareCursor().

func (*TUI) HasOverlay

func (t *TUI) HasOverlay() bool

HasOverlay reports whether any overlay entry is mounted. The interactive driver uses this for the upstream hasOverlayEntries renderer-switch guard.

func (*TUI) Height

func (t *TUI) Height() int

Height returns the current terminal height.

func (*TUI) HideCursor

func (t *TUI) HideCursor()

HideCursor hides the terminal cursor.

func (*TUI) OpenOverlay

func (t *TUI) OpenOverlay(c Component, opts OverlayOptions) *OverlayHandle

OpenOverlay pushes a component onto the overlay append stack and returns a targeted handle. Callers must Close when the overlay is dismissed.

func (*TUI) QueryCellSize

func (t *TUI) QueryCellSize()

QueryCellSize writes the cell-size query when the terminal supports images, since only image rendering uses the cell size. Mirrors upstream tui.ts queryCellSize, which start() sends after the terminal starts.

func (*TUI) QueryTerminalBackgroundColor

func (t *TUI) QueryTerminalBackgroundColor(options TerminalColorQueryOptions) <-chan TerminalBackgroundColorResult

QueryTerminalBackgroundColor writes OSC 11 and returns a one-shot completion. A timed-out query retains its FIFO reply slot so a late reply cannot settle a newer query. Stop does not cancel these deadlines, matching the terminal query's independent Promise lifetime.

func (*TUI) Render

func (t *TUI) Render()

Render performs a differential render pass using inline-flow output.

Mirrors upstream pi-tui's `render()`. New content is appended with `\r\n`, which scrolls the viewport up and pushes older lines into the terminal's native scrollback. The terminal's normal scrolling makes our chat history reachable via the user's mouse wheel / Cmd-↑ after pig exits, just like a regular shell.

Algorithm sketch:

  1. Detect width/height change → fullRender(clear).
  2. First render → fullRender(no clear). Lines emitted with `\r\n` between them flow naturally.
  3. Diff prevLines vs newLines to find [firstChanged, lastChanged].
  4. If visible tail content shrinks and exposes rows above the old viewport, repaint only the new visible viewport.
  5. If only deletions remain, clear those rows in place.
  6. If firstChanged is above the current viewport → fullRender(clear).
  7. Otherwise: move cursor to firstChanged (scrolling if it's below the viewport bottom), rewrite affected lines, clear any extras.

func (*TUI) RenderSnapshot

func (t *TUI) RenderSnapshot(width int) []string

RenderSnapshot returns the current frame's fully rendered lines at the given width without writing to the terminal. Used by the /debug command to dump the frame. Mirrors upstream TUI.render(width) (tui.ts).

func (*TUI) RepaintAll

func (t *TUI) RepaintAll()

RepaintAll forces an immediate screen-clearing repaint after an external program has changed the terminal. Ordinary editor updates use differential rendering instead.

func (*TUI) RequestImmediateRender

func (t *TUI) RequestImmediateRender()

RequestImmediateRender preempts a throttled frame and coalesces keyboard updates onto the next owner-loop turn. It exposes TuiBase.requestImmediateRender to the Go driver's separately owned input path.

func (*TUI) RequestRender

func (t *TUI) RequestRender()

RequestRender asks the TUI to render soon, coalescing repeated calls and enforcing the upstream 16ms frame throttle. Use this for hot streaming paths (thinking/text deltas); direct Render() is reserved for low-frequency state changes and final flushes.

func (*TUI) RestoreRenderState

func (t *TUI) RestoreRenderState(state TUIRenderState)

RestoreRenderState restores a previously captured render state so the next differential render is computed against the pre-switch screen. Image lines are blanked and the Kitty image-id set is cleared, since those images are no longer on the terminal after the switch. Mirrors upstream TuiMainScreen.restoreRenderState.

func (*TUI) SetClearOnShrink

func (t *TUI) SetClearOnShrink(enabled bool)

SetClearOnShrink configures whether shrinking content triggers a full redraw when no overlays are active. Mirrors upstream TUI.setClearOnShrink().

func (*TUI) SetFixedSize

func (t *TUI) SetFixedSize(cols, rows int)

SetFixedSize changes the size of a renderer built with a fixed size (NewWithOutput), as a terminal resize would; the next render sees it. Renderers that read the real terminal size ignore it.

func (*TUI) SetFocus

func (t *TUI) SetFocus(component Component)

SetFocus records a non-overlay target for focus restoration.

func (*TUI) SetLogDirectory

func (t *TUI) SetLogDirectory(dir string)

SetLogDirectory sets the redraw and overflow log directory. Empty disables redraw logging and selects the OS temp directory for crash dumps, matching TuiBase's logDirectory constructor argument.

func (*TUI) SetOnHeightChange

func (t *TUI) SetOnHeightChange(fn func(height int))

SetOnHeightChange registers a callback that fires whenever the terminal height changes between render frames. Thread-safe.

func (*TUI) SetOnWidthChange

func (t *TUI) SetOnWidthChange(fn func(width int))

SetOnWidthChange registers a callback that fires whenever the terminal width changes between render frames. Thread-safe.

func (*TUI) SetOverlayCommandDispatcher

func (t *TUI) SetOverlayCommandDispatcher(dispatch func(func()))

SetOverlayCommandDispatcher installs the ordered ingress used by remote producers. The dispatcher owns command ordering on the application loop.

func (*TUI) SetRenderDispatcher

func (t *TUI) SetRenderDispatcher(dispatch func(render func()))

SetRenderDispatcher installs a hook that runs throttled scheduled renders on the caller's main loop. The dispatcher receives a render closure and is responsible for eventually invoking it on the goroutine that owns component-tree mutation (it may enqueue it on an event loop). When nil (default), scheduled renders run inline on the throttle-timer goroutine, which is correct for standalone / single-goroutine use. Thread-safe.

func (*TUI) SetShowHardwareCursor

func (t *TUI) SetShowHardwareCursor(enabled bool)

SetShowHardwareCursor controls whether the real terminal cursor is shown while still positioning it for IME/caret parity. Mirrors upstream TUI.setShowHardwareCursor().

func (*TUI) SetTickDispatcher

func (t *TUI) SetTickDispatcher(dispatch func(func()))

SetTickDispatcher installs the blocking owner-loop seam for owned state-machine ticks (alt-screen selection auto-scroll). It must marshal fn onto the loop that owns rendering, backpressuring rather than dropping while that loop is alive; see the tickOnMain doc. When unset the tick runs inline. Thread-safe.

func (*TUI) ShowCursor

func (t *TUI) ShowCursor()

ShowCursor shows the terminal cursor.

func (*TUI) Start

func (t *TUI) Start()

Start resumes the main-screen renderer after a terminal handoff. The driver restores input and requests the full repaint, as Pi's TUI.start does.

func (*TUI) Stop

func (t *TUI) Stop()

func (*TUI) StopWithOptions

func (t *TUI) StopWithOptions(options StopOptions)

StopWithOptions tears down the main-screen renderer. With PreserveScreen set (a live tui-mode switch), it skips the final cursor-park-and-newline emission so the swap produces no end-of-session output; mirrors upstream TuiMainScreen.stop({ preserveScreen }). Plain Stop() keeps the shutdown behavior that parks the cursor below the content.

func (*TUI) Width

func (t *TUI) Width() int

Width returns the current terminal width.

func (*TUI) WriteRaw

func (t *TUI) WriteRaw(data string)

WriteRaw writes data to the terminal as is, as upstream's terminal.write does for a component that drives the terminal itself.

type TUIKeybinding

type TUIKeybinding = string

TUIKeybinding is a named action for TUI components.

const (
	KBAltScreenHalfPageUp     TUIKeybinding = "tui.altScreen.halfPageUp"
	KBAltScreenHalfPageDown   TUIKeybinding = "tui.altScreen.halfPageDown"
	KBAltScreenLineUp         TUIKeybinding = "tui.altScreen.lineUp"
	KBAltScreenLineDown       TUIKeybinding = "tui.altScreen.lineDown"
	KBAltScreenSearch         TUIKeybinding = "tui.altScreen.search"
	KBAltScreenSearchNext     TUIKeybinding = "tui.altScreen.searchNext"
	KBAltScreenSearchPrevious TUIKeybinding = "tui.altScreen.searchPrevious"
	KBAltScreenSearchClose    TUIKeybinding = "tui.altScreen.searchClose"
)

Alt-screen viewport actions added in pi-tui v0.87.1 keybindings.ts. The action names are defined here; their default keys join tuiKeybindingDefs with the per-platform TUI defaults.

const (
	// Editor navigation and editing
	KBEditorCursorUp          TUIKeybinding = "tui.editor.cursorUp"
	KBEditorCursorDown        TUIKeybinding = "tui.editor.cursorDown"
	KBEditorHistoryPrevious   TUIKeybinding = "tui.editor.historyPrevious"
	KBEditorHistoryNext       TUIKeybinding = "tui.editor.historyNext"
	KBEditorCursorLeft        TUIKeybinding = "tui.editor.cursorLeft"
	KBEditorCursorRight       TUIKeybinding = "tui.editor.cursorRight"
	KBEditorCursorWordLeft    TUIKeybinding = "tui.editor.cursorWordLeft"
	KBEditorCursorWordRight   TUIKeybinding = "tui.editor.cursorWordRight"
	KBEditorCursorLineStart   TUIKeybinding = "tui.editor.cursorLineStart"
	KBEditorCursorLineEnd     TUIKeybinding = "tui.editor.cursorLineEnd"
	KBEditorJumpForward       TUIKeybinding = "tui.editor.jumpForward"
	KBEditorJumpBackward      TUIKeybinding = "tui.editor.jumpBackward"
	KBEditorPageUp            TUIKeybinding = "tui.editor.pageUp"
	KBEditorPageDown          TUIKeybinding = "tui.editor.pageDown"
	KBEditorDeleteCharBack    TUIKeybinding = "tui.editor.deleteCharBackward"
	KBEditorDeleteCharForward TUIKeybinding = "tui.editor.deleteCharForward"
	KBEditorDeleteWordBack    TUIKeybinding = "tui.editor.deleteWordBackward"
	KBEditorDeleteWordForward TUIKeybinding = "tui.editor.deleteWordForward"
	KBEditorDeleteToLineStart TUIKeybinding = "tui.editor.deleteToLineStart"
	KBEditorDeleteToLineEnd   TUIKeybinding = "tui.editor.deleteToLineEnd"
	KBEditorYank              TUIKeybinding = "tui.editor.yank"
	KBEditorYankPop           TUIKeybinding = "tui.editor.yankPop"
	KBEditorUndo              TUIKeybinding = "tui.editor.undo"

	// Generic input actions
	KBInputNewLine TUIKeybinding = "tui.input.newLine"
	KBInputSubmit  TUIKeybinding = "tui.input.submit"
	KBInputTab     TUIKeybinding = "tui.input.tab"
	KBInputCopy    TUIKeybinding = "tui.input.copy"

	// Generic selection actions
	KBSelectUp       TUIKeybinding = "tui.select.up"
	KBSelectDown     TUIKeybinding = "tui.select.down"
	KBSelectPageUp   TUIKeybinding = "tui.select.pageUp"
	KBSelectPageDown TUIKeybinding = "tui.select.pageDown"
	KBSelectConfirm  TUIKeybinding = "tui.select.confirm"
	KBSelectCancel   TUIKeybinding = "tui.select.cancel"

	// Alt-screen (fullscreen) viewport actions
	KBAltScreenPageUp         TUIKeybinding = "tui.altScreen.pageUp"
	KBAltScreenPageDown       TUIKeybinding = "tui.altScreen.pageDown"
	KBAltScreenPreviousPrompt TUIKeybinding = "tui.altScreen.previousPrompt"
	KBAltScreenNextPrompt     TUIKeybinding = "tui.altScreen.nextPrompt"
	KBAltScreenTop            TUIKeybinding = "tui.altScreen.top"
	KBAltScreenBottom         TUIKeybinding = "tui.altScreen.bottom"
)

TUI keybinding action constants: mirrors upstream Keybindings interface.

type TUIKeybindingConflict

type TUIKeybindingConflict struct {
	Key     string
	Actions []string
}

TUIKeybindingConflict records a key bound to multiple actions.

type TUIKeybindingDef

type TUIKeybindingDef struct {
	DefaultKeys []string
	Description string
}

TUIKeybindingDef defines a keybinding's default keys and description.

type TUIKeybindingsManager

type TUIKeybindingsManager struct {
	// contains filtered or unexported fields
}

TUIKeybindingsManager resolves keybindings for TUI components. Mirrors upstream KeybindingsManager in packages/tui/src/keybindings.ts.

func GetKeybindings

func GetKeybindings() *TUIKeybindingsManager

GetKeybindings mirrors upstream getKeybindings().

func GetTUIKeybindings

func GetTUIKeybindings() *TUIKeybindingsManager

GetTUIKeybindings returns the global TUI keybinding manager, creating a default one if none has been set.

func NewKeybindingsManager

func NewKeybindingsManager(definitions map[string]TUIKeybindingDef, userBindings map[string][]string) *TUIKeybindingsManager

NewKeybindingsManager creates a manager over an explicit definition table. Mirrors upstream `new KeybindingsManager(definitions, userBindings)`; the coding agent passes its merged tui.* and app.* table here so components in this package resolve app actions (tree labels, thinking save) through the same manager, as upstream's single KEYBINDINGS table does.

func NewTUIKeybindingsManager

func NewTUIKeybindingsManager(userBindings map[string][]string) *TUIKeybindingsManager

NewTUIKeybindingsManager creates a manager with the built-in TUI definitions for this host and optional user overrides.

func (*TUIKeybindingsManager) GetConflicts

func (m *TUIKeybindingsManager) GetConflicts() []TUIKeybindingConflict

GetConflicts returns any user-binding conflicts detected.

func (*TUIKeybindingsManager) GetDefinition

func (m *TUIKeybindingsManager) GetDefinition(action TUIKeybinding) (TUIKeybindingDef, bool)

GetDefinition returns the definition for a keybinding action.

func (*TUIKeybindingsManager) GetKeys

func (m *TUIKeybindingsManager) GetKeys(action TUIKeybinding) []string

GetKeys returns the resolved keys for a keybinding action.

func (*TUIKeybindingsManager) GetResolvedBindings

func (m *TUIKeybindingsManager) GetResolvedBindings() map[string]any

GetResolvedBindings returns the fully resolved binding table after applying defaults and user overrides. Mirrors upstream getResolvedBindings().

func (*TUIKeybindingsManager) GetUserBindings

func (m *TUIKeybindingsManager) GetUserBindings() map[string][]string

GetUserBindings returns a defensive copy of the raw user overrides. Mirrors upstream KeybindingsManager.getUserBindings().

func (*TUIKeybindingsManager) HasBinding

func (m *TUIKeybindingsManager) HasBinding(action TUIKeybinding) bool

HasBinding reports whether the manager owns an action, including an explicit empty user override for an app.* action bridged from coding-agent.

func (*TUIKeybindingsManager) Matches

func (m *TUIKeybindingsManager) Matches(data string, action TUIKeybinding) bool

Matches checks whether raw terminal input data matches a keybinding action. Uses the same keyIDInputs lookup table as the app-level keybindings for legacy terminal sequence matching.

func (*TUIKeybindingsManager) SetUserBindings

func (m *TUIKeybindingsManager) SetUserBindings(bindings map[string][]string)

SetUserBindings replaces user overrides and rebuilds.

type TUIRenderState

type TUIRenderState struct {
	PrevLines         []string
	PrevWidth         int
	PrevHeight        int
	CursorRow         int
	HardwareCursorRow int
	MaxLinesRendered  int
	PrevViewportTop   int
}

Stop cleanly shuts down the TUI. Moves the cursor to the end of rendered content, writes a newline, and shows the cursor. This preserves the screen content so the user sees the final state after exit. Mirrors upstream tui.ts stop() (lines 473-494). TUIRenderState is a snapshot of the main-screen renderer's inline-flow render state. It lets InteractiveMode preserve regular-mode scrollback position across a live tui-mode switch (a fullscreen round-trip discards and rebuilds the renderer). Mirrors upstream TuiMainScreenRenderState (tui-main-screen.ts:46).

type Terminal

type Terminal interface {
	// Start owns input framing, negotiation filtering and native normalization before invoking onInput for each event. The resize callback follows terminal dimension changes.
	Start(onInput func([]byte), onResize func()) error

	// Stop reverses Start: cancels and joins the input goroutine, removes the
	// resize handler, and restores cooked mode without draining unread input.
	// Call DrainInput explicitly before Stop only at process shutdown.
	Stop()

	DrainInput(maxWait, idleWait time.Duration) error
	Write(data string)
	Columns() int
	Rows() int
	KittyProtocolActive() bool
	MoveBy(lines int)
	HideCursor()
	ShowCursor()
	ClearLine()
	ClearFromCursor()
	ClearScreen()
	SetTitle(title string)
	SetProgress(active bool)
}

Terminal mirrors the control surface of upstream `terminal.ts` in Go form.

Faithful port note: upstream's `start(onInput, onResize)` / `stop()` pair is provided here as `Start` / `Stop`. They are thin wrappers over `EnterRawMode` + a goroutine input loop + SIGWINCH notify, so legacy caller-owns-loop code paths (interactive mode, session selectors, the extension UI) keep working through `EnterRawMode` directly. New callers can use `Start`/`Stop` for a behavior-equivalent surface to upstream.

type TerminalBackgroundColorResult

type TerminalBackgroundColorResult struct {
	Color *RgbColor
	Err   error
}

TerminalBackgroundColorResult is the completion of a background query. Color is nil for a timeout or an unparseable reply; Err reports a failed terminal write.

type TerminalCapabilities

type TerminalCapabilities struct {
	Images     ImageProtocol
	TrueColor  bool
	Hyperlinks bool
}

func DetectCapabilities

func DetectCapabilities(tmuxForwardsHyperlink func() bool) TerminalCapabilities

DetectCapabilities mirrors upstream detectCapabilities: PI_HYPERLINKS, PI_IMAGE_PROTOCOL, and PI_TRUE_COLOR override auto-detection, and an explicit PI_HYPERLINKS replaces the tmux probe. A nil tmuxForwardsHyperlink uses the default tmux probe.

func GetCapabilities

func GetCapabilities() TerminalCapabilities

GetCapabilities mirrors upstream getCapabilities: detection with the PI_* environment, then the settings overrides on top.

type TerminalColorQueryOptions

type TerminalColorQueryOptions struct {
	TimeoutMs float64
}

TerminalColorQueryOptions specifies the terminal query deadline in milliseconds.

type TerminalColorScheme

type TerminalColorScheme = TerminalTheme

TerminalColorScheme is the terminal's dark or light palette preference.

func ParseTerminalColorSchemeReport

func ParseTerminalColorSchemeReport(data string) TerminalColorScheme

ParseTerminalColorSchemeReport returns the last scheme in a complete sequence of palette reports, or an empty value for nonmatching input.

type TerminalInput

type TerminalInput struct {
	C <-chan time.Time
	// contains filtered or unexported fields
}

TerminalInput owns framing and protocol-response deadlines for one input loop. The caller serializes Process, Flush, FlushPending, and Close, and selects C alongside raw input. Callbacks run synchronously in sequence order; the dispatch owner applies native modifier normalization once before focus routing.

func NewTerminalInput

func NewTerminalInput(onInput func(string)) *TerminalInput

NewTerminalInput constructs the process terminal's decoder for a caller-owned input loop.

func (*TerminalInput) Close

func (p *TerminalInput) Close()

Close stops owned timers and discards pending input without dispatching it. It can be called from the input callback to stop the rest of a batch.

func (*TerminalInput) Flush

func (p *TerminalInput) Flush()

Flush dispatches expired framing and negotiation deadlines in chronological order.

func (*TerminalInput) FlushPending

func (p *TerminalInput) FlushPending()

FlushPending delivers any remaining input when the source reaches EOF.

func (*TerminalInput) Process

func (p *TerminalInput) Process(data []byte)

Process decodes a UTF-8 terminal read and dispatches complete sequences. Input ready alongside a timeout is processed first, so continuations can finish their pending sequence.

type TerminalTheme

type TerminalTheme string

func GetThemeForRgbColor

func GetThemeForRgbColor(rgb RgbColor) TerminalTheme

type TerminalThemeDetection

type TerminalThemeDetection struct {
	Theme      TerminalTheme
	Source     string
	Detail     string
	Confidence string
}

func DetectTerminalBackground

func DetectTerminalBackground(options TerminalThemeDetectionOptions) TerminalThemeDetection

DetectTerminalBackground parses COLORFGBG with JavaScript whitespace and decimal-prefix semantics, then falls back to a low-confidence dark theme when no index is valid.

type TerminalThemeDetectionOptions

type TerminalThemeDetectionOptions struct {
	Env map[string]string
}

type Text

type Text struct {
	Content    string
	PaddingX   int
	PaddingY   int
	CustomBgFn func(string) string
	Style      string // pig compatibility: extra ANSI prefix applied per line
	// contains filtered or unexported fields
}

Text component - displays multi-line text with word wrapping.

func NewPaddedText

func NewPaddedText(content string, paddingX, paddingY int, bgFn func(string) string) *Text

NewPaddedText creates a text component with explicit padding.

func NewText

func NewText(content string) *Text

NewText creates a text component. pig keeps zero padding as the default for existing call sites; upstream-style padding is available via fields.

func (*Text) Invalidate

func (t *Text) Invalidate()

func (*Text) IsDirty

func (i *Text) IsDirty() bool

func (*Text) NeedsRedraw

func (i *Text) NeedsRedraw() bool

func (*Text) Render

func (t *Text) Render(width int) []string

func (*Text) SetCustomBgFn

func (t *Text) SetCustomBgFn(bgFn func(string) string)

func (*Text) SetText

func (t *Text) SetText(content string)

type TextInput

type TextInput struct {
	Focused bool

	OnSubmit func(string)
	OnEscape func()
	// contains filtered or unexported fields
}

TextInput is a single-line input with UTF-16 cursor offsets and grapheme-aware editing. Unpaired UTF-16 units use the internal WTF-8 string representation.

func NewInput

func NewInput(options InputOptions) *TextInput

NewInput creates upstream Input's callback-driven component, initially unfocused.

func NewTextInput

func NewTextInput(_ string) *TextInput

NewTextInput creates a host-owned confirmation input. The title is supplied by its enclosing dialog; Done and Cancelled report completion.

func (*TextInput) Cancelled

func (t *TextInput) Cancelled() bool

func (*TextInput) Done

func (t *TextInput) Done() bool

func (*TextInput) GetValue

func (t *TextInput) GetValue() string

GetValue returns the current JavaScript string, retaining unpaired UTF-16 units.

func (*TextInput) HandleInput

func (t *TextInput) HandleInput(data string)

HandleInput applies one input event. Paste state spans chunks; submission and cancellation use the selected owner/callback contract.

func (*TextInput) HandleMouse

func (t *TextInput) HandleMouse(event TuiMouseEvent) *TuiMouseDispatchResult

HandleMouse places the UTF-16 cursor at the clicked grapheme and requests focus.

func (*TextInput) Invalidate

func (i *TextInput) Invalidate()

func (*TextInput) IsDirty

func (i *TextInput) IsDirty() bool

func (*TextInput) NeedsRedraw

func (i *TextInput) NeedsRedraw() bool

func (*TextInput) Render

func (t *TextInput) Render(width int) []string

Render returns the prompt, horizontally scrolled value and fake cursor. Cursor slicing follows UTF-16 even when setValue retained a surrogate-half offset.

func (*TextInput) SetFocused

func (t *TextInput) SetFocused(focused bool)

SetFocused records whether the input holds TUI focus; only a focused input emits the hardware-cursor marker.

func (*TextInput) SetText

func (t *TextInput) SetText(value string)

SetText sets the component text. Callback-driven Input retains its cursor as setValue does; host confirmation inputs prefill at the end.

func (*TextInput) SetValue

func (t *TextInput) SetValue(value string)

SetValue replaces the value and clamps the existing UTF-16 cursor without rounding surrogate-half positions.

func (*TextInput) Text

func (t *TextInput) Text() string

type Theme

type Theme struct {
	// Name of the theme (e.g. "dark", "light", or a custom name).
	Name string

	// ─── Core colors ─────────────────────────────────────────
	Accent  string // accent text (teal/cyan)
	Success string // green
	Error   string // red
	Warning string // yellow
	Muted   string // gray
	Dim     string // dim gray
	Text    string // default text (empty = terminal default)

	// ─── Border colors ───────────────────────────────────────
	Border       string // blue
	BorderAccent string // cyan
	BorderMuted  string // dark gray

	// ─── Background colors ───────────────────────────────────
	UserMessageBg      string // ANSI bg escape
	UserMessageText    string // fg text on user message bg
	ToolPendingBg      string // tool running
	ToolSuccessBg      string // tool completed successfully
	ToolErrorBg        string // tool failed
	ToolTitle          string // tool header text
	ToolOutput         string // tool output text (gray)
	SelectedBg         string // selected item bg
	CustomMessageBg    string // custom message bg
	CustomMessageText  string // custom message text
	CustomMessageLabel string // custom message label

	// ─── Markdown colors ─────────────────────────────────────
	MDHeading         string
	MDLink            string
	MDLinkUrl         string
	MDCode            string
	MDCodeBlock       string
	MDCodeBlockBorder string
	MDQuote           string
	MDQuoteBorder     string
	MDHr              string
	MDListBullet      string

	// ─── Diff colors ─────────────────────────────────────────
	ToolDiffAdded   string
	ToolDiffRemoved string
	ToolDiffContext string

	// ─── Syntax highlighting ─────────────────────────────────
	SyntaxComment     string
	SyntaxKeyword     string
	SyntaxFunction    string
	SyntaxVariable    string
	SyntaxString      string
	SyntaxNumber      string
	SyntaxType        string
	SyntaxOperator    string
	SyntaxPunctuation string

	// ─── Thinking level indicators ───────────────────────────
	ThinkingText    string
	ThinkingOff     string
	ThinkingMinimal string
	ThinkingLow     string
	ThinkingMedium  string
	ThinkingHigh    string
	ThinkingXhigh   string

	// ─── Misc ────────────────────────────────────────────────
	BashMode string // bash mode indicator

	// ─── Export colors (for HTML export) ─────────────────────
	ExportPageBg string // hex string (not ANSI)
	ExportCardBg string // hex string
	ExportInfoBg string // hex string

	// Reset escapes.
	BgClose string
	Reset   string
	// contains filtered or unexported fields
}

Theme holds the resolved color palette for the current session. All fields are pre-computed ANSI escape sequences (fg or bg).

func ActiveTheme

func ActiveTheme() *Theme

ActiveTheme returns the current theme.

func LoadBuiltinTheme

func LoadBuiltinTheme(name string) (*Theme, error)

LoadBuiltinTheme returns a built-in theme by name ("dark" or "light").

func LoadThemeFile

func LoadThemeFile(path string) (*Theme, error)

LoadThemeFile reads a theme JSON file and returns the resolved Theme, reporting invalid JSON with ECMAScript SyntaxError text.

func (*Theme) ANSIPalette

func (t *Theme) ANSIPalette() (map[string]string, map[string]string)

ANSIPalette returns every resolved token as foreground and background ANSI openings. It is used at process boundaries where theme helper functions cannot cross but their current immutable token table can.

func (*Theme) Bg

func (t *Theme) Bg(token string) string

Bg returns the ANSI background escape for a named color token. Mirrors upstream theme.bg(tokenName, text).

func (*Theme) ColorKeys

func (t *Theme) ColorKeys() []string

ColorKeys returns the color token names in their original JSON insertion order. Used by HTML export to emit CSS variables in the same order as upstream.

func (*Theme) ColorMode

func (t *Theme) ColorMode() ColorMode

ColorMode mirrors theme.ts Theme.getColorMode.

func (*Theme) Colors

func (t *Theme) Colors() map[string]string

Colors returns the resolved theme colors as CSS values keyed by token name, with 256-color indexes converted to hex and terminal-default colors mapped to Pi's light/dark HTML fallback (theme.ts getResolvedThemeColors). Used by HTML export to mirror upstream CSS variable generation.

func (*Theme) Fg

func (t *Theme) Fg(token string) string

Fg returns the ANSI foreground escape for a named color token. Mirrors upstream theme.fg(tokenName, text). Returns empty string if token not found (terminal default).

func (*Theme) FgText

func (t *Theme) FgText(token, text string) string

FgText returns text wrapped in the foreground color and reset. Mirrors upstream theme.fg(tokenName, text).

func (*Theme) Inverse

func (t *Theme) Inverse(text string) string

Inverse wraps text in reverse video. Mirrors upstream theme.inverse().

func (*Theme) WithColorMode

func (t *Theme) WithColorMode(mode ColorMode) *Theme

WithColorMode returns this theme resolved in mode, mirroring theme.ts createTheme(themeJson, mode). Rebuilt themes are not cached, so obsolete themes can be collected. A theme without JSON source is returned unchanged. The variant keeps the theme's name: it is the same theme in another mode, and a registry entry activated by name must stay that name even when its JSON names another theme.

type ThemeColorValue

type ThemeColorValue struct {
	Text    string
	Index   int
	IsIndex bool
	// contains filtered or unexported fields
}

ThemeColorValue mirrors theme-json.ts ColorValue: a hex color, variable reference or empty string (Text), or a 256-color palette index (Index, when IsIndex is set).

func (*ThemeColorValue) UnmarshalJSON

func (v *ThemeColorValue) UnmarshalJSON(data []byte) error

UnmarshalJSON accepts a JSON string or an integral JSON number. The 0..255 range is enforced by ValidateThemeJSON for user-authored themes.

type ThemeJSON

type ThemeJSON struct {
	Name   string                     `json:"name"`
	Vars   map[string]ThemeColorValue `json:"vars"`
	Colors map[string]ThemeColorValue `json:"colors"`
	Export map[string]ThemeColorValue `json:"export,omitempty"`
	// contains filtered or unexported fields
}

ThemeJSON is the upstream-compatible theme file schema. Mirrors upstream theme-schema.json.

type ThemeRegistry

type ThemeRegistry struct {
	// contains filtered or unexported fields
}

ThemeRegistry holds all loaded themes and enables switching.

func ActiveThemeRegistry

func ActiveThemeRegistry() *ThemeRegistry

ActiveThemeRegistry returns the global theme registry. Initializes with built-in themes on first call.

func NewThemeRegistry

func NewThemeRegistry() *ThemeRegistry

NewThemeRegistry creates a registry with the built-in dark and light themes.

func (*ThemeRegistry) Add

func (r *ThemeRegistry) Add(t *Theme)

Add registers a theme. If a theme with the same name already exists, it is replaced. The name is derived from the theme's Name field.

func (*ThemeRegistry) AddFile

func (r *ThemeRegistry) AddFile(t *Theme, path string)

AddFile registers a theme loaded from path and records path as its source, which the startup resource listing and getAllThemes report.

func (*ThemeRegistry) Get

func (r *ThemeRegistry) Get(name string) *Theme

Get returns a theme by name, or nil.

func (*ThemeRegistry) LoadDir

func (r *ThemeRegistry) LoadDir(dir string) error

LoadDir scans a directory for .json theme files and registers them, recording each theme's source file so extensions can report it.

func (*ThemeRegistry) Names

func (r *ThemeRegistry) Names() []string

Names returns the available theme names in registration order as a defensive copy.

func (*ThemeRegistry) PathOf

func (r *ThemeRegistry) PathOf(name string) string

PathOf returns the file a theme was loaded from, or "" for built-ins.

type ThemeSelectorComponent

type ThemeSelectorComponent struct {
	// contains filtered or unexported fields
}

ThemeSelectorComponent renders a theme picker with live preview.

func NewThemeSelector

func NewThemeSelector(
	currentTheme string,
	onSelect func(string),
	onCancel func(),
	onPreview func(string),
) *ThemeSelectorComponent

NewThemeSelector creates a theme selector. currentTheme is pre-selected; onPreview fires on cursor movement for live preview.

func (*ThemeSelectorComponent) HandleInput

func (ts *ThemeSelectorComponent) HandleInput(data string)

HandleInput delegates to the list.

func (*ThemeSelectorComponent) Invalidate

func (i *ThemeSelectorComponent) Invalidate()

func (*ThemeSelectorComponent) IsDirty

func (i *ThemeSelectorComponent) IsDirty() bool

func (*ThemeSelectorComponent) List

List returns the underlying FilterableList for input handling.

func (*ThemeSelectorComponent) NeedsRedraw

func (i *ThemeSelectorComponent) NeedsRedraw() bool

func (*ThemeSelectorComponent) Render

func (ts *ThemeSelectorComponent) Render(width int) []string

Render wraps the list with borders.

type ThemeWatcher

type ThemeWatcher struct {
	// contains filtered or unexported fields
}

ThemeWatcher owns native notifications and the reload worker for one interactive mode. Close cancels and joins the worker. Dispatch transfers publication to the UI owner; file reading and color resolution stay on the worker.

func StartThemeWatcher

func StartThemeWatcher(ctx context.Context, directory string, dispatch func(context.Context, func()) error) *ThemeWatcher

StartThemeWatcher enables custom-theme watching for the selected name. The caller owns Close. A nil dispatcher publishes directly for non-UI callers.

func (*ThemeWatcher) Close

func (w *ThemeWatcher) Close()

Close stops notifications and drains owned reload work. Already queued UI actions check cancellation and generation before publishing.

type ThinkingBlock

type ThinkingBlock struct {
	// contains filtered or unexported fields
}

ThinkingBlock is a TUI component that renders a thinking/reasoning block.

func NewThinkingBlock

func NewThinkingBlock(hidden bool) *ThinkingBlock

NewThinkingBlock creates a thinking block. Pass hidden=true when the user has toggled visibility off (Ctrl+T). Content starts empty (invisible).

func (*ThinkingBlock) Content

func (b *ThinkingBlock) Content() string

Content returns the current thinking text.

func (*ThinkingBlock) Invalidate

func (i *ThinkingBlock) Invalidate()

func (*ThinkingBlock) IsDirty

func (i *ThinkingBlock) IsDirty() bool

func (*ThinkingBlock) NeedsRedraw

func (i *ThinkingBlock) NeedsRedraw() bool

func (*ThinkingBlock) Render

func (b *ThinkingBlock) Render(width int) []string

Render implements Component. Returns nil/empty when content is empty (invisible, takes zero height).

func (*ThinkingBlock) SetContent

func (b *ThinkingBlock) SetContent(content string)

SetContent updates the thinking text (streaming or final).

func (*ThinkingBlock) SetHidden

func (b *ThinkingBlock) SetHidden(hidden bool)

SetHidden controls whether the full text or a "Thinking..." indicator is shown.

type ToolDefinitionRenderers

type ToolDefinitionRenderers struct {
	Self   bool
	Call   func(ToolRenderInput) (Component, bool)
	Result func(ToolRenderInput) (Component, bool)
}

ToolDefinitionRenderers is a registered tool definition as the card draws it. Call and Result run the definition's renderCall and renderResult for the card's current state and return the component. They report false when the definition has no such renderer or the renderer failed; the card then draws upstream's fallback. Self is renderShell "self".

type ToolExecutionComponent

type ToolExecutionComponent struct {
	Name  string
	Label string // human-readable display name (if set, used in header instead of Name)
	// ArgsPreview is a short human-readable rendering of the tool args.
	// Build it with FormatToolArgs() before assigning, or use SetRunning().
	ArgsPreview string

	// Cwd is the session working directory, used to resolve relative tool
	// paths to absolute file:// URLs for OSC-8 hyperlinks in the header.
	Cwd string

	State  ToolExecutionState
	Output string

	// Collapsed controls the renderer's expanded state. New tool cards start
	// collapsed to match upstream; final results may apply tool-specific rules.
	Collapsed bool

	// Elapsed is shown on done/error states when > 0.
	Elapsed time.Duration

	// StartedAt records when the tool began executing. Used to render a live
	// "Elapsed X.Xs" footer while a shell tool runs (mirrors upstream bash.ts
	// renderResult, which ticks the elapsed every second during execution).
	StartedAt time.Time

	// Configurable thresholds. Zero values fall back to defaults.
	AutoCollapseLines int // default 8
	BodyMaxLines      int // default 40

	// BodyRenderer, when non-nil, replaces the default plain-text body
	// rendering. Used for per-tool rich displays: unified diff for
	// edit, line-numbered output for read, etc. The function receives
	// the available width and the current expanded state so it can show
	// a truncated preview or full output depending on Ctrl+O toggle.
	//
	// When set, the line-count annotation in the header is computed
	// from the renderer's row count instead of the raw Output text so
	// `(N lines, 1.2s)` accurately reflects what the user can see.
	BodyRenderer func(width int, expanded bool) []string

	// ImageBlocks holds image content blocks from tool results.
	// When non-empty and ShowImages is true, they render after the body.
	// Mirrors upstream tool-execution.ts imageComponents/imageSpacers.
	ImageBlocks []ImageBlock

	// ShowImages controls whether ImageBlocks are rendered.
	// Mirrors upstream ToolExecutionOptions.showImages.
	ShowImages bool

	// ImageWidthCells caps the width of rendered images in columns.
	// Mirrors upstream ToolExecutionOptions.imageWidthCells (default 60).
	ImageWidthCells int

	// IsPartial mirrors upstream tool-execution.ts isPartial. true while
	// the tool is still being streamed/executed, false after final result.
	// Controls the pending bg tint before execution completes.
	IsPartial bool
	// contains filtered or unexported fields
}

ToolExecutionComponent renders one tool call in the chat transcript.

Visual model (mirrors upstream per-tool renderCall functions):

$ expr 20 + 22             ← bash: bold "$ <command>"
read README.md             ← read: bold "read <path>"
write out.txt              ← write: bold "write <path>"
edit main.go               ← edit: bold "edit <path>"
grep /pattern/ in .           ← grep: bold "grep /<pat>/ in <path>"
find *.go in .             ← find: bold "find <pat> in <path>"
ls src/                    ← ls: bold "ls <path>"

No lifecycle markers (✓/▶/✗): upstream conveys state only via background color (pending, success, error). No "(N lines, Xs)" annotation in the header: upstream shows duration in body footer.

State transitions:

  • SetRunning: state → Running, output cleared
  • SetResult: state → Done or Error, body filled

Output thresholds:

  • autoCollapseLines: outputs longer than this start collapsed (overridden to expanded for errors)
  • bodyMaxLines: lines shown in the expanded view; overflow shows a "\u2026 (N more lines)" footer line.

func NewToolExecutionComponent

func NewToolExecutionComponent(name, argsPreview string) *ToolExecutionComponent

NewToolExecutionComponent returns a Running-state component for the given tool. Args may be empty.

func (*ToolExecutionComponent) ApplyConvertedImage

func (c *ToolExecutionComponent) ApplyConvertedImage(req KittyImageConversion, converted *ConvertedImage) bool

ApplyConvertedImage mirrors the resolution half of upstream maybeConvertImagesForKitty. A failed conversion (nil) or one that finishes after its image block was replaced is ignored (upstream issue #8577); otherwise the conversion is cached and the component invalidated. It reports whether the conversion was applied, so the caller knows to request a render.

func (*ToolExecutionComponent) Collapse

func (c *ToolExecutionComponent) Collapse()

Collapse forces the body closed.

func (*ToolExecutionComponent) Expand

func (c *ToolExecutionComponent) Expand()

Expand forces the body open.

func (*ToolExecutionComponent) FinalizeAborted

func (c *ToolExecutionComponent) FinalizeAborted(elapsed time.Duration)

FinalizeAborted freezes a still-running tool when its turn is aborted mid-execution. It transitions out of Running so the live "Elapsed X.Xs" footer stops recomputing time.Since(StartedAt) on every subsequent render (which otherwise forced a repaint on every keystroke and agent chunk, breaking terminal scrollback) while keeping any partial streamed output. No-op if the tool already reached a terminal state.

func (*ToolExecutionComponent) HandleMouse

HandleMouse delegates to nested renderer components before toggling a completed or partial result. Images and the outer spacer never toggle the card.

func (*ToolExecutionComponent) HasDefinition

func (c *ToolExecutionComponent) HasDefinition() bool

HasDefinition reports whether the card draws a registered tool definition.

func (*ToolExecutionComponent) Invalidate

func (c *ToolExecutionComponent) Invalidate()

Invalidate marks the card for redraw. A card with a definition also reruns its renderers, as upstream ToolExecutionComponent.invalidate calls updateDisplay.

func (*ToolExecutionComponent) IsDirty

func (c *ToolExecutionComponent) IsDirty() bool

IsDirty reports whether the component needs re-rendering. While a shell tool runs, the live "Elapsed X.Xs" footer recomputes time.Since(StartedAt) on every frame driven by the 100ms tick loop, but the tick does not Invalidate this component. Reporting dirty while that footer is live keeps the per-child render cache from freezing the elapsed counter.

func (*ToolExecutionComponent) MarkExecutionStarted

func (c *ToolExecutionComponent) MarkExecutionStarted()

MarkExecutionStarted records that the tool has begun executing. Mirrors upstream tool-execution.ts markExecutionStarted.

func (*ToolExecutionComponent) NeedsRedraw

func (i *ToolExecutionComponent) NeedsRedraw() bool

func (*ToolExecutionComponent) PendingKittyImageConversions

func (c *ToolExecutionComponent) PendingKittyImageConversions() []KittyImageConversion

PendingKittyImageConversions mirrors the selection half of upstream maybeConvertImagesForKitty: on a Kitty terminal it returns every image block with data and a MIME type that is not PNG and has no conversion cached for its current source. The caller converts each one off the UI loop and hands the result to ApplyConvertedImage on the loop.

func (*ToolExecutionComponent) Render

func (c *ToolExecutionComponent) Render(width int) []string

Render emits lifecycle-colored tool content followed by images. Definition-backed tools use their Box or self shell; native built-ins retain the same padded content layout.

func (*ToolExecutionComponent) ResultValue

func (c *ToolExecutionComponent) ResultValue() any

ResultValue returns the structured result recorded by SetResultValue.

func (*ToolExecutionComponent) SetArgsComplete

func (c *ToolExecutionComponent) SetArgsComplete()

SetArgsComplete records that the args JSON is finalized. Mirrors upstream tool-execution.ts setArgsComplete.

func (*ToolExecutionComponent) SetDefinition

func (c *ToolExecutionComponent) SetDefinition(definition *ToolDefinitionRenderers, args json.RawMessage)

SetDefinition makes the card draw a registered tool definition as upstream does, instead of the built-in or generic presentation. args are the call's current arguments.

func (*ToolExecutionComponent) SetDefinitionArgs

func (c *ToolExecutionComponent) SetDefinitionArgs(args json.RawMessage)

SetDefinitionArgs replaces the arguments the definition's renderers receive, as upstream updateArgs does.

func (*ToolExecutionComponent) SetExpanded

func (c *ToolExecutionComponent) SetExpanded(expanded bool)

SetExpanded forces the body open or closed and records the user's intent so subsequent SetResult calls don't snap it back. Used by global Ctrl+O (toggle-all-tools) so every component lands in the same state.

func (*ToolExecutionComponent) SetHeaderArgs

func (c *ToolExecutionComponent) SetHeaderArgs(args json.RawMessage)

SetHeaderArgs records the call arguments the collapsed read card's compact label is drawn from.

func (*ToolExecutionComponent) SetImageWidthCells

func (c *ToolExecutionComponent) SetImageWidthCells(width int)

SetImageWidthCells updates the max image width. Mirrors upstream setImageWidthCells.

func (*ToolExecutionComponent) SetResult

func (c *ToolExecutionComponent) SetResult(output string, isError bool, elapsed time.Duration)

SetResult finalises the component with output text and an error flag, applying the auto-collapse rule unless the user has already toggled.

func (*ToolExecutionComponent) SetResultValue

func (c *ToolExecutionComponent) SetResultValue(result any)

SetResultValue records the structured tool result, partial while the tool runs, that the definition's result renderer receives.

func (*ToolExecutionComponent) SetRunning

func (c *ToolExecutionComponent) SetRunning(argsPreview string)

SetRunning marks the component as in-flight with the given pre-formatted args preview. Idempotent.

func (*ToolExecutionComponent) SetShowImages

func (c *ToolExecutionComponent) SetShowImages(show bool)

SetShowImages toggles image rendering. Mirrors upstream setShowImages.

func (*ToolExecutionComponent) SetStreaming

func (c *ToolExecutionComponent) SetStreaming(snapshot string)

SetStreaming updates the live output body during execution without changing expansion state. Only SetExpanded or Toggle changes that state while running.

func (*ToolExecutionComponent) SetStructuredArgs

func (c *ToolExecutionComponent) SetStructuredArgs(args json.RawMessage)

SetStructuredArgs enables the generic extension tool-details renderer and retains a valid argument value for width-aware collapsed and expanded views.

func (*ToolExecutionComponent) Toggle

func (c *ToolExecutionComponent) Toggle()

Toggle flips the collapsed state and records that the user touched it so subsequent SetResult calls don't snap it back.

func (*ToolExecutionComponent) UpdateArgs

func (c *ToolExecutionComponent) UpdateArgs(name string, partialArgsJSON string)

UpdateArgs updates the displayed header from partial/complete args. Called progressively during streaming as ToolCallDelta events arrive. Mirrors upstream tool-execution.ts updateArgs.

type ToolExecutionState

type ToolExecutionState int

ToolExecutionState is the lifecycle stage of a tool call display.

const (
	ToolStateRunning ToolExecutionState = iota
	ToolStateDone
	ToolStateError
)

type ToolRenderInput

type ToolRenderInput struct {
	Args             json.RawMessage
	ExecutionStarted bool
	ArgsComplete     bool
	IsPartial        bool
	Expanded         bool
	ShowImages       bool
	IsError          bool
}

ToolRenderInput is the card state upstream ToolExecutionComponent passes to a registered tool definition's renderers.

type TreeNode

type TreeNode interface {
	NodeID() string
	NodeLabel() string // single-line display, no \n
	NodeChildren() []TreeNode
}

TreeNode is the shape TreeSelect operates on. SessionTreeNode in codingagent satisfies this via a thin adapter.

type TreeNodeSearchableText

type TreeNodeSearchableText interface {
	// NodeSearchableText returns the lowercase-matchable text for the
	// node, excluding any ANSI formatting.
	NodeSearchableText() string
}

TreeNodeSearchableText is implemented by adapters that expose the plain-text a type-to-search query is matched against. Mirrors upstream `getSearchableText` (tree-selector.ts:559-600): the label plus role, message content, and entry-type fields. Adapters that don't implement it are matched on their NodeLabel only.

type TreeNodeWithBranchLabel

type TreeNodeWithBranchLabel interface {
	// NodeBranchLabel returns the user-set branch label, or "" when none is set.
	NodeBranchLabel() string
}

TreeNodeWithBranchLabel is implemented by adapters that carry a user-set branch label. Upstream renders this label outside the entry text as theme.fg("warning", "[label] ") (tree-selector.ts:673); it must not be folded into NodeLabel(), otherwise it loses its warning colour and selected rows bold the label instead of only bolding entry content.

type TreeNodeWithCopyText

type TreeNodeWithCopyText interface {
	NodeCopyText() *string
}

TreeNodeWithCopyText exposes complete copyable entry content separately from its abbreviated display label.

type TreeNodeWithFilterTags

type TreeNodeWithFilterTags interface {
	// NodeFilterTags returns zero or more semantic tags. Stable per
	// node: the picker caches them at flatten time.
	NodeFilterTags() []string
}

TreeNodeWithFilterTags is implemented by adapters that classify nodes for filter-mode skip-sets. Settings, tool, user, and labeled tags drive the default, no-tools, user-only, labeled-only, and all modes; the usage tag hides a node in every mode. Adapters without tags remain visible in every mode.

type TreeNodeWithLabelTimestamp

type TreeNodeWithLabelTimestamp interface {
	// NodeLabelTimestamp returns the upstream wire-format timestamp
	// of the LabelEntry that set the label, or "" when no label is
	// set or no timestamp is available.
	NodeLabelTimestamp() string
}

TreeNodeWithLabelTimestamp is implemented by adapters that carry a user-set branch label with its set-time. When `T` toggles label timestamps on, the picker prepends `hh:mm` (or a longer form for cross-day stamps) to the row content. Adapters that don't implement this interface render with no timestamp - equivalent to upstream's silent-empty branch when `flatNode.node.labelTimestamp` is undefined (tree-selector.ts:678-682).

type TreeSelect

type TreeSelect struct {
	Title string
	// MaxVisibleLines is the number of tree rows shown at once. Upstream
	// TreeSelectorComponent uses max(5, floor(terminalHeight / 2)); see
	// TreeVisibleLines. Zero uses treeWindow.
	MaxVisibleLines int

	// OnLabelEdit is called when the user commits a label (Enter).
	// entryID is the target entry; label is the new name (empty string
	// clears any existing label, matching upstream undefined→delete).
	// The caller is responsible for persisting via Session.AppendLabelChange.
	OnLabelEdit func(entryID, label string)
	// OnCopy receives the full selected entry text, or nil when the entry has no copyable text.
	OnCopy func(*string)
	// contains filtered or unexported fields
}

TreeSelect overlay. Done()/Cancelled()/SelectedID() mirror the FilterableList contract.

func NewTreeSelect

func NewTreeSelect(title string, root TreeNode) *TreeSelect

NewTreeSelect builds a selector in the default filter mode.

func NewTreeSelectWithInitialFilter

func NewTreeSelectWithInitialFilter(title string, root TreeNode, initialFilterMode string) *TreeSelect

NewTreeSelectWithInitialFilter builds a selector whose first visibility pass uses initialFilterMode, mirroring the TreeSelectorComponent initialFilterMode argument (tree-selector.ts constructor). An unknown mode falls back to "default".

func (*TreeSelect) Cancelled

func (t *TreeSelect) Cancelled() bool

func (*TreeSelect) Done

func (t *TreeSelect) Done() bool

Done / Cancelled / SelectedID implement the modal contract.

func (*TreeSelect) HandleInput

func (t *TreeSelect) HandleInput(data string)

HandleInput moves the cursor, commits the selection, or delegates label editing to the shared Input.

Ctrl+Left/Alt+Left folds the highlighted branch or moves to the current branch segment start. Ctrl+Right/Alt+Right unfolds it or moves to the next branch segment. Shift+T toggles label timestamps. Colliding bindings use upstream's action priority.

func (*TreeSelect) Invalidate

func (i *TreeSelect) Invalidate()

func (*TreeSelect) IsDirty

func (i *TreeSelect) IsDirty() bool

func (*TreeSelect) NeedsRedraw

func (i *TreeSelect) NeedsRedraw() bool

func (*TreeSelect) Render

func (t *TreeSelect) Render(width int) []string

Render draws the header and tree rows or the active label input, followed by the closing border. Label hints show the current configured keys.

func (*TreeSelect) SelectedID

func (t *TreeSelect) SelectedID() string

func (*TreeSelect) SetInitialCursor

func (t *TreeSelect) SetInitialCursor(currentLeafID, initialSelectedID string)

SetInitialCursor orders and marks the active root-to-leaf path, then selects initialSelectedID or the current leaf. A hidden target resolves to its nearest visible ancestor. Call it after construction and before rendering.

type TruncatedText

type TruncatedText struct {
	Content  string
	MaxLines int
	PaddingX int
	PaddingY int
	// contains filtered or unexported fields
}

TruncatedText renders text truncated to fit viewport width.

func NewPaddedTruncatedText

func NewPaddedTruncatedText(content string, paddingX, paddingY int) *TruncatedText

NewPaddedTruncatedText creates a truncated text with padding.

func NewTruncatedText

func NewTruncatedText(content string, maxLines int) *TruncatedText

func (*TruncatedText) Invalidate

func (i *TruncatedText) Invalidate()

func (*TruncatedText) IsDirty

func (i *TruncatedText) IsDirty() bool

func (*TruncatedText) NeedsRedraw

func (i *TruncatedText) NeedsRedraw() bool

func (*TruncatedText) Render

func (t *TruncatedText) Render(width int) []string

type TuiAltScreen

type TuiAltScreen struct {
	// contains filtered or unexported fields
}

TuiAltScreen is the alternate-screen renderer. It embeds tuiBase for the shared render machinery (requestRender coalescing, overlays, terminal I/O).

func NewTuiAltScreen

func NewTuiAltScreen(options TuiAltScreenOptions) *TuiAltScreen

NewTuiAltScreen creates an alt-screen renderer writing to stdout at the current terminal size. Used in production by the fullscreen driver.

func NewTuiAltScreenWithOutput

func NewTuiAltScreenWithOutput(out io.Writer, cols, rows int, options TuiAltScreenOptions) *TuiAltScreen

NewTuiAltScreenWithOutput creates a fixed-size alt-screen renderer for tests.

func (*TuiAltScreen) ActiveOverlay

func (t *TuiAltScreen) ActiveOverlay() Component

ActiveOverlay refreshes overlay visibility and restores eligible focus before input dispatch. An active replacement keeps input until it changes focus, even if it is not mounted in the render tree.

func (*TuiAltScreen) CancelPendingRender

func (t *TuiAltScreen) CancelPendingRender()

CancelPendingRender invalidates a throttled frame, including one whose timer callback has already handed it to the owner loop. It maps the single-threaded JavaScript event-loop rule that a later state transition can consume a queued request before its callback runs.

func (*TuiAltScreen) ConsumeCellSizeResponse

func (t *TuiAltScreen) ConsumeCellSizeResponse(data string) bool

ConsumeCellSizeResponse reports whether data is a complete cell-size response. A response with positive dimensions updates the cell dimensions, invalidates every mounted component so images re-render at the new size, and requests a render; a response with a zero dimension is still consumed. Any other input returns false so it reaches the focused component. Mirrors upstream tui.ts consumeCellSizeResponse.

func (*TuiAltScreen) ConsumeOsc11BackgroundResponse

func (t *TuiAltScreen) ConsumeOsc11BackgroundResponse(data string) bool

ConsumeOsc11BackgroundResponse consumes one strict OSC 11 reply only when a query still owns a reply slot. Call it before terminal-input listeners or focused-component dispatch, including after a query timeout.

func (*TuiAltScreen) CopyActiveSelectionToClipboard

func (t *TuiAltScreen) CopyActiveSelectionToClipboard() bool

CopyActiveSelectionToClipboard copies the current selection and reports success.

func (*TuiAltScreen) Flash

func (t *TuiAltScreen) Flash(message string, durationMs int)

Flash shows a transient message in the alternate-screen flash stack.

func (*TuiAltScreen) FocusedComponent

func (t *TuiAltScreen) FocusedComponent() Component

FocusedComponent returns the current overlay or non-overlay focus target.

func (*TuiAltScreen) ForceFullRender

func (t *TuiAltScreen) ForceFullRender()

ForceFullRender marks the next frame as a full redraw. The alt-screen detects a full redraw when previousScreen is empty, so this resets the render state. Mirrors TUI.ForceFullRender (the main-screen sets forceRedraw, consumed by its differential renderer).

func (*TuiAltScreen) GetCopyOnSelect

func (t *TuiAltScreen) GetCopyOnSelect() bool

GetCopyOnSelect reports whether a completed selection is copied automatically.

func (*TuiAltScreen) GetShowHardwareCursor

func (t *TuiAltScreen) GetShowHardwareCursor() bool

GetShowHardwareCursor reports whether the real terminal cursor is shown. Mirrors upstream TUI.getShowHardwareCursor().

func (*TuiAltScreen) HandleFocusedSearchInput

func (t *TuiAltScreen) HandleFocusedSearchInput(data string) bool

HandleFocusedSearchInput delivers a key to the transcript search box when it has focus and reports whether it did. Upstream's TUI hands focused-component input to the search box itself; PiG's driver owns input routing, so the driver calls this where upstream would reach the focused component.

func (*TuiAltScreen) HandleViewportInput

func (t *TuiAltScreen) HandleViewportInput(data string) bool

HandleViewportInput routes a raw input chunk that targets the viewport: focus reports, mouse reports, and viewport keybindings. It returns true when it consumed the input so the driver does not dispatch it as a keystroke. Mirrors upstream handleViewportInput.

func (*TuiAltScreen) HasActiveSelection

func (t *TuiAltScreen) HasActiveSelection() bool

HasActiveSelection reports whether the fullscreen viewport has selected text.

func (*TuiAltScreen) HasOverlay

func (t *TuiAltScreen) HasOverlay() bool

HasOverlay reports whether any overlay entry is mounted. The interactive driver uses this for the upstream hasOverlayEntries renderer-switch guard.

func (*TuiAltScreen) Height

func (t *TuiAltScreen) Height() int

Height returns the current terminal height.

func (*TuiAltScreen) HideCursor

func (t *TuiAltScreen) HideCursor()

HideCursor hides the terminal cursor.

func (*TuiAltScreen) IsFollowingOutput

func (t *TuiAltScreen) IsFollowingOutput() bool

IsFollowingOutput reports whether the primary scroll view is pinned to the end.

func (*TuiAltScreen) IsSearchFocused

func (t *TuiAltScreen) IsSearchFocused() bool

IsSearchFocused reports whether the transcript search box has focus.

func (*TuiAltScreen) Mode

func (t *TuiAltScreen) Mode() string

Mode reports the renderer mode. Mirrors upstream `mode = "fullscreen"`.

func (*TuiAltScreen) OpenOverlay

func (t *TuiAltScreen) OpenOverlay(c Component, opts OverlayOptions) *OverlayHandle

OpenOverlay pushes a component onto the overlay append stack and returns a targeted handle. Callers must Close when the overlay is dismissed.

func (*TuiAltScreen) QueryCellSize

func (t *TuiAltScreen) QueryCellSize()

QueryCellSize writes the cell-size query when the terminal supports images, since only image rendering uses the cell size. Mirrors upstream tui.ts queryCellSize, which start() sends after the terminal starts.

func (*TuiAltScreen) QueryTerminalBackgroundColor

func (t *TuiAltScreen) QueryTerminalBackgroundColor(options TerminalColorQueryOptions) <-chan TerminalBackgroundColorResult

QueryTerminalBackgroundColor writes OSC 11 and returns a one-shot completion. A timed-out query retains its FIFO reply slot so a late reply cannot settle a newer query. Stop does not cancel these deadlines, matching the terminal query's independent Promise lifetime.

func (*TuiAltScreen) Render

func (t *TuiAltScreen) Render()

Render performs a differential render pass using inline-flow output.

Mirrors upstream pi-tui's `render()`. New content is appended with `\r\n`, which scrolls the viewport up and pushes older lines into the terminal's native scrollback. The terminal's normal scrolling makes our chat history reachable via the user's mouse wheel / Cmd-↑ after pig exits, just like a regular shell.

Algorithm sketch:

  1. Detect width/height change → fullRender(clear).
  2. First render → fullRender(no clear). Lines emitted with `\r\n` between them flow naturally.
  3. Diff prevLines vs newLines to find [firstChanged, lastChanged].
  4. If visible tail content shrinks and exposes rows above the old viewport, repaint only the new visible viewport.
  5. If only deletions remain, clear those rows in place.
  6. If firstChanged is above the current viewport → fullRender(clear).
  7. Otherwise: move cursor to firstChanged (scrolling if it's below the viewport bottom), rewrite affected lines, clear any extras.

func (*TuiAltScreen) RenderSnapshot

func (t *TuiAltScreen) RenderSnapshot(width int) []string

RenderSnapshot returns the rendered document lines at the given width. Mirrors TUI.RenderSnapshot; the alt-screen renders the layout root (or base children) at natural height, matching upstream render(width).

func (*TuiAltScreen) RepaintAll

func (t *TuiAltScreen) RepaintAll()

RepaintAll forces an immediate full repaint. Mirrors TUI.RepaintAll (which clears hasRendered then renders); the alt-screen clears its differential state.

func (*TuiAltScreen) RequestImmediateRender

func (t *TuiAltScreen) RequestImmediateRender()

RequestImmediateRender preempts a throttled frame and coalesces keyboard updates onto the next owner-loop turn. It exposes TuiBase.requestImmediateRender to the Go driver's separately owned input path.

func (*TuiAltScreen) RequestRender

func (t *TuiAltScreen) RequestRender()

RequestRender asks the TUI to render soon, coalescing repeated calls and enforcing the upstream 16ms frame throttle. Use this for hot streaming paths (thinking/text deltas); direct Render() is reserved for low-frequency state changes and final flushes.

func (*TuiAltScreen) ScrollBy

func (t *TuiAltScreen) ScrollBy(lines int)

ScrollBy scrolls the primary scroll view by the given number of lines.

func (*TuiAltScreen) ScrollToBottom

func (t *TuiAltScreen) ScrollToBottom()

ScrollToBottom scrolls the primary scroll view to its end.

func (*TuiAltScreen) ScrollToTop

func (t *TuiAltScreen) ScrollToTop()

ScrollToTop scrolls the primary scroll view to its start.

func (*TuiAltScreen) SetClearOnShrink

func (t *TuiAltScreen) SetClearOnShrink(bool)

SetClearOnShrink is a no-op for the alt-screen, which always repaints a full-height screen (clearing via \x1b[2J on full redraw) and has no clear-on-shrink heuristic. Present to satisfy the Renderer contract. Mirrors TUI.SetClearOnShrink, whose shrink behavior only applies to the inline-flow main-screen renderer.

func (*TuiAltScreen) SetCopyOnSelect

func (t *TuiAltScreen) SetCopyOnSelect(enabled bool)

SetCopyOnSelect changes automatic selection copy without rebuilding the renderer.

func (*TuiAltScreen) SetFixedSize

func (t *TuiAltScreen) SetFixedSize(cols, rows int)

SetFixedSize changes the size of a renderer built with a fixed size (NewWithOutput), as a terminal resize would; the next render sees it. Renderers that read the real terminal size ignore it.

func (*TuiAltScreen) SetFocus

func (t *TuiAltScreen) SetFocus(component Component)

SetFocus records a non-overlay target for focus restoration.

func (*TuiAltScreen) SetLayoutRoot

func (t *TuiAltScreen) SetLayoutRoot(component Component)

SetLayoutRoot installs the fullscreen layout tree (transcript scroll view + pinned footer). nil falls back to the implicit scroll view wrapping the base document. Mirrors upstream setLayoutRoot.

func (*TuiAltScreen) SetOnHeightChange

func (t *TuiAltScreen) SetOnHeightChange(fn func(height int))

SetOnHeightChange registers a callback that fires whenever the terminal height changes between render frames. Thread-safe.

func (*TuiAltScreen) SetOnWidthChange

func (t *TuiAltScreen) SetOnWidthChange(fn func(width int))

SetOnWidthChange registers a callback that fires whenever the terminal width changes between render frames. Thread-safe.

func (*TuiAltScreen) SetOverlayCommandDispatcher

func (t *TuiAltScreen) SetOverlayCommandDispatcher(dispatch func(func()))

SetOverlayCommandDispatcher installs the ordered ingress used by remote producers. The dispatcher owns command ordering on the application loop.

func (*TuiAltScreen) SetRenderDispatcher

func (t *TuiAltScreen) SetRenderDispatcher(dispatch func(render func()))

SetRenderDispatcher installs a hook that runs throttled scheduled renders on the caller's main loop. The dispatcher receives a render closure and is responsible for eventually invoking it on the goroutine that owns component-tree mutation (it may enqueue it on an event loop). When nil (default), scheduled renders run inline on the throttle-timer goroutine, which is correct for standalone / single-goroutine use. Thread-safe.

func (*TuiAltScreen) SetShowHardwareCursor

func (t *TuiAltScreen) SetShowHardwareCursor(enabled bool)

SetShowHardwareCursor toggles the hardware cursor and repaints if already rendered so the next frame emits the correct cursor visibility. Mirrors TUI.SetShowHardwareCursor.

func (*TuiAltScreen) SetTickDispatcher

func (t *TuiAltScreen) SetTickDispatcher(dispatch func(func()))

SetTickDispatcher installs the blocking owner-loop seam for owned state-machine ticks (alt-screen selection auto-scroll). It must marshal fn onto the loop that owns rendering, backpressuring rather than dropping while that loop is alive; see the tickOnMain doc. When unset the tick runs inline. Thread-safe.

func (*TuiAltScreen) ShowCursor

func (t *TuiAltScreen) ShowCursor()

ShowCursor shows the terminal cursor.

func (*TuiAltScreen) Start

func (t *TuiAltScreen) Start()

Start enters the alternate screen and begins rendering. The driver calls this once at session start. Mirrors upstream beforeTerminalStart + the enter write.

func (*TuiAltScreen) Stop

func (t *TuiAltScreen) Stop()

Stop tears down the alternate screen and reflows the transcript into the main-screen scrollback. Satisfies the Renderer interface (matching the driver's no-arg Stop call sites); use StopWithOptions for preserve-screen teardown.

func (*TuiAltScreen) StopWithOptions

func (t *TuiAltScreen) StopWithOptions(options StopOptions)

StopWithOptions tears down the alternate screen. Mirrors upstream beforeTerminalStop + afterTerminalStop.

func (*TuiAltScreen) ViewportTop

func (t *TuiAltScreen) ViewportTop() int

ViewportTop returns the primary scroll view's current scroll offset.

func (*TuiAltScreen) Width

func (t *TuiAltScreen) Width() int

Width returns the current terminal width.

func (*TuiAltScreen) WriteRaw

func (t *TuiAltScreen) WriteRaw(data string)

WriteRaw writes data to the terminal as is, as upstream's terminal.write does for a component that drives the terminal itself.

type TuiAltScreenOptions

type TuiAltScreenOptions struct {
	// WheelScrollLines is the number of logical lines moved per wheel event
	// (default 1).
	WheelScrollLines int
	// Mouse captures mouse events for viewport scrolling and selection.
	Mouse *bool
	// CopyOnSelect copies a completed text selection. The default is true.
	CopyOnSelect *bool
	// CopySelection writes selected text to the host clipboard. OSC 52 is used when nil.
	CopySelection func(text string) error
	// OpenURL activates an OSC 8 hyperlink on primary-button click.
	OpenURL func(url string)
	// SearchMatchStyle styles a non-current transcript search match.
	SearchMatchStyle func(text string) string
	// SearchCurrentMatchStyle styles the current transcript search match.
	SearchCurrentMatchStyle func(text string) string
	// SearchNavigationButtonStyle styles a transcript search navigation button.
	SearchNavigationButtonStyle func(text string, hovered bool) string
	// ScrollToEndIndicator renders a clickable jump-to-end label, centered on
	// the last row of a follow-end primary scroll view while that view is
	// scrolled away from its end.
	ScrollToEndIndicator func() string
	// OnRightClickPaste handles an unmodified secondary-button press for
	// clipboard paste. Currently enabled on Windows only.
	OnRightClickPaste func()
}

TuiAltScreenOptions configures the alt-screen renderer. Mirrors upstream TuiAltScreenOptions.

type TuiMouseButton

type TuiMouseButton string

TuiMouseButton mirrors upstream TuiMouseButton.

const (
	MouseButtonLeft   TuiMouseButton = "left"
	MouseButtonMiddle TuiMouseButton = "middle"
	MouseButtonRight  TuiMouseButton = "right"
	MouseButtonNone   TuiMouseButton = "none"
)

type TuiMouseDispatchResult

type TuiMouseDispatchResult struct {
	TuiMouseEventResult
	Target TuiMouseDispatchTarget
	// FocusTarget is the keyboard focus target, which may be a delegating
	// parent container. nil means Target.Component.
	FocusTarget Component
}

TuiMouseDispatchResult is a handled result bound to its target. Mirrors upstream TuiMouseDispatchResult. A handler returning a result whose Target.Component is nil has not been dispatched yet.

func DispatchMouseEvent

func DispatchMouseEvent(component Component, event TuiMouseEvent) *TuiMouseDispatchResult

DispatchMouseEvent dispatches an event to a component and retains the exact target and coordinate transform. Containers use it to forward events to nested children. Mirrors upstream dispatchMouseEvent.

type TuiMouseDispatchTarget

type TuiMouseDispatchTarget struct {
	Component Component
	OriginX   int
	OriginY   int
	Width     int
	Height    int
}

TuiMouseDispatchTarget records the exact component a mouse event reached and the coordinate transform used to reach it. Mirrors upstream TuiMouseDispatchTarget.

type TuiMouseEvent

type TuiMouseEvent struct {
	Type    TuiMouseEventType
	Button  TuiMouseButton
	X       int
	Y       int
	ScreenX int
	ScreenY int
	Width   int
	Height  int
	Shift   bool
	Alt     bool
	Ctrl    bool
	// WheelDelta is the logical line delta of a wheel event (negative scrolls
	// up); zero on every other event.
	WheelDelta int
	// ClickCount is the consecutive click count of a click event; zero on every
	// other event.
	ClickCount int
}

TuiMouseEvent is a normalized cell-based mouse event. Coordinates are zero-based. X/Y are local to the receiving component, ScreenX/ScreenY are absolute terminal coordinates, and Width/Height are the receiving component's current bounds. Mirrors upstream TuiMouseEvent.

func RetargetMouseEvent

func RetargetMouseEvent(event TuiMouseEvent, target TuiMouseDispatchTarget) TuiMouseEvent

RetargetMouseEvent recreates local coordinates for a previously dispatched mouse target. Mirrors upstream retargetMouseEvent.

type TuiMouseEventResult

type TuiMouseEventResult struct {
	// Handled stops propagation and suppresses renderer-level fallback behavior.
	Handled bool
	// Capture routes subsequent drag/release events to this component. Implies
	// Handled.
	Capture bool
	// Focus gives keyboard focus to this component. Implies Handled.
	Focus bool
	// Render explicitly requests (true) or suppresses (false) a render. nil
	// takes the default: move and release do not render; press, click, drag,
	// and wheel do.
	Render *bool
}

TuiMouseEventResult mirrors upstream TuiMouseEventResult.

type TuiMouseEventType

type TuiMouseEventType string

TuiMouseEventType mirrors upstream TuiMouseEventType.

const (
	MousePress   TuiMouseEventType = "press"
	MouseRelease TuiMouseEventType = "release"
	MouseMove    TuiMouseEventType = "move"
	MouseDrag    TuiMouseEventType = "drag"
	MouseClick   TuiMouseEventType = "click"
	MouseWheel   TuiMouseEventType = "wheel"
)

type UndoStack

type UndoStack[S any] struct {
	// contains filtered or unexported fields
}

UndoStack stores detached state snapshots for undo/redo style flows.

func (*UndoStack[S]) Clear

func (u *UndoStack[S]) Clear()

Clear removes all snapshots.

func (*UndoStack[S]) Len

func (u *UndoStack[S]) Len() int

Len reports the number of snapshots.

func (*UndoStack[S]) Pop

func (u *UndoStack[S]) Pop() (S, bool)

Pop returns the most recent snapshot.

func (*UndoStack[S]) Push

func (u *UndoStack[S]) Push(state S)

Push stores a snapshot.

type UserMessageBlock

type UserMessageBlock struct {
	// contains filtered or unexported fields
}

UserMessageBlock renders user Markdown in a padded background with OSC 133 zone markers. Closing markers prefix the existing bottom padding row and do not add height.

func NewUserMessageBlock

func NewUserMessageBlock(text string) *UserMessageBlock

NewUserMessageBlock preserves source list markers and backslash escapes in user text.

func (*UserMessageBlock) Dispose

func (u *UserMessageBlock) Dispose()

Dispose releases this message's pending Markdown generation.

func (*UserMessageBlock) Invalidate

func (u *UserMessageBlock) Invalidate()

Invalidate also invalidates the child Markdown transform state so display transformers run again.

func (*UserMessageBlock) IsDirty

func (i *UserMessageBlock) IsDirty() bool

func (*UserMessageBlock) NeedsRedraw

func (i *UserMessageBlock) NeedsRedraw() bool

func (*UserMessageBlock) Render

func (u *UserMessageBlock) Render(width int) []string

func (*UserMessageBlock) SetAsyncMarkdownTransform

func (u *UserMessageBlock) SetAsyncMarkdownTransform(transform *AsyncMarkdownTransform)

SetAsyncMarkdownTransform installs an off-loop rewrite that completes before the message content is painted.

func (*UserMessageBlock) SetMarkdownTransform

func (u *UserMessageBlock) SetMarkdownTransform(transform func(string, int) string)

SetMarkdownTransform installs the display-only constructor transform at the message's available content width.

func (*UserMessageBlock) SetMarkdownTransformState

func (u *UserMessageBlock) SetMarkdownTransformState(fn func() string)

SetMarkdownTransformState declares the external state the installed transform reads, for the Markdown render cache key.

func (*UserMessageBlock) SetOutputPad

func (u *UserMessageBlock) SetOutputPad(padding int)

SetOutputPad changes horizontal content padding while retaining the Markdown child and its transform lifetime.

type UserMessageSelector

type UserMessageSelector struct {
	// contains filtered or unexported fields
}

UserMessageSelector renders the upstream /fork user-message picker in the editor slot. It mirrors user-message-selector.ts: a title, descriptive copy, dynamic borders, and a chronological user-message list with the newest message selected by default.

func NewUserMessageSelector

func NewUserMessageSelector(messages []string) *UserMessageSelector

NewUserMessageSelector creates a selector for chronological user-message texts (oldest to newest). The newest message is selected initially.

func (*UserMessageSelector) Cancelled

func (s *UserMessageSelector) Cancelled() bool

func (*UserMessageSelector) Done

func (s *UserMessageSelector) Done() bool

func (*UserMessageSelector) HandleInput

func (s *UserMessageSelector) HandleInput(data string)

func (*UserMessageSelector) Invalidate

func (i *UserMessageSelector) Invalidate()

func (*UserMessageSelector) IsDirty

func (i *UserMessageSelector) IsDirty() bool

func (*UserMessageSelector) NeedsRedraw

func (i *UserMessageSelector) NeedsRedraw() bool

func (*UserMessageSelector) Render

func (s *UserMessageSelector) Render(width int) []string

func (*UserMessageSelector) SelectedIndex

func (s *UserMessageSelector) SelectedIndex() int

SelectedIndex returns the selected chronological message index, or -1 when no message was selected.

type VStack

type VStack struct {
	*Stack
}

VStack ports pi-tui's VStack: children laid out top to bottom with flexbox heights.

func NewVStack

func NewVStack(children []StackChild, options StackOptions) *VStack

NewVStack constructs a vertical stack.

func (VStack) Invalidate

func (i VStack) Invalidate()

func (VStack) IsDirty

func (i VStack) IsDirty() bool

func (VStack) NeedsRedraw

func (i VStack) NeedsRedraw() bool

func (*VStack) Render

func (v *VStack) Render(width int) []string

Render ports upstream VStack.render.

type ViewportTUI

type ViewportTUI interface {
	Mode() string
	ViewportTop() int
	IsFollowingOutput() bool
	SetLayoutRoot(component Component)
}

ViewportTUI is implemented by renderers with an application-owned scrollable viewport (the alt-screen renderer). Mirrors upstream ViewportTUI; the driver uses it to set the fullscreen layout root. Upstream's VIEWPORT_TUI Symbol brand is expressed here as a distinct Go interface.

type VisualTruncateResult

type VisualTruncateResult struct {
	VisualLines  []string
	SkippedCount int
}

VisualTruncateResult holds truncated lines and a skip count.

func TruncateToVisualLines

func TruncateToVisualLines(text string, maxVisualLines, width int, paddingX ...int) VisualTruncateResult

TruncateToVisualLines truncates text to maxVisualLines from the end, wrapping lines at the given width. The optional padding matches Text's horizontal padding.

type WordNavigationOptions

type WordNavigationOptions struct {
	Segment         func(text string) iter.Seq[SegmentData]
	IsAtomicSegment func(segment string) bool
}

WordNavigationOptions replaces word segmentation or marks indivisible segments such as collapsed paste markers.

Source Files

Directories

Path Synopsis
Package widthx implements Pi's terminal width, grapheme and ANSI operations with JavaScript UTF-16 semantics.
Package widthx implements Pi's terminal width, grapheme and ANSI operations with JavaScript UTF-16 semantics.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL