A lightweight, record-based command-line argument parser for Free Pascal. ArgParser-FP
is designed for small to medium console applications, offering a clean API to handle arguments with minimal setup.
Why use ArgParser-FP
-
Small, dependency-free, and focused on console apps built with Free Pascal.
-
Compact API: define options, parse once, and retrieve typed values.
Quickstart — run in under 30 seconds
-
Copy both
src/ArgParser.pas
andsrc/ArgTokenizer.pas
into your project folder, and addArgParser
touses
. -
Save this minimal program as
quick.pas
and compile:
program Quick;
uses ArgParser, SysUtils;
var
P: TArgParser;
begin
P.Init;
P.AddBoolean('h','help','Show this help message');
P.AddString('f','file','Input file','',True);
P.ParseCommandLine;
if P.HasError then
begin
Writeln('Error: ', P.Error);
P.ShowUsage;
Exit;
end;
if P.GetBoolean('help') then
begin
P.ShowHelp;
Exit;
end;
Writeln('File=',P.GetString('file'));
end.
Build & run (PowerShell):
fpc quick.pas
.\quick.exe --help
More examples and full docs are below. If you like short, clear APIs, try the examples/
folder.
- Type-Safe Parsing: Natively parse strings, integers, floats, booleans, and arrays.
- Flexible Syntax: Support for multiple argument formats:
- Short options:
-f input.txt
or-finput.txt
- Boolean flags:
--verbose
or--verbose=true/false
- Short options:
- Automatic Help Text: Generates
--help
and usage text from your option definitions. - Required Options: Enforce mandatory arguments.
- Default Values: Provide default values for optional arguments.
Here is a complete example of a simple application:
// File: examples/MyApp/MyApp.pas
program MyApp;
uses
SysUtils,
ArgParser;
var
Parser: TArgParser;
i: integer;
begin
// Initialize
Parser.Init;
Parser.SetUsage('MyApp [options]');
// Add options using convenience methods
Parser.AddInteger('c', 'count', 'Set count value', 5);
Parser.AddBoolean('v', 'verbose', 'Enable verbose mode');
Parser.AddString('f', 'file', 'Specify a file path', '', True); // Required
Parser.AddArray('t', 'tags', 'Comma-separated list of tags'); // Add array option
Parser.AddBoolean('h', 'help', 'Show this help message');
// Parse command line arguments with one call
if Parser.HasError then
begin
Writeln('Error: ', Parser.Error);
Parser.ShowUsage;
Exit;
end;
// Show help if requested
if Parser.GetBoolean('help') then
begin
Parser.ShowHelp;
Exit;
end;
// Access parsed values
Writeln('Count: ', Parser.GetInteger('count'));
Writeln('File: ', Parser.GetString('file'));
// Display array values if provided
if Length(Parser.GetArray('tags')) > 0 then
begin
Write('Tags: ');
for i := 0 to High(Parser.GetArray('tags')) do
begin
Write(Parser.GetArray('tags')[i]);
if i < High(Parser.GetArray('tags')) then
Write(', ');
end;
Writeln;
end;
if Parser.GetBoolean('verbose') then
Writeln('Verbose mode is ON');
Writeln('Done.');
end.
Compile and run the application with --help to see the auto-generated documentation:
fpc MyApp.pas
./MyApp --help
Output:
Usage: MyApp [options]
Options:
-h, --help Show this help message
-c, --count Set count value
-v, --verbose Enable verbose mode
-f, --file Specify a file path (required)
-t, --tags Comma-separated list of tags
Note: the help printer (`ShowHelp`) automatically appends " (required)" to the
help text for any option or positional argument marked `Required = True`.
Example Usage
# Traditional format
./MyApp --file input.txt --count 10 --verbose
# Equals format
./MyApp --file=input.txt --count=10 --verbose=true
# Mixed formats
./MyApp --file=input.txt -v --count 10
Additional notes: quote arguments containing spaces according to your shell's rules.
-
Standalone tokens without a preceding option
- A token not starting with
-
must be the value of the previous option. Otherwise it triggersInvalid argument format: <token>
.
- A token not starting with
-
Boolean flags and values
- Presence sets to true:
--verbose
⇒ true. - If you need an explicit value, use
--verbose=true|false
or-v=false
. Writing--verbose false
treatsfalse
as a separate token and will fail.
- Presence sets to true:
-
Short combined flags
- The tokenizer's default policy (controlled by
SplitCombinedShorts
insrc/ArgTokenizer.pas
) will split small all-alpha combined shorts like-abc
into separate flags-a -b -c
. Mixed or numeric groups (for example-a1b
) are preserved as a single token. SetSplitCombinedShorts := False
if you prefer conservative behavior.
- The tokenizer's default policy (controlled by
-
PowerShell split quirk (Windows)
- PowerShell may split
-finput.txt
into two tokens:-finput
and.txt
. The parser reattaches.txt
for string options so the value becomesinput.txt
.
- PowerShell may split
-
Single dash and negative numbers
- A single dash token
-
is preserved as a positional token (commonly used to mean stdin). Numeric tokens that start with-
such as-1
are treated as positional values unless an option matching that token exists.
Examples:
- Read from stdin: mytool - input.txt # '-' preserved as a positional (stdin)
- Negative numeric positional: mytool process -1 # '-1' is a positional value, not an option
- A single dash token
-
Arrays are comma-separated
- Use a single token like
--list=a,b,c
. If values contain spaces, quote according to your shell.
- Use a single token like
-- separator and leftovers
ParseCommandLine
now detects a --
separator automatically. Any tokens after a --
are not parsed as options and are returned to the caller via the Leftovers
property. This simplifies the common call-site: you can call ParseCommandLine
and then inspect Parser.Leftovers
to forward any remaining arguments.
Examples:
var
Parser: TArgParser;
leftovers: TStringDynArray;
begin
Parser.Init;
try
Parser.AddBoolean('v','verbose','Enable verbose');
Parser.ParseCommandLine;
leftovers := Parser.Leftovers; // tokens after `--`, if any
finally
Parser.Done;
end;
end;
Important: the parser no longer prints help or exits during parsing. The presence of -h
/--help
sets the built-in help
flag; after calling ParseCommandLine
your program should check Parser.HasError
and Parser.GetBoolean('help')
and then call Parser.ShowUsage
or Parser.ShowHelp
and exit if appropriate. This prevents the parser from freeing internal resources unexpectedly while your program continues running.
Additional notes
- Boolean negation: long boolean options also support a
--no-<name>
form to explicitly set a boolean flag to False. Example:--no-verbose
. - Positional arguments:
AddPositional
creates ordered (positional) arguments. Use the optionalNArgs
parameter to control how many tokens a positional consumes:NArgs = 0
(default): single tokenNArgs = -1
: greedy mode (consume all remaining tokens until next option or end)- Note: Values >0 are accepted but currently behave as 0 (single token)
- AllowMultiple / GetAll*: For options that can appear multiple times (for example
--tag a --tag b
), use theGetAll*
helpers (e.g.,GetAllString
,GetAllArray
) to retrieve every occurrence in the order parsed.
For deeper details and examples, see the Beginner's Guide and the Cheat Sheet.
- Compiler: FPC 3.2.2+
- IDE: Lazarus 4.0+ (recommended, for running the examples and tests)
- Platforms: Windows, Linux (cross-platform by design)
- Dependencies: None. Uses only standard FPC RTL units.
- Copy both
src/ArgParser.pas
andsrc/ArgTokenizer.pas
into your project folder, and addArgParser
touses
. - Compile with FPC:
fpc MyProgram.pas
For detailed documentation on all available procedures and functions, please see the Beginner's Guide and the Cheat Sheet.
- Open the
TestRunner.lpi
using Lazarus IDE - Compile the project
- Run the Test Runner:
cd tests
./TestRunner.exe -a --format=plain
Note: v0.4.0 introduced a dedicated ArgTokenizer
unit and focused tokenizer unit tests (tests/ArgTokenizer.Test.pas
) to validate token shapes and normalization rules.
- Code Simplification: Refactored internal implementation to reduce complexity and remove duplicate code patterns without losing any functionality.
- Helper Functions: Introduced helper functions for common operations like TArgValue initialization and array management to reduce repetitive code.
- Cleaner Type Parsing: Split the complex
ParseValue
method into focused type-specific parsing functions for better maintainability. - Simplified Tokenizer: Extracted helper functions in ArgTokenizer to improve code readability and reduce complexity.
- Streamlined Methods: Consolidated duplicate initialization patterns in
AddXXX
methods and simplified array operations throughout the codebase. - Improved Error Messages: Fixed misleading error messages for missing required positional arguments to follow standard CLI conventions.
Note (v0.7.0): This release contains internal simplifications, refactoring, and improved error messaging. All public APIs remain unchanged and fully backward compatible.
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the Project
- Create your Feature Branch (git checkout -b feature/AmazingFeature)
- Commit your Changes (git commit -m 'Add some AmazingFeature')
- Push to the Branch (git push origin feature/AmazingFeature)
- Open a Pull Request
This project is licensed under the MIT License - see the LICENSE.md file for details.
- Free Pascal Dev Team for the Pascal compiler.
- Lazarus IDE Team for such an amazing IDE.
- The kind and helpful individuals on various online platforms such as: