Commits (5)
This diff is collapsed.
# Command Line Parser
# Parser for command Line options
The command line parser allows you to easyly managed command line arguments
......@@ -15,7 +15,7 @@ The following features are available :
First let's look at the anatomy of a flag.
It's a simple structure with the following required fields :
- `cpp_tools::cl_parser::str_vec flags` : a vector of strings with the different versions of the flag
- `const char* description` : the description of the flag that will appear in the help
- `const std::string description` : the description of the flag that will appear in the help
- `using type = float` : the type of the flag
- `type def = 1.0` : the default value of the flag (optional)
......@@ -33,7 +33,7 @@ struct n_count
// to the flags variable.
cpp_tools::cl_parser::str_vec flags = {"--n-count", "-n"};
// then, you specify the description of the flag/s
const char* description = "An integer to catch.";
const std::string description = "An integer to catch.";
// register the type of the flag/s
using type = int;
// put the def variable to the default value of the flag (optional)
......@@ -44,25 +44,25 @@ struct n_count
struct delta
{
cpp_tools::cl_parser::str_vec flags = {"--delta", "-d"};
const char* description = "Delta to apply.";
const std::string description = "Delta to apply.";
using type = double;
type def = 0.1;
};
```
Now let's add a required flag that will throw an exception if not provided :
Now let's add a required flag that will throw an exception if not provided
```cpp
\\ you need to inherit from required_tag to register your flag as required.
struct input_file : cpp_tools::cl_parser::required_tag
{
cpp_tools::cl_parser::str_vec flags = {"--input-file", "-fin"};
const char* description = "Input filename.";
const std::string description = "Input filename.";
using type = std::string;
};
```
After defining all of our flags, we can create our parser :
After defining all of our flags, we create our parser:
```cpp
auto main(int argc, char* argv[]) -> int
......@@ -78,12 +78,124 @@ auto main(int argc, char* argv[]) -> int
...
}
```
Note that we added the `cpp_tools::cl_parser::help{}` flag to generate automaticaly
the help command line argument.
And finally we can access the flag value as follow :
Note that we added the `cpp_tools::cl_parser::help{}` flag to automatically generate the help command line arguments.
And finally we access the flag value by the `get` method as follows.
```cpp
const auto n_count = parser.get<n_count>();
const auto file = parser.get<input_file>();
```
## Details
### Parameters descriptors
The parameter description is aa class that exposes the following public interface.
- `type` argument type
- `flag` (std::string) a vector of sting that contains the list of the option
- `description` (std::string) (optional), argument default value
- `def` (optional) argument default value
- `flag` enum
- `required` (optional) the argument must be specified once
- `stackable` (optional) the argument may be specified several time and the value are stacked
- `hidden` (optional) the argument must be hidden in help message
- `flagged` bool typed parameter which value defaults to `false`.
- `input_hint` (std::string) the type of the parameter
- `tag`
- `stackable_tag`
- `required_tag` if the parameter is mandatory.
### Examples
#### Required flag
We consider that the inputFile parameter is required to run the program. If the
```cpp
struct inputFile {
using type = std::string; /*!< The type */
enum { required };
std::vector<std::string> flags = {"--input-file", "-fin", };
const char* std::string description = "Input filename.";
std::string input_hint = "std::string";
};
```
Another way is to inherit the `required_tag`
```cpp
struct inputFile : cpp_tools::cl_parser::required_tag
{
cpp_tools::cl_parser::str_vec flags = {"--input-file", "-fin"};
const std::string description = "Input filename.";
using type = std::string;
};
```
```bash
my_program --input-file results.csv
```
If `--input-file` is not in the command line an error occurs.
### flag argument
```cpp
struct quiet {
using type = bool;
enum { flagged };
std::vector<std::string> flags = {"--quiet", "-q"};
std::string description = "No verbose node.";
};
```bash
my_program1 --quiet
```
### Default values
```cpp
//
struct OutputFile {
using type = std::string;
cpp_tools::cl_parser::str_vec flags = {"--output-file", "-of"};
std::string description = "The output file name";
std::string input_hint = "std::string";
type def = "output.txt" ;
};
```
if `--output-file` is specified with a name file we select this name and if teh option is not set then the name for teh OutputFile descriptor is the default value `output.txt`
```bash
my_program2 --output-file results.csv
```
or
```bash
my_program2 --output-file results.csv
```
### An array in parameter
Now we want to pass a set of values of the same type as an argument like the dimension of an array, point, ...
Below, the structure center corresponds to a point of type double.
```cpp
struct centre
{
cpp_tools::cl_parser::str_vec flags = {"--centre", "-c"}; /
std::string description = "the center of the final distribution";
std::string input_hint = "value,value,value";
using type = std::vector<double>;
};
```
```bash
my_program --centre 0.0,1.0,2.0
```
### Methods to access parameters
- the `get` method gets the value(s) for a given parameter.
```cpp
const auto file = parser.get<input_file>();
```
- `exists` method checks whether option was specified in CLI
``` cpp
if (parser.exists<output_file>()) {
const auto output = parser.get<output_file>();
}
```
......@@ -20,48 +20,48 @@ namespace cpp_tools::cl_parser
/// flags
std::vector<std::string> flags = {"t"};
/// optional, argument description
const char* description;
const char *description;
/// optional, argument default value
type def;
enum
{
stackable, ///< optional, the argument may be specified several time
stackable, ///< optional, the argument may be specified several time
///< and the value are stacked
required, ///< optional, the argument must be specified once
hidden, ///< optional, the argument must be hidden in help message
required, ///< optional, the argument must be specified once
hidden, ///< optional, the argument must be hidden in help message
};
/// optional, called after parameter parsing
template<class Parser>
void visit(Parser& p, std::vector<std::string>& args, typename std::vector<std::string>::iterator& current_arg);
template <class Parser>
void visit(Parser &p, std::vector<std::string> &args, typename std::vector<std::string>::iterator &current_arg);
/// optional, customize parameter parsing
bool parse(std::vector<std::string>& args, typename std::vector<std::string>::iterator& current_arg,
type& data);
bool parse(std::vector<std::string> &args, typename std::vector<std::string>::iterator &current_arg,
type &data);
};
/**
* \brief Basic parameter descriptor
*
* \tparam T Parameter underlying type.
* \tparam Tag Optional tag class use to differenciate two parameters with
* \tparam Tag Optional tag class use to differentiate two parameters with
* the same type.
*/
template<class T, class Tag = void>
template <class T, class Tag = void>
struct parameter_descriptor
{
using type = T;
std::vector<std::string> flags;
parameter_descriptor() = default;
parameter_descriptor(const parameter_descriptor&) = default;
parameter_descriptor(parameter_descriptor&&) = default;
parameter_descriptor& operator=(const parameter_descriptor&) = default;
parameter_descriptor& operator=(parameter_descriptor&&) = default;
parameter_descriptor(const parameter_descriptor &) = default;
parameter_descriptor(parameter_descriptor &&) = default;
parameter_descriptor &operator=(const parameter_descriptor &) = default;
parameter_descriptor &operator=(parameter_descriptor &&) = default;
parameter_descriptor(const std::vector<std::string>& new_flags)
: flags(new_flags)
parameter_descriptor(const std::vector<std::string> &new_flags)
: flags(new_flags)
{
}
};
......@@ -83,6 +83,6 @@ namespace cpp_tools::cl_parser
};
};
} // namespace cpptools::cl_parser
} // namespace cpptools::cl_parser
#endif /* TCLI_PARAMETER_MODEL_HPP */