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
- Host: GitHub
- URL: https://github.com/dax89/cl
- Owner: Dax89
- License: mit
- Created: 2023-11-05T20:45:30.000Z (about 2 years ago)
- Default Branch: master
- Last Pushed: 2024-01-08T18:39:53.000Z (almost 2 years ago)
- Last Synced: 2024-01-08T20:09:49.727Z (almost 2 years ago)
- Topics: argument-parser, c-plus-plus, cli-parser, cpp17, header-only, mit-license, no-dependencies, option-parser, positional-arguments
- Language: C++
- Homepage:
- Size: 36.1 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
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;
}
```