Skip to content

Latest commit

 

History

History
200 lines (167 loc) · 6.11 KB

File metadata and controls

200 lines (167 loc) · 6.11 KB

Parser for command Line options

The command line parser allows you to easyly managed command line arguments of your programs.

The following features are available : - multiple names for a flag (i.e --a-very-long-name, -shortname, --unotherone, etc) - required flags that force the user to provide a value. - vector of values as input of a flag - automatic help flag generation.

Example

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 - 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)

To use the library, two files are required cpp_tools/cl_parser/tcli.hpp and cpp_tools/cl_parser/help_descriptor.hpp

Now, let's have a look a a first example :

#include <cpp_tools/cl_parser/cl_parser.hpp>

struct n_count
{
    // here, you specify several flags by providing an initializer list of strings
    // to the flags variable.
    cpp_tools::cl_parser::str_vec flags = {"--n-count", "-n"};
    // then, you specify the description of the flag/s
    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)
    type def = 1;
};

// another example with some flaoting point type
struct delta
{
    cpp_tools::cl_parser::str_vec flags = {"--delta", "-d"};
    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

\\ 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"};
    std::string description = "Input filename.";
    using type = std::string;
};

After defining all of our flags, we create our parser:

auto main(int argc, char* argv[]) -> int
{
    // Parameter handling, register all your flags and add the help flag for automated help.
    auto parser = cpp_tools::cl_parser::make_parser( cpp_tools::cl_parser::help{}
                                                   , n_count{}
                                                   , delta{}
                                                   , input_file{});

    // then, we ask the parser to parse argc and argv
    parser.parse(argc, argv);
    ...
}

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.

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

struct inputFile {
  using type = std::string; /*!< The type */

  enum { required };

  std::vector<std::string> flags = {"--input-file", "-fin", }; 
        std::string description = "Input filename.";
 
  std::string input_hint = "std::string"; 
};

Another way is to inherit the required_tag

    struct inputFile : cpp_tools::cl_parser::required_tag
    {
        cpp_tools::cl_parser::str_vec flags = {"--input-file", "-fin"};
        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

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

//
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

my_program2  --output-file results.csv

or

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.

    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>;
    };
my_program --centre 0.0,1.0,2.0 

Methods to access parameters

  • the get method gets the value(s) for a given parameter.
    const auto file = parser.get<input_file>();
  • exists method checks whether option was specified in CLI
if (parser.exists<output_file>()) {
   const auto output = parser.get<output_file>();
 }