Empirical
ArgManager.h
Go to the documentation of this file.
1 // This file is part of Empirical, https://github.com/devosoft/Empirical
2 // Copyright (C) Michigan State University, 2016.
3 // Released under the MIT Software license; see doc/LICENSE
4 //
5 // A simple ArgManager tool for sythesizing command-line arguments and config files.
6 
7 
8 #ifndef EMP_CL_ARG_MANAGER_H
9 #define EMP_CL_ARG_MANAGER_H
10 
11 #include <string>
12 #include <vector>
13 
14 #include "command_line.h"
15 #include "config.h"
16 
17 namespace emp {
18  namespace cl {
19 
20  class ArgManager {
21  private:
23  emp::vector<std::string> arg_names;
24  emp::vector<std::string> arg_descs;
25 
26  public:
27  ArgManager() : args(), arg_names(), arg_descs() { ; }
28  ArgManager(int argc, char* argv[])
29  : args(args_to_strings(argc, argv)), arg_names(), arg_descs() { ; }
30  ~ArgManager() { ; }
31 
32  size_t size() const { return args.size(); }
33  auto begin() -> decltype(args.begin()) { return args.begin(); }
34  auto end() -> decltype(args.end()) { return args.end(); }
35  std::string & operator[](size_t i) { return args[i]; }
36  const std::string & operator[](size_t i) const { return args[i]; }
37 
38  // UseArg takes a name, a variable and an optional description. If the name exists,
39  // it uses the next argument to change the value of the variable.
40  // Return 1 if found, 0 if not found, and -1 if error (no value provided)
41  template <typename T>
42  int UseArg(const std::string & name, T & var, const std::string & desc="") {
43  arg_names.push_back(name);
44  arg_descs.push_back(desc);
45  return use_arg_value(args, name, var);
46  }
47 
48  // UseArg can also take a config object and a name, and use the argument to set the
49  // config object.
50  int UseArg(const std::string & name, Config & config, const std::string & cfg_name,
51  const std::string & desc="") {
52  arg_names.push_back(name);
53  arg_descs.push_back(desc);
54  std::string var;
55  bool rv = use_arg_value(args, name, var);
56  if (rv==1) config.Set(cfg_name, var);
57  return rv;
58  }
59 
60  // UseFlag take a name and an optional description. If the name exists, return true,
61  // otherwise return false.
62  bool UseFlag(const std::string & name, const std::string & desc="") {
63  arg_names.push_back(name);
64  arg_descs.push_back(desc);
65  return use_flag(args, name);
66  }
67 
68  void PrintHelp(std::ostream & os) const {
69  size_t max_name_size = 0;
70  for (const auto & name : arg_names) {
71  if (max_name_size < name.size()) max_name_size = name.size();
72  }
73  for (size_t i = 0; i < arg_names.size(); i++) {
74  os << arg_names[i]
75  << std::string(max_name_size + 1 - arg_names[i].size(), ' ')
76  << arg_descs[i]
77  << std::endl;
78  }
79  }
80 
81  // Test Unknown sees if there are any unprocessed arguments, and if so, gives and error.
82  // Return bool for "should program proceed" (i.e., true=continue, false=exit).
83  bool TestUnknown(std::ostream & os=std::cerr) const {
84  if (args.size() > 1) {
85  os << "Unknown args:";
86  for (size_t i = 1; i < args.size(); i++) os << " " << args[i];
87  os << std::endl;
88  PrintHelp(os);
89  return false;
90  }
91  return true;
92  }
93 
94  // ProcessConfigOptions converts settings from a configure object to command-line arguments.
95  // Return bool for "should program proceed" (i.e., true=continue, false=exit).
96  bool ProcessConfigOptions(Config & config, std::ostream & os,
97  const std::string & cfg_file="",
98  const std::string & macro_file="") {
99  for (auto e : config) {
100  auto entry = e.second;
101  std::string desc = emp::to_string( entry->GetDescription(),
102  " (type=", entry->GetType(), "; default=", entry->GetDefault(), ')' );
103  UseArg(to_string('-', entry->GetName()), config, entry->GetName(), desc);
104  }
105 
106  bool print_help = UseFlag("--help", "Print help information.");
107  bool create_config = cfg_file.size() && UseFlag("--gen", "Generate configuration file.");
108  bool const_macros = macro_file.size() && UseFlag("--const", "Generate const version of macros file.");
109 
110  if (print_help) { PrintHelp(os); return false; }
111  if (create_config) { config.Write(cfg_file); return false; }
112  if (const_macros) { config.WriteMacros(macro_file, true); return false; }
113 
114  return true;
115  }
116 
117  };
118 
119 
120  }
121 }
122 
123 #endif
bool UseFlag(const std::string &name, const std::string &desc="")
Definition: ArgManager.h:62
std::string to_string(ALL_TYPES &&...all_values)
Definition: string_utils.h:511
bool ProcessConfigOptions(Config &config, std::ostream &os, const std::string &cfg_file="", const std::string &macro_file="")
Definition: ArgManager.h:96
iterator end() noexcept
Definition: vector.h:155
Master configuration class that manages all of the settings.
Definition: config.h:113
int UseArg(const std::string &name, Config &config, const std::string &cfg_name, const std::string &desc="")
Definition: ArgManager.h:50
Definition: ArgManager.h:20
Config & Set(std::string setting_name, const std::string &new_value, const std::string &in_desc="")
Definition: config.h:403
int use_arg_value(emp::vector< std::string > &args, const std::string &pattern, Ts &...vars)
Definition: command_line.h:114
Maintains a set of configuration options.
void push_back(PB_Ts &&...args)
Definition: vector.h:189
ArgManager(int argc, char *argv[])
Definition: ArgManager.h:28
bool use_flag(emp::vector< std::string > &args, const std::string &pattern)
Definition: command_line.h:66
size_t size() const
Definition: vector.h:151
size_t size() const
Definition: ArgManager.h:32
~ArgManager()
Definition: ArgManager.h:30
int UseArg(const std::string &name, T &var, const std::string &desc="")
Definition: ArgManager.h:42
static const PrintStr endl("<br>")
Pre-define emp::endl to insert a "<br>" and thus acting like a newline.
emp::vector< std::string > args_to_strings(int argc, char *argv[])
Definition: command_line.h:44
bool TestUnknown(std::ostream &os=std::cerr) const
Definition: ArgManager.h:83
iterator begin() noexcept
Definition: vector.h:153
void PrintHelp(std::ostream &os) const
Definition: ArgManager.h:68
If we are in emscripten, make sure to include the header.
Definition: array.h:37
ArgManager()
Definition: ArgManager.h:27
std::string & operator[](size_t i)
Definition: ArgManager.h:35
const std::string & operator[](size_t i) const
Definition: ArgManager.h:36
auto end() -> decltype(args.end())
Definition: ArgManager.h:34
auto begin() -> decltype(args.begin())
Definition: ArgManager.h:33