36#define POPL_VERSION "1.2.0"
126 std::string
name (
OptionName what_name,
bool with_hypen =
false)
const;
306 template<
typename T,
Attribute attribute,
typename... Ts>
307 std::shared_ptr<T>
add (Ts && ... params);
312 template<
typename T,
typename... Ts>
313 std::shared_ptr<T>
add (Ts && ... params);
318 void parse (
int argc,
const char *
const argv[]);
331 const std::vector<Option_ptr>&
options()
const;
496 description_ (
std::move (description)),
499 throw std::invalid_argument (
"length of short name must be <= 1: '" +
short_name +
"'");
503 throw std::invalid_argument (
"short and long name are empty");
554 assign_to_ (nullptr) {
568 return values_.size();
574 return !values_.empty();
594 if (!this->is_set() && default_) {
598 if (!is_set() || (idx >= count())) {
599 std::stringstream optionStr;
601 optionStr <<
"option not set: \"";
604 optionStr <<
"index out of range (" << idx <<
") for \"";
615 throw std::out_of_range (optionStr.str());
625 this->default_.reset (
new T);
626 *this->default_ = value;
633 return (this->default_ !=
nullptr);
639 if (!has_default()) {
640 throw std::runtime_error (
"no default value set");
642 return *this->default_;
648 if (!has_default()) {
651 out << *this->default_;
664 if (strlen (value) == 0) {
675 std::string strValue;
676 if (value !=
nullptr) {
680 std::istringstream is (strValue);
683 if (is.peek() != EOF) {
697 if (valuesRead > 1) {
701 if (strValue.empty()) {
705 this->add_value (parsed_value);
711 if (this->assign_to_) {
712 if (this->is_set() || default_) {
713 *this->assign_to_ = value();
721 values_.push_back (value);
750 if ( (value !=
nullptr) && (strlen (value) > 0)) {
754 this->add_value (*this->default_);
786 template<
typename T,
typename... Ts>
788 return add<T, Attribute::optional> (std::forward<Ts> (params)...);
792 template<
typename T,
Attribute attribute,
typename... Ts>
795 std::is_base_of<Option, typename std::decay<T>::type>::value,
796 "type T must be Switch, Value or Implicit"
798 std::shared_ptr<T> option = std::make_shared<T> (std::forward<Ts> (params)...);
801 if ( (option->short_name() != 0) && (option->short_name() == o->short_name())) {
802 throw std::invalid_argument (
"duplicate short option name '-" + std::string (1, option->short_name()) +
"'");
804 if (!option->long_name().empty() && (option->long_name() == (o->long_name()))) {
805 throw std::invalid_argument (
"duplicate long option name '--" + option->long_name() +
"'");
808 option->set_attribute (attribute);
835 for (
const auto & option :
options_)
844 for (
const auto & option :
options_)
856 throw std::invalid_argument (
"option not found: " +
long_name);
858 auto result = std::dynamic_pointer_cast<T> (option);
860 throw std::invalid_argument (
"cannot cast option to T: " +
long_name);
870 throw std::invalid_argument (
"option not found: " + std::string (1,
short_name));
872 auto result = std::dynamic_pointer_cast<T> (option);
874 throw std::invalid_argument (
"cannot cast option to T: " + std::string (1,
short_name));
887 for (
int n = 1; n < argc; ++n) {
888 const std::string arg (argv[n]);
891 for (
int m = n + 1; m < argc; ++m) {
895 else if (arg.find (
"--") == 0) {
897 std::string opt = arg.substr (2);
899 size_t equalIdx = opt.find (
'=');
900 if (equalIdx != std::string::npos) {
901 optarg = opt.substr (equalIdx + 1);
902 opt.resize (equalIdx);
911 if (!optarg.empty()) {
916 if (optarg.empty() && n < argc - 1) {
929 else if (arg.find (
'-') == 0) {
931 std::string opt = arg.substr (1);
932 bool unknown =
false;
933 for (
size_t m = 0; m < opt.size(); ++m) {
944 optarg = opt.substr (m + 1);
946 if (optarg.empty() && n < argc - 1) {
953 optarg = opt.substr (m + 1);
976 std::string option = opt->long_name().empty() ? std::string (1, opt->short_name()) : opt->long_name();
985 return option_printer.
print (max_attribute);
998 std::stringstream line;
999 if (option->short_name() != 0) {
1000 line <<
" -" << option->short_name();
1001 if (!option->long_name().empty()) {
1008 if (!option->long_name().empty()) {
1009 line <<
"--" << option->long_name();
1014 std::stringstream defaultStr;
1015 if (option->get_default (defaultStr)) {
1016 if (!defaultStr.str().empty()) {
1017 line <<
" (=" << defaultStr.str() <<
")";
1022 std::stringstream defaultStr;
1023 if (option->get_default (defaultStr)) {
1024 line <<
" [=arg(=" << defaultStr.str() <<
")]";
1038 throw std::invalid_argument (
"attribute must be 'optional', 'advanced', or 'default'");
1041 std::stringstream s;
1046 size_t optionRightMargin (20);
1047 const size_t maxDescriptionLeftMargin (40);
1051 optionRightMargin = std::max (optionRightMargin,
to_string (option).size() + 2);
1053 optionRightMargin = std::min (maxDescriptionLeftMargin - 2, optionRightMargin);
1057 (option->attribute() > max_attribute)) {
1060 std::string optionStr =
to_string (option);
1061 if (optionStr.size() < optionRightMargin) {
1062 optionStr.resize (optionRightMargin,
' ');
1065 optionStr +=
"\n" + std::string (optionRightMargin,
' ');
1070 std::vector<std::string> lines;
1071 std::stringstream description (option->description());
1072 while (std::getline (description, line,
'\n')) {
1073 lines.push_back (line);
1076 std::string empty (optionRightMargin,
' ');
1077 for (
size_t n = 0; n < lines.size(); ++n) {
1099 std::stringstream line;
1100 if (option->short_name() != 0) {
1101 line <<
"-" << option->short_name();
1102 if (!option->long_name().empty()) {
1106 if (!option->long_name().empty()) {
1107 line <<
"--" << option->long_name();
1112 std::stringstream defaultStr;
1113 if (option->get_default (defaultStr)) {
1114 if (!defaultStr.str().empty()) {
1115 line <<
" (=" << defaultStr.str() <<
")";
1120 std::stringstream defaultStr;
1121 if (option->get_default (defaultStr)) {
1122 line <<
" [=arg(=" << defaultStr.str() <<
")]";
1136 throw std::invalid_argument (
"attribute must be 'optional', 'advanced', or 'default'");
1139 std::stringstream s;
1146 (option->attribute() > max_attribute)) {
1149 s <<
".TP\n\\fB" <<
to_string (option) <<
"\\fR\n";
1150 if (!option->description().empty()) {
1151 s << option->description() <<
"\n";
1172 std::stringstream s;
1177 cur="$ {COMP_WORDS[COMP_CWORD]}"
1178 prev="$ {COMP_WORDS[COMP_CWORD - 1]}"
1181 for (const auto& option: option_parser_->options())
1183 if (option->attribute() > Attribute::hidden)
1185 if (option->short_name() != 0)
1186 s << " - " << option->short_name() << " ";
1187 if (!option->long_name().empty())
1188 s << "--" << option->long_name() << " ";
1193 if [[ ${cur} == -* ]] ; then
1194 COMPREPLY=( $(compgen -W "$ {opts}" -- ${cur}) )
1207 static inline std::ostream&
operator<< (std::ostream& out,
const OptionParser& op) {
1208 return out << op.help();
Option printer for bash completion.
~BashCompletionOptionPrinter() override=default
std::string program_name_
std::string print(const Attribute &max_attribute=Attribute::optional) const override
BashCompletionOptionPrinter(const OptionParser *option_parser, std::string program_name)
BashCompletionOptionPrinter implementation /////////////////////////////////.
Option printer for the console.
std::string print(const Attribute &max_attribute=Attribute::optional) const override
~ConsoleOptionPrinter() override=default
ConsoleOptionPrinter(const OptionParser *option_parser)
ConsoleOptionPrinter implementation /////////////////////////////////.
std::string to_string(Option_ptr option) const
Option printer for man pages.
~GroffOptionPrinter() override=default
std::string to_string(Option_ptr option) const
GroffOptionPrinter(const OptionParser *option_parser)
GroffOptionPrinter implementation /////////////////////////////////.
std::string print(const Attribute &max_attribute=Attribute::optional) const override
Value option with implicit default value.
Implicit(const std::string &short_name, const std::string &long_name, const std::string &description, const T &implicit_val, T *assign_to=nullptr)
Implicit implementation /////////////////////////////////.
Argument argument_type() const override
void parse(OptionName what_name, const char *value) override
Abstract Base class for Options.
Option(const Option &)=default
default copy constructor
Attribute attribute() const
std::string description() const
virtual ~Option()=default
Destructor.
virtual Argument argument_type() const =0
virtual bool get_default(std::ostream &out) const =0
Option & operator=(const Option &)=default
default assignement operator
Option(Option &&)=default
default move constructor
virtual bool is_set() const =0
Option(const std::string &short_name, const std::string &long_name, std::string description)
Option implementation /////////////////////////////////.
virtual void parse(OptionName what_name, const char *value)=0
virtual size_t count() const =0
std::string long_name() const
virtual void clear()=0
Clear the internal data structure.
std::string name(OptionName what_name, bool with_hypen=false) const
void set_attribute(const Attribute &attribute)
OptionParser manages all Options.
Option_ptr find_option(const std::string &long_name) const
std::shared_ptr< T > add(Ts &&... params)
virtual ~OptionParser()=default
Destructor.
std::vector< Option_ptr > options_
std::string description() const
const std::vector< Option_ptr > & options() const
std::string help(const Attribute &max_attribute=Attribute::optional) const
std::vector< std::string > non_option_args_
const std::vector< std::string > & unknown_options() const
const std::vector< std::string > & non_option_args() const
std::shared_ptr< T > get_option(const std::string &long_name) const
std::vector< std::string > unknown_options_
void parse(int argc, const char *const argv[])
OptionParser(std::string description="")
OptionParser implementation /////////////////////////////////.
Base class for an OptionPrinter.
const OptionParser * option_parser_
virtual ~OptionPrinter()=default
Destructor.
virtual std::string print(const Attribute &max_attribute=Attribute::optional) const =0
OptionPrinter(const OptionParser *option_parser)
Value option without value.
void set_default(const bool &value)=delete
Switch(const std::string &short_name, const std::string &long_name, const std::string &description, bool *assign_to=nullptr)
Switch implementation /////////////////////////////////.
Argument argument_type() const override
void parse(OptionName what_name, const char *value) override
Value option with optional default value.
virtual void update_reference()
bool is_set() const override
Value(const std::string &short_name, const std::string &long_name, const std::string &description, const T &default_val, T *assign_to=nullptr)
Argument argument_type() const override
T value(size_t idx=0) const
void set_default(const T &value)
void clear() override
Clear the internal data structure.
size_t count() const override
Value(const std::string &short_name, const std::string &long_name, const std::string &description)
Value implementation /////////////////////////////////.
virtual void add_value(const T &value)
bool get_default(std::ostream &out) const override
void set_value(const T &value)
std::unique_ptr< T > default_
void parse(OptionName what_name, const char *value) override
OptionName what_name() const
const Option * option() const
invalid_option(const Option *option, invalid_option::Error error, const std::string &text)
invalid_option(const Option *option, invalid_option::Error error, OptionName what_name, std::string value, const std::string &text)
std::string value() const
Global namespace for Piduino.
Attribute
Option's attribute.
Argument
Option's argument type.
OptionName
Option name type. Used in invalid_option exception.
std::shared_ptr< Option > Option_ptr
static std::ostream & operator<<(std::ostream &out, const OptionParser &op)