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 
25 // Add default parameters that are included in every program.
26 PARAM_FLAG("help", "Default help info.", "h");
27 PARAM_STRING_IN("info", "Print help on a specific option.", "", "");
28 PARAM_FLAG("verbose", "Display informational messages and the full list of "
29  "parameters and timers at the end of execution.", "v");
30 PARAM_FLAG("version", "Display the version of mlpack.", "V");
31 
36 void ParseCommandLine(int argc, char** argv)
37 {
38  // First, we need to build the CLI11 variables for parsing.
39  CLI::App app;
40  app.set_help_flag();
41 
42  // Go through list of options in order to add them.
43  std::map<std::string, util::ParamData>& parameters = IO::Parameters();
44  using ItType = std::map<std::string, util::ParamData>::iterator;
45 
46  for (ItType it = parameters.begin(); it != parameters.end(); ++it)
47  {
48  // Add the parameter to desc.
49  util::ParamData& d = it->second;
50  IO::GetSingleton().functionMap[d.tname]["AddToCLI11"](d, NULL, (void*)
51  &app);
52  }
53 
54  // Mark that we did parsing.
55  IO::GetSingleton().didParse = true;
56 
57  // Parse the command line, then place the values in the right place.
58  try
59  {
60  try
61  {
62  app.parse(argc, argv);
63  }
64  catch (const CLI::ArgumentMismatch& err)
65  {
66  Log::Fatal << "An option is defined multiple times: "
67  << app.exit(err) << std::endl;
68  }
69  catch (const CLI::OptionNotFound& onf)
70  {
71  Log::Fatal << "Required option --" << app.exit(onf) << "!" << std::endl;
72  }
73  catch (const CLI::ParseError& pe)
74  {
75  Log::Fatal << app.exit(pe) << std::endl;
76  }
77  }
78  catch (std::exception& ex)
79  {
80  Log::Fatal << "Caught exception from parsing command line: "
81  << ex.what() << std::endl;
82  }
83 
84  // If the user specified any of the default options (--help, --version, or
85  // --info), handle those.
86 
87  // --version is prioritized over --help.
88  if (IO::HasParam("version"))
89  {
90  std::cout << IO::GetSingleton().ProgramName() << ": part of "
91  << util::GetVersion() << "." << std::endl;
92  exit(0); // Don't do anything else.
93  }
94 
95  // Default help message.
96  if (IO::HasParam("help"))
97  {
98  Log::Info.ignoreInput = false;
99  PrintHelp();
100  exit(0); // The user doesn't want to run the program, he wants help.
101  }
102 
103  // Info on a specific parameter.
104  if (IO::HasParam("info"))
105  {
106  Log::Info.ignoreInput = false;
107  std::string str = IO::GetParam<std::string>("info");
108 
109  // The info node should always be there, but the user may not have specified
110  // anything.
111  if (str != "")
112  {
113  PrintHelp(str);
114  exit(0);
115  }
116 
117  // Otherwise just print the generalized help.
118  PrintHelp();
119  exit(0);
120  }
121 
122  // Print whether or not we have debugging symbols. This won't show anything
123  // if we have not compiled in debugging mode.
124  Log::Debug << "Compiled with debugging symbols." << std::endl;
125 
126  if (IO::HasParam("verbose"))
127  {
128  // Give [INFO ] output.
129  Log::Info.ignoreInput = false;
130  }
131 
132  // Now, issue an error if we forgot any required options.
133  for (std::map<std::string, util::ParamData>::const_iterator iter =
134  parameters.begin(); iter != parameters.end(); ++iter)
135  {
136  util::ParamData d = iter->second;
137  if (d.required)
138  {
139  // CLI11 expects the parameter name to have "--" prepended.
140  std::string cliName;
141  IO::GetSingleton().functionMap[d.tname]["MapParameterName"](d, NULL,
142  (void*) &cliName);
143  cliName = "--" + cliName;
144 
145  if (!app.count(cliName))
146  {
147  Log::Fatal << "Required option " << cliName << " is undefined."
148  << std::endl;
149  }
150  }
151  }
152 }
153 
154 } // namespace cli
155 } // namespace bindings
156 } // namespace mlpack
157 
158 #endif
Linear algebra utility functions, generally performed on matrices or vectors.
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.
bool didParse
True, if IO was used to parse command line options.
Definition: io.hpp:322
static MLPACK_EXPORT util::PrefixedOutStream Fatal
Prints fatal messages prefixed with [FATAL], then terminates the program.
Definition: log.hpp:90
void ParseCommandLine(int argc, char **argv)
Parse the command line, setting all of the options inside of the CLI object to their appropriate give...
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...
This structure holds all of the information about a single parameter, including its value (which is s...
Definition: param_data.hpp:52
static IO & GetSingleton()
Retrieve the singleton.
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...
static bool HasParam(const std::string &identifier)
See if the specified flag was found while parsing.
bool required
True if this option is required.
Definition: param_data.hpp:71
void PrintHelp(const std::string &param="")
Print the help for the given parameter.
FunctionMapType functionMap
Definition: io.hpp:313
PARAM_FLAG("help", "Default help info.", "h")
PARAM_STRING_IN("info", "Print help on a specific option.", "", "")
static std::map< std::string, util::ParamData > & Parameters()
Return a modifiable list of parameters that IO knows about.
static std::string ProgramName()
Get the program name as set by the BINDING_NAME() macro.