Documentation
¶
Overview ¶
Package output owns every byte flow writes to a terminal. It is the only package outside internal/ciwait permitted to import a Charm library: commands ask the renderer for output, they never construct a style themselves. That is what keeps a later theme change, or a full TUI, a single-file change.
Index ¶
- Constants
- Variables
- func FangColorScheme(plain bool) func(lipgloss.LightDarkFunc) fang.ColorScheme
- func FangErrorHandler(aborted, alreadyReported func(error) bool) fang.ErrorHandler
- func Truncate(s string, width int) string
- type ErrNotInteractive
- type Options
- type Renderer
- func (r *Renderer) ColorEnabled() bool
- func (r *Renderer) Confirm(title, description string, defaultYes, assumeYes bool) error
- func (r *Renderer) ErrWriter() io.Writer
- func (r *Renderer) Failure(format string, a ...any)
- func (r *Renderer) Field(label, value string)
- func (r *Renderer) Heading(s string)
- func (r *Renderer) Input(title, def string) (string, error)
- func (r *Renderer) Interactive() bool
- func (r *Renderer) JSON(v any) error
- func (r *Renderer) JSONError(code, message string)
- func (r *Renderer) JSONMode() bool
- func (r *Renderer) Line(s string)
- func (r *Renderer) Printf(format string, a ...any)
- func (r *Renderer) Println(a ...any)
- func (r *Renderer) Profile() colorprofile.Profile
- func (r *Renderer) Select(title string, options []SelectOption) (string, error)
- func (r *Renderer) Spin(ctx context.Context, title string, fn func() error) error
- func (r *Renderer) Status(format string, a ...any)
- func (r *Renderer) Stdin() io.Reader
- func (r *Renderer) Success(format string, a ...any)
- func (r *Renderer) Table(headers []string, rows [][]string)
- func (r *Renderer) Warn(format string, a ...any)
- func (r *Renderer) Width() int
- type SelectOption
- type Theme
Constants ¶
const ( SymOK = "✔" SymFail = "✘" SymWarn = "!" SymSkip = "·" SymPending = "◦" )
Symbols used across the CLI and the CI progress display.
Variables ¶
var ErrAborted = errors.New("aborted by user")
ErrAborted is returned when the user declines a confirmation or presses ctrl-c at a prompt. Callers map it to exit code 6.
Functions ¶
func FangColorScheme ¶
func FangColorScheme(plain bool) func(lipgloss.LightDarkFunc) fang.ColorScheme
FangColorScheme derives fang's help and error styling from flow's own palette, so help pages and command output never disagree about color.
plain is decided by main before fang parses flags, because fang renders before any command's pre-run hook has looked at --no-color or --json.
func FangErrorHandler ¶
func FangErrorHandler(aborted, alreadyReported func(error) bool) fang.ErrorHandler
FangErrorHandler builds fang's error handler. It lives here rather than in internal/cli because its signature names fang's own types, and internal/cli must not import a Charm library.
aborted and alreadyReported are injected so this file needs no knowledge of flow's error taxonomy.
Types ¶
type ErrNotInteractive ¶
type ErrNotInteractive struct {
// Flag is the escape hatch, e.g. "--yes".
Flag string
// What describes the decision that could not be made.
What string
}
ErrNotInteractive is returned when a prompt is required but stdin is not a terminal. The message always names the flag that would have avoided it.
func (*ErrNotInteractive) Error ¶
func (e *ErrNotInteractive) Error() string
type Options ¶
type Options struct {
JSON bool
NoColor bool
Verbose int
// Writers default to the process's own when nil. Tests inject buffers.
Stdout io.Writer
Stderr io.Writer
Stdin io.Reader
}
Options describe how a Renderer should behave. They come straight from the global flags on the root command.
type Renderer ¶
Renderer is the single sink for user-facing output. The primary result goes to stdout; progress, warnings and logs go to stderr, so that `cd $(flow path)` keeps working.
func New ¶
New builds a Renderer, deciding the color profile exactly once. --no-color, NO_COLOR, --json and a non-TTY writer each force plain ASCII; because the decision is made here and shared with huh, charmbracelet/log and fang, all four can never disagree about whether color is on.
func (*Renderer) ColorEnabled ¶
ColorEnabled reports whether the terminal can render color. It is false for --no-color, NO_COLOR, --json and every non-terminal writer, which together are exactly the cases where a live progress display must fall back to plain appended lines.
func (*Renderer) Confirm ¶
Confirm asks a yes/no question. assumeYes short-circuits it (--yes), and a non-interactive session fails with the flag that would have answered it.
func (*Renderer) ErrWriter ¶
ErrWriter exposes the profile-aware stderr writer, for the CI progress display which drives its own bubbletea program.
func (*Renderer) Interactive ¶
Interactive reports whether prompting the user is possible.
func (*Renderer) Line ¶
Line writes one bare line to stdout with no styling. This is the contract for `flow path` and `flow assets`: exactly one line, nothing else.
func (*Renderer) Profile ¶
func (r *Renderer) Profile() colorprofile.Profile
Profile reports the resolved color profile, so nested programs (bubbletea, huh) render with the same capabilities as plain output.
func (*Renderer) Select ¶
func (r *Renderer) Select(title string, options []SelectOption) (string, error)
Select asks the user to choose one of options.
func (*Renderer) Spin ¶
Spin runs fn while showing a one-line indeterminate spinner on stderr. In JSON or non-interactive mode it just runs fn, so scripted output stays clean.
func (*Renderer) Table ¶
Table renders rows with lipgloss/table, which measures rendered width and so aligns correctly even when cells carry ANSI escapes.
type SelectOption ¶
SelectOption is one choice in a Select prompt.
type Theme ¶
type Theme struct {
Success lipgloss.Style
Warn lipgloss.Style
Error lipgloss.Style
Muted lipgloss.Style
Heading lipgloss.Style
Ticket lipgloss.Style
Path lipgloss.Style
Bold lipgloss.Style
// Raw colors, for the widgets that take a color rather than a style.
AccentColor color.Color
SuccessColor color.Color
WarnColor color.Color
ErrorColor color.Color
MutedColor color.Color
}
Theme holds every style flow uses. Construct it once, from a LightDarkFunc, and pass it around: lipgloss v2 dropped AdaptiveColor in favour of resolving light/dark up front, so styles cannot be package-level values any more.