| libargparse |
| =========== |
| This is (yet another) simple command-line parser for C++ applications, inspired by Python's agparse module. |
| |
| It requires only a C++11 compiler, and has no external dependancies. |
| |
| One of the advantages of libargparse is that all conversions from command-line strings to program types (bool, int etc.) are performed when the command line is parsed (and not when the options are accessed). |
| This avoids command-line related errors from showing up deep in the program execution, which can be problematic for long-running programs. |
| |
| Basic Usage |
| =========== |
| |
| ```cpp |
| #include "argparse.hpp" |
| |
| struct Args { |
| argparse::ArgValue<bool> do_foo; |
| argparse::ArgValue<bool> enable_bar; |
| argparse::ArgValue<std::string> filename; |
| argparse::ArgValue<size_t> verbosity; |
| }; |
| |
| int main(int argc, const char** argv) { |
| Args args; |
| auto parser = argparse::ArgumentParser(argv[0], "My application description"); |
| |
| parser.add_argument(args.filename, "filename") |
| .help("File to process"); |
| |
| parser.add_argument(args.do_foo, "--foo") |
| .help("Causes foo") |
| .default_value("false") |
| .action(argparse::Action::STORE_TRUE); |
| |
| parser.add_argument(args.enable_bar, "--bar") |
| .help("Control bar") |
| .default_value("false"); |
| |
| parser.add_argument(args.verbosity, "--verbosity", "-v") |
| .help("Sets the verbosity") |
| .default_value("1") |
| .choices({"0", "1", "2"}); |
| |
| parser.parse_args(argc, argv); |
| |
| //Show the arguments |
| std::cout << "args.filename: " << args.filename << "\n"; |
| std::cout << "args.do_foo: " << args.do_foo << "\n"; |
| std::cout << "args.verbosity: " << args.verbosity << "\n"; |
| std::cout << "\n"; |
| |
| //Do work |
| if (args.do_foo) { |
| if (args.verbosity > 0) { |
| std::cout << "Doing foo with " << args.filename << "\n"; |
| } |
| if (args.verbosity > 1) { |
| std::cout << "Doing foo step 1" << "\n"; |
| std::cout << "Doing foo step 2" << "\n"; |
| std::cout << "Doing foo step 3" << "\n"; |
| } |
| } |
| |
| if (args.enable_bar) { |
| if (args.verbosity > 0) { |
| std::cout << "Bar is enabled" << "\n"; |
| } |
| } else { |
| if (args.verbosity > 0) { |
| std::cout << "Bar is disabled" << "\n"; |
| } |
| } |
| |
| return 0; |
| } |
| ``` |
| |
| and the resulting help: |
| |
| ``` |
| $ ./argparse_example -h |
| usage: argparse_example filename [--foo] [--bar {true, false}] |
| [-v {0, 1, 2}] [-h] |
| |
| My application description |
| |
| arguments: |
| filename File to process |
| --foo Causes foo (Default: false) |
| --bar {true, false} |
| Control whether bar is enabled (Default: false) |
| -v {0, 1, 2}, --verbosity {0, 1, 2} |
| Sets the verbosity (Default: 1) |
| -h, --help Shows this help message |
| ``` |
| By default the usage and help messages are line-wrapped to 80 characters. |
| |
| Custom Conversions |
| ================== |
| By default libargparse performs string to program type conversions using ``<sstream>``, meaning any type supporting ``operator<<()`` and ``operator>>()`` should be automatically supported. |
| |
| However this does not always provide sufficient flexibility. |
| As a result libargparse also supports custom conversions, allowing user-defined mappings between command-line strings to program types. |
| |
| If we wanted to modify the above example so the '--bar' argument accepted the strings 'on' and 'off' (instead of the default 'true' and 'false') we would define a custom class as follows: |
| ```cpp |
| struct OnOff { |
| ConvertedValue<bool> from_str(std::string str) { |
| ConvertedValue<bool> converted_value; |
| |
| if (str == "on") converted_value.set_value(true); |
| else if (str == "off") converted_value.set_value(false); |
| else converted_value.set_error("Invalid argument value"); |
| return converted_value; |
| } |
| |
| ConvertedValue<std::string> to_str(bool val) { |
| ConvertedValue<std::string> converted_value; |
| if (val) converted_value.set_value("on"); |
| else converted_value.set_value("off"); |
| return converted_value; |
| } |
| |
| std::vector<std::string> default_choices() { |
| return {"on", "off"}; |
| } |
| }; |
| ``` |
| |
| Where the `from_str()` and `to_str()` define the conversions to and from a string, and `default_choices()` returns the set of valid choices. Note that default_choices() can return an empty vector to indicate there is no specified default set of choices. |
| |
| We then modify the ``add_argument()`` call to use our conversion object: |
| ```cpp |
| parser.add_argument<bool,OnOff>(args.enable_bar, "--bar") |
| .help("Control whether bar is enabled") |
| .default_value("off"); |
| ``` |
| |
| with the resulting help: |
| ``` |
| usage: argparse_example filename [--foo] [--bar {on, off}] [-v {0, 1, 2}] |
| [-h] |
| |
| My application description |
| |
| arguments: |
| filename File to process |
| --foo Causes foo (Default: false) |
| --bar {on, off} Control whether bar is enabled (Default: off) |
| -v {0, 1, 2}, --verbosity {0, 1, 2} |
| Sets the verbosity (Default: 1) |
| -h, --help Shows this help message |
| ``` |
| |
| Advanced Usage |
| ============== |
| For more advanced usage such as argument groups see [argparse_test.cpp](argparse_test.cpp) and [argparse.hpp](src/argparse.hpp). |
| |
| Future Work |
| =========== |
| libargparse is missing a variety of more advanced features found in Python's argparse, including (but not limited to): |
| * action: append, count |
| * subcommands |
| * mutually exclusive options |
| * parsing only known args |
| * concatenated short options (e.g. `-xvf`, for options `-x`, `-v`, `-f`) |
| * equal concatenated option values (e.g. `--foo=VALUE`) |
| |
| Acknowledgements |
| ================ |
| Python's [argparse module](https://docs.python.org/2.7/library/argparse.html) |