A lightweight, header-only C++20 argument parser library with a fluent, chainable API.
Argonaut is a lightweight, single-header C++20 library for parsing command-line arguments. It features a readable fluent API, automatic help generation, exception-based control flow, and an extensible type conversion system.
- Header-Only: Just copy
Argonaut.hinto your project and include it. - Fluent API: Use method chaining to define arguments and configure the parser.
- Rich Argument Support:
- Options with values (e.g.,
--mode fastor--mode=fast) - Flags (boolean switches, e.g.,
--verbose) - Positional arguments (e.g.,
my-app <input-file>)
- Options with values (e.g.,
- Automatic Help & Version:
- Generates a formatted help message with
AutoHelp(true). - Handles version requests with
AutoVersion(true).
- Generates a formatted help message with
- Clean Flow Control: Throws exceptions like
HelpRequestedExceptioninstead of callingexit(0), giving your application full control over its lifecycle. - Modern & Robust: Supports required arguments, default values, multi-value arguments, and callbacks.
- Type Safe: Retrieve values directly as
int,float,bool,double, or define Custom Types using theArgumentConvertersystem.
- C++20 Compiler: Argonaut uses C++20 features like
std::map::containsandstd::ranges. - Standard Library: No external dependencies.
Argonaut is a header-only library.
- Download
Argonaut.hfrom this repository. - Place it in your project's include path.
#include "Argonaut.h"in yourmain.cppor equivalent.
Here is a complete example of a simple application using type-safe retrieval.
#include "Argonaut.h"
#include <iostream>
#include <string>
#include <vector>
int main(int argc, char* argv[])
{
// 1. Create a parser instance
Argonaut::Parser parser;
// 2. Configure the parser using the fluent API
parser
.SetVersion("v1.2.3")
.AutoHelp(true)
.AutoVersion(true)
.Add(
// A required positional argument
Argonaut::Argument("FILE")
.SetDescription("The input file to process.")
.Required()
)
.Add(
// An integer option with default value
Argonaut::Argument("COUNT")
.SetDescription("Number of iterations.")
.AddAlias("-n")
.AddAlias("--count")
.SetDefaultValue("10")
)
.Add(
// A simple flag
Argonaut::Argument("VERBOSE")
.SetDescription("Enable verbose output.")
.AddAlias("--verbose")
.Flag()
)
.Add(
// A floating point multi-value option
Argonaut::Argument("SCALE")
.SetDescription("Scale factors.")
.AddAlias("-s")
.AddAlias("--scale")
.MultiValue()
);
// 3. Run the parser inside a try...catch block
try
{
parser.Parse(argc, argv);
}
catch (const Argonaut::HelpRequestedException& e)
{
std::cout << e.what(); // Print help and exit
return 0;
}
catch (const Argonaut::VersionRequestedException& e)
{
std::cout << "My-App " << e.what() << std::endl; // Print version and exit
return 0;
}
catch (const Argonaut::Exception& e)
{
std::cerr << "Error: " << e.what() << "\n\n";
std::cerr << parser.Help(); // Print help on error
return 1;
}
// 4. Retrieve your parsed values (Type-Safe!)
try
{
// Retrieve string (default)
std::string inputFile = parser.GetValuesOf("FILE")[0];
// Retrieve integer automatically
int count = parser.GetValuesOf<int>("COUNT")[0];
// Retrieve boolean automatically (checks for "true", "1", "yes", "on")
// For flags, we usually check emptiness, but GetValuesOf<bool> works if provided explicitly.
bool verbose = !parser.GetValuesOf("VERBOSE").empty();
// Retrieve vector of floats
std::vector<float> scales = parser.GetValuesOf<float>("SCALE");
// --- Application Logic ---
std::cout << "File: " << inputFile << "\n";
std::cout << "Count: " << count << "\n";
std::cout << "Verbose: " << std::boolalpha << verbose << "\n";
for(float s : scales) std::cout << "Scale: " << s << "\n";
}
catch(const std::exception& e)
{
std::cerr << "Conversion Error: " << e.what() << std::endl;
return 1;
}
return 0;
}You can teach Argonaut how to parse your own types by specializing Argonaut::ArgumentConverter<T>.
struct Vector3 { float x, y, z; };
// Specialize the converter in the Argonaut namespace
namespace Argonaut {
template<> struct ArgumentConverter<Vector3> {
static Vector3 Convert(const std::string& v) {
// Example parsing logic for "1.0,2.0,3.0"
Vector3 result{0,0,0};
sscanf(v.c_str(), "%f,%f,%f", &result.x, &result.y, &result.z);
return result;
}
};
}
// Usage in main:
// parser.Add(Argonaut::Argument("POS").AddAlias("--pos"));
// ...
// Vector3 pos = parser.GetValuesOf<Vector3>("POS")[0];# Compile (requires C++20)
g++ -std=c++20 main.cpp -o my_app
# Run with --help
./my_app --help
# Output:
# Usage: ./my_app [OPTIONS] <FILE>
#
# Positional Arguments:
# FILE The input file to process.
# [REQUIRED]
#
# Options:
# -m <value>, --mode <value> Set processing mode (fast, safe).
# [Default: "safe"]
# --verbose Enable verbose output.
# -I <value>, --include <value> Path to include.
# [Multi-value]
# -h, --help Show this help message and exit.
# -v, --version Show version.
# Run normally
./my_app "data.bin" --verbose -I ./lib -I /usr/lib --mode=fast
# Output:
# [Callback] Including path: ./lib
# [Callback] Including path: /usr/lib
# --- Application Running ---
# Input File: data.bin
# Mode: fast
# Verbose: true
# Final Include Path: ./lib
# Final Include Path: /usr/lib
# Run with an error
./my_app --mode
# Error: Argonaut Exception: Last argument should take value.
#
# Usage: ./my_app [OPTIONS] <FILE>
# ... (help message) ...Created by calling Argonaut::Argument("UNIQUE_ID").
| Method | Description |
|---|---|
SetDescription(std::string desc) |
Sets the text shown in the help message. |
AddAlias(std::string alias) |
Adds a trigger alias (e.g., "-f" or "--file"). |
Required(bool value = true) |
Marks the argument as mandatory. |
Flag(bool value = true) |
Marks the argument as a boolean flag (takes no value). |
MultiValue(bool value = true) |
Allows the argument to be provided multiple times. |
SetDefaultValue(std::string value) |
Provides a default value if not specified by the user. |
SetCallback(std::function<...>) |
Sets a void(const std::string&) callback to run when the argument is parsed. |
The main class used to manage parsing.
| Method | Description |
|---|---|
Add(Argument arg) |
Adds a configured Argument object to the parser. |
AutoHelp(bool value = true) |
Automatically adds the --help and -h arguments. |
AutoVersion(bool value = true) |
Automatically adds the --version and -v arguments. |
SetVersion(std::string version) |
Sets the version string to be displayed. |
Parse(int argc, char* argv[]) |
Parses the command-line arguments. Throws exceptions on errors or for help/version requests. |
GetValuesOf<T>(std::string id) |
Returns a std::vector of values. Automatically converts string input to T. Supports int, float, double, bool, etc. |
GetAllValues() |
Returns a const std::map<std::string, std::vector<std::string>>& of all parsed results. |
Help() |
Returns the formatted help message as a std::string. |
GetProgramName() |
Returns the program name (argv[0]). |
- No Short Option Clustering:
Argonautdoes not currently support combining short options (e.g.,-xvf). Each short option must be specified separately (e.g.,-x -v -f).
This project is licensed under the MIT License.