Documentation
¶
Overview ¶
Package ui is the Bubble Tea front-end for `a-novel build`: a branded, keyboard-driven flow of three phases — select targets, run them, read the report. lipgloss handles all presentation; this file owns the state machine.
Index ¶
- Variables
- func Banner(version string) string
- func CommandHelpView(version, name string) string
- func CoverageView(results []build.Result, width int) string
- func DryRunView(version string, verb Verb, targets []detect.Target) string
- func EnvConflictView(verb Verb, conflicts []build.Conflict) string
- func EnvNote(s string) string
- func EnvPrompt(s string) string
- func EnvStep(s string) string
- func HelpView(version string) string
- func RenderTextReport(results []build.Result, aborted bool, elapsed time.Duration, verb Verb) string
- type Model
- type Verb
Constants ¶
This section is empty.
Variables ¶
var ( VerbBuild = Verb{ Base: "build", Ing: "building", Upper: "BUILD", Looks: "a go.mod (Go), a package.json with build* scripts (pnpm), or builds/*.Dockerfile (Podman)", } VerbTest = Verb{ Base: "test", Ing: "testing", Upper: "TEST", Looks: "a go.mod (Go tests) or a package.json with test* scripts (pnpm)", } VerbRun = Verb{ Base: "run", Ing: "running", Upper: "RUN", Looks: "a Go `package main` (cmd/…) or a package.json with run* scripts", } )
Functions ¶
func Banner ¶
Banner renders the branded header shown at the top of every screen. version is the resolved CLI version (see internal/version).
func CommandHelpView ¶
CommandHelpView is the per-command help: banner, that command's usage, a description, and only the flags/examples that apply to it. An unknown name falls back to the generic screen (the caller has already validated in most paths; this keeps it safe regardless).
func CoverageView ¶
CoverageView renders the COVERAGE report section: Go packages as a colour-banded percentage list with a mean, and each pnpm target's native vitest table verbatim beneath it. Returns "" when nothing was measured (flag off, or no coverage produced) so callers can drop it in unconditionally.
func DryRunView ¶
DryRunView answers "what would `a-novel <verb>` do here?" without running anything: a short explanation, a per-kind count strip, then a table of every detected target with its exact command. Sections are separated by titled rules so the structure is obvious at a glance.
func EnvConflictView ¶
EnvConflictView renders the leftover-environment warning shown by the preflight: a critical titled section, a short explanation, and the stale envs with their containers nested beneath — styled to match the report rather than plain stderr text.
func HelpView ¶
HelpView is the generic help: banner, usage, and the command list only. Per-command flags/examples are intentionally NOT here — they live behind `a-novel <command> --help` (see CommandHelpView).
func RenderTextReport ¶
func RenderTextReport(results []build.Result, aborted bool, elapsed time.Duration, verb Verb) string
RenderTextReport produces the authoritative, scrollback-safe build report.
It is printed two ways:
- after the interactive TUI tears down, so the FULL failing logs survive (the in-TUI report only shows a tail);
- as the entire output of non-interactive mode (`a-novel build -y`).
Unlike the TUI views it never truncates failure output — this is the copy a user pastes into an issue or scrolls back through. elapsed is the real wall-clock run time tracked by the runner; it is shown as "took". Summary.CumulativeDuration is deliberately NOT used here — under parallelism it overstates how long the user actually waited.
Types ¶
type Model ¶
type Model struct {
// contains filtered or unexported fields
}
Model is the root Bubble Tea model. Construct it with New.
func New ¶
func New(ctx context.Context, version string, verb Verb, targets []detect.Target, jobs int, timeout time.Duration) Model
New builds a Model from discovered targets. Every target starts selected — the common case is "build everything", and opting out is one keystroke.
jobs is the maximum number of builds to run concurrently once the user confirms; jobs <= 0 means runtime.NumCPU(). Parallelism is interactive-only; the non-interactive path stays strictly sequential by design.
func NewSelect ¶
NewSelect builds a target picker that reuses build/test's exact selection UI, then quits on `enter` returning the chosen targets via Model.Selected. It carries no run state (no ctx/jobs/timeout) — `run` drives the actual processes itself. `runMode` ("container" / "live" / "") is displayed in the picker title so the user can tell at a glance which list this is.
func (Model) Elapsed ¶
Elapsed is the real wall-clock run time: frozen when the run completed, or measured to now if it was aborted mid-flight. Zero if no build ever started.
func (Model) Results ¶
Results / Aborted expose terminal state so the caller can print an authoritative plain-text report (with full logs) after the TUI tears down. Results are returned in queue (dispatch) order, not completion order, so the report is deterministic regardless of which parallel build finished first.
func (Model) Selected ¶
Selected is the targets the user confirmed in select-only mode (empty if aborted or nothing was picked). Pair with Model.Aborted.
type Verb ¶
type Verb struct {
Base string // "build" / "test"
Ing string // "building" / "testing"
Upper string // "BUILD" / "TEST"
Looks string // what discovery scans for — used in the "nothing found" error
}
Verb parameterises the screens shared by `build` and `test` so the same model/report/dry-run render the right wording for each.