Documentation
¶
Overview ¶
Package render turns theme roles into concrete lipgloss styles and renders structured event bodies (diffs, markdown, dialogs, headers) into styled text. Every function here is pure: input in, string out, no I/O and no package state.
Markdown renders CommonMark + GFM (headings, paragraphs, lists, ordered + task lists, blockquotes, fenced + indented + inline code, tables, links, horizontal rules, strikethrough, emphasis/strong) through charm.land/glamour/v2, mapped to the theme palette so a markdown block matches the rest of the screen at every colour tier.
Package render turns theme roles into concrete lipgloss styles and renders structured event bodies (diffs, minimal markdown) into styled text. Every function here is pure: input in, string out, no I/O, no package state.
Index ¶
- Constants
- func Bordered(t theme.Theme, tier theme.Tier, r theme.Role, width int, content string) string
- func BorderedWithHint(t theme.Theme, tier theme.Tier, r, hintRole theme.Role, width int, ...) string
- func Columns(gap int, rows [][]string) []string
- func ContextRole(pct int) theme.Role
- func Dialog(t theme.Theme, tier theme.Tier, width, height int, title, body, hint string) string
- func DialogBodyRows(height int) int
- func DialogBodyWidth(width int) int
- func DialogHitsBackdrop(width, height, contentRowCount, clickX, clickY int) bool
- func DialogHitsClose(width, height, contentRowCount, clickX, clickY int) bool
- func DialogNoBackdrop(t theme.Theme, tier theme.Tier, width, height int, title, body, hint string) string
- func DialogNoBackdropBodyRows(height int) int
- func DialogNoBackdropBodyWidth(width int) int
- func DialogNoBackdropHitsClose(width, height, clickX, clickY int) bool
- func Diff(t theme.Theme, tier theme.Tier, d uievent.Diff) string
- func DiffLineCount(d uievent.Diff) int
- func DiffLines(t theme.Theme, tier theme.Tier, d uievent.Diff) []string
- func FillBG(t theme.Theme, tier theme.Tier, r theme.Role, text string) string
- func FormatArgs(args map[string]any) string
- func FormatCommandOutput(t theme.Theme, tier theme.Tier, output string, ok bool, width int) ([]string, bool)
- func FormatDiagnosticsOutput(t theme.Theme, tier theme.Tier, output string, width int) []string
- func FormatDiffLines(t theme.Theme, tier theme.Tier, width int, d uievent.Diff) []string
- func FormatDispatchTasksOutput(t theme.Theme, tier theme.Tier, output string, width int) (string, []string)
- func FormatElapsed(ms int) string
- func FormatFileReadOutput(t theme.Theme, tier theme.Tier, output string, width int) ([]string, bool)
- func FormatFileReadOutputWithContext(t theme.Theme, tier theme.Tier, filePath string, startLine int, output string, ...) ([]string, bool)
- func FormatGrepOutput(t theme.Theme, tier theme.Tier, output string, width int) (string, []string)
- func FormatGrepOutputWithContext(t theme.Theme, tier theme.Tier, query, output string, width int) (string, []string)
- func FormatInspectRepositoryOutput(t theme.Theme, tier theme.Tier, output string, width int) (string, []string)
- func FormatJSONOutput(t theme.Theme, tier theme.Tier, output string, width int) []string
- func FormatLedgerOutput(t theme.Theme, tier theme.Tier, output string, width int) (string, []string)
- func FormatListDirOutput(t theme.Theme, tier theme.Tier, output string, width int) (string, []string)
- func FormatMemoryOutput(t theme.Theme, tier theme.Tier, output string, width int) (string, []string)
- func FormatMessagingOutput(t theme.Theme, tier theme.Tier, name string, args map[string]any, ...) (summary string, body []string, collapsible bool)
- func FormatOrchestrationRunOutput(t theme.Theme, tier theme.Tier, output string, width int) (string, []string)
- func FormatRunEventsOutput(t theme.Theme, tier theme.Tier, output string, width int) (string, []string)
- func FormatToolDetail(name string, args map[string]any) string
- func FormatToolOutput(t theme.Theme, tier theme.Tier, name, output string, ok bool, width int) (detail string, body []string, collapsible bool)
- func FormatToolOutputWithContext(t theme.Theme, tier theme.Tier, name string, args map[string]any, ...) (detail string, body []string, collapsible bool)
- func FormatWorkflowOutput(t theme.Theme, tier theme.Tier, output string, width int) (string, []string)
- func GroupThousands(n int) string
- func HardWrap(line string, width int) []string
- func Header(t theme.Theme, tier theme.Tier, width int, spec HeaderSpec) string
- func Help(t theme.Theme, tier theme.Tier, rows []keymap.HelpRow) string
- func HighlightCode(t theme.Theme, tier theme.Tier, filenameOrLang, code string) []string
- func HintFits(width int, hint string) bool
- func Lip(s theme.Style) lipgloss.Style
- func Markdown(t theme.Theme, tier theme.Tier, width int, in string) (out string)
- func ProgressBar(width, step, total int) string
- func ProseMeasure(width int) int
- func ReadOnlyToolClass(name string) string
- func Role(t theme.Theme, tier theme.Tier, r theme.Role) lipgloss.Style
- func Split(t theme.Theme, tier theme.Tier, width, height int, focus Side, ...) string
- func SplitAt(t theme.Theme, tier theme.Tier, width, height, leftWidth int, focus Side, ...) string
- func SplitAtDialog(t theme.Theme, tier theme.Tier, width, height, leftWidth int, navFocused bool, ...) string
- func SplitDialog(t theme.Theme, tier theme.Tier, width, height int, navFocused bool, ...) string
- func SplitDiff(t theme.Theme, tier theme.Tier, width int, d uievent.Diff) string
- func SplitDiffLines(t theme.Theme, tier theme.Tier, width int, d uievent.Diff) []string
- func SplitListDetail(listLines, detailLines []string, selectedLine, height int, notice string) string
- func SplitWidths(width int) (reading, nav int)
- func ThinkBadge(words int) string
- func UnwrapJSONString(payload string) string
- func WindowSlice(total, cursor, maxRows int) (start, end int)
- func WithBg(st lipgloss.Style, t theme.Theme, tier theme.Tier, r theme.Role) lipgloss.Style
- func Wrap(text string, measure int) []string
- type HeaderSpec
- type Side
Constants ¶
const MinSplitDiffWidth = 60
MinSplitDiffWidth is the minimum terminal width required to render a side-by-side split diff. Below this width, FormatDiffLines falls back to a clean unified diff to preserve legibility.
SplitNavMax caps the navigation pane's absolute width: a share of a very wide terminal is still too much list (30% of 300 columns is 90 columns of paths). Past the cap the reading pane takes everything extra.
SplitNavShare is the width share the navigation pane (a list the user picks from) takes in a two-pane split, in percent. 30 keeps a path list readable and leaves the reading pane the reading measure (gh-dash's list/detail ratio is the same shape).
Variables ¶
This section is empty.
Functions ¶
func Bordered ¶
Bordered wraps content in a rounded border whose colour is the given border role resolved at the tier. Like WithBg, a tier with no colour for the role (the no-colour/ASCII tiers) still draws the border, just uncoloured: the box is structure, and structure survives NO_COLOR.
width is the INNER width in cells; width <= 0 sizes the box to the content (lipgloss default). A caller whose content windows or scrolls must pass a fixed width, or the border breathes with every content change - the box must not move while the user reads it.
func BorderedWithHint ¶
func BorderedWithHint(t theme.Theme, tier theme.Tier, r, hintRole theme.Role, width int, content, hint string) string
BorderedWithHint wraps content in a rounded border with an optional right-aligned hint in the top border row, drawn in hintRole. The role is a parameter because the hint is not always the same kind of thing: the composer's is a key reminder (subtle), the approval prompt's names a state the reader must not miss (warning).
func Columns ¶
Columns aligns a table of pre-styled cells into columns: every column is padded to the widest cell that occupies it across the whole row set, so status/count fields land in the same screen column on every row instead of drifting with each row's own content width (the settings sections' failure mode this replaces).
gap is the number of plain spaces between one column's padded content and the next. Rows may carry a different number of cells (a "ragged" table): a column only exists where some row supplies it, and a shorter row is never padded past its own last cell, so it produces no trailing whitespace.
Cells may already carry ANSI styling; width is measured with ansi.StringWidth so padding accounts for display width, not byte length. Pure: input in, string slice out, no I/O and no package state.
func ContextRole ¶
ContextRole returns the semantic theme role for a context-fill percentage. The thresholds match the topbar's existing coloring contract (70/90) with an additional RoleInfo step below 70% to surface early signal in the status line, where the ctx pill currently renders with no color at any fill level.
pct >= 90 → RoleDanger (critical, matches existing topbar danger boundary) pct >= 70 → RoleWarning (caution, matches existing topbar warning boundary) pct >= 50 → RoleInfo (informational notice: context is in active use) pct < 50 → RoleFGSubtle (neutral; comparison-based so pct > 100 is still danger)
func Dialog ¶
Dialog renders title, body, and hint inside a bordered, inset-filled box centered on a width x height terminal. It is the one centered dialog primitive: this renderer has no compositing layer, so the dialog is the whole frame and the padding around the box carries the base background - the conversation behind it is not shown.
Content that does not fit is truncated, not scrolled: lines clip to the inner width and surplus body rows drop off the bottom. A scrolling body is deliberately out of scope for v1; every caller today (theme preview, model picker, help) fits or is better served by the pager for full-height reading.
Degrade tiers follow the same ladder as WithBg and Bordered: at ASCII/NoTTY the inset and base backgrounds contribute nothing (a colour fill without colour is broken), and the border stays as plain glyphs - structure survives NO_COLOR.
func DialogBodyRows ¶
DialogBodyRows is how many body rows a Dialog framed to height can show, after its margins, border, padding, title, separators, and hint. A caller that windows scrollable body content by rows must use this number: scrolling by a larger step leaves tail rows unreachable, because Dialog clips what does not fit.
func DialogBodyWidth ¶
DialogBodyWidth is the inner width a Dialog framed to width gives its body rows, after the same margin shrinking the clip applies. A caller that renders its own surface INTO the body (an embedded chat, not a plain string) sizes it to this so the clip never has to cut it.
func DialogHitsBackdrop ¶
DialogHitsBackdrop reports whether a click at (clickX, clickY) landed outside the centered dialog box.
func DialogHitsClose ¶
DialogHitsClose reports whether a click at (clickX, clickY) lands on the [x] close button area of a dialog centered on a width x height terminal.
func DialogNoBackdrop ¶
func DialogNoBackdrop(t theme.Theme, tier theme.Tier, width, height int, title, body, hint string) string
DialogNoBackdrop renders title, body, and hint inside a bordered, inset-filled dialog box that fills the given width x height exactly without any outer margin/backdrop.
func DialogNoBackdropBodyRows ¶
DialogNoBackdropBodyRows is how many body rows a DialogNoBackdrop framed to height can show (height less 2 border rows, 2 padding rows, and 3 title/separator/hint rows).
func DialogNoBackdropBodyWidth ¶
DialogNoBackdropBodyWidth is the inner width a DialogNoBackdrop framed to width gives its body rows (width less 2 border columns and 4 padding columns).
func DialogNoBackdropHitsClose ¶
DialogNoBackdropHitsClose reports whether a click at (clickX, clickY) lands on the [x] close button of a DialogNoBackdrop box sized to width x height.
func Diff ¶
Diff renders the hunks of a unified diff as styled text. Hunk headers use RoleDiffHunk; added/removed lines use the diff fg/bg role pairs; context lines use RoleFGMuted with no background.
It renders NO summary line. The path and the +N -M counts belong to the enclosing block's header, in its detail and meta columns (wireframes-panes.md section 11), and rendering them here too printed them twice.
func DiffLineCount ¶
DiffLineCount is how many lines Diff renders: one per hunk header plus one per diff line.
func DiffLines ¶
DiffLines is Diff as one string per rendered line, so surfaces that window into a diff (the scrollable approval preview) can slice it without re-parsing styled text.
func FillBG ¶
FillBG paints text onto role r's background.
A lipgloss Background() on a block colours only up to the first SGR reset inside it, and styled text is a chain of runs that each end in one. Every run after the first therefore drew on the terminal's own background: dark rectangles behind a light dialog's code sample, and a screen that kept the terminal's colour after the theme changed. FillBG re-establishes the background after every reset, so a fill is whole rather than patchy.
A run that carries its OWN background (a diff line, a selected picker row) still wins: this only paints what is otherwise unpainted, and picks up again where that run resets.
Callers pad rows to the width they want covered first - FillBG colours the cells it is given and adds none.
It returns text unchanged at a tier with no colour for r, matching the degradation ladder WithBg and Bordered follow: a colour fill without colour is nothing, and NO_COLOR output must stay byte-identical.
func FormatArgs ¶
FormatArgs renders a tool-call argument map as a stable, sorted "k=v k2=v2" string. Shared by every component that displays a tool call (transcript, approval).
func FormatCommandOutput ¶
func FormatDiagnosticsOutput ¶
FormatDiagnosticsOutput formats compiler / linter diagnostic lines with severity markers.
func FormatDiffLines ¶
FormatDiffLines renders diffs using side-by-side columns when width >= MinSplitDiffWidth, and falls back to unified DiffLines when narrower.
func FormatDispatchTasksOutput ¶
func FormatDispatchTasksOutput(t theme.Theme, tier theme.Tier, output string, width int) (string, []string)
FormatDispatchTasksOutput formats a dispatch_tasks result into one line per task instead of the raw JSON a generic dump would otherwise produce. dispatch_tasks returns one of two shapes depending on "wait": the default wait="run" blocks for the batch and returns a bare JSON array of per-task envelopes (handled here); wait="none"/"task" returns immediately with the same {"run_id":...,"task_results":[...]} envelope inspect_agents/join_run use, delegated to FormatOrchestrationRunOutput rather than duplicated.
func FormatElapsed ¶ added in v0.1.1
FormatElapsed renders a duration in milliseconds with the one duration grammar every surface shares (transcript-polish.md R5; docs/design/wireframes-panes.md section 4):
- below 1s: "250ms"
- below 60s: "4.1s" (one decimal)
- 60s or more: "1m 05s"
A negative input renders "0ms": a clock that ran backwards is a measurement error, and the honest floor is zero, not a sign.
The seconds rung ends at 59950ms, not 60000ms: %.1f would round 59950 up to "60.0s", a value the minutes rung owns.
Pure: input in, string out, no I/O and no package state.
func FormatFileReadOutput ¶
func FormatFileReadOutput(t theme.Theme, tier theme.Tier, output string, width int) ([]string, bool)
FormatFileReadOutput previews file content with line numbers when long.
func FormatFileReadOutputWithContext ¶
func FormatFileReadOutputWithContext(t theme.Theme, tier theme.Tier, filePath string, startLine int, output string, width int) ([]string, bool)
FormatFileReadOutputWithContext previews file content with syntax highlighting and line numbers.
func FormatGrepOutput ¶
FormatGrepOutput groups grep/search results by file.
func FormatGrepOutputWithContext ¶
func FormatGrepOutputWithContext(t theme.Theme, tier theme.Tier, query, output string, width int) (string, []string)
FormatGrepOutputWithContext groups grep/search results by file supporting both NDJSON and standard ripgrep output.
func FormatInspectRepositoryOutput ¶
func FormatInspectRepositoryOutput(t theme.Theme, tier theme.Tier, output string, width int) (string, []string)
FormatInspectRepositoryOutput formats an inspect_repository result - matches grouped by file with line numbers, mirroring the grouping FormatGrepOutputWithContext already uses for grep/glob/symbol tools - instead of a raw JSON dump of the provenance+results envelope.
func FormatJSONOutput ¶
FormatJSONOutput formats JSON objects or arrays into readable key-value summary lines or syntax-highlighted json.
func FormatLedgerOutput ¶
func FormatLedgerOutput(t theme.Theme, tier theme.Tier, output string, width int) (string, []string)
FormatLedgerOutput formats ledger/output responses into clean content blocks without envelope metadata, differentiating not-found refs, recorded errors/messages, and malformed-ref shapes instead of treating every response identically. The summary doubles as the tool-end header detail, so it carries the facts a reader needs without expanding: ref, size, and the truncation/paging state (tool-output-polish.md R3/R4).
func FormatListDirOutput ¶
func FormatListDirOutput(t theme.Theme, tier theme.Tier, output string, width int) (string, []string)
FormatListDirOutput formats directory listings into clean tree rows.
func FormatMemoryOutput ¶
func FormatMemoryOutput(t theme.Theme, tier theme.Tier, output string, width int) (string, []string)
FormatMemoryOutput renders memory search/list results into clean memory cards.
func FormatMessagingOutput ¶
func FormatMessagingOutput(t theme.Theme, tier theme.Tier, name string, args map[string]any, output string, width int) (summary string, body []string, collapsible bool)
FormatMessagingOutput formats inter-agent messages and blackboard entries into structured cards.
func FormatOrchestrationRunOutput ¶
func FormatOrchestrationRunOutput(t theme.Theme, tier theme.Tier, output string, width int) (string, []string)
FormatOrchestrationRunOutput formats an inspect_agents/spawn_agent/ join_run result into a run summary, a per-task status list, and any pending parked questions, instead of a raw JSON dump.
func FormatRunEventsOutput ¶
func FormatRunEventsOutput(t theme.Theme, tier theme.Tier, output string, width int) (string, []string)
FormatRunEventsOutput formats a list_run_events result into a chronological, icon-coded event timeline instead of a raw JSON dump.
func FormatToolDetail ¶
FormatToolDetail renders a domain-specific, readable detail string for a tool call. It formats commands with "$ <cmd>", file tools with their relative path, search tools with their query/scope, and web tools with their domain, falling back to FormatArgs for generic tools.
func FormatToolOutput ¶
func FormatToolOutput(t theme.Theme, tier theme.Tier, name, output string, ok bool, width int) (detail string, body []string, collapsible bool)
FormatToolOutput formats raw tool outputs (commands, grep searches, file reads, JSON payloads) into clean, structured, readable transcript lines styled through theme roles.
func FormatToolOutputWithContext ¶
func FormatToolOutputWithContext(t theme.Theme, tier theme.Tier, name string, args map[string]any, output string, ok bool, width int) (detail string, body []string, collapsible bool)
FormatToolOutputWithContext formats raw tool outputs using both tool name and parsed tool arguments.
func FormatWorkflowOutput ¶
func FormatWorkflowOutput(t theme.Theme, tier theme.Tier, output string, width int) (string, []string)
FormatWorkflowOutput formats workflow execution results into summary and step items.
func GroupThousands ¶ added in v0.1.1
GroupThousands renders an integer with a comma every three digits, the grouping style docs/design/wireframes-panes.md section 4 already uses for token counts ("1,284 in"). The sign of a negative value is kept: "-1,284".
It deliberately does not compact to "1.3k": a transcript number a user may cite or grep must equal the fact, not an approximation of it (see transcript-polish.md R6 for the same decision).
Pure: input in, string out, no I/O and no package state.
func HardWrap ¶
HardWrap breaks one logical line into the terminal rows it occupies at width, cutting mid-token. Tool output and code are not prose: a break on a word boundary would misrepresent the bytes the tool produced.
It is ANSI-aware, so a styled line keeps its escapes and they cost no display columns.
func Header ¶
Header renders a block header, placing meta and state inline right after the detail. When the columns cannot all fit, the DETAIL is clipped and marked - never the state, which carries meaning, and never the label, which identifies the block.
Contract, relied on by Block.Height: for width > 0 the result is AT MOST width display columns, on one row, and contains no newline. A header that overflowed would wrap, and the live window would then budget one row for content that draws two.
Pure: input in, string out, no I/O and no package state.
func Help ¶
Help renders the keymap as a styled block, grouped by context.
It is GENERATED from the binding table, never hand-written. A help screen maintained beside the dispatch table drifts from it, and the drift is invisible until a user presses a key the help promised.
Pure: input in, string out.
func HighlightCode ¶
HighlightCode applies syntax highlighting to source code based on filename or language identifier. It returns a slice of styled lines. At TierASCII or TierNoTTY, ANSI escapes are omitted.
func HintFits ¶
HintFits reports whether BorderedWithHint can place hint in the top border row of a box of the given width.
It is exported because the hint is not always decoration: the approval prompt puts WHAT is being approved there, and a caller that would lose content when the hint is dropped has to ask before deciding where to put it. The rule lives here, beside the renderer that applies it, so the two cannot disagree.
func Lip ¶
Lip converts a resolved theme.Style into a foreground lipgloss.Style. Structural emphasis (Bold/Dim) applies regardless of colour tier so it survives NO_COLOR; colour is applied only when the Style carries one.
func Markdown ¶
Markdown renders assistant markdown as ANSI-styled text using the theme palette. It is tier-aware: every role's hex (truecolor/256), ANSI16 index (16-colour), or absence (ASCII/NoTTY) flows through Glamour's style config and chroma formatter.
It returns in unchanged when Glamour returns an error or panics. Glamour surfaces markdown errors as strings rather than panics, and the renderer wraps its body in defer recover() because goldmark plugins have historically been panic-prone in adjacent code paths. The cost is one deferred closure per call; the alternative - a crashed transcript - is not acceptable.
A width of 0 or negative is clamped to minMarkdownWidth so Glamour never sees a 0-column wrap. The transcript already guards this with max(20, width-2); this floor is the last line of defence.
func ProgressBar ¶
ProgressBar draws the subagent progress bar from the section 3 glyph table: "#" for done, "." for remaining, with the percentage beside it. Both glyphs are ASCII, so the bar is identical at every colour tier.
func ProseMeasure ¶
ProseMeasure is the wrap width for prose at a given terminal width. Prose wraps to a measure, not to the terminal, because a full-width line on a wide terminal is hard to read (wireframes-panes.md 14).
func ReadOnlyToolClass ¶ added in v0.1.1
ReadOnlyToolClass reports the read-only lookup class of a tool name: "read" for file reads, "search" for grep/find/glob/symbol lookups. The transcript coalesces consecutive same-class calls into one leader row (transcript-polish.md R2). "" means the tool is not read-only.
func Role ¶
Role resolves a theme role at the given tier and returns its foreground lipgloss style, the common case for component call sites.
func Split ¶
func Split(t theme.Theme, tier theme.Tier, width, height int, focus Side, left, right string) string
Split composes the reading column and the nav sidebar side by side, separated by a 1-column gutter. The nav sidebar has a subtle card background (RoleBGSubtle) matching the composer where the user types.
Both columns draw exactly height rows: content is padded, and surplus rows clip from the bottom (Split never scrolls - windowing belongs to the pane's owner, so there stays one implementation of it).
This is the codebase's only side-by-side composition; it exists so the ratio, the height contract, and the layout convention live in one place when more panes arrive.
func SplitAt ¶
func SplitAt(t theme.Theme, tier theme.Tier, width, height, leftWidth int, focus Side, left, right string) string
SplitAt is Split with the left pane's content width given directly instead of derived from SplitWidths. Split's 30%-capped-at-60 share is one policy for one caller (a file list beside a diff); a settings screen's five-word nav sidebar needs a different share and a different cap, and neither belongs in this package (uikitconfig owns literals - see internal/uikit/config's package doc). SplitAt is the geometry both policies share: left is drawn at exactly leftWidth, separated by a 1-column gutter, and right takes what remains with RoleBGSubtle background.
func SplitAtDialog ¶
func SplitAtDialog(t theme.Theme, tier theme.Tier, width, height, leftWidth int, navFocused bool, title, body, hint, nav string) string
SplitAtDialog is SplitDialog with the dialog's (left pane's) content width given directly, the SplitDialog counterpart to SplitAt: a caller whose nav sidebar is not Split's 30%-capped-at-60 share still wants its editor to open as a dialog beside that sidebar rather than full-width.
func SplitDialog ¶
func SplitDialog(t theme.Theme, tier theme.Tier, width, height int, navFocused bool, title, body, hint, nav string) string
SplitDialog is the split with its reading column replaced by a centered dialog: the dialog is sized to the reading column's whole area, so the blocks compose with no gap, and the nav pane stays visible and legible beside it instead of hiding behind a full-surface dialog.
func SplitDiffLines ¶
SplitDiffLines renders each hunk as aligned side-by-side rows with line numbers.
func SplitListDetail ¶
func SplitListDetail(listLines, detailLines []string, selectedLine, height int, notice string) string
SplitListDetail lays out a scrollable row list above an optional collapsible detail preview, sharing one height budget, with a pinned notice line at the bottom when present. It is the shared geometry the settings screen's grouped sections need: a header/row list on top, window-scrolled to keep the selection visible, and a preview of the selected row beneath it, extracted from the Skills section so the Agents section (and any future grouped section) can present the same layout without re-deriving the same height math.
listLines is every list row already rendered (including any group headers) in display order. detailLines is the selected item's pre-rendered preview body, or nil when nothing is selected or the section has no preview to show for the current row. selectedLine is the listLines index the window must keep visible; pass a negative value when the list is empty. height is the section's full available row budget. notice, when non-empty, must already be styled by the caller (this package has no theme access here) and consumes its own trailing row, taking priority over detail rows the same way the section's own notice line always has.
func SplitWidths ¶
SplitWidths is the pane geometry Split assigns: nav is the right pane's width including its divider column, at SplitNavShare of width capped at SplitNavMax; reading is the left pane's. Exported so a caller that renders content INTO a pane sizes that content to the same numbers the frame draws around it - blocks pad and clip, they never re-wrap, so wide rows are the caller's to cut.
func ThinkBadge ¶ added in v0.1.1
ThinkBadge is the dim line that replaces a removed <think> dump.
func UnwrapJSONString ¶ added in v0.1.1
UnwrapJSONString returns payload with up to maxEnvelopeUnwrapDepth JSON string layers peeled off: a payload that unmarshals to a string is replaced by that string until it stops being one. Values that are not JSON strings pass through unchanged.
func WindowSlice ¶
WindowSlice calculates the [start, end) index range to window total items within maxRows visible lines such that cursor is guaranteed to be within [start, end). If maxRows <= 0 or total <= maxRows, it returns (0, total).
func WithBg ¶
WithBg layers a background role onto an existing style. A tier with no colour for the role (e.g. the no-colour/ASCII tier) contributes no background, matching the degradation ladder.
func Wrap ¶
Wrap breaks text at the given measure on word boundaries, preserving existing newlines. A word longer than the measure is left whole rather than split: breaking an identifier or a URL mid-token hurts more than one long line does.
Pure: input in, string slice out. Every width here is a DISPLAY width, not a byte count. A byte count wraps accented prose at half the measure and CJK at a third of it.
Types ¶
type HeaderSpec ¶
type HeaderSpec struct {
// Marker is the collapse glyph, "v", ">" or " ".
Marker string
Label string
Detail string
DiffAdd int
DiffDel int
Meta string
State string
// StateRole colours the state word. The word is always rendered, so
// meaning never depends on colour alone.
StateRole theme.Role
}
HeaderSpec is the content of a block header row, in four columns. wireframes-panes.md section 2: the collapse marker at column 1, the label at column 3, the detail after it, then meta and state placed inline immediately after the detail, separated by minHeaderGap.
func SanitizeSpec ¶
func SanitizeSpec(spec HeaderSpec) HeaderSpec
SanitizeSpec cleans every string field in spec of control and format characters.
Source Files
¶
- background.go
- columns.go
- context.go
- dialog.go
- diff.go
- diff_split.go
- elapsed.go
- envelope.go
- header.go
- help.go
- inspect_repository_output.go
- ledger_output.go
- listdetail.go
- markdown.go
- memory_output.go
- messaging_formatter.go
- numbers.go
- orchestration_output.go
- output_formatter.go
- run_events_output.go
- split.go
- style.go
- syntax.go
- text.go
- tool_class.go
- tool_header.go