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.