Commit 3d309dc0be32601ea98c6c36e5969a982fcb869e
1 parent
d28c230e
Adding fail if required values missing
Showing
5 changed files
with
37 additions
and
5 deletions
examples/simple.cpp
| @@ -8,7 +8,10 @@ int main(int argc, char **argv) { | @@ -8,7 +8,10 @@ int main(int argc, char **argv) { | ||
| 8 | CLI::Option *opt = app.add_option("-f,--file,file", file, "File name"); | 8 | CLI::Option *opt = app.add_option("-f,--file,file", file, "File name"); |
| 9 | 9 | ||
| 10 | int count; | 10 | int count; |
| 11 | - CLI::Option *copt = app.add_flag("-c,--count", count, "Counter"); | 11 | + CLI::Option *copt = app.add_option("-c,--count", count, "Counter"); |
| 12 | + | ||
| 13 | + int v; | ||
| 14 | + CLI::Option *flag = app.add_flag("--flag", v, "Some flag that can be passed multiple times"); | ||
| 12 | 15 | ||
| 13 | double value; // = 3.14; | 16 | double value; // = 3.14; |
| 14 | app.add_option("-d,--double", value, "Some Value"); | 17 | app.add_option("-d,--double", value, "Some Value"); |
| @@ -19,6 +22,7 @@ int main(int argc, char **argv) { | @@ -19,6 +22,7 @@ int main(int argc, char **argv) { | ||
| 19 | << ", opt count: " << opt->count() << std::endl; | 22 | << ", opt count: " << opt->count() << std::endl; |
| 20 | std::cout << "Working on count: " << count << ", direct count: " << app.count("--count") | 23 | std::cout << "Working on count: " << count << ", direct count: " << app.count("--count") |
| 21 | << ", opt count: " << copt->count() << std::endl; | 24 | << ", opt count: " << copt->count() << std::endl; |
| 25 | + std::cout << "Recieved flag: " << v << " (" << flag->count() << ") times\n"; | ||
| 22 | std::cout << "Some value: " << value << std::endl; | 26 | std::cout << "Some value: " << value << std::endl; |
| 23 | 27 | ||
| 24 | return 0; | 28 | return 0; |
include/CLI/App.hpp
| @@ -1196,7 +1196,9 @@ class App { | @@ -1196,7 +1196,9 @@ class App { | ||
| 1196 | if(num_left_over > 0) { | 1196 | if(num_left_over > 0) { |
| 1197 | args = remaining(false); | 1197 | args = remaining(false); |
| 1198 | std::reverse(std::begin(args), std::end(args)); | 1198 | std::reverse(std::begin(args), std::end(args)); |
| 1199 | - throw ExtrasError("[" + detail::rjoin(args, " ") + "]"); | 1199 | + throw ExtrasError((args.size() > 1 ? "The following argument was not expected: " |
| 1200 | + : "The following arguments were not expected: ") + | ||
| 1201 | + detail::rjoin(args, " ")); | ||
| 1200 | } | 1202 | } |
| 1201 | } | 1203 | } |
| 1202 | } | 1204 | } |
| @@ -1415,7 +1417,7 @@ class App { | @@ -1415,7 +1417,7 @@ class App { | ||
| 1415 | args.pop_back(); | 1417 | args.pop_back(); |
| 1416 | already_ate_one = true; | 1418 | already_ate_one = true; |
| 1417 | } | 1419 | } |
| 1418 | - } else | 1420 | + } else { |
| 1419 | while(num > 0 && !args.empty()) { | 1421 | while(num > 0 && !args.empty()) { |
| 1420 | num--; | 1422 | num--; |
| 1421 | std::string current_ = args.back(); | 1423 | std::string current_ = args.back(); |
| @@ -1424,6 +1426,12 @@ class App { | @@ -1424,6 +1426,12 @@ class App { | ||
| 1424 | parse_order_.push_back(op.get()); | 1426 | parse_order_.push_back(op.get()); |
| 1425 | } | 1427 | } |
| 1426 | 1428 | ||
| 1429 | + if(num > 0) { | ||
| 1430 | + throw RequiredError(op->single_name() + ": " + std::to_string(num) + " required " + | ||
| 1431 | + op->get_type_name() + " missing"); | ||
| 1432 | + } | ||
| 1433 | + } | ||
| 1434 | + | ||
| 1427 | if(!rest.empty()) { | 1435 | if(!rest.empty()) { |
| 1428 | rest = "-" + rest; | 1436 | rest = "-" + rest; |
| 1429 | args.push_back(rest); | 1437 | args.push_back(rest); |
| @@ -1499,6 +1507,10 @@ class App { | @@ -1499,6 +1507,10 @@ class App { | ||
| 1499 | parse_order_.push_back(op.get()); | 1507 | parse_order_.push_back(op.get()); |
| 1500 | args.pop_back(); | 1508 | args.pop_back(); |
| 1501 | } | 1509 | } |
| 1510 | + if(num > 0) { | ||
| 1511 | + throw RequiredError(op->single_name() + ": " + std::to_string(num) + " required " + | ||
| 1512 | + op->get_type_name() + " missing"); | ||
| 1513 | + } | ||
| 1502 | } | 1514 | } |
| 1503 | return; | 1515 | return; |
| 1504 | } | 1516 | } |
include/CLI/Option.hpp
| @@ -551,6 +551,9 @@ class Option : public OptionBase<Option> { | @@ -551,6 +551,9 @@ class Option : public OptionBase<Option> { | ||
| 551 | /// Set the type name displayed on this option | 551 | /// Set the type name displayed on this option |
| 552 | void set_type_name(std::string val) { typeval_ = val; } | 552 | void set_type_name(std::string val) { typeval_ = val; } |
| 553 | 553 | ||
| 554 | + /// Get the typename for this option | ||
| 555 | + std::string get_type_name() const { return typeval_; } | ||
| 556 | + | ||
| 554 | ///@} | 557 | ///@} |
| 555 | 558 | ||
| 556 | protected: | 559 | protected: |
tests/AppTest.cpp
| @@ -230,6 +230,19 @@ TEST_F(TApp, TakeLastOpt) { | @@ -230,6 +230,19 @@ TEST_F(TApp, TakeLastOpt) { | ||
| 230 | EXPECT_EQ(str, "two"); | 230 | EXPECT_EQ(str, "two"); |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | +TEST_F(TApp, MissingValueNonRequiredOpt) { | ||
| 234 | + int count; | ||
| 235 | + app.add_option("-c,--count", count); | ||
| 236 | + | ||
| 237 | + args = {"-c"}; | ||
| 238 | + EXPECT_ANY_THROW(run()); | ||
| 239 | + | ||
| 240 | + app.reset(); | ||
| 241 | + | ||
| 242 | + args = {"--count"}; | ||
| 243 | + EXPECT_ANY_THROW(run()); | ||
| 244 | +} | ||
| 245 | + | ||
| 233 | TEST_F(TApp, RequiredOptsSingle) { | 246 | TEST_F(TApp, RequiredOptsSingle) { |
| 234 | 247 | ||
| 235 | std::string str; | 248 | std::string str; |
| @@ -1189,7 +1202,7 @@ TEST_F(TApp, OrderedModifingTransforms) { | @@ -1189,7 +1202,7 @@ TEST_F(TApp, OrderedModifingTransforms) { | ||
| 1189 | TEST_F(TApp, ThrowingTransform) { | 1202 | TEST_F(TApp, ThrowingTransform) { |
| 1190 | std::string val; | 1203 | std::string val; |
| 1191 | auto m = app.add_option("-m,--mess", val); | 1204 | auto m = app.add_option("-m,--mess", val); |
| 1192 | - m->transform([](std::string x) -> std::string { throw CLI::ValidationError("My Message"); }); | 1205 | + m->transform([](std::string) -> std::string { throw CLI::ValidationError("My Message"); }); |
| 1193 | 1206 | ||
| 1194 | EXPECT_NO_THROW(run()); | 1207 | EXPECT_NO_THROW(run()); |
| 1195 | app.reset(); | 1208 | app.reset(); |
tests/NewParseTest.cpp