mon

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Mar 5, 2026 License: MIT Imports: 11 Imported by: 0

README

mon(itor)

Go Reference

A simple and clean abstraction for reporting progress to a user in a CLI.

go run ./demo/main.go

Features

  • Built-in CLI animations and terminal UI.
  • Runs asynchronously in the background using goroutines.
  • Fluent builder API for adding tasks to the monitor.
  • Supports determinate (fixed number of steps) and indeterminate tasks.
  • Automatic estimated completion time calculations for determinate tasks.
  • Extensible human-readable formatting for values.

Usage

Import the mon library and create a new monitor.

package main

import (
	"context"

	"github.com/apollosoftwarexyz/mon"
)

Then, create and show a new monitor. As soon as Show is called, the monitor is displayed in the terminal. It can be removed by calling the returned cancel() function which should always be called with a defer.

// Create a new monitor.
m := mon.New("Please wait")

// Show the monitor. The returned cancel method allows the UI to be cleaned
// up programmatically or automatically (with defer) when the work is done.
ctx, cancel := m.Show(context.WithCancelCause(context.Background()))
defer cancel(nil)

Finally, track some tasks! You can get a new task builder by calling AddTask on the monitor.

  • Use Apply on the builder when you want to show the task on the monitor (normally this is immediately).
  • For determinate tasks (where the number of total steps is known), set TotalSteps on the builder as shown below and then track work with CompleteStep or CompleteSteps.
  • As steps are completed, statistics such as the estimated remaining time and number of completed steps per second are automatically computed.
// Do the work
task := m.AddTask().Name("my task").TotalSteps(2048).Apply()

// Increment the number of completed steps.
task.CompleteStep()
task.CompleteStep()

// Bulk increment the number of completed steps.
task.CompleteSteps(1024)

Indeterminate tasks are also supported, simply don't set TotalSteps and call CompleteStep when done:

// Also supports indeterminate tasks!
indeterminateTask := m.AddTask().Name("indeterminate task").Apply()

// ...just use CompleteStep when it's done!
indeterminateTask.CompleteStep()

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type M

type M interface {
	// AddTask creates a [TaskBuilder] that can be used to define and add a new
	// task to the monitor.
	AddTask() TaskBuilder

	// IsCancellationBlocked returns true if cancellation has been blocked with
	// [M.BlockCancellation] (or if it has been unblocked with
	// [M.AllowCancellation]).
	IsCancellationBlocked() bool

	// AllowCancellation permits the user to press Ctrl+C to cancel the context
	// used by the monitor.
	//
	// This is the default behavior and need only be called to restore
	// cancellation behavior if it has been blocked with [M.BlockCancellation].
	//
	// The same monitor instance is returned to allow for a fluent API.
	AllowCancellation() M

	// BlockCancellation ignores user actions such as Ctrl+C that would
	// otherwise cancel the context used by the monitor.
	//
	// This function is unable to block all forms of cancellation (for example,
	// SIGKILL) - the intention is just to help discourage the user from
	// cancelling a task at a bad moment.
	//
	// The same monitor instance is returned to allow for a fluent API.
	BlockCancellation() M

	// GetCaption of the monitor.
	GetCaption() string

	// SetCaption of the monitor.
	SetCaption(caption string)

	// Show the monitor in the CLI.
	//
	// The [CancelFunc] should be deferred immediately after Show is called:
	//
	//	ctx, cancel := m.Show(context.WithCancelCause(context.Background()))
	//	defer cancel()
	Show(ctx context.Context, cancel context.CancelCauseFunc) (context.Context, context.CancelCauseFunc)
}

M is a CLI monitor for various Task statuses.

func New

func New(caption string) M

New monitor.

Once configured, the monitor can be displayed with [M.Show].

type Task

type Task interface {
	// GetName of the task.
	GetName() string

	// SetName of the task.
	SetName(name string)

	// GetCaption of the task.
	GetCaption() string

	// SetCaption of the task.
	SetCaption(caption string)

	// GetCategory of the task.
	GetCategory() string

	// SetCategory of the task.
	SetCategory(category string)

	// GetUnit of the task. This is used to render progress based on steps.
	GetUnit() formatting.Unit

	// IsError returns true if Error has been called with a non-nil error.
	IsError() bool

	// GetError status of the task.
	//
	// If there is no error, GetError returns nil. Otherwise, a non-nil error is
	// returned.
	GetError() error

	// Error records that the task has failed with the given error.
	//
	// The error must not be nil, calling Error with a nil error is a no-op.
	// Once an error has been set, it cannot be cleared as the task is marked as
	// complete.
	Error(err error)

	// GetStartedAt returns the time that the task was started at.
	GetStartedAt() time.Time

	// GetCompletedAt returns the time that the task was completed at. If the
	// task is not completed (i.e., IsCompleted is false), this function returns
	// a time for which [time.Time.IsZero] returns true.
	GetCompletedAt() time.Time

	// GetElapsed time since the task was created and before the task was
	// stopped.
	GetElapsed() time.Duration

	// GetProgress expressed as a percentage. For tasks where IsIndeterminate is
	// true, this is always zero or 100%.
	GetProgress() float64

	// GetAverageTimePerStep computes a mean average of time per step using up
	// to 256 discrete previous step times. If there are no completed steps,
	// this function returns zero and false.
	GetAverageTimePerStep() (time.Duration, bool)

	// GetEstimatedCompletion duration from now.
	//
	// This function uses [Task.GetAverageTimePerStep] and the number of
	// remaining steps to extrapolate a completion time. This relies on an
	// assumption that steps are sequential within a task and that steps are
	// equal (that is, they should nominally take roughly the same amount of
	// time to complete).
	//
	// If there are no completed steps, or the task is already complete, this
	// function returns zero and false.
	GetEstimatedCompletion() (time.Duration, bool)

	// IsIndeterminate indicates whether a total number of steps is known.
	//
	// If it is not (i.e., StepsTotal is 0) then the task is indeterminate.
	IsIndeterminate() bool

	// IsCompleted indicates that a task is fully completed. If the task
	// IsIndeterminate, this is true if there are any completed steps.
	IsCompleted() bool

	// CompleteStep increments the number of steps that have already been
	// completed as part of this task.
	//
	// This is a convenience function for [CompleteSteps] with a value of one.
	//
	// If the task IsDone, this function is a no-op.
	CompleteStep()

	// GetCompleteSteps returns the number of steps that have already been
	// completed as part of this task.
	GetCompleteSteps() uint64

	// CompleteSteps adds n to the number of steps that have already been
	// completed as part of this task. The value is clamped at the number of
	// total steps for the task.
	//
	// If n is less than one, this function is a no-op.
	//
	// If the task IsDone, this function is a no-op.
	CompleteSteps(n uint64)

	// SetCompletedSteps sets the number of steps that have already been
	// completed as part of this task. The value is clamped to the number
	// of total steps for the task.
	//
	// If the given number of complete steps is less than or equal to the
	// current number of complete steps, this function is a no-op. (In other
	// words, it is not possible to 'un-complete' steps).
	//
	// Given the above, if completeSteps is zero, this function is a no-op.
	//
	// If the task IsDone, this function is a no-op.
	SetCompletedSteps(completeSteps uint64)

	// GetTotalSteps returns the number of steps that must be completed as part
	// of this task.
	GetTotalSteps() uint64

	// TotalSteps sets the total number of steps that must be completed as part
	// of this task.
	//
	// If the task IsDone, this function is a no-op.
	TotalSteps(totalSteps uint64)
}

Task tracked by a monitor, M.

type TaskBuilder

type TaskBuilder interface {
	// Name sets the name of the task.
	Name(name string) TaskBuilder

	// Caption sets the caption of the task.
	Caption(caption string) TaskBuilder

	// Category sets the category of the task.
	Category(category string) TaskBuilder

	// Unit renderer for step progress.
	Unit(unit formatting.Unit) TaskBuilder

	// TotalSteps sets the total number of steps that must be completed as part
	// of this task. If this is not set, then [Task.IsIndeterminate] is true.
	TotalSteps(totalSteps uint64) TaskBuilder

	// Apply the task to the monitor that created the builder.
	//
	// This is the terminal step of the builder and returns the [Task] reference
	// that was added to the monitor.
	Apply() Task
}

TaskBuilder for adding new Task references to a monitor (M).

Directories

Path Synopsis
Package formatting contains formatting tools for the https://github.com/apollosoftwarexyz/mon package.
Package formatting contains formatting tools for the https://github.com/apollosoftwarexyz/mon package.

Jump to

Keyboard shortcuts

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