Commit 3d309dc0be32601ea98c6c36e5969a982fcb869e

Authored by Henry Fredrick Schreiner
1 parent d28c230e

Adding fail if required values missing

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&lt;Option&gt; { @@ -551,6 +551,9 @@ class Option : public OptionBase&lt;Option&gt; {
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
@@ -91,5 +91,5 @@ TEST_F(TApp, BuiltinComplexFail) { @@ -91,5 +91,5 @@ TEST_F(TApp, BuiltinComplexFail) {
91 91
92 args = {"-c", "4"}; 92 args = {"-c", "4"};
93 93
94 - EXPECT_THROW(run(), CLI::ConversionError); 94 + EXPECT_THROW(run(), CLI::RequiredError);
95 } 95 }