DAS  3.0
Das Analysis System
Options

Description

Common class to interpret the command line, based on Boost Program Options.

Options may also be partly provided via a configuration file. Additional options to split the input file are also possible. Minimal working example:

Options options("Global description.", Options::config | Options::split);
options.input ("input" , &input , "input ROOT file" );
options.output("output", &output, "output ROOT file");
options.arg<int>("myArg", "correction.here", "my description");
options.args("allOtherArgs", "correction.there.list", "garbage collector");
auto const& config = options(argc, argv);

where the config is a Boost Property Tree. A one-liner is even possible:

auto const& config = Options("Global description.", Options::config | Options::split).input("input", &input, "input ROOT file").output("output", &output, "output ROOT file").arg<int>("myArg", "correction.here", "my description").args("allOtherArgs", "correction.there.list", "garbage collector")(argc, argv);

The order matters only for the positional options, where input(s) should be given first, then output(s), then additional positional options. The position of explicit options (e.g. -v) does not matter. Options::args may be used as a garbage collector for extra positional options.

#include <Options.h>

+ Collaboration diagram for Options:

Public Member Functions

 Options (const std::string &, int=none, const char *commit=DARWIN_GIT_COMMIT, const char *example=DARWIN_EXAMPLE)
 
 Options ()=delete
 
Optionsinput (const char *, std::filesystem::path *, const char *)
 
Optionsinputs (const char *, std::vector< std::filesystem::path > *, const char *)
 
Optionsoutput (const char *, std::filesystem::path *, const char *)
 
template<typename T >
Optionsarg (const char *name, const char *configpath, const char *desc)
 
Optionsargs (const char *name, const char *configpath, const char *desc)
 
const boost::property_tree::ptree & operator() (int, const char *const [])
 
auto commit () const
 
int steering () const
 
std::pair< unsigned, unsigned > slice () const
 
 Options (const std::string &, int=none, const char *commit=DARWIN_GIT_COMMIT, const char *example=DARWIN_EXAMPLE)
 
 Options ()=delete
 
Optionsinput (const char *, std::filesystem::path *, const char *)
 
Optionsinputs (const char *, std::vector< std::filesystem::path > *, const char *)
 
Optionsoutput (const char *, std::filesystem::path *, const char *)
 
template<typename T >
Optionsarg (const char *name, const char *configpath, const char *desc)
 
Optionsargs (const char *name, const char *configpath, const char *desc)
 
const boost::property_tree::ptree & operator() (int, const char *const [])
 
auto commit () const
 
int steering () const
 
std::pair< unsigned, unsigned > slice () const
 

Static Public Member Functions

static std::string parse_env_var (std::string)
 
static const char * parse_env_var (const char *p)
 
static std::filesystem::path parse_env_var (const std::filesystem::path &p)
 
static void parse_config (boost::property_tree::ptree &, std::string="")
 
static std::string parse_env_var (std::string)
 
static const char * parse_env_var (const char *p)
 
static std::filesystem::path parse_env_var (const std::filesystem::path &p)
 
static void parse_config (boost::property_tree::ptree &, std::string="")
 

Static Public Attributes

static std::string full_cmd
 

Private Types

enum  Stage {
  Input, Output, Arg, Args,
  Input, Output, Arg, Args
}
 
enum  Stage {
  Input, Output, Arg, Args,
  Input, Output, Arg, Args
}
 

Private Member Functions

void parse_helper (int, const char *const [])
 
void parse_common (int, const char *const [])
 
void parse_custom (int, const char *const [])
 
Optionsset (const char *, const boost::program_options::value_semantic *, const char *)
 
template<typename T >
std::function< void(T)> put (const char *configpath)
 
bool allow_unregistered () const
 
std::string exec (const std::string &)
 
void parse_helper (int, const char *const [])
 
void parse_common (int, const char *const [])
 
void parse_custom (int, const char *const [])
 
Optionsset (const char *, const boost::program_options::value_semantic *, const char *)
 
template<typename T >
std::function< void(T)> put (const char *configpath)
 
bool allow_unregistered () const
 
std::string exec (const std::string &)
 

Static Private Member Functions

static void check_input (const std::filesystem::path &)
 
static void check_output (const std::filesystem::path &)
 
static void check_input (const std::filesystem::path &)
 
static void check_output (const std::filesystem::path &)
 

Private Attributes

boost::program_options::options_description hidden
 
boost::program_options::options_description helper
 
boost::program_options::options_description common
 
boost::program_options::options_description custom
 
boost::program_options::positional_options_description pos_hide
 
boost::property_tree::ptree pt_conf
 
const std::filesystem::path example
 
std::filesystem::path config_file
 
const std::string tutorial
 
std::string synopsis
 
std::vector< std::string > names
 
std::vector< std::string > configpaths
 
std::optional< unsigned > registered
 
Stage stage
 
const int params
 
const std::string m_commit
 
int steer
 
unsigned j
 
unsigned k
 

Static Private Attributes

static std::filesystem::path prefix
 

Member Enumeration Documentation

◆ Stage [1/2]

enum Stage
private
Enumerator
Input 

first the inputs

Output 

then the outputs (inputs are no longer allowed)

Arg 

then the registered arguments (inputs and outputs no longer allowed)

Args 

finally the remaining arguments / garbage collector (must be very last)

Input 

first the inputs

Output 

then the outputs (inputs are no longer allowed)

Arg 

then the registered arguments (inputs and outputs no longer allowed)

Args 

finally the remaining arguments / garbage collector (must be very last)

140  {
141  Input,
142  Output,
143  Arg,
144  Args
145  };

◆ Stage [2/2]

enum Stage
private
Enumerator
Input 

first the inputs

Output 

then the outputs (inputs are no longer allowed)

Arg 

then the registered arguments (inputs and outputs no longer allowed)

Args 

finally the remaining arguments / garbage collector (must be very last)

Input 

first the inputs

Output 

then the outputs (inputs are no longer allowed)

Arg 

then the registered arguments (inputs and outputs no longer allowed)

Args 

finally the remaining arguments / garbage collector (must be very last)

140  {
141  Input,
142  Output,
143  Arg,
144  Args
145  };

Constructor & Destructor Documentation

◆ Options() [1/4]

Options ( const std::string &  tuto,
int  pars = none,
const char *  commit = DARWIN_GIT_COMMIT,
const char *  example = DARWIN_EXAMPLE 
)

Constructor:

  • contains a parser for the help itself
  • contains a parser for the options, like config file and verbosity
  • and contains a parser for the input, output, and any other option as positional arguments
Parameters
tutodescription, to be displayed in the helper
parsflags for explicit, generic command options (see enum)
commitgit commit for --git
examplepath to example
99  : hidden{"Hidden"}, helper{"Helper"}, common{"Options"}, custom{"Positional options"},
100  tutorial(tuto), stage(Stage::Input), params(pars),
101  m_commit(commit ? commit : DARWIN_VERSION), steer(0), j(1), k(0),
102  example(example ? example : DARWIN "/test/example.info")
103 {
104  if ((params & split) == split) hidden.add_options()
105  ("prefix,p", po::value<fs::path>(&prefix), "Prefix command, `parallel` or `submit` (for history only)");
106 
107  // first the helper
108  helper.add_options()
109  ("help,h", "Help screen (what you are seeing right now)")
110  ("tutorial,t", "Brief description of the command's purpose")
111  ("git,g", "Commit hash of this executable at compilation time");
112  if ((params & config) == config) helper.add_options()
113  ("example,e", "Print config example");
114 
115  // then the running options
116  common.add_options()
117  ("verbose,v", po::bool_switch()->default_value(false), "Enable debug mode (typically in slow operations such as the event loop)")
118  ("mute,m" , po::bool_switch()->default_value(false)->notifier(set_mute), "Disable standard output stream");
119  if ((params & config) == config) common.add_options()
120  ("config,c" , po::value<fs::path>(&config_file), "Configuration file in INFO, JSON, or XML format");
121  if ((params & split) == split) common.add_options()
122  ("nSplit,j" , po::value<unsigned>(&j)->default_value(j), "Number of slices")
123  ("nNow,k" , po::value<unsigned>(&k)->default_value(k), "Index of present slice");
124  if ((params & fill) == fill) common.add_options()
125  ("fill,f", po::bool_switch()->default_value(false), "Enable `TTree::Fill()`");
126  if ((params & Friend) == Friend) common.add_options()
127  ("Friend,F", po::bool_switch()->default_value(false), "Use `TTree` friends instead of cloning the whole input `TTree`");
128  if ((params & syst) == syst) common.add_options()
129  ("syst,s", po::bool_switch()->default_value(false), "Enable systematic variations");
130 
131  // positional arguments should be defined by hand by the user with the various public members
132 }

◆ Options() [2/4]

Options ( )
delete

No default constructor is allowed.

◆ Options() [3/4]

Options ( const std::string &  ,
int  = none,
const char *  commit = DARWIN_GIT_COMMIT,
const char *  example = DARWIN_EXAMPLE 
)

Constructor:

  • contains a parser for the help itself
  • contains a parser for the options, like config file and verbosity
  • and contains a parser for the input, output, and any other option as positional arguments
Parameters
commitgit commit for --git
examplepath to example

◆ Options() [4/4]

Options ( )
delete

No default constructor is allowed.

Member Function Documentation

◆ allow_unregistered() [1/2]

bool allow_unregistered ( ) const
inlineprivate
Returns
true if Options::registered has been initialised.
133 { return bool(registered); }

◆ allow_unregistered() [2/2]

bool allow_unregistered ( ) const
inlineprivate
Returns
true if Options::registered has been initialised.
133 { return bool(registered); }

◆ arg() [1/2]

Options& arg ( const char *  name,
const char *  configpath,
const char *  desc 
)
inline

Member to add an argument. It can be called several times in a row. Each argument may be provided via the configuration file too.

Returns
the object itself, so that the arguments can be given in a row.
Parameters
namename of the option, will be shown in helper
configpathpath in config
descdescription, shown in helper too
216  {
217  if (stage > Stage::Arg)
218  BOOST_THROW_EXCEPTION(std::runtime_error("Not possible to add another argument at this stage"));
219  stage = Stage::Arg;
220 
221  names.push_back(name);
222  configpaths.push_back(configpath);
223  const boost::program_options::value_semantic * s =
224  boost::program_options::value<T>()->notifier(put<T>(configpath));
225  return set(name, s, desc);
226  }

◆ arg() [2/2]

Options& arg ( const char *  name,
const char *  configpath,
const char *  desc 
)
inline

Member to add an argument. It can be called several times in a row. Each argument may be provided via the configuration file too.

Returns
the object itself, so that the arguments can be given in a row.
Parameters
namename of the option, will be shown in helper
configpathpath in config
descdescription, shown in helper too
216  {
217  if (stage > Stage::Arg)
218  BOOST_THROW_EXCEPTION(std::runtime_error("Not possible to add another argument at this stage"));
219  stage = Stage::Arg;
220 
221  names.push_back(name);
222  configpaths.push_back(configpath);
223  const boost::program_options::value_semantic * s =
224  boost::program_options::value<T>()->notifier(put<T>(configpath));
225  return set(name, s, desc);
226  }

◆ args() [1/2]

Options& args ( const char *  name,
const char *  configpath,
const char *  desc 
)

Member to collect any addition arguments provided in command line. It should be called maximum once. The additional options will be collected as a list of strings.

Parameters
namegeneric name for unregistered options
configpathpath in config.
descdescription, shown in helper too

◆ args() [2/2]

Options & args ( const char *  name,
const char *  configpath,
const char *  desc 
)

Member to collect any addition arguments provided in command line. It should be called maximum once. The additional options will be collected as a list of strings.

Parameters
namegeneric name for unregistered options
configpathpath in config.
descdescription, shown in helper too
474 {
475  if (stage >= Stage::Args)
476  BOOST_THROW_EXCEPTION(runtime_error("Only one garbage collector is possible"));
477  stage = Stage::Args;
478 
479  synopsis += " [" + string(name) + "...]";
480  configpaths.push_back(configpath);
481 
482  registered = pos_hide.max_total_count();
483  const po::value_semantic * s =
484  po::value<vector<string>>()->multitoken()->zero_tokens();
485  custom.add_options()(name, s, desc);
486  pos_hide.add(name, -1);
487 
488  return *this;
489 }

◆ check_input() [1/2]

void check_input ( const std::filesystem::path &  input)
staticprivate

Function used by Boost Program Options to check if the file does exist, and if yes, if it is readable and readable.

Parameters
inputpath to input
38 {
39  if (!fs::exists(input))
40  BOOST_THROW_EXCEPTION(fs::filesystem_error("Bad input", input,
41  make_error_code(errc::no_such_file_or_directory)));
42 
43  full_cmd += ' ' + fs::canonical(input).string();
44 
45  if ((fs::status(input).permissions() & fs::perms::owner_read) == fs::perms::none)
46  BOOST_THROW_EXCEPTION(fs::filesystem_error("Input exists but cannot be read",
47  input, make_error_code(errc::permission_denied)));
48 }

◆ check_input() [2/2]

static void check_input ( const std::filesystem::path &  )
staticprivate

Function used by Boost Program Options to check if the file does exist, and if yes, if it is readable and readable.

◆ check_output() [1/2]

void check_output ( const std::filesystem::path &  output)
staticprivate

Function used by Boost Program Options to check if the file may already exist, and if yes, then if it is writable, and not a directory. (At this stage, the automatic naming of the output according to the name of the input should not happen. Such a thing should rather be done in the executable directly.)

Parameters
outputpath to output
51 {
52  fs::path outputHist = output;
53  if (!prefix.empty() && !fs::is_directory(output)) outputHist.remove_filename();
54  full_cmd += ' ' + outputHist.string();
55 
56  if (!fs::exists(output)) return;
57 
58  if ((fs::status(output).permissions() & fs::perms::owner_write) == fs::perms::none) {
59  full_cmd.clear();
60  BOOST_THROW_EXCEPTION(fs::filesystem_error("Output already exists and cannot be overwritten",
61  output, make_error_code(errc::permission_denied)));
62  }
63 
64  if (fs::is_directory(output) && fs::equivalent(output,".")) {
65  full_cmd.clear();
66  BOOST_THROW_EXCEPTION(fs::filesystem_error("Not a valid output",
67  output, make_error_code(errc::invalid_argument)));
68  }
69  else if (output != "/dev/null")
70  cerr << orange << "Warning: you are overwriting " << output << def << '\n';
71 }

◆ check_output() [2/2]

static void check_output ( const std::filesystem::path &  )
staticprivate

Function used by Boost Program Options to check if the file may already exist, and if yes, then if it is writable, and not a directory. (At this stage, the automatic naming of the output according to the name of the input should not happen. Such a thing should rather be done in the executable directly.)

◆ commit() [1/2]

auto commit ( ) const
inline

Git commit information.

270 { return m_commit; }

◆ commit() [2/2]

auto commit ( ) const
inline

Git commit information.

270 { return m_commit; }

◆ exec() [1/2]

std::string exec ( const std::string &  cmd)
private
Returns
output from command given to shell
Parameters
cmdcmd to run in the shell
408 {
409  string result;
410  char buffer[128];
411  cerr << red;
412  FILE * pipe = popen(cmd.c_str(), "r");
413  while (!feof(pipe))
414  if (fgets(buffer, 128, pipe) != NULL)
415  result += buffer;
416  pclose(pipe);
417  cerr << def;
418  return result;
419 }

◆ exec() [2/2]

std::string exec ( const std::string &  )
private
Returns
output from command given to shell

◆ input() [1/2]

Options& input ( const char *  ,
std::filesystem::path *  ,
const char *   
)

Member to add an input. It can be called several times in a row. This option should always be provided from the command line, and never via the config file.

Returns
the object itself, so that the arguments can be given in a row.

◆ input() [2/2]

Options & input ( const char *  name,
std::filesystem::path *  file,
const char *  desc 
)

Member to add an input. It can be called several times in a row. This option should always be provided from the command line, and never via the config file.

Returns
the object itself, so that the arguments can be given in a row.
Parameters
namename of the option, will be shown in helper
filepath pointer to file
descdescription, shown in helper too
398 {
399  if (stage > Stage::Input)
400  BOOST_THROW_EXCEPTION(runtime_error("Not possible to add another input at this stage"));
401 
402  const po::value_semantic * s =
403  po::value<fs::path>(file)->notifier(check_input)->required();
404  return set(name, s, desc);
405 }

◆ inputs() [1/2]

Options& inputs ( const char *  ,
std::vector< std::filesystem::path > *  ,
const char *   
)

Member to add an undefined amount of input. It can be called only once. This option should always be provided from the command line, and never via the config file. There can be no garbage collector in addition.

Returns
the object itself, so that the arguments can be given in a row.

◆ inputs() [2/2]

Options & inputs ( const char *  name,
std::vector< std::filesystem::path > *  files,
const char *  desc 
)

Member to add an undefined amount of input. It can be called only once. This option should always be provided from the command line, and never via the config file. There can be no garbage collector in addition.

Returns
the object itself, so that the arguments can be given in a row.
Parameters
namename of the options, will be shown in helper
filespaths to files
descdescriptions
422 {
423  if (stage > Stage::Input)
424  BOOST_THROW_EXCEPTION(runtime_error("Not possible to add another input at this stage"));
425 
426  auto store = [files,this](const string& pathRegex) {
427 
428  const string& ls = exec("ls -1d " + pathRegex);
429 
430  vector<fs::path> paths;
431  al::split(paths, ls, al::is_any_of("\n"), al::token_compress_on);
432  for (fs::path const& p: paths) {
433  if (!fs::exists(p)) continue;
434  // p = fs::canonical(p); // TODO?
435  files->push_back(p);
436  }
437 
438  if (files->empty()) {
439  fs::path p = pathRegex;
440  full_cmd.clear();
441  BOOST_THROW_EXCEPTION(fs::filesystem_error("No input file could be found", p,
442  make_error_code(errc::no_such_file_or_directory)));
443  }
444 
445  auto inputs = accumulate(files->begin(), files->end(), string(),
446  [](string inputs, fs::path input) { return inputs + fs::canonical(input).string() + ' '; });
447  inputs.resize(inputs.size()-1);
448  if (files->size() > 1)
449  inputs = '"' + inputs + '"';
450  full_cmd += ' ' + inputs;
451  };
452 
453  const po::value_semantic * s =
454  po::value<string>()->notifier(store)->required();
455  string full_desc = desc;
456  full_desc += " (use a regular expression, surrounded by quotation marks)";
457  return set(name, s, full_desc.c_str());
458 }

◆ operator()() [1/2]

const boost::property_tree::ptree& operator() ( int  ,
const char * const  [] 
)

Unique parser accessible by the user of the class. It should be directly given argc and argv from the main function.

◆ operator()() [2/2]

const boost::property_tree::ptree & operator() ( int  argc,
const char * const  argv[] 
)

Unique parser accessible by the user of the class. It should be directly given argc and argv from the main function.

361 {
362  pt_conf.clear();
363  full_cmd.clear();
364  prefix.clear();
365 
366  try {
367  parse_helper(argc, argv);
368  parse_common(argc, argv);
369  parse_custom(argc, argv);
371 
372  if (steer & split && j > 1) full_cmd += " -j " + to_string(j);
373  if (steer & syst ) full_cmd += " -s";
374  if (steer & fill ) full_cmd += " -f";
375  else if (steer & Friend ) full_cmd += " -F";
376 
377  pt_conf.put<string>("history", full_cmd);
378  }
379  catch (const po::error& e) {
380  BOOST_THROW_EXCEPTION(po::error(e.what()));
381  }
382 
383  return pt_conf;
384 }

◆ output() [1/2]

Options& output ( const char *  ,
std::filesystem::path *  ,
const char *   
)

Member to add an output. It can be called several times in a row. This option should always be provided from the command line, and never via the config file.

Returns
the object itself, so that the arguments can be given in a row.

◆ output() [2/2]

Options & output ( const char *  name,
std::filesystem::path *  file,
const char *  desc 
)

Member to add an output. It can be called several times in a row. This option should always be provided from the command line, and never via the config file.

Returns
the object itself, so that the arguments can be given in a row.
Parameters
namename of the option, will be shown in helper
filepath pointer to file
descdescription, shown in helper too
461 {
462  if (stage > Stage::Output) {
463  full_cmd.clear();
464  BOOST_THROW_EXCEPTION(runtime_error("Not possible to add another output at this stage"));
465  }
466  stage = Stage::Output;
467 
468  const po::value_semantic * s =
469  po::value<fs::path>(file)->notifier(check_output)->required();
470  return set(name, s, desc);
471 }

◆ parse_common() [1/2]

void parse_common ( int  argc,
const char * const  argv[] 
)
private

Parser for generic options, such as the config (with -c) or slices. It should be directly given argc and argv from the main function.

238 {
239  po::options_description cmd_line;
240  cmd_line.add(common)
241  .add(hidden);
242 
243  po::command_line_parser parser{argc, argv};
244  parser.options(cmd_line)
245  .allow_unregistered();
246 
247  po::variables_map vm;
248  po::store(parser.run(), vm);
249  po::notify(vm);
250 
251  if (vm.count("config")) {
252  const string ext = config_file.extension();
253  if (ext == ".json") pt::read_json(config_file.c_str(), pt_conf);
254  else if (ext == ".info") pt::read_info(config_file.c_str(), pt_conf);
255  else if (ext == ".xml" ) {
256  pt::ptree userinfo;
257  pt::read_xml(config_file.c_str(), userinfo);
258  pt_conf = userinfo.get_child("userinfo");
259  }
260  else BOOST_THROW_EXCEPTION(fs::filesystem_error("Extension should be .json, .xml, or .info",
261  config_file, make_error_code(errc::invalid_argument)));
262  }
263 
264  if ((params & fill ) == fill && vm["fill" ].as<bool>()) steer = steer | fill ;
265  if ((params & Friend ) == Friend && vm["Friend" ].as<bool>()) steer = steer | Friend ;
266  if ((params & syst ) == syst && vm["syst" ].as<bool>()) steer = steer | syst ;
267  if ( vm["verbose"].as<bool>()) steer = steer | verbose;
268 }

◆ parse_common() [2/2]

void parse_common ( int  ,
const char * const  [] 
)
private

Parser for generic options, such as the config (with -c) or slices. It should be directly given argc and argv from the main function.

◆ parse_config() [1/2]

static void parse_config ( boost::property_tree::ptree &  ,
std::string  = "" 
)
static

Parse config if given. This method calls itself to parse the tree structure.

◆ parse_config() [2/2]

static void parse_config ( boost::property_tree::ptree &  ,
std::string  = "" 
)
static

Parse config if given. This method calls itself to parse the tree structure.

◆ parse_custom() [1/2]

void parse_custom ( int  ,
const char * const  [] 
)
private

Parser for options provided with args(), defined differently in each application. It should be directly given argc and argv from the main function.

◆ parse_custom() [2/2]

void parse_custom ( int  argc,
const char * const  argv[] 
)
private

Parser for options provided with args(), defined differently in each application. It should be directly given argc and argv from the main function.

271 {
272  po::options_description cmd_line;
273  cmd_line.add(common) // only here to avoid using `allow_unregistered()`
274  .add(hidden) // idem
275  .add(custom);
276 
277  po::command_line_parser parser{argc, argv};
278  parser.options(cmd_line)
279  .positional(pos_hide);
280 
281  po::variables_map vm;
282  po::parsed_options parsed = parser.run();
283  po::store(parsed, vm);
284 
285  // if no config file is given, then options are all required
286  if (!fs::exists(config_file))
287  for (auto& name: names) {
288  if (vm.count(name)) continue;
289  throw po::required_option(name);
290  }
291 
292  if (!prefix.empty())
293  full_cmd = prefix.string() + ' ';
294  full_cmd += argv[0];
295 
296  po::notify(vm); // necessary for config to be given the value from the cmd line
297  // note: `full_cmd` is modified here
298 
299  // first fetch values from config (some may be overwritten later)
300  for (auto& configpath: configpaths) {
301  auto arg = pt_conf.get_optional<string>(configpath);
302  if (!arg) continue;
303  al::erase_all(*arg, "\n");
304  al::erase_all(*arg, " ");
305  al::erase_all(*arg, "\"");
306  if (arg->empty()) continue;
307  full_cmd += ' ' + *arg;
308  }
309 
310  if (allow_unregistered()) { // garbage collector
311 
312  string configpath = configpaths.back();
313  if (!pt_conf.count(configpath))
314  pt_conf.add<string>(configpath, "");
315  auto& subtree = pt_conf.get_child(configpath);
316 
317  for (auto& item: subtree) {
318  string key = item.first,
319  value = item.second.get_value<string>();
320  if (key.empty() || key == "item")
321  full_cmd += ' ' + value;
322  else if (value.empty())
323  full_cmd += ' ' + key;
324  }
325 
326  vector<string> items = po::collect_unrecognized(parsed.options,
327  po::include_positional);
328  if (items.size() > *registered) {
329 
330  items.erase(items.begin(), items.begin() + *registered);
331 
332  for (auto& item: items) {
333  if (subtree.count(item)) continue;
334  subtree.add<string>(item, "");
335  full_cmd += ' ' + item;
336  }
337  }
338  } // end of garbage collector
339 
341 }

◆ parse_env_var() [1/6]

static const char* parse_env_var ( const char *  p)
inlinestatic

Parse environment variable in C-style string.

252  { return parse_env_var(std::string(p)).c_str(); }

◆ parse_env_var() [2/6]

static const char* parse_env_var ( const char *  p)
inlinestatic

Parse environment variable in C-style string.

252  { return parse_env_var(std::string(p)).c_str(); }

◆ parse_env_var() [3/6]

static std::filesystem::path parse_env_var ( const std::filesystem::path &  p)
inlinestatic

Parse environment variable in a path.

257  { return std::filesystem::path(parse_env_var(p.string())); }

◆ parse_env_var() [4/6]

static std::filesystem::path parse_env_var ( const std::filesystem::path &  p)
inlinestatic

Parse environment variable in a path.

257  { return std::filesystem::path(parse_env_var(p.string())); }

◆ parse_env_var() [5/6]

string parse_env_var ( std::string  s)
static

Parse environment variable in string. Adapted from https://codereview.stackexchange.com/questions/172644/c-environment-variable-expansion

Remarks
Curly brackets are needed (e.g. ${VAR}, not just $VAR)
74 {
75  static const regex env_re{R"--(\$\{([^}]+)\})--"};
76  smatch match;
77  while (regex_search(s, match, env_re)) {
78  auto const from = match[0];
79  auto const name = match[1].str();
80  auto const value = getenv(name.c_str());
81  if (!value)
82  BOOST_THROW_EXCEPTION(runtime_error("Environment variable ${" + name + "} does not exist."));
83  s.replace(from.first, from.second, value);
84  }
85  return s;
86 }

◆ parse_env_var() [6/6]

static std::string parse_env_var ( std::string  )
static

Parse environment variable in string. Adapted from https://codereview.stackexchange.com/questions/172644/c-environment-variable-expansion

Remarks
Curly brackets are needed (e.g. ${VAR}, not just $VAR)

◆ parse_helper() [1/2]

void parse_helper ( int  ,
const char * const  [] 
)
private

First parser that is called. As soon as -h is given, or if the command is run without options, then the helper is shown. It should be directly given argc and argv from the main function.

◆ parse_helper() [2/2]

void parse_helper ( int  argc,
const char * const  argv[] 
)
private

First parser that is called. As soon as -h is given, or if the command is run without options, then the helper is shown. It should be directly given argc and argv from the main function.

172 {
173  po::command_line_parser parser{argc, argv};
174  parser.options(helper) // parse only the helper, but no other option at this stage
175  .allow_unregistered(); // ignore unregistered options
176 
177  // defines actions
178  po::variables_map vm;
179  po::store(parser.run(), vm);
180  po::notify(vm); // necessary for config to be given the value from the cmd line
181 
182  if (vm.count("help") || argc == 1) {
183  fs::path executable = argv[0];
184  cout << bold << executable.filename().string() << synopsis << def
185  << "\nwhere";
186  for (const auto& option: custom.options())
187  cout << '\t' << option->long_name() << " = " << option->description() << '\n';
188  }
189 
190  if (vm.count("help")) {
191  po::options_description cmd_line;
192  cmd_line.add(helper)
193  .add(common); // only used to display the helper message, but not to parse
194  cout << cmd_line << endl;
195  }
196 
197  if (vm.count("tutorial"))
198  cout << wrap_paragraph(tutorial) << '\n'
199  << wrap_paragraph("General remarks: "
200  "unless stated otherwise, all options except the input(s) and output files "
201  "may be given either from the command line or from such a config. Unused "
202  "options in the config are simply ignored. The `flags` should be set at "
203  "the creation of the n-tuples; the `corrections` should be added step "
204  "by step (typically a couple of corrections per executable at most). How "
205  "the config is parsed may change from executable to executable. This "
206  "example uses the Boost INFO format, but JSON and XML formats are also "
207  "possible. It is possible to extract such a config from an existing ROOT "
208  "file by using `getMetaInfo`. Arguments from command line overwrite "
209  "arguments from the config.") << endl;
210 
211  if (vm.count("git"))
212  cout << commit() << endl;
213 
214  if (vm.count("example")) {
215  if (!fs::exists(example))
216  BOOST_THROW_EXCEPTION(fs::filesystem_error("The example could not be found",
217  example, make_error_code(errc::no_such_file_or_directory)));
218  pt::read_info(example, pt_conf);
219 
220  pt::ptree reduced_config;
221  for (auto const& key: configpaths) {
222  auto value = pt_conf.get<string>(key);
223  reduced_config.add<string>(key, value);
224  }
225 
226  stringstream ss;
227  write_info(ss, reduced_config);
228  string str = ss.str();
229  al::erase_all(str, "\"\"");
230  cout << str << flush;
231  }
232 
233  if (!vm.empty() || argc == 1)
234  exit(EXIT_SUCCESS);
235 }

◆ put() [1/2]

std::function<void(T)> put ( const char *  configpath)
inlineprivate

Helper to call boost::property_tree::put in Darwin::Toos::Options::args.

Returns
true if Options::registered has been initialised.
Parameters
configpathpath in config file
125  {
126  return [configpath,this](T value) { pt_conf.put<T>(configpath, value); };
127  }

◆ put() [2/2]

std::function<void(T)> put ( const char *  configpath)
inlineprivate

Helper to call boost::property_tree::put in Darwin::Toos::Options::args.

Returns
true if Options::registered has been initialised.
Parameters
configpathpath in config file
125  {
126  return [configpath,this](T value) { pt_conf.put<T>(configpath, value); };
127  }

◆ set() [1/2]

Options& set ( const char *  ,
const boost::program_options::value_semantic *  ,
const char *   
)
private

Generic code to add options. It is called internally by Options::input(), Options::output(), and Options::args().

Returns
the object itself, so that the arguments can be given in a row.

◆ set() [2/2]

Options & set ( const char *  name,
const boost::program_options::value_semantic *  s,
const char *  desc 
)
private

Generic code to add options. It is called internally by Options::input(), Options::output(), and Options::args().

Returns
the object itself, so that the arguments can be given in a row.
Parameters
nameoptions name
shttps://www.boost.org/doc/libs/1_80_0/doc/html/boost/program_options/value_semantic.html
descdescription (for helper)
387 {
388  if (allow_unregistered())
389  BOOST_THROW_EXCEPTION(invalid_argument("Once `Options::args()` has been called, "
390  "it is no longer possible to add any further options."));
391  synopsis += ' '; synopsis += name;
392  pos_hide.add(name, 1);
393  custom.add_options()(name, s, desc);
394  return *this;
395 }

◆ slice() [1/2]

std::pair<unsigned, unsigned> slice ( ) const
inline

Compactify slice information into a pair.

279  {
280  if (!(params & split))
281  BOOST_THROW_EXCEPTION(std::invalid_argument("No splitting of the input file."));
282  return std::make_pair(j,k);
283  }

◆ slice() [2/2]

std::pair<unsigned, unsigned> slice ( ) const
inline

Compactify slice information into a pair.

279  {
280  if (!(params & split))
281  BOOST_THROW_EXCEPTION(std::invalid_argument("No splitting of the input file."));
282  return std::make_pair(j,k);
283  }

◆ steering() [1/2]

int steering ( ) const
inline

Steering information for running of executable.

274 { return steer; }

◆ steering() [2/2]

int steering ( ) const
inline

Steering information for running of executable.

274 { return steer; }

Member Data Documentation

◆ common

boost::program_options::options_description common
private

generic + explicit options like --verbose

◆ config_file

std::filesystem::path config_file
private

path to INFO, JSON, or XML config file

◆ configpaths

std::vector< std::string > configpaths
private

path to the options in config (except for I/O)

◆ custom

boost::program_options::options_description custom
private

for positional arguments, depending on the actual command

◆ example

const std::filesystem::path example
private

path to example config

◆ full_cmd

static std::string full_cmd
static

extended version of the command for reproducibility

◆ helper

boost::program_options::options_description helper
private

to display the helper

◆ hidden

boost::program_options::options_description hidden
private

hidden interface (not for lambda user)

◆ j

unsigned j
private

slices

slices

◆ k

unsigned k
private

slice index

◆ m_commit

const std::string m_commit
private

Commit SHA for –git.

◆ names

std::vector< std::string > names
private

names of the different options (shown in synopsis)

◆ params

const int params
private

input parameters to interpret explicit options

◆ pos_hide

boost::program_options::positional_options_description pos_hide
private

parser for positional arguments

◆ prefix

static std::filesystem::path prefix
staticprivate

prefix command to steer -j and -k

◆ pt_conf

boost::property_tree::ptree pt_conf
private

internal config obtained from arugments and input config

◆ registered

std::optional< unsigned > registered
private

collect the number of registered options (only if Options::args has been called before)

◆ stage

Stage stage
private

internal stage

◆ steer

int steer
private

output parameters for code executation

◆ synopsis

std::string synopsis
private

stores the clean version of the command, displayed with -h

◆ tutorial

const std::string tutorial
private

define in constructor, shown with option -t


The documentation for this class was generated from the following files:
DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.name
name
Definition: DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.py:48
Darwin::Tools::Options::parse_env_var
static std::string parse_env_var(std::string)
Definition: Options.cc:73
Ntupliser_cfg.cerr
cerr
Definition: Ntupliser_cfg.py:93
Darwin::Tools::Options::check_input
static void check_input(const std::filesystem::path &)
Definition: Options.cc:37
Darwin::Tools::Options::tutorial
const std::string tutorial
define in constructor, shown with option -t
Definition: Options.h:88
Darwin::Tools::Options::Options
Options()=delete
No default constructor is allowed.
DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.options
options
Definition: DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.py:41
Darwin::Tools::Options::custom
boost::program_options::options_description custom
for positional arguments, depending on the actual command
Definition: Options.h:62
Darwin::Tools::syst
@ syst
activate -s to systematic uncertainties
Definition: Options.h:30
Darwin::Tools::verbose
@ verbose
bit for debug mode (-v is always available)
Definition: Options.h:31
Step::def
static const char * def
Definition: Step.h:36
Darwin::Tools::none
@ none
default (for simple executables)
Definition: Options.h:25
Ntupliser_cfg.paths
paths
Definition: Ntupliser_cfg.py:299
Darwin::Tools::Options::inputs
Options & inputs(const char *, std::vector< std::filesystem::path > *, const char *)
Definition: Options.cc:421
Darwin::Tools::Options::allow_unregistered
bool allow_unregistered() const
Definition: Options.h:133
Darwin::Tools::Options::output
Options & output(const char *, std::filesystem::path *, const char *)
Definition: Options.cc:460
Darwin::Tools::Options::args
Options & args(const char *name, const char *configpath, const char *desc)
Definition: Options.cc:473
Ntupliser_cfg.p
p
Definition: Ntupliser_cfg.py:361
Darwin::Tools::Options::check_output
static void check_output(const std::filesystem::path &)
Definition: Options.cc:50
Darwin::Tools::Options::Input
@ Input
first the inputs
Definition: Options.h:141
Darwin::Tools::Options::hidden
boost::program_options::options_description hidden
hidden interface (not for lambda user)
Definition: Options.h:59
Darwin::Tools::Options::params
const int params
input parameters to interpret explicit options
Definition: Options.h:149
jercExample.key
string key
Definition: jercExample.py:109
Darwin::Tools::Options::input
Options & input(const char *, std::filesystem::path *, const char *)
Definition: Options.cc:397
compareFiles.files
files
Definition: compareFiles.py:125
Darwin::Tools::Options::synopsis
std::string synopsis
stores the clean version of the command, displayed with -h
Definition: Options.h:89
Darwin::Tools::Options::pos_hide
boost::program_options::positional_options_description pos_hide
parser for positional arguments
Definition: Options.h:63
Darwin::Tools::Options::parse_config
static void parse_config(boost::property_tree::ptree &, std::string="")
Parse config if given. This method calls itself to parse the tree structure.
Darwin::Tools::Options::steer
int steer
output parameters for code executation
Definition: Options.h:151
Darwin::Tools::Options::commit
auto commit() const
Git commit information.
Definition: Options.h:270
Darwin::Tools::Options::Output
@ Output
then the outputs (inputs are no longer allowed)
Definition: Options.h:142
Darwin::Tools::Options::parse_common
void parse_common(int, const char *const [])
Definition: Options.cc:237
Darwin::Tools::fill
@ fill
activate -f to fill the tree
Definition: Options.h:28
prefix
Definition: prefix.py:1
Darwin::Tools::Options::parse_helper
void parse_helper(int, const char *const [])
Definition: Options.cc:171
Step::red
static const char * red
Definition: Step.h:34
cmd
cmd
Definition: Core-cfgcmd.txt:1
Darwin::Tools::Options::names
std::vector< std::string > names
names of the different options (shown in synopsis)
Definition: Options.h:90
Darwin::Tools::split
@ split
activate -k and -j to define slice
Definition: Options.h:27
Ntupliser_cfg.config
config
Definition: Ntupliser_cfg.py:263
orange
static const char * orange
Definition: colours.h:6
Darwin::Tools::Options::k
unsigned k
slice index
Definition: Options.h:154
Darwin::Tools::Options::set
Options & set(const char *, const boost::program_options::value_semantic *, const char *)
Definition: Options.cc:386
wrap_paragraph
string wrap_paragraph(const string &text)
Definition: Options.cc:137
Darwin::Tools::config
@ config
activate -c option to provide config file
Definition: Options.h:26
Darwin::Tools::Options::Args
@ Args
finally the remaining arguments / garbage collector (must be very last)
Definition: Options.h:144
Darwin::Tools::Options::arg
Options & arg(const char *name, const char *configpath, const char *desc)
Definition: Options.h:212
Darwin::Tools::Options::stage
Stage stage
internal stage
Definition: Options.h:147
DARWIN_VERSION
#define DARWIN_VERSION
Definition: version.h:1
Darwin::Tools::Options::registered
std::optional< unsigned > registered
collect the number of registered options (only if Options::args has been called before)
Definition: Options.h:129
Darwin::Tools::Options::m_commit
const std::string m_commit
Commit SHA for –git.
Definition: Options.h:150
Darwin::Tools::Options::helper
boost::program_options::options_description helper
to display the helper
Definition: Options.h:60
Darwin::Tools::Options::j
unsigned j
Definition: Options.h:153
Darwin::Tools::Options::parse_custom
void parse_custom(int, const char *const [])
Definition: Options.cc:270
Darwin::Tools::Options::config_file
std::filesystem::path config_file
path to INFO, JSON, or XML config file
Definition: Options.h:85
compareFiles.parser
parser
Definition: compareFiles.py:118
DAS::Normalisation::match
DAS::FourVector match(const DAS::FourVector &jet, const std::vector< DAS::FourVector > *hltJets)
Definition: match.h:7
set_mute
void set_mute(bool flag)
Function used by Boost::PO to disable standard error.
Definition: Options.cc:90
Darwin::Tools::Options::exec
std::string exec(const std::string &)
Definition: Options.cc:407
Darwin::Tools::Friend
@ Friend
activate -F to only fill the new branches
Definition: Options.h:29
Darwin::Tools::Options::Arg
@ Arg
then the registered arguments (inputs and outputs no longer allowed)
Definition: Options.h:143
Darwin::Tools::Options::configpaths
std::vector< std::string > configpaths
path to the options in config (except for I/O)
Definition: Options.h:91
Darwin::Tools::Options::full_cmd
static std::string full_cmd
extended version of the command for reproducibility
Definition: Options.h:266
Darwin::Tools::Options::pt_conf
boost::property_tree::ptree pt_conf
internal config obtained from arugments and input config
Definition: Options.h:64
Darwin::Tools::Options::common
boost::program_options::options_description common
generic + explicit options like --verbose
Definition: Options.h:61
Darwin::Tools::Options::example
const std::filesystem::path example
path to example config
Definition: Options.h:66
Step::bold
static const char * bold
Definition: Step.h:35