aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTaylor C. Richberger <Taywee@gmx.com>2016-06-14 19:35:48 -0600
committerTaylor C. Richberger <Taywee@gmx.com>2016-06-14 19:35:48 -0600
commit8c1154cbcddf5dfcb278e3a821cb1d0a3a6c984e (patch)
tree36ece64bf25c6cf76012da7c7a5bd7be1a75cf2e
parentfixed problem hopefully (diff)
downloadargs.hxx-8c1154cbcddf5dfcb278e3a821cb1d0a3a6c984e.tar.xz
add new feature
-rw-r--r--args.hxx34
-rw-r--r--test.cxx30
2 files changed, 59 insertions, 5 deletions
diff --git a/args.hxx b/args.hxx
index ac9ccfc..26cb4f6 100644
--- a/args.hxx
+++ b/args.hxx
@@ -175,6 +175,15 @@ namespace args
virtual ~MapError() {};
};
+ /** Error that occurs when a singular flag is specified multiple times
+ */
+ class ExtraError : public ParseError
+ {
+ public:
+ ExtraError(const std::string &problem) : ParseError(problem) {}
+ virtual ~ExtraError() {};
+ };
+
/** An exception that indicates that the user has requested help
*/
class Help : public Error
@@ -393,11 +402,14 @@ namespace args
*/
class FlagBase : public NamedBase
{
+ private:
+ const bool extraError;
+
protected:
const Matcher matcher;
public:
- FlagBase(const std::string &name, const std::string &help, Matcher &&matcher) : NamedBase(name, help), matcher(std::move(matcher)) {}
+ FlagBase(const std::string &name, const std::string &help, Matcher &&matcher, const bool extraError = false) : NamedBase(name, help), extraError(extraError), matcher(std::move(matcher)) {}
virtual ~FlagBase() {}
@@ -405,6 +417,12 @@ namespace args
{
if (matcher.Match(flag))
{
+ if (extraError && matched)
+ {
+ std::ostringstream problem;
+ problem << "Flag '" << flag << "' was passed multiple times, but should only be allowed to be passed once";
+ throw ExtraError(problem.str());
+ }
matched = true;
return this;
}
@@ -415,6 +433,12 @@ namespace args
{
if (matcher.Match(flag))
{
+ if (extraError && matched)
+ {
+ std::ostringstream problem;
+ problem << "Flag '" << flag << "' was passed multiple times, but should only be allowed to be passed once";
+ throw ExtraError(problem.str());
+ }
matched = true;
return this;
}
@@ -445,7 +469,7 @@ namespace args
class ValueFlagBase : public FlagBase
{
public:
- ValueFlagBase(const std::string &name, const std::string &help, Matcher &&matcher) : FlagBase(name, help, std::move(matcher)) {}
+ ValueFlagBase(const std::string &name, const std::string &help, Matcher &&matcher, const bool extraError = false) : FlagBase(name, help, std::move(matcher), extraError) {}
virtual ~ValueFlagBase() {}
virtual void ParseValue(const std::string &value) = 0;
@@ -1254,7 +1278,7 @@ namespace args
class Flag : public FlagBase
{
public:
- Flag(Group &group, const std::string &name, const std::string &help, Matcher &&matcher): FlagBase(name, help, std::move(matcher))
+ Flag(Group &group, const std::string &name, const std::string &help, Matcher &&matcher, const bool extraError = false): FlagBase(name, help, std::move(matcher), extraError)
{
group.Add(*this);
}
@@ -1389,7 +1413,7 @@ namespace args
public:
- ValueFlag(Group &group, const std::string &name, const std::string &help, Matcher &&matcher, const T &defaultValue = T()): ValueFlagBase(name, help, std::move(matcher)), value(defaultValue)
+ ValueFlag(Group &group, const std::string &name, const std::string &help, Matcher &&matcher, const T &defaultValue = T(), const bool extraError = false): ValueFlagBase(name, help, std::move(matcher), extraError), value(defaultValue)
{
group.Add(*this);
}
@@ -1469,7 +1493,7 @@ namespace args
public:
- MapFlag(Group &group, const std::string &name, const std::string &help, Matcher &&matcher, const Map &map, const T &defaultValue = T()): ValueFlagBase(name, help, std::move(matcher)), map(map), value(defaultValue)
+ MapFlag(Group &group, const std::string &name, const std::string &help, Matcher &&matcher, const Map &map, const T &defaultValue = T(), const bool extraError = false): ValueFlagBase(name, help, std::move(matcher), extraError), map(map), value(defaultValue)
{
group.Add(*this);
}
diff --git a/test.cxx b/test.cxx
index b4c451b..c368bf9 100644
--- a/test.cxx
+++ b/test.cxx
@@ -412,3 +412,33 @@ TEST_CASE("Mapping types work as needed", "[args]")
REQUIRE((args::get(mpl) == std::vector<MappingEnum>{MappingEnum::red, MappingEnum::def}));
REQUIRE_THROWS_AS(parser.ParseArgs(std::vector<std::string>{"--mf=YeLLoW"}), args::MapError);
}
+
+TEST_CASE("An exception should be thrown when a single-argument flag is matched multiple times and the constructor option is specified", "[args]")
+{
+ std::unordered_map<std::string, MappingEnum> map{
+ {"default", MappingEnum::def},
+ {"foo", MappingEnum::foo},
+ {"bar", MappingEnum::bar},
+ {"red", MappingEnum::red},
+ {"yellow", MappingEnum::yellow},
+ {"green", MappingEnum::green}};
+
+ std::ostream null(nullptr);
+ args::ArgumentParser parser("Test command");
+ args::Flag foo(parser, "Foo", "Foo", {'f', "foo"}, true);
+ args::ValueFlag<std::string> bar(parser, "Bar", "Bar", {'b', "bar"}, "", true);
+ args::Flag bix(parser, "Bix", "Bix", {'x', "bix"});
+ args::MapFlag<std::string, MappingEnum> baz(parser, "Baz", "Baz", {'B', "baz"}, map, MappingEnum::def, true);
+ REQUIRE_THROWS_AS(parser.ParseArgs(std::vector<std::string>{"--foo", "-f", "-bblah"}), args::ExtraError);
+ REQUIRE_NOTHROW(parser.ParseArgs(std::vector<std::string>{"--foo", "-xxx", "--bix", "-bblah", "--bix"}));
+ REQUIRE_THROWS_AS(parser.ParseArgs(std::vector<std::string>{"--foo", "-bblah", "-blah"}), args::ExtraError);
+ REQUIRE_THROWS_AS(parser.ParseArgs(std::vector<std::string>{"--foo", "-bblah", "--bar", "blah"}), args::ExtraError);
+ REQUIRE_THROWS_AS(parser.ParseArgs(std::vector<std::string>{"--baz=red", "-B", "yellow"}), args::ExtraError);
+ REQUIRE_THROWS_AS(parser.ParseArgs(std::vector<std::string>{"--baz", "red", "-Byellow"}), args::ExtraError);
+ REQUIRE_NOTHROW(parser.ParseArgs(std::vector<std::string>{"--foo", "-Bgreen"}));
+ REQUIRE(foo);
+ REQUIRE_FALSE(bar);
+ REQUIRE_FALSE(bix);
+ REQUIRE(baz);
+ REQUIRE(args::get(baz) == MappingEnum::green);
+}