From 67c441b527ffa265023eec6c294f44eaf04039ab Mon Sep 17 00:00:00 2001 From: Philip Top Date: Sat, 10 Aug 2019 06:24:47 -0700 Subject: [PATCH] add separate condition for index into vectors remove restrictions on tuple size, and add some additional tests and modified documentation fix some issues with the negative number check add some test for indexed validation on tuple allow specific validators for specific elements in a type with multiple values, or to just apply to the last given argument --- README.md | 8 +- include/CLI/App.hpp | 12 ++- include/CLI/Option.hpp | 39 +++++-- include/CLI/TypeTools.hpp | 202 +++++++++++-------------------------- include/CLI/Validators.hpp | 17 +++- tests/AppTest.cpp | 102 +++++++++++++++++++ tests/HelpersTest.cpp | 41 +++++++- 7 files changed, 259 insertions(+), 162 deletions(-) diff --git a/README.md b/README.md index f3ece0dc..27af1a34 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ After I wrote this, I also found the following libraries: | [Clara][] | Simple library built for the excellent [Catch][] testing framework. Unique syntax, limited scope. | | [Argh!][] | Very minimalistic C++11 parser, single header. Don't have many features. No help generation?!?! At least it's exception-free. | | [CLI][] | Custom language and parser. Huge build-system overkill for very little benefit. Last release in 2009, but still occasionally active. | -|[argparse][] | C++17 single file argument parser. Design seems similar to CLI11 in some ways. | +| [argparse][] | C++17 single file argument parser. Design seems similar to CLI11 in some ways. | See [Awesome C++][] for a less-biased list of parsers. You can also find other single file libraries at [Single file libs][]. @@ -194,7 +194,7 @@ While all options internally are the same type, there are several ways to add an app.add_option(option_name, help_str="") // 🆕 app.add_option(option_name, - variable_to_bind_to, // bool, int, float, vector, 🆕 enum, or string-like, or anything with a defined conversion from a string or that takes an int🚧, double🚧, or string in a constructor. Also allowed are tuples(up to 5 elements) and tuple like structures such as std::array or std::pair. + variable_to_bind_to, // bool, int, float, vector, 🆕 enum, or string-like, or anything with a defined conversion from a string or that takes an int🚧, double🚧, or string in a constructor. Also allowed are tuples🚧,std::array🚧 or std::pair🚧. help_string="") app.add_option_function(option_name, @@ -202,7 +202,7 @@ app.add_option_function(option_name, help_string="") app.add_complex(... // Special case: support for complex numbers -//🚧There is a template overload which takes two template parameters the first is the type of object to assign the value to, the second is the conversion type. The conversion type should have a known way to convert from a string, such as any of the types that work in the non-template version. If XC is a std::pair and T is some non pair type. Then a two argument constructor for T is called to assign the value. +//🚧There is a template overload which takes two template parameters the first is the type of object to assign the value to, the second is the conversion type. The conversion type should have a known way to convert from a string, such as any of the types that work in the non-template version. If XC is a std::pair and T is some non pair type. Then a two argument constructor for T is called to assign the value. For tuples or other multi element types, XC must be a single type or a tuple like object of the same size as the assignment type app.add_option(option_name, T &output, // output must be assignable or constructible from a value of type XC help_string="") @@ -261,7 +261,7 @@ otherwise the output would default to a string. The add_option can be used with Type such as optional, optional, and optional are supported directly, other optional types can be added using the two parameter template. See [CLI11 Internals][] for information on how this could done and how you can add your own converters for additional types. -Vector types can also be used int the two parameter template overload +Vector types can also be used in the two parameter template overload ``` std::vector v1; app.add_option,int>("--vs",v1); diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index 43ceb653..fddb01b8 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -1859,8 +1859,14 @@ class App { return detail::Classifier::SUBCOMMAND; if(detail::split_long(current, dummy1, dummy2)) return detail::Classifier::LONG; - if(detail::split_short(current, dummy1, dummy2)) + if(detail::split_short(current, dummy1, dummy2)) { + if(dummy1[0] >= '0' && dummy1[0] <= '9') { + if(get_option_no_throw(std::string{'-', dummy1[0]}) == nullptr) { + return detail::Classifier::NONE; + } + } return detail::Classifier::SHORT; + } if((allow_windows_style_options_) && (detail::split_windows_style(current, dummy1, dummy2))) return detail::Classifier::WINDOWS; if((current == "++") && !name_.empty() && parent_ != nullptr) @@ -2314,7 +2320,7 @@ class App { (opt->get_items_expected() < 0 && opt->count() == 0lu)) { if(validate_positionals_) { std::string pos = positional; - pos = opt->_validate(pos); + pos = opt->_validate(pos, 0); if(!pos.empty()) { continue; } @@ -2334,7 +2340,7 @@ class App { (static_cast(opt->count()) < opt->get_items_expected() || opt->get_items_expected() < 0)) { if(validate_positionals_) { std::string pos = positional; - pos = opt->_validate(pos); + pos = opt->_validate(pos, 0); if(!pos.empty()) { continue; } diff --git a/include/CLI/Option.hpp b/include/CLI/Option.hpp index 5c1a2a25..8d980677 100644 --- a/include/CLI/Option.hpp +++ b/include/CLI/Option.hpp @@ -408,8 +408,17 @@ class Option : public OptionBase