https://github.com/platisd/cpp-command-parser
Parse CLI commands with compile-time checks for your sanity
https://github.com/platisd/cpp-command-parser
c-plus-plus cli cpp parser
Last synced: 11 months ago
JSON representation
Parse CLI commands with compile-time checks for your sanity
- Host: GitHub
- URL: https://github.com/platisd/cpp-command-parser
- Owner: platisd
- License: mit
- Created: 2022-11-16T17:10:02.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2023-10-27T12:54:09.000Z (over 2 years ago)
- Last Synced: 2025-03-13T22:41:39.366Z (over 1 year ago)
- Topics: c-plus-plus, cli, cpp, parser
- Language: C++
- Homepage:
- Size: 1.03 MB
- Stars: 1
- Watchers: 2
- Forks: 1
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Command Parser
[](https://codecov.io/gh/platisd/cpp-command-parser) [](https://github.com/platisd/cpp-command-parser/actions/workflows/build-ut-coverage.yml) [](https://github.com/platisd/cpp-command-parser/actions/workflows/clang-format.yml) [](https://github.com/platisd/cpp-command-parser/actions/workflows/clang-tidy.yml) [](https://github.com/platisd/cpp-command-parser/actions/workflows/commit-messages.yml)
Command Parser is a C++17 header-only utility library for parsing command line "commands".
We define a _command_ as the _first_ CLI argument passed to a binary in the form of:
```bash
./your_binary command_name [arg3]
# `command_name` is the command
```
A command may optionally take some (boolean) options
```bash
./your_binary command_name --option1 --option2 [arg3]
```
As long as your CLI application requires the _first_ argument to be a "command", this library will help you parse the
command, as well as any subcommands and options.
To put it simply, **there must be at least one argument**. That first argument to the binary is your "command".
If your logic does _not_ require at least one argument to be passed as a "command", then this library is not for you.
## Usage
See [example_main.cpp](example_main.cpp) for a simple example of how to use the library. In a nutshell:
```cpp
const auto all = UnparsedCommand::create("all", "Print current configuration");
const auto get = UnparsedCommand::create("get", "Get configuration key", "[-xyz] [default]")
.withOptions({ "x", "y", "z" }) // Can be --x or -x etc
.withAliases({ "g", "get-key" }); // Alternative IDs for the command instead of "get"
.withArgs>();
const auto encrypt = UnparsedCommand::create(
"encrypt"
"Encrypt the given files with the specified policy",
" [file...]")
.withArgs>();
const std::tuple commands { all, get, encrypt };
const auto parsedCommand = UnparsedCommand::parse(argc, argv, commands);
if (parsedCommand.is(all)) {
std::cout << "all" << std::endl;
// auto config = parsedCommand.getArgs(all); // Does not compile because all has no args
} else if (parsedCommand.is(get)) {
const auto [key, defaultValue] = parsedCommand.getArgs(get);
const auto x = parsedCommand.hasOption("x");
const auto y = parsedCommand.hasOption("y");
const auto z = parsedCommand.hasOption("z");
std::cout << "get " << key << " " << x << " " << y << " " << z << std::endl;
if (defaultValue) {
std::cout << "default " << defaultValue.value() << std::endl;
}
} else if (parsedCommand.is(encrypt)) {
const auto [policy, files] = parsedCommand.getArgs(encrypt);
std::cout << "encrypt " << policy << std::endl;
for (const auto& file : files) {
std::cout << "file " << file << std::endl;
}
} else {
std::cout << "Available commands:" << std::endl;
std::cout << parsedCommand.help() << std::endl;
}
```
### Allowed types
The following types are permitted as arguments. They are mandatory unless otherwise specified and their usage rules are
enforced during compilation:
* `std::string`
* `bool`
* The following (case-insensitive) strings are considered `true` and everything else `false`:
* `true`
* `yes`
* `y`
* `on`
* `1`
* `int`
* `long`
* `long long`
* `unsigned long`
* `unsigned long long`
* `float`
* `double`
* `long double`
* `std::optional` where `T` is any of the above types
* Optional argument: May not be provided but must be at the end of the argument list
* `std::vector` where `T` is any of the above types
* Zero or more optional arguments: May be of any number or not provided, but cannot precede a mandatory argument and
cannot be combined with a `std::optional` argument
In addition to the above, any user-defined type that is default constructible and constructible from a `std::string` is
also allowed.
## Why not `insert your favorite CLI parsing library here`?
In all fairness, this library was created under the misconception that [cxxopts](https://github.com/jarro2783/cxxopts)
was not able to satisfy our use-case out of the box, which is **not** true. Some of its cool features are:
* Compile-time check of argument count and types (i.e. you cannot "forget" to parse an argument or parse one that was
not expected)
* Header-only
* No dependencies
* No macros
* No exceptions
## Acknowledgements
This library was developed internally at [neat.no](https://neat.no) and is now open-sourced.