mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-05-03 14:03:52 +00:00
Add vectors, fix bad bug
This commit is contained in:
parent
c36c913ac0
commit
47a7c3b89f
@ -87,7 +87,7 @@ struct Combiner {
|
|||||||
Combiner operator() (int n) const {
|
Combiner operator() (int n) const {
|
||||||
Combiner self = *this;
|
Combiner self = *this;
|
||||||
self.num = n;
|
self.num = n;
|
||||||
return *this;
|
return self;
|
||||||
}
|
}
|
||||||
/// Call to give a validator
|
/// Call to give a validator
|
||||||
Combiner operator() (std::function<bool(std::string)> func) const {
|
Combiner operator() (std::function<bool(std::string)> func) const {
|
||||||
@ -182,8 +182,7 @@ const Combiner NOTHING {0, false,false,false, {}};
|
|||||||
const Combiner REQUIRED {1, false,true, false, {}};
|
const Combiner REQUIRED {1, false,true, false, {}};
|
||||||
const Combiner DEFAULT {1, false,false,true, {}};
|
const Combiner DEFAULT {1, false,false,true, {}};
|
||||||
const Combiner POSITIONAL {1, true, false,false, {}};
|
const Combiner POSITIONAL {1, true, false,false, {}};
|
||||||
const Combiner ARGS {1, false,false,false, {}};
|
const Combiner ARGS {-1, false,false,false, {}};
|
||||||
const Combiner UNLIMITED {-1,false,false,false, {}};
|
|
||||||
const Combiner VALIDATORS {1, false, false, false, {}};
|
const Combiner VALIDATORS {1, false, false, false, {}};
|
||||||
|
|
||||||
// Warning about using these validators:
|
// Warning about using these validators:
|
||||||
@ -196,6 +195,8 @@ const Combiner NonexistentPath {1, false, false, false, {_NonexistentPath}};
|
|||||||
typedef std::vector<std::vector<std::string>> results_t;
|
typedef std::vector<std::vector<std::string>> results_t;
|
||||||
typedef std::function<bool(results_t)> callback_t;
|
typedef std::function<bool(results_t)> callback_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Option {
|
class Option {
|
||||||
public:
|
public:
|
||||||
protected:
|
protected:
|
||||||
@ -433,27 +434,28 @@ public:
|
|||||||
* std::string filename
|
* std::string filename
|
||||||
* program.add_option("filename", filename, "discription of filename");
|
* program.add_option("filename", filename, "discription of filename");
|
||||||
*/
|
*/
|
||||||
void add_option(
|
Option* add_option(
|
||||||
std::string name, ///< The name, long,short
|
std::string name, ///< The name, long,short
|
||||||
callback_t callback, ///< The callback
|
callback_t callback, ///< The callback
|
||||||
std::string discription="", ///< Discription string
|
std::string discription="", ///< Discription string
|
||||||
Combiner opts=ARGS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
|
Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
|
||||||
) {
|
) {
|
||||||
Option myopt{name, discription, opts, callback};
|
Option myopt{name, discription, opts, callback};
|
||||||
if(std::find(std::begin(options), std::end(options), myopt) == std::end(options))
|
if(std::find(std::begin(options), std::end(options), myopt) == std::end(options))
|
||||||
options.push_back(myopt);
|
options.push_back(myopt);
|
||||||
else
|
else
|
||||||
throw OptionAlreadyAdded(myopt.get_name());
|
throw OptionAlreadyAdded(myopt.get_name());
|
||||||
|
return &options.back();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add option for string
|
/// Add option for string
|
||||||
template<typename T, enable_if_t<!std::is_array<T>::value, detail::enabler> = dummy>
|
template<typename T, enable_if_t<!std::is_array<T>::value, detail::enabler> = dummy>
|
||||||
void add_option(
|
Option* add_option(
|
||||||
std::string name, ///< The name, long,short
|
std::string name, ///< The name, long,short
|
||||||
T &variable, ///< The variable to set
|
T &variable, ///< The variable to set
|
||||||
std::string discription="", ///< Discription string
|
std::string discription="", ///< Discription string
|
||||||
Combiner opts=ARGS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
|
Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|
||||||
@ -469,38 +471,37 @@ public:
|
|||||||
return lexical_cast(res[0][0], variable);
|
return lexical_cast(res[0][0], variable);
|
||||||
};
|
};
|
||||||
|
|
||||||
add_option(name, fun, discription, opts);
|
return add_option(name, fun, discription, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add option for vector of results
|
/// Add option for vector of results
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_option(
|
Option* add_option(
|
||||||
std::string name, ///< The name, long,short
|
std::string name, ///< The name, long,short
|
||||||
std::vector<T> &variable, ///< The variable to set
|
std::vector<T> &variable, ///< The variable to set
|
||||||
std::string discription="", ///< Discription string
|
std::string discription="", ///< Discription string
|
||||||
Combiner opts=ARGS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
|
Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
|
||||||
) {
|
) {
|
||||||
|
|
||||||
if(opts.num==0)
|
if(opts.num==0)
|
||||||
throw IncorrectConstruction("Must have ARGS(1) or be a vector.");
|
throw IncorrectConstruction("Must have ARGS or be a vector.");
|
||||||
CLI::callback_t fun = [&variable](CLI::results_t res){
|
CLI::callback_t fun = [&variable](CLI::results_t res){
|
||||||
bool retval = true;
|
bool retval = true;
|
||||||
int count = 0;
|
|
||||||
variable.clear();
|
variable.clear();
|
||||||
for(const auto &a : res)
|
for(const auto &a : res)
|
||||||
for(const auto &b : a) {
|
for(const auto &b : a) {
|
||||||
variable.emplace_back();
|
variable.emplace_back();
|
||||||
retval &= lexical_cast(b, variable.back());
|
retval &= lexical_cast(b, variable.back());
|
||||||
}
|
}
|
||||||
return count != 0 && retval;
|
return variable.size() > 0 && retval;
|
||||||
};
|
};
|
||||||
|
|
||||||
add_option(name, fun, discription, opts);
|
return add_option(name, fun, discription, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Add option for flag
|
/// Add option for flag
|
||||||
void add_flag(
|
Option* add_flag(
|
||||||
std::string name, ///< The name, short,long
|
std::string name, ///< The name, short,long
|
||||||
std::string discription="" ///< Discription string
|
std::string discription="" ///< Discription string
|
||||||
) {
|
) {
|
||||||
@ -508,12 +509,12 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
add_option(name, fun, discription, NOTHING);
|
return add_option(name, fun, discription, NOTHING);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add option for flag
|
/// Add option for flag
|
||||||
template<typename T, enable_if_t<std::is_integral<T>::value, detail::enabler> = dummy>
|
template<typename T, enable_if_t<std::is_integral<T>::value, detail::enabler> = dummy>
|
||||||
void add_flag(
|
Option* add_flag(
|
||||||
std::string name, ///< The name, short,long
|
std::string name, ///< The name, short,long
|
||||||
T &count, ///< A varaible holding the count
|
T &count, ///< A varaible holding the count
|
||||||
std::string discription="" ///< Discription string
|
std::string discription="" ///< Discription string
|
||||||
@ -525,19 +526,22 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
add_option(name, fun, discription, NOTHING);
|
return add_option(name, fun, discription, NOTHING);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add set of options
|
/// Add set of options
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_set(
|
Option* add_set(
|
||||||
std::string name, ///< The name, short,long
|
std::string name, ///< The name, short,long
|
||||||
T &member, ///< The selected member of the set
|
T &member, ///< The selected member of the set
|
||||||
std::unordered_set<T> options, ///< The set of posibilities
|
std::unordered_set<T> options, ///< The set of posibilities
|
||||||
std::string discription="", ///< Discription string
|
std::string discription="", ///< Discription string
|
||||||
Combiner opts=ARGS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
|
Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
if(opts.num!=1)
|
||||||
|
throw IncorrectConstruction("Must have ARGS(1).");
|
||||||
|
|
||||||
CLI::callback_t fun = [&member, options](CLI::results_t res){
|
CLI::callback_t fun = [&member, options](CLI::results_t res){
|
||||||
if(res.size()!=1) {
|
if(res.size()!=1) {
|
||||||
return false;
|
return false;
|
||||||
@ -551,7 +555,7 @@ public:
|
|||||||
return std::find(std::begin(options), std::end(options), retval) != std::end(options);
|
return std::find(std::begin(options), std::end(options), retval) != std::end(options);
|
||||||
};
|
};
|
||||||
|
|
||||||
add_option(name, fun, discription, opts);
|
return add_option(name, fun, discription, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -249,10 +249,37 @@ TEST_F(TApp, FileExists) {
|
|||||||
EXPECT_FALSE(CLI::_ExistingFile(myfile));
|
EXPECT_FALSE(CLI::_ExistingFile(myfile));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(TApp, VectorFixedString) {
|
||||||
|
std::vector<std::string> strvec;
|
||||||
|
std::vector<std::string> answer{"mystring", "mystring2", "mystring3"};
|
||||||
|
|
||||||
// TODO: Add directory test
|
CLI::Option* opt = app.add_option("s,string", strvec, "", CLI::ARGS(3));
|
||||||
|
EXPECT_EQ(3, opt->expected());
|
||||||
|
|
||||||
TEST_F(TApp, Basic) {
|
args = {"--string", "mystring", "mystring2", "mystring3"};
|
||||||
|
run();
|
||||||
|
EXPECT_EQ(3, app.count("string"));
|
||||||
|
EXPECT_EQ(answer, strvec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(TApp, VectorUnlimString) {
|
||||||
|
std::vector<std::string> strvec;
|
||||||
|
std::vector<std::string> answer{"mystring", "mystring2", "mystring3"};
|
||||||
|
|
||||||
|
CLI::Option* opt = app.add_option("s,string", strvec, "", CLI::ARGS);
|
||||||
|
EXPECT_EQ(-1, opt->expected());
|
||||||
|
|
||||||
|
args = {"--string", "mystring", "mystring2", "mystring3"};
|
||||||
|
EXPECT_NO_THROW(run());
|
||||||
|
EXPECT_EQ(3, app.count("string"));
|
||||||
|
EXPECT_EQ(answer, strvec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(TApp, BasicSubcommands) {
|
||||||
auto sub1 = app.add_subcommand("sub1");
|
auto sub1 = app.add_subcommand("sub1");
|
||||||
auto sub2 = app.add_subcommand("sub2");
|
auto sub2 = app.add_subcommand("sub2");
|
||||||
|
|
||||||
@ -272,6 +299,9 @@ TEST_F(TApp, Basic) {
|
|||||||
EXPECT_EQ(sub2, app.get_subcommand());
|
EXPECT_EQ(sub2, app.get_subcommand());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add directory test
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct SubcommandProgram : public TApp {
|
struct SubcommandProgram : public TApp {
|
||||||
|
|
||||||
@ -316,7 +346,7 @@ TEST_F(SubcommandProgram, SpareSub) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add vector arguments
|
// TODO: Add vector arguments
|
||||||
// TODO: Maybe add function to call on subcommand parse?
|
// TODO: Maybe add function to call on subcommand parse? Stashed.
|
||||||
// TODO: Check help output
|
// TODO: Check help output
|
||||||
// TODO: Add default/type info to help
|
// TODO: Add default/type info to help
|
||||||
// TODO: Add set checking
|
// TODO: Add set checking
|
||||||
|
Loading…
x
Reference in New Issue
Block a user