Browse documentation

Overview

Overview

Start here

Your first CLIRunnable examplesGuide index

How do I...?

Common recipesShell completionProject generator

Learn

Commands and subcommandsOptions and validationOutput, errors, and progress

Reference

Public APICurrent limitations

Inside cli-fp

Technical design

Project

Contributing and support

Output, errors, and progress

How do I...? · Examples · API reference

Use CLI.Console for coloured output and CLI.Progress for a spinner or progress bar. These calls normally live inside the Execute method of your TBaseCommand descendant; the framework does not decide what your command prints.

Colour is disabled when stdout is redirected or when the NO_COLOR environment variable has a non-empty value (even NO_COLOR=0 disables colour); an empty value does not disable colour by itself. Terminal text removes NUL and ESC control characters while preserving ordinary prose, Unicode, and line breaks. Coloured writes reset to default colours in finally, including when output raises an error. They do not restore arbitrary colours set by an earlier call.

Coloured output

Import CLI.Console in the command unit and call the TConsole class directly—there is no console instance to declare. This is an Execute-body fragment:

TConsole.WriteLn('Done', ccGreen);
TConsole.WriteLn('Could not connect', ccRed);

TConsole.Write and TConsole.WriteLn also have uncoloured overloads. See ColorDemo for a runnable program.

Spinner

Use a spinner when the duration is unknown. This complete Execute-method fragment belongs to a declared TDownloadCommand = class(TBaseCommand); its command unit needs CLI.Interfaces and CLI.Progress:

function TDownloadCommand.Execute: Integer;
var
  Spinner: IProgressIndicator;
begin
  Spinner := CreateSpinner(ssLine);
  Spinner.Start;
  try
    Spinner.Update(0, 'Downloading');
    // Perform the download here.
  finally
    Spinner.Stop;
  end;
  Result := 0;
end;

Always stop the indicator in finally.

Update renders immediately; it does not sleep. Choose the refresh cadence in the work loop that calls it.

Progress bar

Use a progress bar when you know the total work. This complete Execute- method fragment belongs to a declared TBatchCommand = class(TBaseCommand); its command unit needs SysUtils, CLI.Interfaces, and CLI.Progress:

function TBatchCommand.Execute: Integer;
var
  Bar: IProgressIndicator;
  Index: Integer;
  Total: Integer;
begin
  Total := 3;
  Bar := CreateProgressBar(Total);
  Bar.Start;
  try
    for Index := 1 to Total do
    begin
      // Process item Index here.
      Bar.Update(Index, Format('Processed %d of %d', [Index, Total]));
    end;
  finally
    Bar.Stop;
  end;
  Result := 0;
end;

The ProgressDemo contains both patterns.

Progress bars cap their configured visual width at 200 characters, so a bad configuration cannot request an enormous allocation. ClearLine uses ANSI line clearing on a capable terminal and falls back to a bounded portable overwrite otherwise.

Fail clearly

Return a non-zero value from your command's Execute for an expected command failure. Catch unexpected exceptions where your application can add useful context, then return 1. The framework reports parse and validation errors before calling Execute.