An open API service indexing awesome lists of open source software.

https://github.com/dax89/cl

Easy command line parsing with EDSL
https://github.com/dax89/cl

argument-parser c-plus-plus cli-parser cpp17 header-only mit-license no-dependencies option-parser positional-arguments

Last synced: 10 months ago
JSON representation

Easy command line parsing with EDSL

Awesome Lists containing this project

README

          

CL: Command Line parsing for C++
-----

CL is a C++17 single header library that provides an Embedded Domain Specific Language (EDSL) by exploiting C++ features for command line argument parsing.

No regex, grammars, lexers and parsers required!

Quick Start
-----

```cpp
#include

int main(int argc, char** argv[]) {
// Needed later for _p operator
using namespace cl::string_literals;

// Set some application info (optional)
cl::set_program("cl_app");
cl::set_name("CL Application");
cl::set_description("CL App Description");
cl::set_version("1.0");

// Define options (needed if you use options later)
cl::Options{
cl::opt("o1", "opt1", "I'm the option 1"),
cl::opt("o2", "opt2", "I'm the option 2"),
cl::opt("o3", "opt3"_o, "I'm the option 3"),
};

// Create parsing rules (for options, the short name can also be used)
cl::Usage{
cl::cmd("command1", "pos1", *"pos2"_p, --"opt1"_p, *--"opt2"_p),
cl::cmd("command2", "pos1", "pos2"_p, --"opt1"_p, --"opt2"_p),
cl::cmd("command3", "pos1", cl::one("val1", "val2", "val3")),
cl::cmd("command4", "pos1", *cl::one("val1", "val2", "val3"), *--"opt3"_p),
cl::cmd("command5"_a, "pos1"),
cl::cmd("command6"_a)

};

cl::Args args = cl::parse(argc, argv);
// ... parse 'args'
return 0;
}
```

* `cl::Options`: defines a list of command line options, they are shared between all rules (if you only need positional arguments you can skip this step).
* `cl::Usage`: this is the most important statement, here we define the rules needed to parse command line arguments (positionals, options, optional arguments, etc)
* String literal operators adds some sugar to the code, here is their meaning:
* `_p` creates a `cl::Param` object (more info below)
* `_a` creates an 'any-type' command (more info below)
* `_o` create a _k=v_ option, if you don't pass this operator, options are just flags (_true/false_ boolean)
* The operator `_p` create a `cl::Param` that overloads some C++ operators, these are their meaning:
* `--"myarg"_p` creates a **required option**.
* if the `*` is present the argument/option becomes optional (eg. `*"pos"_p`, `*--"opt"_p`)
* The operator `_a` allows any command to be passed (these rules are quite permissive: add them at the end of usage list)
* `cl::one("a", "b", "c", ...)`: is for positional arguments where only one of the provided values are valid (by adding a `*` makes this argument optional)

Help is autogenerated, for the sample code above.

**NOTE:** `cl_app --help` and `cl_app --version` are builtin.
```
CL App 1.0
App Description

Usage:
cl_app command1 [pos2] --opt1 [--opt2]
cl_app command2 --opt1 --opt2
cl_app command3 (val1|val2|val3)
cl_app command4 [(val1|val2|val3)] [--opt3=ARG]
cl_app {command5}
cl_app {command6}
cl_app --version
cl_app --help

Options:
-h --help Show this screen
-v --version Show version
-o1 --opt1 I'm the option 1
-o2 --opt2 I'm the option 2
-o3 --opt3=ARG I'm the option 3
```

Extract argument information (explained)
-----
This part is inspired by [docopt.cpp](https://github.com/docopt/docopt.cpp).

Calling `cl::parse()` function returns a `cl::Args` object, which is simply an `std::unordered_map`

Here are some examples:

Case 1
-------
cl_app called as `cl_app command4 val1 val2`

```ruby
opt3 = null
command1 = false
pos1 = "arg1" # The 1st positional argument for this command
pos2 = null
command2 = false
command3 = false
opt2 = false
val1 = false
val2 = true # We have selected 'val2' for cl::one() param
val3 = false
command4 = "command4" # We called this command
command5 = false
command6 = false
help = false
version = false
opt1 = false
```

Case 2
-------
cl_app called as `cl_app command2 arg1 arg2 -o1 --opt2`

```ruby
opt3 = null
command1 = false
pos1 = "arg1" # The 1st positional argument for this command
pos2 = "arg2" # The 2nd positional argument for this command
command2 = "command2" # We called this command
command3 = false
opt2 = true # opt2 is set
val1 = false
val2 = false
val3 = false
command4 = false
command5 = false
command6 = false
help = false
version = false
opt1 = true # opt1 is set
```

Extract argument information (C++ code)
----
In C++ the code looks like this:

```cpp
#include
#include

int main(int argc, char** argv[]) {
//... create rules & options

cl::Args args = cl::parse(argc, argv);

if(args["command2"]) {
std::cout << "Called command2" << std::endl;
std::cout << "Positionals: " << args["pos1"] << ", " << args["pos2"] << std::endl;
std::cout << "Options: " << args["opt1"] << ", " << args["opt2"] << std::endl;
}
else if(args["command4"]) {
std::cout << "Called command4" << std::endl;
std::cout << "Positionals: " << args["pos1"] << std::endl;

if(args["val2"].to_bool() == true)
std::cout << "Val2 is set" << std::endl;
else
std::cout << "Val2 is NOT set" << std::endl;
}

return 0;
}
```