progress

package module
v1.0.8 Latest Latest
Warning

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

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

README

Go Version   Go Reference   pre-commit   tests   lint   coverage

Simple Terminal Progress Tracker

The progress package provides status updates to the terminal as units of work are incrementally completed.

Incremental calculations retain high-precision, while imposing minimal overhead upon callers.


Example Usage

See the examples directory for examples of the modal API.

Run the example programs to see the UI in action.

Here are a couple of real-world examples:


Features include:

  • race-free and lock-free by design:
    • concurrency-safe and well-suited to highly-scaled concurrent processing systems
    • uses Go concurrency primitives for synchronization
    • uses atomic.Uint64 and atomic.Pointer types to:
      • provide lock-free updates of internal state for highly-scaled concurrent workloads
      • obviate mutex contention
      • minimize memory allocation and impose minimal GC overhead
      • enable fast and efficient UI synchronization via comparisons of:
        • string pointers (atomic.Pointer[string])
        • string handles (unique.Handle[string])
        • atomic.Uint64 values
  • context-aware:
    • correctly handles cancellation of the parent context, ensuring a clean exit under reasonable circumstances
  • very efficient with minimal memory footprint:
    • optimized for low CPU usage, even at refresh rates beyond human perception
    • the use of a background rendering loop throttled at ~60 FPS combined with atomic types:
      • decouples the progress status tracker from the workers processing the workload
      • allows workers to report progress updates to the tracker asynchronously
      • ensures that UI rendering (which involves I/O and syscalls) never blocks the workers
    • dynamically pre-allocates a concurrency-safe, optimally-sized reusable atomic.Pointer[[]byte] buffer for all I/O:
      • increased dynamically as needed by a terminal window resize event listener
    • condenses all I/O operations into a single, atomic system call per frame, minimizing I/O latency
    • skips redundant UI redraws, further minimizing I/O and ensuring the terminal is never overwhelmed
    • uses bit-packed atomic.Uint32 types and bitwise operations to further reduce memory allocation and efficiently handle updates of internal state
  • supports two tracking modes:
    • weight-based accumulation: callers specify the total known amount of work (e.g., 100 tasks)
    • fractional allocation: callers add the relative share of the total budget as work is discovered (e.g., recursively traversing a directory to process its contents)
  • supports multiple progress status tracking implementations which are well-suited to different sets of inputs:
    • progress.Standard: suitable for mostly unique status updates (uses atomic.Pointer[string])
    • progress.Unique: suitable for mostly repetitive status updates (uses atomic.Value and unique.Handle[string] to canonicalize status, further reducing memory footprint)
  • supports multiple progress status formats:
    • progress.Fraction: writes progress status as a proper fraction (x/y) given a prescribed fixed total units of work (y)
    • progress.Percent: writes only the percentage calculation to the terminal
  • transparently handles pipes, redirections, and non-TTY environments
  • correctly handles UTF-8 strings passed by callers
  • supports concurrency-safe terminal window resizing, dynamically adapting the layout, formatting the rendered output accordingly, and ensuring layout and output integrity during concurrent writes to the terminal

Limitations:

  • the precision of percentage calculations starts to progressively degrade at ~1 quadrillion (1e15) units of work
    • a workload capacity limited to 1 quadrillion units still allows for extremely fine-grained budget splitting and / or extremely deep recursion
  • handling of terminal resize events on Windows systems is not supported
  • truncated status updates may render incorrectly in terminals which lack UTF-8 support

See Go Reference for API documentation and DeepWiki for technical internal implementation details.


Motivation

This library originated as an experiement to satisfy the author's curiosity about the practical application of modern, idiomatic Go features (e.g., context, sync/atomic, unique) in a context where concurrency is paramount after a nearly eight-year break from coding Go, back when 1.10 was the latest release.

The implementation was then iteratively optimized well beyond the point of overengineering, for fun and as a learning exercise.


Further Reading // Viewing

Documentation

Overview

Package progress provides status updates to the terminal as units of work are incrementally completed.

Index

Constants

View Source
const (
	// Standard is the default tracker, and is suitable for tracking mostly unique status updates.
	Standard strategy = iota

	// Unique is suitable for tracking repetitive status updates.
	Unique

	// Fraction renders status updates to the UI as a proper fraction (x/y).
	Fraction

	// Percent renders only the percentage of completed work.
	Percent
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Option added in v1.0.2

type Option func(*Progress) // exported to allow callers to create []*progress.Option to pass to New(...)

Option defines a functional configuration for Progress.

func WithTheme added in v1.0.8

func WithTheme(c string) Option

WithTheme allows callers to override the default color (green) of the progress bar, e.g.:

progress.New(ctx, 100, os.Stderr, progress.WithTheme("yellow"))

Silently falls back to the default ("green") if an invalid theme name is specified.

func WithTracker added in v1.0.2

func WithTracker(s strategy) Option

WithTracker allows callers to override the default progress.Standard status tracker, e.g.:

progress.New(ctx, 100, os.Stderr, progress.WithTracker(progress.Fraction))

type Progress

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

Progress implements a throttled, concurrency-safe, high-precision status indicator for workloads.

func New

func New(ctx context.Context, totalUnits uint64, output io.Writer, opts ...Option) *Progress

New initializes a throttled, concurrency-safe, high-precision work progress tracker and starts a work completion status rendering loop in the background.

The value of the `totalUnits` parameter determines the accumulation mode used internally:

pass totalUnits >  0 for weight-based accumulation  (when totalUnits is known)
pass totalUnits == 0 for fractional path allocation (when totalUnits is unknown)

func (*Progress) AddTotal

func (p *Progress) AddTotal(n uint64)

AddTotal dynamically increases the total work budget as new tasks are discovered. It is concurrency-safe and ensures the total budget never exceeds scale.

func (*Progress) Close

func (p *Progress) Close()

Close stops the background renderer and waits for cleanup to complete.

func (*Progress) InitialBudget

func (p *Progress) InitialBudget() float64

InitialBudget returns the full internal scale (100%) to be used as the starting budget for tracking fractional progress.

func (*Progress) Report

func (p *Progress) Report(weight float64, status string)

Report updates the current progress status.

if total >  0: weight represents the relative weight of the work completed, and the
               progress percentage is calculated as accumulated weight / totalUnits

if total == 0: weight represents the portion of the InitialBudget(),
               which must be divided among all sub-tasks by the caller

Jump to

Keyboard shortcuts

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