mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-05-01 13:13:53 +00:00
Support for multiple names on option
This commit is contained in:
parent
a80ac7b750
commit
cc3fa6009d
@ -287,34 +287,6 @@ inline void cleanup_names(const std::vector<std::string> &input) {
|
||||
}
|
||||
}
|
||||
|
||||
// Splits a string into long and short names
|
||||
inline std::tuple<std::string, std::string> split(std::string fullname) {
|
||||
if(fullname.find(" ") != std::string::npos)
|
||||
throw BadNameString("Cannot have space in name string: "+fullname);
|
||||
std::vector<std::string> output = split_names(fullname);
|
||||
cleanup_names(output);
|
||||
|
||||
if(output.size() > 2)
|
||||
throw BadNameString(fullname);
|
||||
else if (output.size() == 2) {
|
||||
if(output[0].length()==0 && output[1].length()==0)
|
||||
throw BadNameString("EMPTY");
|
||||
else if(output[0].length()<2)
|
||||
return std::tuple<std::string,std::string>(output[0], output[1]);
|
||||
else if(output[1].length() < 2)
|
||||
return std::tuple<std::string,std::string>(output[0], output[1]);
|
||||
else
|
||||
throw BadNameString(fullname);
|
||||
} else {
|
||||
if(output[0].length()==0)
|
||||
throw BadNameString("EMPTY");
|
||||
else if(output[0].length() == 1)
|
||||
return std::tuple<std::string,std::string>(output[0], "");
|
||||
else
|
||||
return std::tuple<std::string,std::string>("", output[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const Combiner NOTHING {0, false,false,false, {}};
|
||||
const Combiner REQUIRED {1, false,true, false, {}};
|
||||
@ -339,8 +311,8 @@ class Option {
|
||||
public:
|
||||
protected:
|
||||
// Config
|
||||
std::string sname;
|
||||
std::string lname;
|
||||
std::vector<std::string> snames;
|
||||
std::vector<std::string> lnames;
|
||||
Combiner opts;
|
||||
std::string discription;
|
||||
callback_t callback;
|
||||
@ -352,7 +324,7 @@ protected:
|
||||
public:
|
||||
Option(std::string name, std::string discription = "", Combiner opts=NOTHING, std::function<bool(results_t)> callback=[](results_t){return true;}) :
|
||||
opts(opts), discription(discription), callback(callback){
|
||||
std::tie(sname, lname) = split(name);
|
||||
std::tie(snames, lnames) = get_names(split_names(name));
|
||||
}
|
||||
|
||||
void clear() {
|
||||
@ -386,44 +358,44 @@ public:
|
||||
return callback(results);
|
||||
}
|
||||
|
||||
/// Indistinguishible options are equal
|
||||
/// If options share any of the same names, they are equal
|
||||
bool operator== (const Option& other) const {
|
||||
if(sname=="" && other.sname=="")
|
||||
return lname==other.lname;
|
||||
else if(lname=="" && other.lname=="")
|
||||
return sname==other.sname;
|
||||
else
|
||||
return sname==other.sname || lname==other.lname;
|
||||
for(const std::string &sname : snames)
|
||||
for(const std::string &othersname : other.snames)
|
||||
if(sname == othersname)
|
||||
return true;
|
||||
for(const std::string &lname : lnames)
|
||||
for(const std::string &otherlname : other.lnames)
|
||||
if(lname == otherlname)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string get_name() const {
|
||||
if(sname=="")
|
||||
return "--" + lname;
|
||||
else if (lname=="")
|
||||
return "-" + sname;
|
||||
else
|
||||
return "-" + sname + ", --" + lname;
|
||||
std::vector<std::string> name_list;
|
||||
for(const std::string& sname : snames)
|
||||
name_list.push_back("-"+sname);
|
||||
for(const std::string& lname : lnames)
|
||||
name_list.push_back("--"+lname);
|
||||
return join(name_list);
|
||||
}
|
||||
|
||||
bool check_name(const std::string& name) const {
|
||||
return name == sname || name == lname || name == sname + "," + lname;
|
||||
bool check_name(std::string name) const {
|
||||
for(int i=0; i<2; i++)
|
||||
if(name.length()>2 && name[0] == '-')
|
||||
name = name.substr(1);
|
||||
|
||||
return check_sname(name) || check_lname(name);
|
||||
}
|
||||
|
||||
bool check_sname(const std::string& name) const {
|
||||
return name == sname;
|
||||
return std::find(std::begin(snames), std::end(snames), name) != std::end(snames);
|
||||
}
|
||||
|
||||
bool check_lname(const std::string& name) const {
|
||||
return name == lname;
|
||||
return std::find(std::begin(lnames), std::end(lnames), name) != std::end(lnames);
|
||||
}
|
||||
|
||||
std::string get_sname() const {
|
||||
return sname;
|
||||
}
|
||||
|
||||
std::string get_lname() const {
|
||||
return lname;
|
||||
}
|
||||
|
||||
void add_result(int r, std::string s) {
|
||||
logit("Adding result: " + s);
|
||||
@ -976,7 +948,7 @@ public:
|
||||
auto op = std::find_if(std::begin(options), std::end(options), [name](const Option &v){return v.check_sname(name);});
|
||||
|
||||
if(op == std::end(options)) {
|
||||
missing_options.push_back("-" + op->get_sname());
|
||||
missing_options.push_back("-" + name);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1044,7 +1016,7 @@ public:
|
||||
auto op = std::find_if(std::begin(options), std::end(options), [name](const Option &v){return v.check_lname(name);});
|
||||
|
||||
if(op == std::end(options)) {
|
||||
missing_options.push_back("--" + op->get_lname());
|
||||
missing_options.push_back("--" + name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,21 @@ TEST_F(TApp, OneFlagLong) {
|
||||
EXPECT_EQ(1, app.count("count"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, DashedOptions) {
|
||||
app.add_flag("-c");
|
||||
app.add_flag("--q");
|
||||
app.add_flag("--this,--that");
|
||||
|
||||
args = {"-c", "--q", "--this", "--that"};
|
||||
EXPECT_NO_THROW(run());
|
||||
EXPECT_EQ(1, app.count("c"));
|
||||
EXPECT_EQ(1, app.count("q"));
|
||||
EXPECT_EQ(2, app.count("this"));
|
||||
EXPECT_EQ(2, app.count("--that"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, OneFlagRef) {
|
||||
int ref;
|
||||
app.add_flag("c,count", ref);
|
||||
@ -454,9 +469,6 @@ TEST_F(TAppValue, DoubleVector) {
|
||||
EXPECT_EQ(std::vector<double>({1.2, 3.4, -1}), *value);
|
||||
}
|
||||
|
||||
// TODO: Maybe add function to call on subcommand parse? Stashed.
|
||||
// TODO: Check help output, better formatting
|
||||
// TODO: Add default/type info to help
|
||||
// TODO: Add regex replacement function (GCC 4.8 support)
|
||||
// TODO: Add README
|
||||
// TODO: Change format of option specifications?
|
||||
|
@ -4,44 +4,6 @@
|
||||
#include <fstream>
|
||||
|
||||
|
||||
TEST(Split, GoodStrings) {
|
||||
std::string s, l;
|
||||
|
||||
std::tie(s, l) = CLI::split("a,boo");
|
||||
EXPECT_EQ("a", s);
|
||||
EXPECT_EQ("boo", l);
|
||||
|
||||
std::tie(s, l) = CLI::split(",coo");
|
||||
EXPECT_EQ("", s);
|
||||
EXPECT_EQ("coo", l);
|
||||
|
||||
std::tie(s, l) = CLI::split("d,");
|
||||
EXPECT_EQ("d", s);
|
||||
EXPECT_EQ("", l);
|
||||
|
||||
std::tie(s, l) = CLI::split("Q,this-is");
|
||||
EXPECT_EQ("Q", s);
|
||||
EXPECT_EQ("this-is", l);
|
||||
|
||||
std::tie(s, l) = CLI::split("s");
|
||||
EXPECT_EQ("s", s);
|
||||
EXPECT_EQ("", l);
|
||||
|
||||
std::tie(s, l) = CLI::split("single");
|
||||
EXPECT_EQ("", s);
|
||||
EXPECT_EQ("single", l);
|
||||
}
|
||||
|
||||
TEST(Split, BadStrings) {
|
||||
|
||||
EXPECT_THROW(CLI::split("a,,boo"), CLI::BadNameString);
|
||||
EXPECT_THROW(CLI::split("a,b,c"), CLI::BadNameString);
|
||||
EXPECT_THROW(CLI::split("ssd,sfd"), CLI::BadNameString);
|
||||
EXPECT_THROW(CLI::split("-a"), CLI::BadNameString);
|
||||
EXPECT_THROW(CLI::split(""), CLI::BadNameString);
|
||||
EXPECT_THROW(CLI::split(","), CLI::BadNameString);
|
||||
EXPECT_THROW(CLI::split("one two"), CLI::BadNameString);
|
||||
}
|
||||
|
||||
TEST(Validators, FileExists) {
|
||||
std::string myfile{"TestFileNotUsed.txt"};
|
||||
|
Loading…
x
Reference in New Issue
Block a user