|
|
@@ -36,11 +36,15 @@ template <typename Impl> Arguments<Impl>::Action::operator bool() const {
|
|
|
|
|
|
template <typename Impl> bool Arguments<Impl>::Action::primed() const {
|
|
|
if (self->primed_) { return true; }
|
|
|
- if (!self->argument_names.empty()) { throw ArgumentMixingError(); }
|
|
|
+ if (self->has_arguments()) { throw ArgumentMixingError(); }
|
|
|
self->action_descriptions.emplace(name, description);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+}
|
|
|
+
|
|
|
+namespace program {
|
|
|
+
|
|
|
template <typename Impl>
|
|
|
template <typename T>
|
|
|
Arguments<Impl>::Argument::operator T() const {
|
|
|
@@ -69,7 +73,7 @@ auto Arguments<Impl>::Argument::operator=(T && value) {
|
|
|
|
|
|
template <typename Impl> bool Arguments<Impl>::Argument::primed() const {
|
|
|
if (self->primed_) { return true; }
|
|
|
- if (!self->actions.empty()) { throw ArgumentMixingError(); }
|
|
|
+ if (self->has_actions()) { throw ArgumentMixingError(); }
|
|
|
if (is_optional) {
|
|
|
self->optional_from = std::min(self->optional_from, index);
|
|
|
} else if (self->optional_from < index) {
|
|
|
@@ -107,7 +111,11 @@ template <typename Impl> auto Arguments<Impl>::Flag::operator=(bool && value) {
|
|
|
|
|
|
template <typename Impl> bool Arguments<Impl>::Flag::primed(bool inv) const {
|
|
|
if (self->primed_) { return self->flags.count(name); }
|
|
|
- self->add_options(name, abbrev, description, std::vector(inv, "no-" + name));
|
|
|
+ std::vector<std::string> aliases;
|
|
|
+ if (name.size() > 1 && inv) {
|
|
|
+ aliases.push_back("no-" + name);
|
|
|
+ }
|
|
|
+ self->add_options(name, abbrev, description, aliases);
|
|
|
self->flag_names.emplace(name);
|
|
|
return false;
|
|
|
}
|
|
|
@@ -136,6 +144,17 @@ auto Arguments<Impl>::Option::operator=(T && value) {
|
|
|
return WithDefault<Option, T>{*this, std::forward<T>(value)};
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+template <typename Impl>
|
|
|
+template <typename T>
|
|
|
+auto Arguments<Impl>::Option::operator=(std::initializer_list<T> value) {
|
|
|
+ if (description.size()) {
|
|
|
+ using ::program::to_string;
|
|
|
+ description += "\n Default Value: " + to_string(value);
|
|
|
+ }
|
|
|
+ return WithDefault<Option, std::initializer_list<T>>{*this, value};
|
|
|
+}
|
|
|
+
|
|
|
template <typename Impl> bool Arguments<Impl>::Option::primed() const {
|
|
|
if (self->primed_) { return true; }
|
|
|
self->add_options(name, abbrev, description);
|
|
|
@@ -205,6 +224,9 @@ template <typename Impl> void Arguments<Impl>::usage() const {
|
|
|
for (auto & [index, name] : argument_names) {
|
|
|
std::cout << " " << (index == optional_from ? "[" : "") << name;
|
|
|
}
|
|
|
+ if (rest_name.size()) {
|
|
|
+ std::cout << " [" << rest_name << "...]";
|
|
|
+ }
|
|
|
if (optional_from != no_optional_args) { std::cout << "]"; }
|
|
|
std::cout << "\nArgument Arguments:\n";
|
|
|
for (auto & [name, desc] : argument_descriptions) {
|
|
|
@@ -223,7 +245,7 @@ void Arguments<Impl>::add_options(std::string const & name, char abbrev,
|
|
|
for (auto & str : aliases) {
|
|
|
str = "--" + str;
|
|
|
}
|
|
|
- aliases.push_back("--" + name);
|
|
|
+ if (name.size() > 1) { aliases.push_back("--" + name); }
|
|
|
if (abbrev) { aliases.push_back(std::string{'-', abbrev}); }
|
|
|
for (auto & str : aliases) {
|
|
|
if (!option_names.emplace(str, name).second) {
|
|
|
@@ -250,39 +272,59 @@ bool Arguments<Impl>::is_flag(std::string const & arg) const {
|
|
|
}
|
|
|
|
|
|
template <typename Impl>
|
|
|
-auto Arguments<Impl>::action(std::string const & name,
|
|
|
- std::string const & description) {
|
|
|
+auto Arguments<Impl>::action(LongArg name, std::string const & description) {
|
|
|
return Action{this, name, description};
|
|
|
}
|
|
|
|
|
|
template <typename Impl>
|
|
|
-auto Arguments<Impl>::argument(size_t index, std::string const & name,
|
|
|
+auto Arguments<Impl>::argument(size_t index, LongArg name,
|
|
|
std::string const & description) {
|
|
|
return Argument{this, index, false, name, description};
|
|
|
}
|
|
|
|
|
|
template <typename Impl>
|
|
|
-auto Arguments<Impl>::flag(std::string const & name,
|
|
|
- std::string const & description) {
|
|
|
+std::vector<std::string> Arguments<Impl>::rest(LongArg name,
|
|
|
+ std::string const & description) {
|
|
|
+ if (has_actions()) { throw ArgumentMixingError(); }
|
|
|
+ if (!rest_name.empty() && rest_name != name.str) {
|
|
|
+ throw ArgumentStructureError("duplicate rest() parameter", name);
|
|
|
+ }
|
|
|
+ rest_name = name;
|
|
|
+ argument_descriptions.emplace(name, description);
|
|
|
+ size_t const i = std::min(arguments.size(), argument_names.size());
|
|
|
+ return {arguments.begin() + i, arguments.end()};
|
|
|
+}
|
|
|
+
|
|
|
+template <typename Impl>
|
|
|
+auto Arguments<Impl>::flag(LongArg name, std::string const & description) {
|
|
|
return Flag{this, name, 0, description, false};
|
|
|
}
|
|
|
|
|
|
template <typename Impl>
|
|
|
-auto Arguments<Impl>::flag(std::string const & name, char abbrev,
|
|
|
+auto Arguments<Impl>::flag(LongArg name, char abbrev,
|
|
|
std::string const & description) {
|
|
|
return Flag{this, name, abbrev, description, false};
|
|
|
}
|
|
|
|
|
|
template <typename Impl>
|
|
|
-auto Arguments<Impl>::option(std::string const & name,
|
|
|
- std::string const & description) {
|
|
|
+auto Arguments<Impl>::flag(char abbrev, std::string const & description) {
|
|
|
+ return Flag{this, {abbrev}, abbrev, description, false};
|
|
|
+}
|
|
|
+
|
|
|
+template <typename Impl>
|
|
|
+auto Arguments<Impl>::option(LongArg name, std::string const & description) {
|
|
|
return Option{this, name, 0, description};
|
|
|
}
|
|
|
|
|
|
template <typename Impl>
|
|
|
-auto Arguments<Impl>::option(std::string const & name, char abbrev,
|
|
|
+auto Arguments<Impl>::option(LongArg name, char abbrev,
|
|
|
std::string const & description) {
|
|
|
return Option{this, name, abbrev, description};
|
|
|
}
|
|
|
|
|
|
+template <typename Impl>
|
|
|
+auto Arguments<Impl>::option(char abbrev, std::string const & description) {
|
|
|
+ return Option{this, {abbrev}, abbrev, description};
|
|
|
+}
|
|
|
+
|
|
|
}
|