Commit 0667d7a88e53248bb5d6b63ac306e24133b334c4
1 parent
47a7c3b8
test Value type
Showing
2 changed files
with
73 additions
and
1 deletions
include/CLI.hpp
| ... | ... | @@ -160,6 +160,9 @@ struct HorribleError : public Error { |
| 160 | 160 | struct IncorrectConstruction : public Error { |
| 161 | 161 | IncorrectConstruction(std::string name) : Error("IncorrectConstruction", name, 8) {} |
| 162 | 162 | }; |
| 163 | +struct EmptyError : public Error { | |
| 164 | + EmptyError(std::string name) : Error("EmptyError", name, 9) {} | |
| 165 | +}; | |
| 163 | 166 | |
| 164 | 167 | const std::regex reg_split{R"regex((?:([a-zA-Z0-9]?)(?:,|$)|^)([a-zA-Z0-9][a-zA-Z0-9_\-]*)?)regex"}; |
| 165 | 168 | const std::regex reg_short{R"regex(-([^-])(.*))regex"}; |
| ... | ... | @@ -372,8 +375,32 @@ bool lexical_cast(std::string input, T& output) { |
| 372 | 375 | |
| 373 | 376 | enum class Classifer {NONE, POSITIONAL_MARK, SHORT, LONG, SUBCOMMAND}; |
| 374 | 377 | |
| 378 | + | |
| 375 | 379 | class App; |
| 376 | 380 | |
| 381 | +// Prototype return value test | |
| 382 | +template <typename T> | |
| 383 | +class Value { | |
| 384 | + friend App; | |
| 385 | +protected: | |
| 386 | + std::unique_ptr<std::unique_ptr<T>> value {new std::unique_ptr<T>()}; | |
| 387 | + std::string name; | |
| 388 | +public: | |
| 389 | + Value(std::string name) : name(name) {} | |
| 390 | + operator bool() const {return (bool) *value;} | |
| 391 | + //explicit operator T () const {return **this;} | |
| 392 | + T operator *() const { | |
| 393 | + if(*value) { | |
| 394 | + //std::cout << "Succ" << std::endl; | |
| 395 | + return **value; | |
| 396 | + } | |
| 397 | + else { | |
| 398 | + //std::cout << "Throwing!!!" << std::endl; | |
| 399 | + throw EmptyError(name); | |
| 400 | + } | |
| 401 | + } | |
| 402 | +}; | |
| 403 | + | |
| 377 | 404 | /// Creates a command line program, with very few defaults. |
| 378 | 405 | /** To use, create a new Program() instance with argc, argv, and a help discription. The templated |
| 379 | 406 | * add_option methods make it easy to prepare options. Remember to call `.start` before starting your |
| ... | ... | @@ -558,6 +585,30 @@ public: |
| 558 | 585 | return add_option(name, fun, discription, opts); |
| 559 | 586 | } |
| 560 | 587 | |
| 588 | + /// Prototype for new output style | |
| 589 | + template<typename T = std::string> | |
| 590 | + Value<T> make_option( | |
| 591 | + std::string name, ///< The name, short,long | |
| 592 | + std::string discription="", | |
| 593 | + Combiner opts=VALIDATORS | |
| 594 | + ) { | |
| 595 | + | |
| 596 | + Value<T> out(name); | |
| 597 | + std::unique_ptr<T> *ptr = out.value.get(); | |
| 598 | + | |
| 599 | + CLI::callback_t fun = [ptr](CLI::results_t res){ | |
| 600 | + if(res.size()!=1) { | |
| 601 | + return false; | |
| 602 | + } | |
| 603 | + if(res[0].size()!=1) { | |
| 604 | + return false; | |
| 605 | + } | |
| 606 | + ptr->reset(new T()); | |
| 607 | + return lexical_cast(res[0][0], **ptr); | |
| 608 | + }; | |
| 609 | + add_option(name, fun, discription, opts); | |
| 610 | + return std::move(out); | |
| 611 | + } | |
| 561 | 612 | |
| 562 | 613 | |
| 563 | 614 | /// Parses the command line - throws errors | ... | ... |
tests/CLITest.cpp
| ... | ... | @@ -345,10 +345,31 @@ TEST_F(SubcommandProgram, SpareSub) { |
| 345 | 345 | EXPECT_THROW(run(), CLI::PositionalError); |
| 346 | 346 | } |
| 347 | 347 | |
| 348 | +class TAppValue : public TApp {}; | |
| 349 | + | |
| 350 | +TEST_F(TAppValue, OneString) { | |
| 351 | + auto str = app.make_option("s,string"); | |
| 352 | + std::string v; | |
| 353 | + args = {"--string", "mystring"}; | |
| 354 | + EXPECT_FALSE((bool) str); | |
| 355 | + EXPECT_THROW(v = *str, CLI::EmptyError); | |
| 356 | + //EXPECT_THROW(v = str, CLI::EmptyError); | |
| 357 | + EXPECT_FALSE((bool) str); | |
| 358 | + EXPECT_NO_THROW(run()); | |
| 359 | + EXPECT_TRUE((bool) str); | |
| 360 | + EXPECT_NO_THROW(v = *str); | |
| 361 | + EXPECT_NO_THROW(v = str); | |
| 362 | + | |
| 363 | + EXPECT_EQ(1, app.count("s")); | |
| 364 | + EXPECT_EQ(1, app.count("string")); | |
| 365 | + EXPECT_EQ(*str, "mystring"); | |
| 366 | + | |
| 367 | +} | |
| 368 | + | |
| 348 | 369 | // TODO: Add vector arguments |
| 349 | 370 | // TODO: Maybe add function to call on subcommand parse? Stashed. |
| 350 | 371 | // TODO: Check help output |
| 351 | 372 | // TODO: Add default/type info to help |
| 352 | 373 | // TODO: Add set checking |
| 353 | 374 | // TODO: Try all of the options together |
| 354 | -// TODO: Add make_option alternative with type | |
| 375 | +// TODO: Add make_option alternative with type? Cancelled for now | ... | ... |