44#define assert_message(expr, message) assert((message, expr))
91 MissingRequiredOption,
174 template<
typename T =
bool>
184 auto addOption(
const std::shared_ptr<Option> &option) -> void;
191 friend class OptionGroup;
192 friend class HelpCommand;
194 enum class Mode { OPTIONS, COMMANDS };
218 template<
typename T =
bool>
316 std::map<std::string, OptionGroup> _groups;
317 std::map<std::string, std::shared_ptr<const Option>> _options;
319 std::map<std::string, Command *> _commands;
320 std::map<std::string, CLI> _commands_cli;
322 [[nodiscard]]
auto buildUsageHelp() const ->
std::
string;
324 [[nodiscard]] auto buildPositionalHelp() const ->
std::
string;
326 [[nodiscard]] static auto buildOptionUsageHelp(const
std::shared_ptr<const
Option> &option) ->
std::
string;
328 static auto checkOptionType(const
std::type_info &type) ->
void;
330 [[nodiscard]] static auto
331 getValueForOption(const
std::shared_ptr<const
Option> &option, const
std::vector<
std::
string> &values)
334 template<typename T =
bool>
336 const
std::
string &name,
337 const
std::
string &description,
338 const
std::
string &group_name,
355 [[nodiscard]]
virtual auto getName() const ->
std::
string = 0;
392 explicit CLIResults(
const std::map<std::string, std::any> &values);
404 std::map<std::string, std::any> _values;
415 explicit HelpCommand(
CLI *cli): _cli(cli) {}
422 return "Display this help message\n"
423 "When COMMAND is given, display help for this command";
439 _parent->addOption<T>(name, description, _name, configuration);
447 return addOption<T>(name, description,
"", configuration);
458 ! _mode.has_value() || _mode.value() != Mode::COMMANDS,
"Cannot add an option group to a cli using commands"
460 _mode = Mode::OPTIONS;
462 assert_message(! _options.contains(name),
"CLI has already this option");
463 assert_message(_groups.contains(group_name),
"Option group does not exist");
467 const std::regex name_regex(
"(.*),(.*)");
468 if (std::smatch match; std::regex_match(name, match, name_regex)) {
469 if (match.size() == 3) {
470 long_name = match[1].str();
471 short_name = match[2].str();
473 short_name.length() == 1 && isalpha(short_name[0]),
"Short name of an option can be only one letter"
478 const auto &type_info =
typeid(T);
479 checkOptionType(type_info);
480 const auto option = std::make_shared<Option>(long_name, short_name, description, type_info, configuration);
481 _options.emplace(long_name, option);
482 _groups.at(group_name).addOption(option);
487template<
typename... Tail>
489 assert_message(_options.contains(option_name),
"Option doesn't exists");
490 const auto option = _options.at(option_name);
491 if (! _positional_options.empty()) {
492 const auto last_option_name = _positional_options[_positional_options.size() - 1];
493 const auto last_option = _options.at(last_option_name);
494 const auto &last_option_type = last_option->type;
498 "Cannot add a new positional argument after one with a list type"
501 ! option->configuration.required || last_option->configuration.required,
502 "Option is required but is placed after a non required one"
506 _positional_options.push_back(option_name);
Definition yeschief.h:387
CLIResults(const std::map< std::string, std::any > &values)
auto get(const std::string &option) const -> std::optional< std::any >
Definition yeschief.h:190
auto addCommand(Command *command) -> CLI &
auto parsePositional(const std::string &option_name, Tail &&...options) -> void
Definition yeschief.h:488
auto addOption(const std::string &name, const std::string &description, const OptionConfiguration &configuration={}) -> CLI &
Definition yeschief.h:444
CLI(std::string name, std::string description)
auto addGroup(const std::string &name) -> OptionGroup &
auto run(int argc, char **argv) const -> std::expected< CLIResults, Fault >
auto help(std::ostream &out=std::cout) const -> void
Definition yeschief.h:350
virtual auto run(const CLIResults &results) -> int=0
virtual auto getDescription() const -> std::string
Definition yeschief.h:359
virtual auto setup(CLI &cli) -> void
Definition yeschief.h:369
virtual auto getName() const -> std::string=0
auto getDescription() const -> std::string override
Definition yeschief.h:421
auto setup(CLI &cli) -> void override
auto getName() const -> std::string override
Definition yeschief.h:417
auto run(const CLIResults &results) -> int override
Definition yeschief.h:149
auto addOption(const std::string &name, const std::string &description, const OptionConfiguration &configuration={}) -> OptionGroup &
Definition yeschief.h:436
OptionGroup(CLI *parent, std::string name)
Definition yeschief.h:109
FaultType type
Definition yeschief.h:117
std::string message
Definition yeschief.h:113
std::string value_help
Definition yeschief.h:65
std::optional< std::any > default_value
Definition yeschief.h:69
bool required
Definition yeschief.h:61
std::optional< std::any > implicit_value
Definition yeschief.h:73
Definition yeschief.h:123
std::string short_name
Definition yeschief.h:131
const std::type_info & type
Definition yeschief.h:139
std::string name
Definition yeschief.h:127
std::string description
Definition yeschief.h:135
OptionConfiguration configuration
Definition yeschief.h:143