cmd/taisce/cliui.go
cmd/taisce · 308 lines · 19 declarations · source
Declarations
const envCLIOutput
const envCLIOutput = "TAISCE_OUTPUT"
const envCLIASCII
const envCLIASCII = "TAISCE_ASCII"
type cliTheme
type cliTheme struct {
width, amber, blue, green, red, dim, reset int
ascii, color bool
}
func fancyOutput
func fancyOutput(out io.Writer) bool
func currentTheme
func currentTheme() cliTheme
func paint
func paint(enabled bool, code, value string) string
func cleanTerminal
func cleanTerminal(value string) string
cleanTerminal makes a value safe to draw: invalid UTF-8 becomes a replacement character; a line break, tab, line separator or paragraph separator becomes one space, so a value cannot start a new line inside a panel; and every control character (category Cc) and format character (category Cf) is removed.
Control characters are removed because an escape sequence in a name would repaint the screen. Format characters are removed because they act on how a line looks without being visible: a direction override reorders what follows it, so an operator reads something other than the value, and a zero-width character makes two different names print identically. They also break width arithmetic — counted as a cell, they draw a panel's border off by one. Removing the zero-width joiner splits a joined emoji into its parts, which is the price of that and is accepted.
Who could put such a character here, read from the code at the time of writing: nobody but the operator. Every value the renderer draws is a constant, a UUID, a rebuild status the schema limits to three words, or a project name the provisioner holds to `^[a-z][a-z0-9_]{0,62}$`. This is defence for the value somebody adds next, not a hole anyone can reach today (#19).
It does NOT normalise whitespace. It once collapsed runs of spaces and trimmed both ends, and every caller that measures width runs text through here — so a label padded to line up a column lost its padding, and a title's surrounding spaces stopped being counted, which drew the top border two cells wider than the rows beneath it (#18). Spacing a caller wrote is layout, not a hazard.
func runeWidth
func runeWidth(r rune) int
func clipDisplay
func clipDisplay(value string, limit int) string
func displayWidth
func displayWidth(value string) int
func statusPanel
func statusPanel(t cliTheme, title string, lines []string) string
func renderHelp
func renderHelp(t cliTheme) string
func meter
func meter(current, total int64, cells int, ascii bool) string
func renderHealth
func renderHealth(t cliTheme, h pg.OperationalHealth, inferenceConfigured bool) string
func renderRebuild
func renderRebuild(t cliTheme, job pg.RebuildJob) string
func renderReportRebuild
func renderReportRebuild(t cliTheme, r reportRebuildResult) string
A report rewrite has no job to point at afterwards, and no progress bar worth drawing: the count that matters is how many subjects are still waiting, which this command reports as staleness beside its own result. So the next step is to read that, which is the JSON form of this same call.
func renderFailure
func renderFailure(t cliTheme, _ error) string
func inferenceIsConfigured
func inferenceIsConfigured() bool
func startCLIActivity
func startCLIActivity(ctx context.Context, label string) func()
startCLIActivity owns one bounded redraw loop on stderr. The deferred stop restores the line on success, failure, or cancellation; structured stdout remains untouched.