XGetOpt is a simple, header-only, constexpr-first C++20 library for parsing command-line options.
See the wiki for complete documentation and examples.
- Fully constexpr, compile-time help-string generation
- First-class support for non-option arguments
- Support for early-stop parsing via
parse_until<StopCondition>()- Stop before/after first non-option argument, or before first error
- Remainder of unparsed arguments provided for further processing
- Preservation of
getoptsemantics- Short options, long options, optional arguments, option clustering, etc
- Matches user expectations
- XGetOpt is in fact a wrapper around
getopt_long
The basic design goals are:
- Simple to use
- No added cost compared to using
getopt_longdirectly - Preservation of familiar semantics
#include "xgetopt.h"
#include <iostream>
int main(int argc, char* argv[]) {
constexpr XGetOpt::OptionParser<
XGetOpt::Option<'h', "help", "Display this help message", XGetOpt::NoArgument>,
XGetOpt::Option<'o', "output", "Specify output file", XGetOpt::RequiredArgument, "file">,
XGetOpt::Option<'p', "parameter", "Specify optional parameter", XGetOpt::OptionalArgument>,
XGetOpt::Option<1001, "long-option-only", "This has no shortopt", XGetOpt::NoArgument>,
XGetOpt::Option<1002, "long-option-with-arg", "This has no shortopt and requires an argument", XGetOpt::RequiredArgument>,
XGetOpt::Option<'s', "", "This has no longopt", XGetOpt::NoArgument>
> parser;
XGetOpt::OptionSequence options;
try { // .parse() will throw an exception if invalid options are provided
options = parser.parse(argc, argv);
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return 1;
}
for (const auto& opt : options) {
switch (opt.getShortOpt()) {
case 'h':
std::cout << parser.getHelpString();
return 0;
case 'p': // Optional argument
if (opt.hasArgument()) {
std::cout << "Parameter option with argument: " << opt.getArgument() << std::endl;
} else {
std::cout << "Parameter option with no argument" << std::endl;
}
break;
case 1001: // --long-option-only
std::cout << "--long-option-only given" << std::endl;
break;
// Etc
}
}
for (const auto& arg : options.getNonOptionArguments()) {
std::cout << "Non-option argument: " << arg << std::endl;
}
}The generated help string looks like this:
-h, --help Display this help message
-o, --output <file> Specify output file
-p, --parameter[=arg] Specify optional parameter
--long-option-only This has no shortopt
--long-option-with-arg <arg> This has no shortopt and requires an argument
-s This has no longopt
And is fully generated at compile-time.
#include "xgetopt.h"
#include <iostream>
int main(int argc, char* argv[]) {
constexpr XGetOpt::OptionParser<
XGetOpt::Option<'h', "help", "Display this help message", XGetOpt::NoArgument>,
XGetOpt::Option<'o', "output", "Specify output file", XGetOpt::RequiredArgument, "file">,
XGetOpt::Option<'p', "parameter", "Specify optional parameter", XGetOpt::OptionalArgument>
> parser;
constexpr XGetOpt::OptionParser<
XGetOpt::Option<'a', "alpha", "Alpha option for subcommand", XGetOpt::NoArgument>,
XGetOpt::Option<'b', "beta", "Beta option for subcommand", XGetOpt::RequiredArgument, "value">,
XGetOpt::Option<'h', "help", "Display this help message for subcommand", XGetOpt::NoArgument>
> subCommandParser;
try {
// The first non-option argument is treated as the subcommand name
auto [options, remainder] = parser.parse_until<XGetOpt::BeforeFirstNonOptionArgument>(argc, argv);
for (const auto& opt : options) {
// Base program options processing...
}
if (remainder.argc == 0) {
return 0; // No subcommand, done
}
std::string_view subcommandName = remainder.argv[0];
if (subcommandName == "subcmd") {
auto subOptions = subCommandParser.parse(remainder.argc, remainder.argv);
for (const auto& opt : subOptions) {
// Subcommand options processing...
}
}
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return 1;
}
}In the above example, the first non-option argument is treated as the subcommand name, and the remaining arguments are parsed using a separate parser for that subcommand.
See the wiki for complete documentation and examples.
Users of Debian-based systems can install XGetOpt via the deb.rail5.org repository:
sudo curl -s -o /etc/apt/trusted.gpg.d/rail5-signing-key.gpg "https://deb.rail5.org/rail5-signing-key.gpg"
sudo curl -s -o /etc/apt/sources.list.d/rail5.list "https://deb.rail5.org/rail5.list"
sudo apt update
sudo apt install xgetopt-devXGetOpt does not guarantee compatibility outside of the GNU ecosystem, but it should work with most getopt_long implementations. See the tests/README.md for a table of tested platforms.
XGetOpt is released under the GNU General Public License v2 or later. See the LICENSE file for details.