progress

package
v1.6.1 Latest Latest
Warning

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

Go to latest
Published: May 16, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package progress provides a shared Bubble Tea progress UI for the `prr audit` and `prr review` commands.

Both commands emit (phase, message) events as their pipelines execute. This package renders those events as a phase list with spinner / per-phase detail / active-phase progress bar / final summary box.

Design notes

Mode-specific concerns (the phase list, the result type, how to render the summary, how to extract progress-bar counters from message strings) are passed in via Config so the same TUI serves both modes. Future UI improvements (token rate, ETA, sparklines) only need to be written here and both modes get them.

The background task runs in a goroutine and emits events via the `emit` closure given to RunTask. emit forwards events through the Bubble Tea program's Send channel so all model mutation happens on the main thread — the goroutine never touches the model directly.

Index

Constants

This section is empty.

Variables

View Source
var ErrCancelled = errors.New("cancelled by user")

ErrCancelled is returned from Run when the user exits the TUI before the background task signals done.

Functions

func RenderPhaseList added in v1.6.0

func RenderPhaseList(phases []PhaseInfo, state *State, activeSpinner string, maxDetailWidth int) string

RenderPhaseList renders the phase rows (no header, no progress bar, no summary) as a pure string. Used both by the bubbletea program in this package and by external callers (the in-app TUI) that want the same rendered shape inside their own layout.

activeSpinner is the glyph drawn for the active phase row; callers without a spinner can pass "" and the active row will use a plain "●". maxDetailWidth caps the truncation of each row's detail string; pass 0 to disable truncation.

func Run

func Run(cfg Config) error

Run executes the TUI to completion. The returned error is the task's error, not the TUI's — a TUI startup failure surfaces wrapped as "progress UI error: ...". User-cancelled (Ctrl+C before doneMsg arrived) returns ErrCancelled.

Types

type Config

type Config struct {
	Header Header
	Phases []PhaseDef

	// RunTask is the background work. emit forwards (phase, message)
	// events into the model on the Bubble Tea main thread. The
	// returned error becomes the run's error (passed to Summary).
	RunTask func(emit func(phase, message string)) error

	// ParseEvent updates counters in s for a (phase, message) pair.
	// Optional. The TUI also recognizes the special phase "warning"
	// as a banner regardless of ParseEvent.
	ParseEvent func(s *State, phase, message string)

	// Summary renders the final box after the run completes.
	// Optional. err is the RunTask return value; elapsed is wall time.
	Summary func(err error, elapsed time.Duration) string

	// OnCancel is called when the user exits the TUI (Ctrl+C / q)
	// before the background task signals done. The task's goroutine
	// is still in flight at this point; the canonical use is for the
	// caller to cancel the context it passed to RunTask so the
	// in-flight LLM call returns quickly instead of orphaning. Optional.
	OnCancel func()
}

Config configures a TUI run.

type Header struct {
	Title    string // e.g. "  prr audit", "  prr review"
	Subtitle string // e.g. repo name, PR number
	Info     string // e.g. "review: model-x  aoi: model-y"
}

Header is the title block shown at the top of the TUI.

type PhaseDef

type PhaseDef struct {
	// Name is the event key the pipeline emits on (e.g. "phase2", "fetch").
	// Must be unique within a Config.Phases slice.
	Name string

	// Label is the human-readable label shown next to the spinner/check.
	Label string

	// ProgressFn computes the active-phase progress bar value (0..1)
	// from the current State. Called only while this phase is active.
	// Return 0 (or leave nil) to skip the progress bar for this phase.
	ProgressFn func(s *State) float64

	// Counter returns (done, total) for inline "X/Y" display next to
	// the phase label. Rendered while the phase is active *and* after
	// it completes (so users can see the final tally per phase).
	// Skipped when total <= 0. Optional.
	Counter func(s *State) (done, total int)

	// Summary returns a stable description of what this phase
	// accomplished. Rendered as the row's detail line when the phase
	// reaches `done` state, replacing the last-write-wins live detail.
	// Falls back to live detail when this returns "" or is nil.
	//
	// Use this to surface structured information that would otherwise
	// be lost as the live detail line flips between transient status
	// messages — e.g., "kept 11 · dismissed 4" for Recheck or
	// "35 done · 58 cached · 3 failed" for Deep Review.
	Summary func(s *State) string
}

PhaseDef describes one phase shown in the TUI.

type PhaseInfo added in v1.6.0

type PhaseInfo struct {
	Def    PhaseDef
	Status PhaseStatus
	Detail string
}

PhaseInfo pairs a phase definition with its current status and the last-write-wins detail string. The bubbletea program in this package owns one of these per phase, and external consumers (e.g. the in-app TUI) build their own slice for RenderPhaseList.

type PhaseStatus added in v1.6.0

type PhaseStatus string

PhaseStatus is the lifecycle of a phase row.

const (
	PhaseWaiting PhaseStatus = "waiting"
	PhaseActive  PhaseStatus = "active"
	PhaseDone    PhaseStatus = "done"
	PhaseError   PhaseStatus = "error"
)

type State

type State struct {
	Counters map[string]int
	Elapsed  time.Duration
}

State exposes live counters and metadata to ProgressFn / ParseEvent closures. Counters is mode-defined — pick any string keys; the TUI doesn't interpret them.

Jump to

Keyboard shortcuts

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