Arg3P

about Arg3P
Arg3P is a small & header-only argument parser designed for C++20. It provides a simple, type-safe interface for defining command-line options with short and/or long names. Boolean arguments act as flags, while all other argument types consume a following value. I primarly created Arg3P to act as a replacement for the original argument parser used for both mfdasm and mfdemu in my mfd0816 project. But since I realise I probably want to use this in all kinds of different future project, I built it as a seperate project and licensed it under the BSD 2-Clause license.
example
This is a small example showing off flagged (or named) arguments, positional arguments and automatic synopsis & help generation.
 #include <iostream>

#include <Arg3P/Arg3P.hpp>

int
main(int argc, const char *argv[])
{
	using namespace Arg3P;

	// Define flagged command-line arguments
	auto threads =
		Arg<int>::make('t', "threads", "set the number of worker threads");
	auto verbose = Arg<bool>::make('v', "verbose", "enable verbose output");
	auto help	 = Arg<bool>::make('h', "help", "show a help text");

	// Define positional command-line arguments
	auto input = PositionalArgument<std::string>::makeRequired(
		"input", "input file path"
	);
	auto config = PositionalArgument<std::string>::make(
		"config", "custom config file path"
	);
	auto bindAddress = PositionalArgument<std::string>::make(
		"bindAddress", "custom bind address"
	);

	// Register arguments with the parser
	Parser<const char *> parser{
		{threads, verbose, help},
		{
			.frontArgs = {input, config},
			.backArgs  = {bindAddress},
		}
	};

	// Parse command line (skip program name)
	const std::optional<Error> error = parser(std::span(argv, argc).subspan(1));

	if(help->get().value_or(false)) {
		std::cout << "SYNOPSIS: example-help " << parser.generateSynopsis()
				  << "\n\n";
		std::cout << parser.generateHelp() << "\n";
		return 0;
	}

	if(error.has_value()) {
		std::cerr << "Error parsing argument: "
				  << errorName(error.value().error) << ": "
				  << error.value().message << "\n";
		return 1;
	}

	// Access results
	std::cout << "Input:   " << input->get().value_or("<none>") << "\n";
	std::cout << "Config: " << config->get().value_or("/etc/someconfig.cfg")
			  << "\n";
	std::cout << "Threads: " << threads->get().value_or(1) << "\n";
	std::cout << "Verbose: " << verbose->get().value_or(false) << "\n";
	std::cout << "bindAddress: " << bindAddress->get().value_or("0.0.0.0")
			  << "\n";
}