Skip to content

Eudox67/LazTermUtils

Repository files navigation

LazTermUtils

Terminal Utility Classes for Coloring and Inputs on terminals

About

This small library contains a few classes for managing terminal I/O using ANSI escape sequences. The goal of this unit is provide the functionality provided by the CRT unit (and some more), but optimized for only the most prevalent systems, by only using escape sequences. It was tested under Windows 10 and Linux and allows for writing portable, pretty console applications on both systems.

The functionality include:

  • Colorizing output (background, foreground)
  • Modifying output (bold, italic, underlined, etc.)
  • Reading input keys and modifiers
  • Managing terminal window (getting size, jumping around, clearing)
  • Non blocking reading of chars and keys
  • Terminal spinner animations
  • Nested styles with auto-reset (Chalk-like)
  • Template literals with style tags
  • Auto color detection
  • Box drawing with borders, padding, margin, and colors
  • Progress bars with ETA, throughput, and multiple styles
  • Multi-progress bars for parallel operations
  • Interactive lists for single/multi-selection
  • Text input with validation and password masking
  • Yes/No confirmations

Requirements

This library uses xTerm compatible ANSI escape sequences.

This works with any Terminal emulator supporting this including, but not limited to xTerm, Konsole, GNOME Terminal and the Windows Terminal in Windows 10 (not compatible with older versions of Windows) If the terminal does not support 24 bit (true) color (e.g. the macOS system terminal emulator), you might want to set the define Col8 (only required in TerminalColor.pas), which limits the output to 8bit colors. Lower than that is not supported.

Usage

See the example directory for some examples.

  • example/ReadkeyExample shows how to read Keystrokes and process them
  • example/Colortest colors the whole display (each cell individually) while measuring the FPS to brenchmark the performance of redrawing every cell
  • example/Textmods prints text with different modifications. Which of them get displayed correctly depends on your Terminal emulator.
  • example/NonBlockingReadTest shows how to use non blocking read to update your view and check for keystrokes single threaded
  • example/SpinnerDemo demonstrates terminal spinner animations with various styles

Spinner Usage

The TSpinner class provides animated spinner indicators:

uses Terminal, TerminalSpinner, TerminalModifier;

var
  Term: TTerminal;
  Spinner: TSpinner;
begin
  Term := TTerminal.Create;
  Spinner := TSpinner.Create(Term.Output, ssBraille);
  
  Spinner.Prefix := 'Loading';
  Spinner.Message := 'Processing...';
  Spinner.Color := ForegroundColor(0, 255, 0);  // Green
  Spinner.Start;
  
  while Working do
  begin
    Spinner.Message := 'Processing item ' + IntToStr(Counter);
    Spinner.Tick;
    Sleep(100);
  end;
  
  Spinner.Stop('Done!', ForegroundColor(0, 255, 0));
  Spinner.Free;
  Term.Free;
end;

Available spinner styles:

  • ssASCII - Classic | / - \ animation
  • ssBraille - Unicode braille patterns (⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏)
  • ssArrows - Arrow directions (←↖↑↗→↘↓↙)
  • ssPulse - Pulse blocks (░▒▓)
  • ssDots - Dot patterns
  • ssMoon - Moon phases (🌑🌒🌓🌔🌕🌖🌗🌘)
  • ssCustom - User-defined frames via SetCustomFrames()

Styled Strings (Chalk-like)

The TStyledString type supports nested styles with automatic reset:

uses Terminal, TerminalStyledString, TerminalModifier;

// Simple color shortcuts
WriteLn(Red('Error: ') + 'Something went wrong');
WriteLn(Green('Success!'));
WriteLn(Bold('Important: ') + Italic('Note this'));

// Nested styles - styles automatically close
WriteLn(Red('Error: ' + Bold('Critical failure') + ' in module'));

// Combining with operators
var msg: TStyledString;
msg := Red('Error: ') + Bold('File not found') + ' at ' + Cyan('line 42');
WriteLn(msg.ToString);

Template Literals

Use style tags in template strings:

uses TerminalStyledString;

// Basic template with auto-closing tags
WriteLn(Template('{red}Error:{/} File not found').ToString);

// Nested tags
WriteLn(Template('{bold}{red}Error:{/} Critical{/}').ToString);

// With format arguments
WriteLn(Template('{green}Success:{/} Processed %d files in %.2f seconds', 
  [FileCount, ElapsedTime]).ToString);

Available template tags:

  • Colors: {red}, {green}, {blue}, {yellow}, {cyan}, {magenta}, {white}, {black}
  • Backgrounds: {bgRed}, {bgGreen}, {bgBlue}, {bgYellow}
  • Styles: {bold}, {italic}, {underline}, {strikethrough}, {dim}, {hidden}, {invert}
  • Close: {/} closes the current style

Auto Color Detection

Detect terminal color support at runtime:

uses Compatibility, Terminal;

var
  ColorSupport: TColorSupport;
begin
  ColorSupport := DetectColorSupport(StandardOut);
  
  case ColorSupport of
    csNone:      WriteLn('No color support');
    cs16:        WriteLn('16 colors (basic ANSI)');
    cs256:       WriteLn('256 colors');
    csTrueColor: WriteLn('True color (24-bit)');
  end;
end;

Box Drawing

Create styled boxes with borders, padding, and colors:

uses TerminalBox, TerminalModifier;

// Simple box
WriteLn(Box('Hello World').Render);

// Styled box with fluent API
WriteLn(Box('Important!')
  .Border(bsRounded)
  .BorderColor(0, 255, 0)
  .Padding(1, 2, 1, 2)
  .Title('Notice')
  .Render);

// Pre-configured styles
WriteLn(BoxInfo('Information message'));
WriteLn(BoxSuccess('Operation completed!'));
WriteLn(BoxWarning('Caution advised'));
WriteLn(BoxError('Something went wrong'));

Available border styles: bsSingle, bsDouble, bsRounded, bsThick, bsASCII, bsCustom

Progress Bar

Display progress with ETA and throughput:

uses Terminal, TerminalProgressBar, TerminalModifier;

var
  Bar: TProgressBar;
begin
  Bar := TProgressBar.Create(40);
  Bar.SetPrefix('Downloading');
  Bar.ShowETA := True;
  Bar.ShowThroughput := True;
  
  for i := 0 to 100 do
  begin
    Write(#13 + Bar.Render(i / 100));
    Sleep(50);
  end;
  WriteLn;
  Bar.Free;
end;

Available styles: pbsClassic, pbsBlocks, pbsDots, pbsArrow, pbsCustom

Multi-Progress Bar

Display multiple progress bars simultaneously:

uses Terminal, TerminalMultiBar;

var
  MultiBar: TMultiProgressBar;
begin
  MultiBar := TMultiProgressBar.Create(Term.Output);
  MultiBar.AddBar('Download', 25);
  MultiBar.AddBar('Upload', 25);
  
  MultiBar.SetBarColor(0, 0, 200, 255);  // Cyan
  MultiBar.SetBarColor(1, 255, 200, 0);  // Orange
  
  MultiBar.Start;
  for i := 0 to 100 do
  begin
    MultiBar.Update(0, i * 0.01);
    MultiBar.Update(1, i * 0.007);
    MultiBar.Render;
    Sleep(50);
  end;
  MultiBar.Finish;
  MultiBar.Free;
end;

Interactive Lists

Single and multi-selection lists:

uses Terminal, TerminalList;

var
  Index: Integer;
  Indices: TIntegerArray;
begin
  // Single selection (radio style)
  Index := SelectItem('Choose:', ['Option A', 'Option B', 'Option C'], 
    Term.Output, Term.Input);
  
  // Multi-selection (checkbox style)
  Indices := SelectItems('Select features:', 
    ['Dark mode', 'Notifications', 'Auto-save'],
    Term.Output, Term.Input);
  
  // Yes/No confirmation
  if Confirm('Delete all files?', False, Term.Output, Term.Input) then
    WriteLn('Deleted!');
end;

Text Input

Interactive text input with validation:

uses Terminal, TerminalInput;

var
  Name, Password: String;
begin
  // Simple text input
  Name := ReadInput('Enter your name:', Term.Output, Term.Input);
  
  // Password input (masked with *)
  Password := ReadPassword('Enter password:', Term.Output, Term.Input);
  
  // With validation and max length
  Input := TTerminalInput.Create(Term.Output, Term.Input);
  Input.SetPrompt('Enter email:');
  Input.SetValidator(@ValidatorEmail);
  Input.SetMaxLength(50);
  Email := Input.ShowAndGetText;
  Input.Free;
end;

Available validators: ValidatorAlpha, ValidatorAlphaNumeric, ValidatorNumeric, ValidatorHex, ValidatorEmail, ValidatorNoSpaces

Unicode on Windows

To use unicode (UTF-8) strings on Windows, you need to set the console code page:

  SetConsoleOutputCP(DefaultSystemCodePage);
  SetTextCodePage(Output, DefaultSystemCodePage);
  SetTextCodePage(ErrOutput, DefaultSystemCodePage);

Further information can be found here: https://wiki.freepascal.org/Lazarus_with_FPC3.0_without_UTF-8_mode#Problem_System_encoding_and_Console_encoding_.28Windows.29

About

Fork of Warfley's LazTermUtils

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages