Documentation
¶
Overview ¶
Package tui holds the terminal-presentation rules Draugr applies everywhere it writes for a person: when color is allowed, what the colors mean, and how to link to more detail.
It exists because those rules were being re-derived per command. The console report, the log handler and the install prompt each had their own copy of the "is this a terminal" check, and two separate ANSI palettes had drifted apart. Output that looks assembled by different people is a real cost for a tool whose terminal *is* the product.
The rules, in one place:
- color only when writing to an interactive terminal, and never when NO_COLOR is set (https://no-color.org)
- a fixed, semantic palette, so callers ask for "critical" rather than for red
- anything that degrades (color, hyperlinks) degrades to plain text, so piped output and CI logs stay readable
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ColorEnabled ¶
ColorEnabled reports whether colored output is appropriate for w: it must be an interactive terminal, and NO_COLOR must be unset.
func Columns ¶ added in v0.116.0
Columns reports how many character cells wide w is, or 0 when that cannot be answered.
A caller that draws in place needs this, because a terminal wraps a line it cannot fit and the wrapped line occupies two rows. Anything that then moves the cursor back over what it drew moves too few rows and erases whatever is above, which is the reader's own scrollback rather than anything this program wrote.
COLUMNS wins over the ioctl so a test, and a reader debugging a layout, can say what the width is without a terminal of that size.
func IsTerminal ¶
IsTerminal reports whether v (an *os.File, in practice stdin/stdout/stderr) is a character device. Accepts any value so it can answer for a reader (is the user there to be prompted?) as well as a writer (should this be colored?).
func Pad ¶
Pad left-aligns s to width, measured on the unstyled text. Padding must be computed before color is applied, or escape codes inflate the apparent length and columns stop lining up.
func Truncate ¶ added in v0.116.0
Truncate shortens s to width character cells, measuring the text a reader sees rather than the bytes. Zero or negative width returns s unchanged, for a caller that could not find out.
Escape sequences are carried through and cost nothing, which is what makes this different from slicing a string: a styled line is mostly bytes the terminal never displays, so cutting by length removes visible text long before the edge and can cut a sequence in half, leaving the rest of the screen wearing a color nothing turns off. A line that is cut ends with a reset for the same reason, and an escape sitting exactly on the cut is kept rather than dropped, so a hyperlink whose text just fits is closed by its own terminator.
Types ¶
type Cell ¶
type Cell struct {
Text string
Style Style
// URL turns the cell into a hyperlink where the terminal supports it. It costs no width,
// which is what makes it usable in a table that's already wide.
URL string
}
Cell is one value in a table row: the text, how it should read, and optionally where it points. The zero value is a plain, unlinked cell, so a caller only names what differs.
type Painter ¶
type Painter struct {
// contains filtered or unexported fields
}
Painter renders styled text, or plain text when color isn't appropriate for the destination. The zero value is a valid plain-text painter, so a caller that forgets to construct one degrades safely instead of emitting escape codes into a file.
func Colored ¶
func Colored() Painter
Colored returns a Painter for a caller that has already decided, such as one whose color setting comes from configuration rather than from inspecting the writer.
func For ¶
For returns a Painter suited to w: color only for an interactive terminal with NO_COLOR unset.
func Plain ¶
func Plain() Painter
Plain returns a Painter that never colors, for tests and for building strings whose destination isn't known yet.
func (Painter) Append ¶
Append is Paint for a caller building a byte buffer, the log handler writes a line per record, and going through strings would allocate on every one.
func (Painter) Enabled ¶
Enabled reports whether this painter emits color, so callers can skip work that only matters when colored.
func (Painter) Link ¶
Link renders text as an OSC 8 terminal hyperlink to url. Terminals that support it show the text and follow the link on click; everywhere else, an older terminal, a pipe, a CI log. The escape codes are absent and the text stands alone. It therefore costs no width, which is what makes it usable in a table that is already wide.
A caller with nowhere to link should pass an empty url and get the text back.
type Style ¶
type Style string
Style is a semantic role, not a color: callers say what a thing *is* and the palette decides how it looks, so the same concept renders identically in every command.
const ( StyleNone Style = "" StyleCritical Style = "1;31" // bold red StyleHigh Style = "31" StyleMedium Style = "33" StyleLow Style = "2" StyleFail Style = "1;31" StylePass Style = "32" StyleAccent Style = "33" // draws the eye without implying severity StyleMuted Style = "2" // supporting detail: headers, labels, units StyleStrong Style = "1" // the part of a line to read first, at no cost in color )
The palette. Severity styles mirror the report bands; the rest are roles, not colors.
type Table ¶
type Table struct {
// contains filtered or unexported fields
}
Table renders aligned columns for a person reading a terminal.
It exists because alignment and color interact badly: any padding computed after styling counts escape bytes as visible width and the columns drift apart. text/tabwriter has the same flaw, its Escape mechanism hides the bytes from parsing but still measures them, so every command that wanted color was going to hand-roll its own width arithmetic. Table measures the plain text, pads, and only then paints.
func NewTable ¶
NewTable starts a table written with p. Headers may be omitted for a table whose columns need no labeling; when given, they're dimmed so they frame the data without competing.
func (*Table) Render ¶
Render writes the table. Columns are sized to their widest plain-text value, and the final column is never padded. Nothing follows it, and trailing spaces are noise in a diff or a copied-out log.
func (*Table) Row ¶
Row appends a row. Rows may be shorter than the header, missing cells render empty.
func (*Table) RowWithNote ¶
RowWithNote appends a row followed by a dimmed continuation line, aligned under the second column. Use it when a row's own columns can't carry the explanation.
func (*Table) RowWithNotes ¶ added in v0.56.0
RowWithNotes appends a row followed by several dimmed continuation lines, each aligned under the second column. Empty strings are dropped, so a caller can pass a line that may or may not have anything to say without guarding at the call site.