druidengine / druidengine/druid

Implement a command line parser.

Open
#11 0 comments 0 reactions 1 assignee Claimed by @jamilly-x86 View on GitHub
enhancement good first issue
Dominant language
C++
Stars
3
Forks
6
PR merge metrics
No merged PRs in 30d

Description

**Is your feature request related to a problem? Please describe.**
I need an API that will accept command line input as a string that can be parsed into various types of fields and data. I would also like the ability to request `--help` for my application and get a list of all available options.

**Describe the solution you'd like**
To start, I think using `boost-program-options` can provide this but its API is rather complicated. Let's wrap this in a simpler, `druid` API to make this more usable for others.

I'd probably lean toward mimicking some of Qt's API found [here](https://doc.qt.io/qt-6/qcommandlineparser.html). I double we need all the feature to begin with but we want to at least have the following:

- [ ] Add `boost-program-options` as a dependency to `vcpkg.json`
- [ ] `druid::CommandLineParser` class implemented in `druid-core`
- [ ] `druid::CommandLineOption` class implemented in `druid-core`
- [ ] Both classes implemented in same modules file `import druid.core.commandlineparser;`
- [ ] The ability to retrieve the list of options and there values.
- [ ] Possibly an option to retrieve a value as a specific type along with an error code if the value could not be converted to that type.

I'm hoping for something that will look like:

```cpp
auto main(int argc, char** argv) -> int
{
std::vector options;
auto option = options.emplace_back("uci");
option.setDescription("This describes what the universal chess interface input is.");
option.setDefaultValue("");

option = options.emplace_back("flag");
option.setDescription("This describes what the flag input is.");
option.setDefaultValue("If no value is given.");

druid::CommandLineParser parser;
parser.addOptions(options);
parser.process(argc, argv);

return 0;
}
```

**Describe alternatives you've considered**
Implementing this from scratch, while possible, would take more time and require more testing. This might be worth considering later but for now, `boost` should be good enough.

**Additional context**
Project `runestone` will need a command line interface to parse data.

Here's an example of how to use the `boost` API.

```cpp
#include
#include
#include
#include

namespace po = boost::program_options;

int main(int argc, char* argv[]) {
try {
// 1. Declare the supported options.
po::options_description desc("Allowed options");
desc.add_options()
("help,h", "Produce help message")
("input-file,i", po::value(), "Input file path")
("output-dir,o", po::value()->default_value("."), "Output directory")
("compression-level,c", po::value()->default_value(5), "Compression level (1-9)");

// 2. Parse the command line arguments.
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);

// 3. Process the options.
if (vm.count("help")) {
std::cout << desc << "\n";
return 0;
}

if (vm.count("input-file")) {
std::cout << "Input file: " << vm["input-file"].as() << "\n";
} else {
std::cerr << "Error: Input file is required.\n";
std::cout << desc << "\n";
return 1;
}

std::cout << "Output directory: " << vm["output-dir"].as() << "\n";
std::cout << "Compression level: " << vm["compression-level"].as() << "\n";

} catch (const po::error& e) {
std::cerr << "Error: " << e.what() << "\n";
return 1;
}

return 0;
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.