parse_command_line.hpp
Go to the documentation of this file.
1 
13 #ifndef MLPACK_BINDINGS_CLI_PARSE_COMMAND_LINE_HPP
14 #define MLPACK_BINDINGS_CLI_PARSE_COMMAND_LINE_HPP
15 
16 #include <mlpack/core.hpp>
17 #include "print_help.hpp"
18 
19 #include "third_party/CLI/CLI11.hpp"
20 
21 namespace mlpack {
22 namespace bindings {
23 namespace cli {
24 
34  int argc,
35  char** argv,
36  const char* bindingName = "")
37 {
38  // First, we need to build the CLI11 variables for parsing.
39  CLI::App app;
40  app.set_help_flag();
41 
42  // Get an empty Params object that will hold all of the parameters for this
43  // call.
44  mlpack::util::Params params = (std::string(bindingName) == "") ?
45  IO::Parameters(STRINGIFY(BINDING_NAME)) :
46  IO::Parameters(bindingName);
47 
48  // Go through list of options in order to add them.
49  std::map<std::string, util::ParamData>& parameters = params.Parameters();
50  using ItType = std::map<std::string, util::ParamData>::iterator;
51 
52  for (ItType it = parameters.begin(); it != parameters.end(); ++it)
53  {
54  // Add the parameter to desc.
55  util::ParamData& d = it->second;
56  params.functionMap[d.tname]["AddToCLI11"](d, NULL, (void*) &app);
57  }
58 
59  // Parse the command line, then place the values in the right place.
60  try
61  {
62  try
63  {
64  app.parse(argc, argv);
65  }
66  catch (const CLI::ArgumentMismatch& err)
67  {
68  Log::Fatal << "An option is defined multiple times: "
69  << app.exit(err) << std::endl;
70  }
71  catch (const CLI::OptionNotFound& onf)
72  {
73  Log::Fatal << "Required option --" << app.exit(onf) << "!" << std::endl;
74  }
75  catch (const CLI::ParseError& pe)
76  {
77  Log::Fatal << app.exit(pe) << std::endl;
78  }
79  }
80  catch (std::exception& ex)
81  {
82  Log::Fatal << "Caught exception from parsing command line: "
83  << ex.what() << std::endl;
84  }
85 
86  // If the user specified any of the default options (--help, --version, or
87  // --info), handle those.
88 
89  // --version is prioritized over --help.
90  if (params.Has("version"))
91  {
92  std::cout << params.Doc().name << ": part of " << util::GetVersion() << "."
93  << std::endl;
94  exit(0); // Don't do anything else.
95  }
96 
97  // Default help message.
98  if (params.Has("help"))
99  {
100  Log::Info.ignoreInput = false;
101  PrintHelp(params);
102  exit(0); // The user doesn't want to run the program, he wants help.
103  }
104 
105  // Info on a specific parameter.
106  if (params.Has("info"))
107  {
108  Log::Info.ignoreInput = false;
109  std::string str = params.Get<std::string>("info");
110 
111  // The info node should always be there, but the user may not have specified
112  // anything.
113  if (str != "")
114  {
115  PrintHelp(params, str);
116  exit(0);
117  }
118 
119  // Otherwise just print the generalized help.
120  PrintHelp(params);
121  exit(0);
122  }
123 
124  // Print whether or not we have debugging symbols. This won't show anything
125  // if we have not compiled in debugging mode.
126  Log::Debug << "Compiled with debugging symbols." << std::endl;
127 
128  if (params.Has("verbose"))
129  {
130  // Give [INFO ] output.
131  Log::Info.ignoreInput = false;
132  }
133 
134  // Now, issue an error if we forgot any required options.
135  for (std::map<std::string, util::ParamData>::const_iterator iter =
136  parameters.begin(); iter != parameters.end(); ++iter)
137  {
138  util::ParamData d = iter->second;
139  if (d.required)
140  {
141  // CLI11 expects the parameter name to have "--" prepended.
142  std::string cliName;
143  params.functionMap[d.tname]["MapParameterName"](d, NULL,
144  (void*) &cliName);
145  cliName = "--" + cliName;
146 
147  if (!app.count(cliName))
148  {
149  Log::Fatal << "Required option " << cliName << " is undefined."
150  << std::endl;
151  }
152  }
153  }
154 
155  return params;
156 }
157 
158 } // namespace cli
159 } // namespace bindings
160 } // namespace mlpack
161 
162 #endif
void PrintHelp(util::Params &params, const std::string &param="")
Print the help for the given parameter.
mlpack::util::Params ParseCommandLine(int argc, char **argv, const char *bindingName="")
Parse the command line, setting all of the options inside of the CLI object to their appropriate give...
const BindingDetails & Doc() const
Get the binding details.
Definition: params.hpp:104
Linear algebra utility functions, generally performed on matrices or vectors.
static util::Params Parameters(const std::string &bindingName)
Return a new Params object initialized with all the parameters of the binding bindingName.
static MLPACK_EXPORT util::NullOutStream Debug
MLPACK_EXPORT is required for global variables, so that they are properly exported by the Windows com...
Definition: log.hpp:79
bool ignoreInput
Discards input, prints nothing if true.
static MLPACK_EXPORT util::PrefixedOutStream Fatal
Prints fatal messages prefixed with [FATAL], then terminates the program.
Definition: log.hpp:90
static MLPACK_EXPORT util::PrefixedOutStream Info
Prints informational messages if –verbose is specified, prefixed with [INFO ].
Definition: log.hpp:84
std::string GetVersion()
This will return either "mlpack x.y.z" or "mlpack master-XXXXXXX" depending on whether or not this is...
std::map< std::string, ParamData > & Parameters()
Get the map of parameters.
Definition: params.hpp:96
This structure holds all of the information about a single parameter, including its value (which is s...
Definition: param_data.hpp:52
T & Get(const std::string &identifier)
Get the value of type T found for the parameter specified by identifier.
bool Has(const std::string &identifier) const
Return true if the specified parameter was given.
std::string tname
Type information of this parameter.
Definition: param_data.hpp:61
Include all of the base components required to write mlpack methods, and the main mlpack Doxygen docu...
bool required
True if this option is required.
Definition: param_data.hpp:71
FunctionMapType functionMap
Map for functions and types.
Definition: params.hpp:130
std::string name
User-friendly name of the binding.
The Params class holds all information about the parameters passed to a specific binding.
Definition: params.hpp:20