Skip to content

Repository files navigation

cli-fp: A CLI framework for Free Pascal

⚑ cli-fp: Native CLIs for Free Pascal

License: MIT Free Pascal Lazarus Supports Windows Supports Linux Version No Dependencies Documentation Tests Status

cli-fp is a lightweight framework for building polished native command-line applications in Free Pascalβ€”with command trees, typed option validation, generated help and shell completion, colours, spinners, and progress bars, but no third-party runtime dependencies.

A complete small CLI:

program HelloCLI;

{$mode objfpc}{$H+}{$J-}

uses
  CLI.Interfaces,
  CLI.Application,
  CLI.Command;

type
  THelloCommand = class(TBaseCommand)
  public
    function Execute: Integer; override;
  end;

function THelloCommand.Execute: Integer;
var
  PersonName: string;
begin
  if not GetParameterValue('--name', PersonName) then
    PersonName := 'World';
  WriteLn('Hello, ', PersonName, '!');
  Result := 0;
end;

var
  App: ICLIApplication;
  Main: THelloCommand;
begin
  Main := THelloCommand.Create('', 'Print a greeting');
  Main.AddStringParameter('-n', '--name', 'Name to greet', False, 'World');
  App := CreateCLIApplication('hello', '1.0.0', Main);
  Halt(App.Execute);
end.
$ ./HelloCLI --name Ada
Hello, Ada!

✨ Why cli-fp?

cli-fp keeps the common parts of a command-line application coherent without hiding the native Pascal program underneath:

  • Build one action, named commands, or deeply nested command trees.
  • Validate strings, integers, floats, booleans, dates, enumerations, and custom values before execution.
  • Generate consistent help plus Bash and PowerShell completion from the same command definitions.
  • Add terminal polish with colours, spinners, progress bars, and debug logging.
  • Compile to normal Windows and Linux executables using standard Free Pascal units only.
  • Use the optional project generator when it helps, or work directly with the runtime library.

The public facade remains deliberately small; parsing, validation, help, completion, and dispatch share the same internal model. See the roadmap for current scope and future work.

πŸš€ Quick start

You need Free Pascal 3.2.2. Install it from the official downloads page, or use the compiler supplied with Lazarus. Check that it is available:

fpc -iV

Clone the repository:

git clone https://github.com/ikelaiah/cli-fp.git
cd cli-fp

Save the complete example above as HelloCLI.lpr in the repository root.

Compile and run it on Linux or macOS:

fpc -Fu./src HelloCLI.lpr
./HelloCLI --name Ada
./HelloCLI --help

Or with PowerShell on Windows:

fpc "-Fu.\src" .\HelloCLI.lpr
.\HelloCLI.exe --name Ada
.\HelloCLI.exe --help

The first command prints:

Hello, Ada!

This example has one application, one root command, and one option. The command implements the work, while the framework owns argument parsing, validation, help, and exit-code handling.

🧭 Choose a CLI shape

Use the smallest shape that fits the program:

Shape Example Start with
One default action hello --name Ada RootCommandDemo
Named commands tool greet --name Ada SimpleDemo
Nested commands tool repo remote add SubCommandDemo

A root command is an unnamed default action. Named commands are registered with App.RegisterCommand, and subcommands are attached to another command with AddSubCommand. Root options belong only to the root action; they are not global options inherited by named commands.

The framework does not currently model positional arguments or persistent options shared across a command tree.

βš™οΈ Options and validation

Commands declare option metadata with focused registration methods:

Command.AddStringParameter('-n', '--name', 'Name to greet', False, 'World');
Command.AddIntegerParameter('-c', '--count', 'Number of runs', True);
Command.AddFloatParameter('-r', '--rate', 'Processing rate', False, '1.0');
Command.AddFlag('-v', '--verbose', 'Show detailed output');
Command.AddBooleanParameter('-d', '--debug', 'Debug mode', False, 'false');
Command.AddEnumParameter('-l', '--level', 'Log level',
  'debug|info|warn|error', False, 'info');
Command.AddDateTimeParameter('-t', '--time', 'Start time');
Command.AddPathParameter('-p', '--path', 'Target path');
Command.AddUrlParameter('-u', '--url', 'Repository URL');
Command.AddArrayParameter('-a', '--items', 'Comma-separated items');
Command.AddPasswordParameter('-k', '--api-key', 'API key');

The framework applies the validation associated with each registered type before executing the command. The current command API returns values as strings, so command implementations convert values when necessary:

if GetParameterValue('--count', RawCount) and
  TryStrToInt(RawCount, Count) then
  WriteLn('Count: ', Count);

Password values are stored as strings. Framework debug diagnostics redact them, but output produced by your command or external logging does not. Path values are not checked for existence. Registered integer and float options accept negative values in both equals and separated forms, for example --count=-1 and --count -1. For other value types that begin with -, use the equals form so the value is not interpreted as another option.

See the user manual for the complete registration and validation rules.

🧰 Built-in behaviour

Applications receive these framework-level options:

Option Behaviour
-h, --help Show application or selected-command help
--help-complete Show the complete command reference
-v, --version Print application version information
--completion-file Write a Bash completion script to standard output
--completion-file-pwsh Write a PowerShell completion script to standard output

--help and --version act at application level when used alone. After a named command, --help describes the selected command. Completion-script options are handled when they are the first argument.

Generate completion scripts by redirecting that output:

./yourcli --completion-file > yourcli-completion.sh
.\yourcli.exe --completion-file-pwsh > yourcli-completion.ps1

Completion covers commands, subcommands, options, Boolean values, and enum choices. Custom completion callbacks are deprecated and non-functional in the 1.x API. See the completion guide for installation instructions.

πŸ“š Examples

Each example is an ordinary Free Pascal program:

Example Demonstrates
RootCommandDemo A focused utility with a default action
SimpleDemo Named commands, options, output, and a spinner
SubCommandDemo Nested command trees
ColorDemo Colours and terminal presentation
ProgressDemo Spinners and progress bars
LongRunningOpDemo Longer operations and cleanup
ErrorHandlingDemo Errors and exit behaviour

Compile an example from the repository root:

fpc -Fu./src ./examples/RootCommandDemo/RootCommandDemo.lpr

In PowerShell, quote the unit search path:

fpc "-Fu.\src" .\examples\RootCommandDemo\RootCommandDemo.lpr

πŸ—οΈ Optional project generator

cli-fp-gen is scaffolding for applications with larger command trees. It is not required to use the runtime framework, and it is not the shortest way to learn the core API.

Build it on Linux or macOS:

fpc -Futools/cli-fp-gen/src tools/cli-fp-gen/cli_fp_gen.lpr
./tools/cli-fp-gen/cli_fp_gen init ./build-temp/myapp --name myapp

Or on Windows:

fpc "-Futools\cli-fp-gen\src" .\tools\cli-fp-gen\cli_fp_gen.lpr
.\tools\cli-fp-gen\cli_fp_gen.exe init .\build-temp\myapp --name myapp

Generated registry and program files are generator-owned. Command units are user-owned and are preserved during normal regeneration. Read the generator guide before changing clifp.json or generated files.

🦎 Lazarus

A runtime-only package is provided at packages/lazarus/cli_fp.lpk. Open the package in Lazarus, compile it, and add it to the project's required packages. Lazarus is optional when compiling directly with FPC.

πŸ› οΈ Developing cli-fp

Run the framework tests on Linux or macOS:

bash tests/run_tests.sh
bash tests/run_cleanup_smoke.sh

Run the generator suites:

bash tests/codegen/run_unit_tests.sh
bash tests/codegen/run_golden_test.sh
bash tests/codegen/run_ops_test.sh
bash tests/codegen/run_compile_smoke.sh

On Windows:

powershell -ExecutionPolicy Bypass -File tests\run_tests.ps1
powershell -ExecutionPolicy Bypass -File tests\codegen\run_all_tests.ps1
powershell -ExecutionPolicy Bypass -File tests\run_cleanup_smoke.ps1

The cleanup smoke check compiles all seven canonical examples in an isolated copy, runs the cleanup script, and verifies that generated artifacts are removed without changing tracked files. CI runs the equivalent Bash and PowerShell checks on Linux and Windows.

CI runs the framework and generator suites on Windows and Linux. See CONTRIBUTING.md for coding style and pull-request guidance.

The framework runners force a complete unit rebuild into a temporary output directory, so stale non-test .ppu files cannot affect the result. Test output capture is compiled only when CLI_FP_TESTING is defined and is absent from normal runtime builds.

πŸ—‚οΈ Repository map

Path Purpose
src/ Runtime framework units
examples/ Focused, runnable applications
tests/ Framework and generator tests
tools/cli-fp-gen/ Optional JSON-driven project generator
packages/lazarus/ Lazarus runtime package
docs/ User, API, generator, and technical guides

πŸ“‹ Requirements and dependencies

  • Free Pascal 3.2.2 is the tested compiler version.
  • The runtime framework has no third-party dependencies.
  • The generator uses the JSON units supplied by the Free Component Library.
  • Windows and Linux are tested in CI.
  • macOS, FreeBSD, and other FPC-supported Unix systems are expected to work but are not currently exercised in CI.

On Debian and Ubuntu, install the compiler and FCL units with:

sudo apt-get install fp-compiler fp-units-fcl

πŸ“– Documentation

🀝 Contributing

Bug reports, focused fixes, documentation improvements, and small features are welcome. For larger changes, open an issue first so the public API and maintenance cost can be discussed before implementation.

πŸ“„ License

cli-fp is available under the MIT License.

About

A robust Free Pascal framework for building professional CLI applications. Create powerful command-line tools with hierarchical commands, rich interactions, and comprehensive help systems - all with type-safe, object-oriented design.

Topics

Resources

Contributing

Stars

35 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages