vg
tools for working with variation graphs
Classes | Namespaces | Typedefs | Functions
options.hpp File Reference
#include "../utility.hpp"
#include <map>
#include <functional>
#include <string>
#include <iostream>
#include <getopt.h>

Classes

struct  vg::subcommand::TickChainLink
 
struct  vg::Range< Number >
 
struct  vg::is_instantiation_of< Subject, Predicate >
 
struct  vg::is_instantiation_of< Predicate< PredicateArgs... >, Predicate >
 
struct  vg::subcommand::BaseValuation
 
struct  vg::subcommand::Valuation< T >
 
struct  vg::subcommand::BaseArgSpec< Receiver >
 
struct  vg::subcommand::ArgSpec< T, Receiver >
 
struct  vg::subcommand::ValueArgSpec< T, Receiver, Holder >
 
struct  vg::subcommand::RangeArgSpec< T, Receiver >
 
struct  vg::subcommand::FlagArgSpec< Receiver >
 
struct  vg::subcommand::BaseOptionGroup
 
struct  vg::subcommand::OptionGroup< Receiver >
 
struct  vg::subcommand::GroupedOptionGroup
 
struct  vg::subcommand::Preset
 

Namespaces

 vg
 
 vg::subcommand
 

Typedefs

template<typename T >
using vg::subcommand::ValidatorFunction = std::function< void(const T &)>
 Function type used to validate arguments. Throw std::domain_error if not allowed, explaining why. More...
 

Functions

template<typename Result >
bool vg::parse (const string &arg, typename enable_if< is_instantiation_of< Result, Range >::value, Result >::type &dest)
 Parse a range as start[:end[:step]]. More...
 
int vg::subcommand::get_option_id ()
 Get a new unique option ID. More...
 
template<typename T >
const char * vg::subcommand::get_metavar ()
 
template<>
const char * vg::subcommand::get_metavar< size_t > ()
 
template<>
const char * vg::subcommand::get_metavar< int > ()
 
template<>
const char * vg::subcommand::get_metavar< int8_t > ()
 
template<>
const char * vg::subcommand::get_metavar< bool > ()
 
template<>
const char * vg::subcommand::get_metavar< double > ()
 
template<>
const char * vg::subcommand::get_metavar< std::string > ()
 
void vg::subcommand::print_table (const std::vector< std::pair< std::string, std::string >> &rows, ostream &out)
 

Detailed Description

options.hpp: option parser system.

Make a BaseOptionGroup, and use add_group<Receiver>(heading) to add subgroups that apply parsed options to instances of a given class.

Set up each option in the group with add_option(), add_range() (for an option that can be cycled through a range of values for a grid search), or add_flag(). Every option always has a logn option name; short option character is optional and comes after it. Options take a pointer-to-member into the group's type (where the value will be ultimately written) and a default value, a help stiring, and an optional "validator function" which gets to check the parsed value and should raise std::domain_error with a complaint if the value isn't acceptable.

Get the help with get_help() on the root group, and use the free print_table() function to print it to a stream with headings and automatic indentation.

To parse options, use make_long_options() and make_short_options() to adjust some (possibly already partly populated) getopt_long() inputs, null-terminate the long options array, and call getopt_long() as normal. Show every option number and optarg value to the root group's parse(), and then continue with your own parsing if it returns false because it does not consume that option.

To apply presets before parsing, make a Preset and fill it in with add_entry<T>(option, value). Then call apply() on the preset with the root group.

To read and write option values manually, use the get_option_value() and set_option_value() methods on the root option group.

To log option values, there is a print_options() method on the root option group.

EXAMPLE

struct ThingDoer { static constexpr int default_count = 5; int count = default_count; };

vg::subcommand::BaseOptionGroup get_parser() { vg::subcommand::BaseOptionGroup parser; auto thing_doer_opts = parser.add_group<ThingDoer>("thing doer configuration"); thing_doer_opts.add_option( "count", 'c', &ThingDoer::count, ThingDoer::default_count, "number of things to do", vg::subcommand::int_is_nonnegative ); return parser; }

int main(int argc, char** argv) { auto parser = get_parser(); std::vector<struct option> long_options; parser.make_long_options(long_options); long_options.push_back({0, 0, 0, 0}); std::string short_options; parser.make_short_optins(short_options); int c; while (true) { int option_index = 0; int option_id = getopt_long (argc, argv, short_options.c_str(), &long_options[0], &option_index); if (option_id == -1) break; if (parser.parse(option_id, optarg)) continue; switch (option_id) { default: vg::subcommand::print_table(parser.get_help(), std::cerr); return 1; } } ThingDoer thing_doer; parser.apply(thing_doer); std::cout << "Doing " << thing_doer.count << " things" << std::endl; return 0; }