feedback

package
v1.28.1 Latest Latest
Warning

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

Go to latest
Published: Jul 8, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package feedback renders lerd's CLI progress output (animated steps, a live line, summaries, prompts, warnings) and owns the shared lerd colour palette. It degrades to plain text when stdout is piped, redirected, or NO_COLOR is set.

Index

Constants

View Source
const (
	GlyphOK   = "✓"
	GlyphFail = "✗"
	GlyphWarn = "⚠"
	GlyphLock = "🔒"
)

Status glyphs for query/report output that renders its own layout rather than using the Step/Live progress flow.

Variables

View Source
var (
	ColTitle   = lipgloss.Color("#FF2D20") // lerd red (Laravel brand)
	ColDim     = lipgloss.Color("#6b7280") // gray-500
	ColDivider = lipgloss.Color("#374151") // gray-700
	ColRunning = lipgloss.Color("#10b981") // emerald-500
	ColStopped = lipgloss.Color("#6b7280") // gray-500
	ColFailing = lipgloss.Color("#ef4444") // red-500
	ColPaused  = lipgloss.Color("#f59e0b") // amber-500
	ColGold    = lipgloss.Color("#fbbf24") // amber-400 (brighter gold for sudo prompts)
	// Interactive accent is the brand red so the TUI, CLI feedback, and the web
	// UI all share one accent rather than diverging on a separate hue.
	ColAccent = lipgloss.Color("#FF2D20") // lerd red
)

Canonical lerd palette (Tailwind hex values). The TUI theme aliases these so CLI feedback and the dashboard share one set of colours.

Functions

func AlreadyShown

func AlreadyShown(err error) bool

AlreadyShown reports whether err, or any error it wraps, was already displayed to the user by a Fail. Callers in main use it to avoid double-printing.

func Amber

func Amber(s string) string

func AmberIf

func AmberIf(on bool, s string) string

func Animated

func Animated() bool

Animated reports whether output supports in-place animation (a colour TTY). When false, Live degrades to a header line plus one plain line per item.

func Begin

func Begin()

Begin prints a single blank line to separate a feedback block from whatever (a shell prompt, a wizard) came before it.

func Confirm

func Confirm(question string, defaultYes bool) bool

Confirm prints a styled yes/no prompt (preceded by a blank line) and reads the answer from stdin, returning defaultYes on an empty response. The prompt matches the step styling: a violet "?" lead-in and a dim "Y/n" hint.

func Dim

func Dim(s string) string

func Done

func Done(msg string)

Done prints a green-check completion line with no timing, for operations where elapsed time isn't meaningful.

func Fail

func Fail(err error)

Fail prints a standalone red ✗ line for err to stderr in the same style (and blank-line spacing) as a Live/Step failure. It is for the top-level command handler to render an error a command returned without surfacing it itself, so every failure reads the same whether it came up through a spinner or bubbled out raw. Errors go to stderr so stdout stays clean for piped data. It records err as shown so nothing reprints it.

func FailOn

func FailOn(w io.Writer, err error)

FailOn is Fail targeted at an explicit writer, colouring only when that writer is a terminal. Lets the top-level handler send errors to stderr and tests capture them in a buffer.

func Green

func Green(s string) string

Green, Red, Amber, and Dim colour a one-off fragment for status reports, honouring NO_COLOR and non-TTY output. Use these so query commands share the progress palette without reaching for raw ANSI codes.

func GreenIf

func GreenIf(on bool, s string) string

GreenIf, RedIf, and AmberIf colour s from the palette only when on is true, else return it plain — for renderers that target an arbitrary writer and gate colour per-writer (e.g. doctor forcing plain text into a bug report). When on is true the usual global NO_COLOR/TTY state is still honoured, so a coloured caller never produces escapes the environment asked to suppress.

func Header(title string)

Header prints a section header — a brand-red "▸ title" with a blank line above and below — to delimit the major phases of a long multi-step command (install, update) so the step lines beneath read as a group instead of one flat wall of output. Routed through emit so it lands cleanly above any live spinner that is still animating.

func Interactive

func Interactive() bool

Interactive reports whether stdout is a terminal, independent of colour. Use it to choose a condensed single-line view over full verbose output: a user who only disabled colour (NO_COLOR) still gets the interactive view rather than the pipe/MCP verbose path. Animated() is the wrong gate for that, since NO_COLOR forces it false even on a real terminal.

func Line

func Line(msg string)

Line prints a standalone step (arrow prefix, no trailing ellipsis) for an already-known fact, e.g. "php 8.4 · node 22 · nginx vhost written".

func LineOn

func LineOn(w io.Writer, msg string)

LineOn is Line targeted at an explicit writer — for an install step that captures or discards its sub-output (e.g. via io.Discard) rather than writing to the live stdout. Mirrors Line's styling so captured output reads the same.

func Note

func Note(msg string)

Note prints a dim, indented sub-detail under a step (e.g. a log hint). It has no glyph so it reads as secondary to the step lines above it.

func Prompt

func Prompt(question string, defaultYes bool)

Prompt renders a styled yes/no question (violet "?", dim "Y/n" hint), preceded by a blank line, WITHOUT reading the answer — for callers that read from a custom source (e.g. /dev/tty so `curl … | bash` prompts still work) instead of stdin. Mirrors Confirm's styling so every prompt looks the same.

func Red

func Red(s string) string

func RedIf

func RedIf(on bool, s string) string

func RenderTable

func RenderTable(headers []string, rows [][]string) string

RenderTable returns the table as a string without printing it, for callers that compose it into other output. On a colour TTY it draws a rounded grid with a bold brand-red header and dim borders; with colour off (NO_COLOR or a pipe) it falls back to plain space-aligned columns so scripted output stays parseable. When the natural grid is wider than the terminal the widest columns are truncated with an ellipsis so every row stays on one line and the grid fits the screen whenever the column count leaves room for it.

func SetAnimated

func SetAnimated(on bool) func()

SetAnimated forces Animated() to on (or off) and returns a restore func. Pair it with SetTestWriter so a test can exercise an animated code path while the spinner frames land in a buffer instead of os.Stdout.

func SetInteractive

func SetInteractive(on bool) func()

SetInteractive overrides Interactive for a test and returns a restore func.

func SetTestWriter

func SetTestWriter(w io.Writer) func()

SetTestWriter redirects output to w in plain mode (no colour) and returns a restore func. Intended for tests in this and other packages.

func Success

func Success(msg string, d time.Duration)

Success prints the terminal line: green check, message, dim elapsed time.

func Sudo

func Sudo(msg string)

Sudo prints a privileged-step line: a gold lock glyph and gold message, so the password prompt the next command (mkcert, a sudo write) raises reads as expected rather than a surprise. Use it in place of a bare "[sudo required] …" print so every privileged step looks the same. Routed through emit so it lands cleanly above any live spinner.

func Table

func Table(headers []string, rows [][]string)

Table prints headers + rows as a single aligned table in the lerd palette so every `lerd … list`/`search` view shares one look instead of hand-rolled printf columns. See RenderTable for the styling and plain-mode fallback.

func Title

func Title(s string) string

Title styles a fragment as the bold lerd-red wordmark colour.

func Val

func Val(s string) string

Val styles a value fragment (violet) for embedding inside a step or summary.

func Warn

func Warn(format string, a ...any)

Warn prints a warning line: an amber warning glyph and amber message. Use in place of a plain "[WARN] …" print.

func WarnOn

func WarnOn(w io.Writer, format string, a ...any)

WarnOn is Warn targeted at an explicit writer rather than the live stdout, for callers that capture or discard their sub-output. Mirrors Warn's styling.

Types

type Live

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

Live is a single in-place progress line with a trailing spinner that accumulates completed items, e.g. "→ configuring .env… ✓ a · b · c ⠙". When it finishes the spinner is dropped and the ✓ line stays put.

func StartLive

func StartLive(msg string) *Live

StartLive begins a live line with the given label. On a non-animated output it just prints the header and each Add on its own line.

func (*Live) Add

func (l *Live) Add(item string)

Add records a completed item; the spinning line redraws to include it.

func (*Live) Done

func (l *Live) Done()

Done stops the spinner, leaving the ✓ line (checkbox replaces the loader).

func (*Live) Fail

func (l *Live) Fail(err error)

Fail stops the spinner and finalises the line with a red cross.

func (*Live) Interrupt

func (l *Live) Interrupt(fn func())

Interrupt suspends the spinner and clears its line so fn can print standalone output (a booting service, a child process's stdout) above the live line without the spinner's \r redraw clobbering it, then lets the spinner resume and redraw beneath. On non-animated output it just runs fn. paused is read and written under the package mu, the same lock draw holds while writing, so no redraw can slip between the clear and fn's output.

type Step

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

Step is one line of progress: Start it before the work, then OK/Info/Fail finishes it. On a colour TTY a spinner animates until then; otherwise nothing prints until the finishing call writes the line once.

func Start

func Start(msg string) *Step

Start records a step with the given present-tense label (e.g. "detecting framework") and begins its spinner on an animated terminal.

func StartOn

func StartOn(w io.Writer, msg string) *Step

StartOn is Start with a fixed render target. The spinner and finishing line write to w rather than the live os.Stdout, so the step can animate while the caller redirects os.Stdout elsewhere (e.g. capturing a sub-step's output) without the spinner frames leaking into that redirect.

func (*Step) Fail

func (s *Step) Fail(err error)

Fail collapses the step with a red cross and the error text.

func (*Step) Info

func (s *Step) Info(result string)

Info collapses the step with a plain result and no mark.

func (*Step) Interrupt

func (s *Step) Interrupt(fn func())

Interrupt suspends the step's spinner and clears its line so fn can print standalone output above it, mirroring Live.Interrupt. On a non-animated step it just runs fn. paused is read and written under the package mu, the same lock frame() holds, so no redraw slips between the clear and fn's output.

func (*Step) OK

func (s *Step) OK(result string)

OK collapses the step with a green check and a result (e.g. "Laravel 11").

func (*Step) Warn added in v1.26.1

func (s *Step) Warn(err error)

Warn collapses the step with an amber warning glyph and message, for a non-fatal hiccup (e.g. a best-effort restart that didn't take) that should be noticed but doesn't mean the command itself failed. Unlike Fail it draws no red cross, so it doesn't read as the whole operation having errored.

type Summary

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

Summary is an aligned key/value block printed after an operation completes.

func NewSummary

func NewSummary() *Summary

NewSummary returns an empty summary block.

func (*Summary) Print

func (s *Summary) Print()

Print renders the block, label column padded to the widest label, preceded by a blank line. No-op when empty.

func (*Summary) Row

func (s *Summary) Row(label, value string) *Summary

Row appends a label/value pair; value may contain styled fragments via Val.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL