progressbar

package
v0.0.21 Latest Latest
Warning

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

Go to latest
Published: Aug 21, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var PackageProps = packageprops.Props{
	WASMWASI:         packageprops.WASMCompiles,
	WASMJS:           packageprops.WASMCompiles,
	WASMFreestanding: packageprops.WASMBlocked,
}

PackageProps records this package's curated properties (ADR-0080). Seeded by `boxer code analysis golang wasmsurvey props generate`; curate by hand. The same group's `props verify` reconciles it.

Functions

func FormatBytes

func FormatBytes(b int64) string

func FormatDuration

func FormatDuration(d time.Duration) string

func FormatETA

func FormatETA(d time.Duration) string

FormatETA formats an ETA duration with reduced precision at larger magnitudes. Under 10 minutes: full resolution. 10–60 min: nearest minute. Over 1 hour: nearest 5 minutes. Coarser labels reduce perceived wait (Harrison et al. 2007).

Types

type Bar

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

Bar is a terminal progress bar supporting determinate (known total) and indeterminate (total=0, spinner only) modes. It is safe for concurrent use.

The rendering path is ANSI-to-stderr by default (see ansi.go). Tests or non-terminal consumers can swap the writer via SetWriter.

func New

func New(total int64, label string) (bar *Bar)

New creates a progress bar. Pass total=0 for indeterminate mode. The label describes what is being counted (e.g. "tiles", "pages").

func (*Bar) Add

func (inst *Bar) Add(delta int64)

Add increments the processed counter by delta.

func (*Bar) Elapsed

func (inst *Bar) Elapsed() time.Duration

Elapsed returns time since the bar was constructed.

func (*Bar) Estimator

func (inst *Bar) Estimator() *Estimator

Estimator exposes the underlying ETA estimator so callers (e.g. the egui2 demo) can inspect smoothed rate/trend and the damped vs. raw ETA.

func (*Bar) LogWriter

func (inst *Bar) LogWriter() (w io.Writer)

LogWriter returns an io.Writer whose output is serialised with the bar's render loop via inst.writeMu. Point a logger at it so log lines land on their own terminal rows instead of tangling with the \r-based progress line:

bar := progressbar.New(total, "items")
log.Logger = log.Output(bar.LogWriter())
bar.Start(ctx)

Each Write is treated as one line-oriented message: on a TTY we first emit \r + erase-line so the in-place bar frame disappears, then the payload, then a '\n' if the payload didn't already end with one. The next render tick (≤250 ms later) repaints the bar on a fresh row below the log line.

In non-TTY mode the writer is a straight passthrough aside from the trailing-newline guarantee.

The trailing-newline guarantee assumes callers pass one complete event per Write. Standard logger writers (log.Logger, zerolog.ConsoleWriter, slog's text/JSON handlers) all satisfy this.

func (*Bar) NewProxyReader

func (inst *Bar) NewProxyReader(r io.Reader) (pr *ProxyReader)

NewProxyReader wraps r with byte-count ticking against this Bar.

func (*Bar) NewProxyWriter

func (inst *Bar) NewProxyWriter(w io.Writer) (pw *ProxyWriter)

NewProxyWriter wraps w with byte-count ticking against this Bar.

func (*Bar) Printf

func (inst *Bar) Printf(format string, args ...any)

Printf formats through LogWriter. A trailing newline is appended by LogWriter if the formatted output doesn't already end with one.

func (*Bar) Println

func (inst *Bar) Println(args ...any)

Println writes one line through LogWriter — convenience for ad-hoc messages that don't go through a logger.

func (*Bar) Processed

func (inst *Bar) Processed() int64

Processed returns the current count.

func (*Bar) SetDetail

func (inst *Bar) SetDetail(fn DetailFunc)

SetDetail registers a callback that returns domain-specific status text appended after the bar on each render. May be called before Start.

func (*Bar) SetWriter

func (inst *Bar) SetWriter(w io.Writer)

SetWriter overrides the output writer (default: os.Stderr). Also flips the bar out of TTY mode so tests/log-capture receive line-based output.

func (*Bar) Start

func (inst *Bar) Start(ctx context.Context)

func (*Bar) Stop

func (inst *Bar) Stop()

func (*Bar) Tick

func (inst *Bar) Tick()

Tick increments the processed counter by 1.

func (*Bar) Total

func (inst *Bar) Total() int64

Total returns the configured total (0 for indeterminate bars).

type DetailFunc

type DetailFunc func(processed int64, total int64) string

DetailFunc is called on each render to format domain-specific status text. It receives the current processed count and total (0 if indeterminate).

type Estimator

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

Estimator uses Holt's Double Exponential Smoothing to produce a smoothed rate estimate that captures both level and trend (acceleration/deceleration), plus a display-dampening layer that prevents the shown ETA from oscillating.

It has no I/O and no concurrency story of its own — callers drive it with Update and read back SmoothedRate / SmoothedTrend / EstimateETA. The CLI renderer and the egui2 demo both use it this way.

Use NewEstimator to construct one with tqdm/Rich-style defaults.

func NewEstimator

func NewEstimator() (inst *Estimator)

NewEstimator returns an Estimator with tqdm/Rich-style defaults (alpha=0.3, beta=0.1, damping=10%). Start must be called before Update.

func (*Estimator) DisplayedETA

func (inst *Estimator) DisplayedETA() time.Duration

DisplayedETA is the last ETA returned by EstimateETA, after damping. Zero if EstimateETA has not yet produced a valid value.

func (*Estimator) EstimateETA

func (inst *Estimator) EstimateETA(remaining float64) (eta time.Duration, valid bool)

EstimateETA returns the damped ETA for `remaining` units of work. Decreases pass through immediately; small increases (within dampingThreshold of the displayed value) are suppressed; large increases break through. See EXPLANATION.md for the rationale.

func (*Estimator) RawETA

func (inst *Estimator) RawETA(remaining float64) (eta time.Duration, valid bool)

RawETA returns remaining/smoothedRate without damping. Useful for demos that want to visualise the damping filter.

func (*Estimator) Reset

func (inst *Estimator) Reset(now time.Time, count int64)

Reset clears all smoothed state and re-anchors at (now, count). Use this when the underlying counter is reset (e.g. a new run) — otherwise the stale level/trend will bias the first few updates.

func (*Estimator) Samples

func (inst *Estimator) Samples() int

Samples returns the number of Update calls that produced a sample (ignores calls skipped by the 50 ms floor).

func (*Estimator) SmoothedRate

func (inst *Estimator) SmoothedRate() float64

SmoothedRate returns the current level estimate S (items/sec).

func (*Estimator) SmoothedTrend

func (inst *Estimator) SmoothedTrend() float64

SmoothedTrend returns the current trend estimate B (items/sec^2-ish — it is the smoothed step-over-step change in the level).

func (*Estimator) Start

func (inst *Estimator) Start(now time.Time, count int64)

Start anchors the estimator at the given time and count. Call before the first Update so dt is measured from a meaningful origin.

func (*Estimator) Update

func (inst *Estimator) Update(now time.Time, count int64)

Update folds the instantaneous rate between the previous observation and (now, count) into the smoothed level and trend. Observations closer than 50 ms apart are ignored to avoid noise from high-frequency sampling.

type ProxyReader

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

ProxyReader wraps an io.Reader, Add-ing the byte count of each successful Read to the Bar. The common use is driving a byte-scale determinate bar from an HTTP response body, a file read, or a compressor stream:

bar := progressbar.New(resp.ContentLength, "bytes")
bar.Start(ctx)
defer bar.Stop()
pr := bar.NewProxyReader(resp.Body)
defer pr.Close()
_, _ = io.Copy(dst, pr)

Close is propagated to the wrapped reader when it implements io.Closer.

func (*ProxyReader) Close

func (inst *ProxyReader) Close() (err error)

Close propagates to the wrapped reader if it is an io.Closer; returns nil otherwise so the ProxyReader can be used in a deferred Close regardless.

func (*ProxyReader) Read

func (inst *ProxyReader) Read(p []byte) (n int, err error)

type ProxyWriter

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

ProxyWriter is the write-side counterpart to ProxyReader. Each successful Write adds its byte count to the Bar.

func (*ProxyWriter) Close

func (inst *ProxyWriter) Close() (err error)

func (*ProxyWriter) Write

func (inst *ProxyWriter) Write(p []byte) (n int, err error)

Jump to

Keyboard shortcuts

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