|
|
@@ -48,6 +48,40 @@ template <typename Impl> bool Arguments<Impl>::Argument::primed() const {
|
|
|
|
|
|
namespace program {
|
|
|
|
|
|
+template <typename Impl>
|
|
|
+template <typename T>
|
|
|
+Arguments<Impl>::Flag::operator T() const {
|
|
|
+ return primed(false) ? static_cast<T>(self->flags.at(name)) : T();
|
|
|
+}
|
|
|
+
|
|
|
+template <typename Impl> Arguments<Impl>::Flag::operator bool() const {
|
|
|
+ return primed(true) ? static_cast<bool>(self->flags.at(name)) : default_value;
|
|
|
+}
|
|
|
+
|
|
|
+template <typename Impl> auto Arguments<Impl>::Flag::operator=(bool && value) {
|
|
|
+ default_value = value;
|
|
|
+ return *this;
|
|
|
+}
|
|
|
+
|
|
|
+template <typename Impl> bool Arguments<Impl>::Flag::primed(bool inv) const {
|
|
|
+ if (self->primed_) { return self->flags.count(name); }
|
|
|
+ std::vector<std::string> aliases{"--" + name};
|
|
|
+ if (abbrev) { aliases.emplace_back(std::string{'-', abbrev}); }
|
|
|
+ if (inv) { aliases.emplace_back("--no-" + name); };
|
|
|
+ for (auto & alias : aliases) {
|
|
|
+ if (!self->option_names.emplace(alias, name).second) {
|
|
|
+ throw ArgumentStructureError("Duplicate option string", alias);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ self->option_descriptions.emplace(join("/", aliases), description);
|
|
|
+ self->flag_names.emplace(name);
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+namespace program {
|
|
|
+
|
|
|
template <typename Impl>
|
|
|
template <typename T>
|
|
|
Arguments<Impl>::Option::operator T() const {
|
|
|
@@ -69,7 +103,7 @@ template <typename Impl> bool Arguments<Impl>::Option::primed() const {
|
|
|
std::vector<std::string> aliases{"--" + name};
|
|
|
if (abbrev) { aliases.emplace_back(std::string{'-', abbrev}); }
|
|
|
for (auto & alias : aliases) {
|
|
|
- if (!self->option_name_mapping.emplace(alias, name).second) {
|
|
|
+ if (!self->option_names.emplace(alias, name).second) {
|
|
|
throw ArgumentStructureError("Duplicate option string", alias);
|
|
|
}
|
|
|
}
|
|
|
@@ -80,6 +114,7 @@ template <typename Impl> bool Arguments<Impl>::Option::primed() const {
|
|
|
}
|
|
|
|
|
|
#define arg_equals(str) !strncmp(argv[i], str, sizeof(str))
|
|
|
+#define arg_starts_with(str) !strncmp(argv[i], str, strlen(str))
|
|
|
namespace program {
|
|
|
|
|
|
template <typename Impl>
|
|
|
@@ -102,14 +137,19 @@ Arguments<Impl>::Arguments(int argc, char const * const * const argv) {
|
|
|
arguments.insert(arguments.end(), &argv[i + 1], &argv[argc]);
|
|
|
break;
|
|
|
} else if (argv[i][0] == '-') {
|
|
|
- if (auto it = option_name_mapping.find(argv[i]);
|
|
|
- it != option_name_mapping.end()) {
|
|
|
- options[it->second].emplace_back(argv[i + 1]);
|
|
|
+ auto it = option_names.find(argv[i]);
|
|
|
+ if (it == option_names.end()) { throw NotAnArgumentError(argv[i]); }
|
|
|
+ auto & name = it->second;
|
|
|
+ // TODO: Flag handling for e.g. -v2 -vv
|
|
|
+ if (!flag_names.count(name)) {
|
|
|
+ options[name].emplace_back(argv[i + 1]);
|
|
|
+ // TODO: Arity
|
|
|
+ ++i;
|
|
|
+ } else if (arg_starts_with("--no-")) {
|
|
|
+ flags[name] = 0;
|
|
|
} else {
|
|
|
- throw NotAnArgumentError(argv[i]);
|
|
|
+ ++flags[name];
|
|
|
}
|
|
|
- // TODO: Arity
|
|
|
- ++i;
|
|
|
} else {
|
|
|
arguments.emplace_back(argv[i]);
|
|
|
}
|
|
|
@@ -132,6 +172,24 @@ template <typename Impl> void Arguments<Impl>::usage() const {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+template <typename Impl>
|
|
|
+auto Arguments<Impl>::argument(size_t index, std::string const & 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) {
|
|
|
+ return Flag{this, name, 0, description, false};
|
|
|
+}
|
|
|
+
|
|
|
+template <typename Impl>
|
|
|
+auto Arguments<Impl>::flag(std::string const & 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) {
|
|
|
@@ -144,11 +202,6 @@ auto Arguments<Impl>::option(std::string const & name, char abbrev,
|
|
|
return Option{this, name, abbrev, description};
|
|
|
}
|
|
|
|
|
|
-template <typename Impl>
|
|
|
-auto Arguments<Impl>::argument(size_t index, std::string const & name,
|
|
|
- std::string const & description) {
|
|
|
- return Argument{this, index, false, name, description};
|
|
|
-}
|
|
|
-
|
|
|
}
|
|
|
#undef arg_equals
|
|
|
+#undef arg_starts_with
|