Skip to content

Progress

AnsiConsole.Progress displays a live, multi-task progress tracker. Each task is one row; the columns - description, bar, percentage, spinner, elapsed, remaining time, downloaded bytes, transfer speed - are user-configurable.

Progress screenshot

When to use

  • Anything with measurable work - downloads, batch processing, build steps.
  • Single tasks too (just add one) - the per-task speed / ETA computations are useful even on their own.

For indeterminate single-task spinners, Status is simpler.

Basic usage

pascal
AnsiConsole.Progress.Start(
  procedure(const ctx : IProgress)
  var
    download : IProgressTask;
    process  : IProgressTask;
  begin
    download := ctx.AddTask('Downloading', 100);
    process  := ctx.AddTask('Processing',  100);
    while not (download.IsFinished and process.IsFinished) do
    begin
      if not download.IsFinished then download.Increment(2);
      if download.Percentage > 30 then process.Increment(1);
      Sleep(60);
    end;
  end);

Each AddTask(description, maxValue) returns an IProgressTask you mutate inside the action. A background ticker thread redraws the board every ~100ms.

Configuring columns

pascal
AnsiConsole.Progress
  .WithColumns([
    Widgets.DescriptionColumn,
    Widgets.ProgressBarColumn(40),
    Widgets.PercentageColumn,
    Widgets.SpinnerColumn,
    Widgets.RemainingTimeColumn])
  .Start(
    procedure(const ctx : IProgress)
    begin
      // ...
    end);

Available column factories on the Widgets record:

FactoryWhat it shows
DescriptionColumnThe label passed to AddTask. Markup supported.
ProgressBarColumnFilled / unfilled bar.
ProgressBarColumn(width)Bar capped at width cells; -1 = no cap.
PercentageColumn42%
ElapsedColumnhh:mm:ss since StartTask.
RemainingTimeColumnhh:mm:ss ETA (or **:**:** if indeterminate).
SpinnerColumn / SpinnerColumn(kind)Animated spinner.
DownloadedColumn512 KB / 1 MB formatted bytes.
TransferSpeedColumn256 KB/s rolling average.

Configuration

MethodPurpose
WithColumns(array)Set the column list.
WithAutoClear(value)Clear the entire board when the action exits. Default False.
WithHideCompleted(value)Hide tasks that have reached their max.
WithRefreshMs(value)Ticker interval (ms). Default ~100ms.
WithAutoRefresh(value)Suppress the ticker; you drive redraw via ctx.Refresh.
WithRenderHook(hook)Wrap the rendered board in a custom renderable each tick - useful for adding a panel/header around the live region.
pascal
AnsiConsole.Progress
  .WithColumns([Widgets.DescriptionColumn, Widgets.ProgressBarColumn(40), Widgets.PercentageColumn])
  .WithAutoClear(True)
  .Start(...);

The IProgress context

Inside the action, ctx : IProgress exposes:

MemberPurpose
AddTask(description, maxValue) : IProgressTaskStart a task.
AddTask(description, maxValue, autoStart : Boolean)Defer auto-start.
AddTaskAt(description, index, maxValue, autoStart)Insert at a specific row index.
AddTaskBefore(description, refTask, ...) / AddTaskAfter(...)Relative-position inserts.
IsFinished : BooleanAll tasks complete?
RefreshForce a redraw.

The IProgressTask handle

MemberPurpose
Increment(by : Double = 1)Bump the value.
StartTask / StopTaskManual lifecycle when autoStart = False.
IsFinished : BooleanValue >= MaxValue.
Value / MaxValue (rw)Direct numeric access.
Description (rw)Update the label after creation.
IsIndeterminate (rw)When True the bar pulses, percentage stops counting.
PercentageRead-only computed value.
SpeedSteps/sec rolling average over a 30s window.
RemainingMsETA based on speed.

Indeterminate tasks

pascal
t := ctx.AddTask('Pre-flight checks', 0);
t.IsIndeterminate := True;
// later, when work becomes measurable:
t.MaxValue := 200;
t.IsIndeterminate := False;

The progress bar pulses while indeterminate (a cosine-fade animation).

Explicit console

pascal
AnsiConsole.Progress(myCapturedConsole).Start(...);

API reference

See also

Released under the MIT License.