www.mooseframework.org
CommandLine.h
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #pragma once
11 
12 // Moose Includes
13 #include "MooseError.h"
14 #include "Conversion.h"
15 #include "MooseEnum.h"
16 #include "InputParameters.h"
17 
18 #include "libmesh/parallel.h"
19 
20 // C++ includes
21 #include <vector>
22 #include <string>
23 #include <map>
24 #include <memory>
25 #include <set>
26 
27 // Forward Declaration
28 class InputParameters;
29 
34 {
35 public:
37 
38  struct Option
39  {
40  std::string description;
41  std::vector<std::string> cli_syntax;
42  bool required;
45  std::vector<std::string> cli_switch;
46  };
47 
48  CommandLine();
49  CommandLine(int argc, char * argv[]);
50  CommandLine(const CommandLine & other);
51  virtual ~CommandLine();
52 
53  void addArguments(int argc, char * argv[]);
54  void addArgument(std::string);
55 
66  void initForMultiApp(const std::string &);
67 
71  const std::vector<std::string> & getArguments() { return _argv; }
72 
74 
75  void populateInputParams(InputParameters & params);
76 
77  void addOption(const std::string & name, Option cli_opt);
78 
84  bool search(const std::string & option_name);
85 
86  template <typename T>
87  bool search(const std::string & option_name, T & argument);
88 
89  template <typename T>
90  bool search(const std::string & option_name, std::vector<T> & argument);
91 
96  std::vector<std::string>::const_iterator find(const std::string & option_name) const;
97 
98  // Return an iterator to the beginning of the container of CLI options
99  std::vector<std::string>::const_iterator begin() const;
100 
101  // Return an iterator to the beginning of the container of CLI options
102  std::vector<std::string>::const_iterator end() const;
103 
107  std::string getExecutableName() const;
108 
112  std::string getExecutableNameBase() const;
113 
117  void printUsage() const;
118 
119  // this needs to be tracked here because CommandLine has a global shared instance across all
120  // multiapps/subapps - and we need to track used/unused CLI hit params globally so we know
121  // which ones don't get used - this can't happen at the within-app level.
122  void markHitParamUsed(int argi) { _used_hiti.insert(argi); };
123  void markHitParam(int argi) { _hiti.insert(argi); }
124 
125  // Returns the unused CLI hit parameters. This accounts for different CLI params being used
126  // by different processes in a process-parallel run, so the communicator is needed to rendezvous
127  // which parameters have been used between them all.
128  std::set<int> unused(const Parallel::Communicator & comm)
129  {
130  comm.set_union(_hiti);
131  comm.set_union(_used_hiti);
132 
133  std::set<int> unused;
134  for (int i : _hiti)
135  {
136  if (_used_hiti.count(i) == 0)
137  unused.insert(i);
138  }
139  return unused;
140  }
141 
142 protected:
146  template <typename T>
147  void setArgument(std::stringstream & stream, T & argument);
148 
152  template <typename T>
153  void setArgument(std::stringstream & stream, T & argument, const std::string & cli_switch);
154 
156  std::map<std::string, Option> _cli_options;
157 
158 private:
160  std::set<int> _used_hiti;
161 
163  std::set<int> _hiti;
164 
166  std::vector<std::string> _argv;
167 
168  std::vector<std::string> _args;
169 };
170 
171 template <typename T>
172 void
173 CommandLine::setArgument(std::stringstream & stream, T & argument)
174 {
175  stream >> argument;
176 }
177 
178 template <typename T>
179 void
180 CommandLine::setArgument(std::stringstream & stream, T & argument, const std::string & cli_switch)
181 {
182  // Keep track of and change the throw on error characteristics so that
183  // we can catch parsing errors for the argument
184  const auto throw_on_error_orig = Moose::_throw_on_error;
185  Moose::_throw_on_error = true;
186 
187  const auto raw_value = stream.str();
188  try
189  {
190  setArgument(stream, argument);
191  }
192  catch (std::exception & e)
193  {
194  Moose::_throw_on_error = throw_on_error_orig;
195  mooseError("While parsing command line argument '",
196  cli_switch,
197  "' with value '",
198  raw_value,
199  "':\n\n",
200  e.what());
201  }
202 
203  Moose::_throw_on_error = throw_on_error_orig;
204 }
205 
206 // Specialization for std::string
207 template <>
208 void CommandLine::setArgument<std::string>(std::stringstream & stream, std::string & argument);
209 // Specialization for MooseEnum
210 template <>
211 void CommandLine::setArgument<MooseEnum>(std::stringstream & stream, MooseEnum & argument);
212 
213 template <typename T>
214 bool
215 CommandLine::search(const std::string & option_name, T & argument)
216 {
217  if (auto pos = _cli_options.find(option_name); pos != _cli_options.end())
218  {
219  const auto & option = pos->second;
220  for (const auto & cli_switch : option.cli_switch)
221  for (const auto arg_i : index_range(_args))
222  {
223  const auto & arg = _args[arg_i];
224 
225  if (arg == cli_switch)
226  {
227  // "Flag" CLI options are added as Boolean types, when we see them
228  // we set the Boolean argument to true
229  if (option.argument_type == ArgumentType::NONE)
230  argument = true;
231  else if (arg_i + 1 < _args.size())
232  {
233  std::stringstream ss;
234  ss << _args[arg_i + 1];
235 
236  setArgument(ss, argument, cli_switch);
237  }
238  else if (option.argument_type == ArgumentType::REQUIRED)
239  {
240  mooseError("The command line argument '",
241  cli_switch,
242  "' requires a value and one was not provided.");
243  }
244  return true;
245  }
246  }
247 
248  if (pos->second.required)
249  {
250  Moose::err << "Required parameter: " << option_name << " missing\n";
251  printUsage();
252  }
253  return false;
254  }
255  mooseError("Unrecognized option name");
256 }
257 
258 template <typename T>
259 bool
260 CommandLine::search(const std::string & option_name, std::vector<T> & argument)
261 {
262  std::map<std::string, Option>::iterator pos = _cli_options.find(option_name);
263  if (pos != _cli_options.end())
264  {
265  for (unsigned int i = 0; i < pos->second.cli_switch.size(); ++i)
266  {
267  for (size_t j = 0; j < _argv.size(); j++)
268  {
269  auto arg = _argv[j];
270 
271  if (arg == pos->second.cli_switch[i])
272  {
273  // "Flag" CLI options added vector of Boolean types may apprear multiple times on the
274  // command line (like a repeated verbosity flag to increase verbosity), when we see them
275  // we append a true value to the vector.
276  if (pos->second.argument_type == ArgumentType::NONE)
277  argument.push_back(T());
278  else if (pos->second.argument_type == ArgumentType::REQUIRED)
279  mooseError("Adding vector command line parameters with required arguments is not "
280  "currently supported");
281  else
282  while (j + 1 < _argv.size() && _argv[j + 1][0] != '-' &&
283  _argv[j + 1].find("=") == std::string::npos)
284  {
285  std::stringstream ss;
286  ss << _argv[j + 1];
287 
288  T item;
289  setArgument(ss, item, pos->second.cli_switch[i]);
290  argument.push_back(item);
291  ++j;
292  }
293  }
294  }
295  }
296 
297  if (pos->second.required && argument.empty())
298  {
299  Moose::err << "Required parameter: " << option_name << " missing\n";
300  printUsage();
301  }
302  return false;
303  }
304  mooseError("Unrecognized option name");
305 }
std::map< std::string, Option > _cli_options
Command line options.
Definition: CommandLine.h:156
void markHitParam(int argi)
Definition: CommandLine.h:123
std::vector< std::string > cli_switch
This gets filled in automagicaly when calling addOption()
Definition: CommandLine.h:45
std::string getExecutableName() const
Get the executable name.
Definition: CommandLine.C:233
std::set< int > unused(const Parallel::Communicator &comm)
Definition: CommandLine.h:128
std::vector< std::string >::const_iterator find(const std::string &option_name) const
Returns an iterator to the underlying argument vector to the position of the option or end if the opt...
Definition: CommandLine.C:181
void addArgument(std::string)
Definition: CommandLine.C:44
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:299
std::string description
Definition: CommandLine.h:40
void markHitParamUsed(int argi)
Definition: CommandLine.h:122
void printUsage() const
Print the usage info for this command line.
Definition: CommandLine.C:251
auto raw_value(const Eigen::Map< T > &in)
Definition: ADReal.h:73
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
std::set< int > _hiti
indices of CLI args that are HIT syntax parameters
Definition: CommandLine.h:163
void initForMultiApp(const std::string &)
Removes multiapp parameters not associated with the supplied name.
Definition: CommandLine.C:67
This class wraps provides and tracks access to command line parameters.
Definition: CommandLine.h:33
void populateInputParams(InputParameters &params)
Definition: CommandLine.C:134
ArgumentType argument_type
Definition: CommandLine.h:43
std::vector< std::string >::const_iterator begin() const
Definition: CommandLine.C:200
std::vector< std::string > _argv
Storage for the raw argv.
Definition: CommandLine.h:166
void addOption(const std::string &name, Option cli_opt)
Definition: CommandLine.C:172
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:31
std::set< int > _used_hiti
indices of CLI args that have been marked as used
Definition: CommandLine.h:160
void setArgument(std::stringstream &stream, T &argument)
Helper for setting the argument value, allows specialization.
Definition: CommandLine.h:173
virtual ~CommandLine()
Definition: CommandLine.C:64
void addCommandLineOptionsFromParams(const InputParameters &params)
Definition: CommandLine.C:116
bool search(const std::string &option_name)
This routine searches the command line for the given option "handle" and returns a boolean indicating...
Definition: CommandLine.C:212
std::vector< std::string > cli_syntax
Definition: CommandLine.h:41
std::vector< std::string >::const_iterator end() const
Definition: CommandLine.C:206
std::vector< std::string > _args
Definition: CommandLine.h:168
bool _throw_on_error
Variable to turn on exceptions during mooseError(), should only be used within MOOSE unit tests or wh...
Definition: Moose.C:646
auto index_range(const T &sizable)
const std::vector< std::string > & getArguments()
Return the raw argv arguments as a vector.
Definition: CommandLine.h:71
std::string getExecutableNameBase() const
Get the exectuable name base (the name without the -[opt,oprof,devel,dbg])
Definition: CommandLine.C:241
void addArguments(int argc, char *argv[])
Definition: CommandLine.C:37