8 static std::uint64_t
id = 0;
12parser::cmd_base::cmd_base(
const std::string&
name,
13 const std::string& alternative,
14 const std::string& description,
19 , command(!
name.empty() ?
"-" +
name :
"")
20 , alternative(!alternative.empty() ?
"--" + alternative :
"")
21 , description(description)
26 , variadic(is_variadic)
31parser::cmd_base::~cmd_base() =
default;
33auto parser::cmd_base::is(
const std::string& given)
const ->
bool
35 return given == command || given == alternative;
38auto parser::parse(
const std::vector<std::string>& elements,
const int&,
int numberBase) ->
int
40 if(elements.size() != 1)
42 throw std::bad_cast();
45 return std::stoi(elements[0],
nullptr, numberBase);
48auto parser::parse(
const std::vector<std::string>& elements,
const bool& defval) ->
bool
52 throw std::runtime_error(
"A boolean command line parameter cannot have any arguments.");
58auto parser::parse(
const std::vector<std::string>& elements,
const double&) ->
double
60 if(elements.size() != 1)
62 throw std::bad_cast();
65 return std::stod(elements[0]);
68auto parser::parse(
const std::vector<std::string>& elements,
const float&) ->
float
70 if(elements.size() != 1)
72 throw std::bad_cast();
75 return std::stof(elements[0]);
78auto parser::parse(
const std::vector<std::string>& elements,
const long double&) ->
long double
80 if(elements.size() != 1)
82 throw std::bad_cast();
85 return std::stold(elements[0]);
88auto parser::parse(
const std::vector<std::string>& elements,
const unsigned int&,
int numberBase) ->
unsigned int
90 if(elements.size() != 1)
92 throw std::bad_cast();
95 return static_cast<unsigned int>(std::stoul(elements[0],
nullptr, numberBase));
98auto parser::parse(
const std::vector<std::string>& elements,
const unsigned long&,
int numberBase) ->
unsigned long
100 if(elements.size() != 1)
102 throw std::bad_cast();
105 return std::stoul(elements[0],
nullptr, numberBase);
108auto parser::parse(
const std::vector<std::string>& elements,
const long&) ->
long
110 if(elements.size() != 1)
112 throw std::bad_cast();
115 return std::stol(elements[0]);
118auto parser::parse(
const std::vector<std::string>& elements,
const std::string&) -> std::string
120 if(elements.size() != 1)
122 throw std::bad_cast();
128auto parser::stringify(
const std::string& str) -> std::string
135 for(
int i = 1; i < argc; ++i)
137 arguments_.push_back(argv[i]);
144 for(
int i = 1; i < argc; ++i)
146 arguments_.push_back(argv[i]);
153 for(
const auto& command_pair : commands_)
155 const auto& command = command_pair.second;
156 if(command->name ==
"h" && command->alternative ==
"--help")
182 for(
auto command = commands_.begin(); command != commands_.end(); ++command)
184 if((*command).second->name ==
"h" && (*command).second->alternative ==
"--help")
186 commands_.erase(command);
195 commands_.shrink_to_fit();
208 return run(std::cout, std::cerr);
213 return run(output, std::cerr);
216auto parser::run(std::ostream& output, std::ostream& error) ->
bool
218 if(!arguments_.empty())
220 auto current = find_default();
222 for(
const auto& arg : arguments_)
224 auto isarg = !arg.empty() && arg[0] ==
'-';
225 auto associated = isarg ? find(arg) :
nullptr;
227 if(associated !=
nullptr)
229 current = associated;
230 associated->handled =
true;
232 else if(current ==
nullptr)
240 current->arguments.push_back(arg);
241 current->handled =
true;
242 if(!current->variadic)
247 current = find_default();
255 for(
auto& command_pair : commands_)
257 auto& command = command_pair.second;
258 if(command->handled && command->dominant && !command->parse(output, error))
260 error << howto_use(command);
266 for(
const auto& command_pair : commands_)
268 const auto& command = command_pair.second;
269 if(command->required && !command->handled)
271 error << howto_required(command);
277 for(
auto& command_pair : commands_)
279 auto& command = command_pair.second;
280 if(command->handled && !command->dominant && !command->parse(output, error))
282 error << howto_use(command);
294 for(
const auto& command_pair : commands_)
296 const auto& command = command_pair.second;
297 if(command->required)
308 return static_cast<int>(commands_.size());
318 std::stringstream ss{};
319 ss <<
"Available parameters:\n\n";
321 for(
const auto& command_pair : commands_)
323 const auto& command = command_pair.second;
325 ss <<
" " << command->command <<
"\t" << command->alternative;
327 if(command->required)
329 ss <<
"\t(required)";
332 ss <<
"\n " << command->description;
334 if(!command->required)
337 <<
"This parameter is optional. The default value is '" + command->print_value() <<
"'.";
350 ss <<
"For more help use --help or -h.\n";
356 std::stringstream ss{};
357 ss <<
"The parameter " << command->name <<
" is required.\n";
358 ss << command->description <<
'\n';
365 std::stringstream ss{};
366 ss <<
"The parameter " << command->name <<
" has invalid arguments.\n";
367 ss << command->description <<
'\n';
374 std::stringstream ss{};
375 ss <<
"No default parameter has been specified.\n";
376 ss <<
"The given argument must be used with a parameter.\n";
383 for(
auto& command_pair : commands_)
385 auto& command = command_pair.second;
386 if(command->name.empty())
388 return command.get();
397 for(
auto& command_pair : commands_)
399 auto& command = command_pair.second;
400 if(command->is(
name))
402 return command.get();
void set_callback(const std::string &name, const std::string &alternative, std::function< T(callback_args &)> callback, const std::string &description="", bool dominant=false)