mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-04-30 12:43:52 +00:00
Massive move to -a,--long,posit syntax
This commit is contained in:
parent
955dd950f0
commit
200d0f277f
@ -6,13 +6,13 @@ int main (int argc, char** argv) {
|
||||
CLI::App app("K3Pi goofit fitter");
|
||||
|
||||
std::string file;
|
||||
app.add_option("f,file", file, "File name");
|
||||
app.add_option("-f,--file", file, "File name");
|
||||
|
||||
int count;
|
||||
app.add_flag("c,count", count, "Counter");
|
||||
app.add_flag("-c,--count", count, "Counter");
|
||||
|
||||
double value = 3.14;
|
||||
app.add_option("-d,--double", value, "Some Value", CLI::DEFAULT);
|
||||
app.add_option("-d,--double", value, "Some Value", CLI::Default);
|
||||
|
||||
try {
|
||||
app.run(argc, argv);
|
||||
@ -20,8 +20,8 @@ int main (int argc, char** argv) {
|
||||
return app.exit(e);
|
||||
}
|
||||
|
||||
std::cout << "Working on file: " << file << ", direct count: " << app.count("file") << std::endl;
|
||||
std::cout << "Working on count: " << count << ", direct count: " << app.count("count") << std::endl;
|
||||
std::cout << "Working on file: " << file << ", direct count: " << app.count("--file") << std::endl;
|
||||
std::cout << "Working on count: " << count << ", direct count: " << app.count("--count") << std::endl;
|
||||
std::cout << "Some value: " << value << std::endl;
|
||||
|
||||
return 0;
|
||||
|
@ -9,10 +9,10 @@ int main (int argc, char** argv) {
|
||||
|
||||
std::cout << app.help();
|
||||
std::string file;
|
||||
start->add_option("f,file", file, "File name");
|
||||
start->add_option("-f,--file", file, "File name");
|
||||
|
||||
int count;
|
||||
stop->add_flag("c,count", count, "Counter");
|
||||
stop->add_flag("-c,--count", count, "Counter");
|
||||
|
||||
try {
|
||||
app.run(argc, argv);
|
||||
@ -20,8 +20,8 @@ int main (int argc, char** argv) {
|
||||
return app.exit(e);
|
||||
}
|
||||
|
||||
std::cout << "Working on file: " << file << ", direct count: " << start->count("file") << std::endl;
|
||||
std::cout << "Working on count: " << count << ", direct count: " << stop->count("count") << std::endl;
|
||||
std::cout << "Working on file: " << file << ", direct count: " << start->count("--file") << std::endl;
|
||||
std::cout << "Working on count: " << count << ", direct count: " << stop->count("--count") << std::endl;
|
||||
if(app.get_subcommand() != nullptr)
|
||||
std::cout << "Subcommand:" << app.get_subcommand()->get_name() << std::endl;
|
||||
|
||||
|
281
include/CLI.hpp
281
include/CLI.hpp
@ -178,7 +178,6 @@ namespace detail {
|
||||
|
||||
struct Combiner {
|
||||
int num;
|
||||
bool positional;
|
||||
bool required;
|
||||
bool defaulted;
|
||||
std::vector<std::function<bool(std::string)>> validators;
|
||||
@ -187,7 +186,6 @@ namespace detail {
|
||||
Combiner operator | (Combiner b) const {
|
||||
Combiner self;
|
||||
self.num = std::min(num, b.num) == -1 ? -1 : std::max(num, b.num);
|
||||
self.positional = positional || b.positional;
|
||||
self.required = required || b.required;
|
||||
self.defaulted = defaulted || b.defaulted;
|
||||
self.validators.reserve(validators.size() + b.validators.size());
|
||||
@ -290,36 +288,39 @@ namespace detail {
|
||||
}
|
||||
|
||||
|
||||
inline std::tuple<std::vector<std::string>,std::vector<std::string>> get_names(const std::vector<std::string> &input) {
|
||||
inline std::tuple<std::vector<std::string>,std::vector<std::string>, std::string>
|
||||
get_names(const std::vector<std::string> &input) {
|
||||
|
||||
std::vector<std::string> short_names;
|
||||
std::vector<std::string> long_names;
|
||||
std::string pos_name;
|
||||
|
||||
for(std::string name : input) {
|
||||
if(name.length() == 0)
|
||||
continue;
|
||||
else if(name.length() == 1)
|
||||
if(valid_first_char(name[0]))
|
||||
short_names.push_back(name);
|
||||
else
|
||||
throw BadNameString("Invalid one char name: "+name);
|
||||
else if(name.length() == 2 && name[0] == '-' && name[1] != '-') {
|
||||
if(valid_first_char(name[1]))
|
||||
else if(name.length() > 1 && name[0] == '-' && name[1] != '-') {
|
||||
if(name.length()==2 && valid_first_char(name[1]))
|
||||
short_names.push_back(std::string(1,name[1]));
|
||||
else
|
||||
throw BadNameString("Invalid one char name: "+name);
|
||||
} else {
|
||||
|
||||
if(name.substr(0,2) == "--")
|
||||
name = name.substr(2);
|
||||
} else if(name.length() > 2 && name.substr(0,2) == "--") {
|
||||
name = name.substr(2);
|
||||
if(valid_name_string(name))
|
||||
long_names.push_back(name);
|
||||
else
|
||||
throw BadNameString("Bad long name"+name);
|
||||
throw BadNameString("Bad long name: "+name);
|
||||
} else if(name == "-" || name == "--") {
|
||||
throw BadNameString("Must have a name, not just dashes");
|
||||
} else {
|
||||
if(pos_name.length() > 0)
|
||||
throw BadNameString("Only one positional name allowed, remove: "+name);
|
||||
pos_name = name;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return std::tuple<std::vector<std::string>,std::vector<std::string>>(short_names, long_names);
|
||||
return std::tuple<std::vector<std::string>,std::vector<std::string>, std::string>
|
||||
(short_names, long_names, pos_name);
|
||||
}
|
||||
|
||||
// Integers
|
||||
@ -373,19 +374,18 @@ namespace detail {
|
||||
|
||||
// Defines for common Combiners (don't use combiners directly)
|
||||
|
||||
const detail::Combiner NOTHING {0, false,false,false, {}};
|
||||
const detail::Combiner REQUIRED {1, false,true, false, {}};
|
||||
const detail::Combiner DEFAULT {1, false,false,true, {}};
|
||||
const detail::Combiner POSITIONAL {1, true, false,false, {}};
|
||||
const detail::Combiner ARGS {-1, false,false,false, {}};
|
||||
const detail::Combiner VALIDATORS {1, false, false, false, {}};
|
||||
const detail::Combiner Nothing {0, false, false, {}};
|
||||
const detail::Combiner Required {1, true, false, {}};
|
||||
const detail::Combiner Default {1, false, true, {}};
|
||||
const detail::Combiner Args {-1, false, false, {}};
|
||||
const detail::Combiner Validators {1, false, false, {}};
|
||||
|
||||
// Warning about using these validators:
|
||||
// The files could be added/deleted after the validation. This is not common,
|
||||
// but if this is a possibility, check the file you open afterwards
|
||||
const detail::Combiner ExistingFile {1, false, false, false, {detail::_ExistingFile}};
|
||||
const detail::Combiner ExistingDirectory {1, false, false, false, {detail::_ExistingDirectory}};
|
||||
const detail::Combiner NonexistentPath {1, false, false, false, {detail::_NonexistentPath}};
|
||||
const detail::Combiner ExistingFile {1, false, false, {detail::_ExistingFile}};
|
||||
const detail::Combiner ExistingDirectory {1, false, false, {detail::_ExistingDirectory}};
|
||||
const detail::Combiner NonexistentPath {1, false, false, {detail::_NonexistentPath}};
|
||||
|
||||
typedef std::vector<std::vector<std::string>> results_t;
|
||||
typedef std::function<bool(results_t)> callback_t;
|
||||
@ -399,6 +399,8 @@ protected:
|
||||
// Config
|
||||
std::vector<std::string> snames;
|
||||
std::vector<std::string> lnames;
|
||||
std::string pname;
|
||||
|
||||
detail::Combiner opts;
|
||||
std::string discription;
|
||||
callback_t callback;
|
||||
@ -412,31 +414,62 @@ protected:
|
||||
|
||||
|
||||
public:
|
||||
Option(std::string name, std::string discription = "", detail::Combiner opts=NOTHING, std::function<bool(results_t)> callback=[](results_t){return true;}) :
|
||||
Option(std::string name, std::string discription = "", detail::Combiner opts=Nothing, std::function<bool(results_t)> callback=[](results_t){return true;}) :
|
||||
opts(opts), discription(discription), callback(callback){
|
||||
std::tie(snames, lnames) = detail::get_names(detail::split_names(name));
|
||||
std::tie(snames, lnames, pname) = detail::get_names(detail::split_names(name));
|
||||
}
|
||||
|
||||
/// Clear the parsed results (mostly for testing)
|
||||
void clear() {
|
||||
results.clear();
|
||||
}
|
||||
|
||||
/// True if option is required
|
||||
bool required() const {
|
||||
return opts.required;
|
||||
}
|
||||
|
||||
/// The number of arguments the option expects
|
||||
int expected() const {
|
||||
return opts.num;
|
||||
}
|
||||
|
||||
/// True if the argument can be given directly
|
||||
bool positional() const {
|
||||
return opts.positional;
|
||||
return pname.length() > 0;
|
||||
}
|
||||
|
||||
/// True if option has at least one non-positional name
|
||||
bool nonpositional() const {
|
||||
return (snames.size() + lnames.size()) > 0;
|
||||
}
|
||||
|
||||
/// True if this should print the default string
|
||||
bool defaulted() const {
|
||||
return opts.defaulted;
|
||||
}
|
||||
|
||||
/// True if option has discription
|
||||
bool has_discription() const {
|
||||
return discription.length() > 0;
|
||||
}
|
||||
|
||||
/// Get the discription
|
||||
const std::string& get_discription() const {
|
||||
return discription;
|
||||
}
|
||||
|
||||
/// The name and any extras needed for positionals
|
||||
std::string help_positional() const {
|
||||
std::string out = pname;
|
||||
if(expected()<1)
|
||||
out = out + "x" + std::to_string(expected());
|
||||
else if(expected()==-1)
|
||||
out = out + "...";
|
||||
out = required() ? out : "["+out+"]";
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Process the callback
|
||||
bool run_callback() const {
|
||||
if(opts.validators.size()>0) {
|
||||
@ -448,7 +481,7 @@ public:
|
||||
return callback(results);
|
||||
}
|
||||
|
||||
/// If options share any of the same names, they are equal
|
||||
/// If options share any of the same names, they are equal (not counting positional)
|
||||
bool operator== (const Option& other) const {
|
||||
for(const std::string &sname : snames)
|
||||
for(const std::string &othersname : other.snames)
|
||||
@ -461,6 +494,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Gets a , sep list of names. Does not include the positional name.
|
||||
std::string get_name() const {
|
||||
std::vector<std::string> name_list;
|
||||
for(const std::string& sname : snames)
|
||||
@ -470,30 +504,40 @@ public:
|
||||
return detail::join(name_list);
|
||||
}
|
||||
|
||||
/// Check a name. Requires "-" or "--" for short / long, supports positional name
|
||||
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);
|
||||
if(name.length()>2 && name.substr(0,2) == "--")
|
||||
return check_lname(name.substr(2));
|
||||
else if (name.length()>1 && name.substr(0,1) == "-")
|
||||
return check_sname(name.substr(1));
|
||||
else
|
||||
return name == pname;
|
||||
}
|
||||
|
||||
/// Requires "-" to be removed from string
|
||||
bool check_sname(const std::string& name) const {
|
||||
return std::find(std::begin(snames), std::end(snames), name) != std::end(snames);
|
||||
}
|
||||
|
||||
/// Requires "--" to be removed from string
|
||||
bool check_lname(const std::string& name) const {
|
||||
return std::find(std::begin(lnames), std::end(lnames), name) != std::end(lnames);
|
||||
}
|
||||
|
||||
|
||||
/// Puts a result at position r
|
||||
void add_result(int r, std::string s) {
|
||||
results.at(r).push_back(s);
|
||||
}
|
||||
|
||||
/// Starts a new results vector (used for r in add_result)
|
||||
int get_new() {
|
||||
results.emplace_back();
|
||||
return results.size() - 1;
|
||||
}
|
||||
|
||||
/// Count the total number of times an option was passed
|
||||
int count() const {
|
||||
int out = 0;
|
||||
for(const std::vector<std::string>& v : results)
|
||||
@ -501,6 +545,7 @@ public:
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Diagnostic representation
|
||||
std::string string() const {
|
||||
std::string val = "Option: " + get_name() + "\n"
|
||||
+ " " + discription + "\n"
|
||||
@ -514,6 +559,7 @@ public:
|
||||
return val;
|
||||
}
|
||||
|
||||
/// The first half of the help print, name plus default, etc
|
||||
std::string help_name() const {
|
||||
std::stringstream out;
|
||||
out << " " << get_name();
|
||||
@ -530,10 +576,12 @@ public:
|
||||
return out.str();
|
||||
}
|
||||
|
||||
/// The length of the name part of the help, for formatting
|
||||
int help_len() const {
|
||||
return help_name().length();
|
||||
}
|
||||
|
||||
/// Make a help string, adjustable len.
|
||||
std::string help(int len = 0) const {
|
||||
std::stringstream out;
|
||||
if(help_len() > len) {
|
||||
@ -547,6 +595,7 @@ public:
|
||||
return out.str();
|
||||
}
|
||||
|
||||
/// Produce a flattened vector of results, vs. a vector of vectors.
|
||||
std::vector<std::string> flatten_results() const {
|
||||
std::vector<std::string> output;
|
||||
for(const std::vector<std::string> result : results)
|
||||
@ -602,6 +651,7 @@ protected:
|
||||
std::vector<std::unique_ptr<App>> subcommands;
|
||||
bool parsed{false};
|
||||
App* subcommand = nullptr;
|
||||
std::string progname = "program";
|
||||
|
||||
std::function<void()> app_callback;
|
||||
|
||||
@ -639,7 +689,7 @@ public:
|
||||
App(std::string prog_discription="")
|
||||
: prog_discription(prog_discription) {
|
||||
|
||||
add_flag("h,help", "Print this help message and exit");
|
||||
add_flag("-h,--help", "Print this help message and exit");
|
||||
|
||||
}
|
||||
|
||||
@ -657,7 +707,7 @@ public:
|
||||
* After start is called, you can use count to see if the value was passed, and
|
||||
* the value will be initialized properly.
|
||||
*
|
||||
* Program::REQUIRED, Program::DEFAULT, and Program::POSITIONAL are options, and can be `|`
|
||||
* Program::Required, Program::Default, and the validators are options, and can be `|`
|
||||
* together. The positional options take an optional number of arguments.
|
||||
*
|
||||
* For example,
|
||||
@ -666,10 +716,10 @@ public:
|
||||
* program.add_option("filename", filename, "discription of filename");
|
||||
*/
|
||||
Option* add_option(
|
||||
std::string name, ///< The name, long,short
|
||||
callback_t callback, ///< The callback
|
||||
std::string discription="", ///< Discription string
|
||||
detail::Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
|
||||
std::string name,
|
||||
callback_t callback,
|
||||
std::string discription="",
|
||||
detail::Combiner opts=Validators
|
||||
) {
|
||||
Option myopt{name, discription, opts, callback};
|
||||
if(std::find(std::begin(options), std::end(options), myopt) == std::end(options))
|
||||
@ -683,15 +733,15 @@ public:
|
||||
/// Add option for string
|
||||
template<typename T, enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy>
|
||||
Option* add_option(
|
||||
std::string name, ///< The name, long,short
|
||||
std::string name,
|
||||
T &variable, ///< The variable to set
|
||||
std::string discription="", ///< Discription string
|
||||
detail::Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
|
||||
std::string discription="",
|
||||
detail::Combiner opts=Validators
|
||||
) {
|
||||
|
||||
|
||||
if(opts.num!=1)
|
||||
throw IncorrectConstruction("Must have ARGS(1) or be a vector.");
|
||||
throw IncorrectConstruction("Must have Args(1) or be a vector.");
|
||||
CLI::callback_t fun = [&variable](CLI::results_t res){
|
||||
if(res.size()!=1) {
|
||||
return false;
|
||||
@ -715,14 +765,14 @@ public:
|
||||
/// Add option for vector of results
|
||||
template<typename T>
|
||||
Option* add_option(
|
||||
std::string name, ///< The name, long,short
|
||||
std::vector<T> &variable, ///< The variable to set
|
||||
std::string discription="", ///< Discription string
|
||||
detail::Combiner opts=ARGS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
|
||||
std::string name,
|
||||
std::vector<T> &variable, ///< The variable vector to set
|
||||
std::string discription="",
|
||||
detail::Combiner opts=Args
|
||||
) {
|
||||
|
||||
if(opts.num==0)
|
||||
throw IncorrectConstruction("Must have ARGS or be a vector.");
|
||||
throw IncorrectConstruction("Must have Args or be a vector.");
|
||||
CLI::callback_t fun = [&variable](CLI::results_t res){
|
||||
bool retval = true;
|
||||
variable.clear();
|
||||
@ -746,10 +796,10 @@ public:
|
||||
/// Multiple options are supported
|
||||
template<typename T, typename... Args>
|
||||
Option* add_option(
|
||||
std::string name, ///< The name, long,short
|
||||
std::string name,
|
||||
T &variable, ///< The variable to set
|
||||
std::string discription, ///< Discription string
|
||||
detail::Combiner opts, ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
|
||||
std::string discription,
|
||||
detail::Combiner opts,
|
||||
detail::Combiner opts2,
|
||||
Args... args ///< More options
|
||||
) {
|
||||
@ -757,23 +807,26 @@ public:
|
||||
}
|
||||
/// Add option for flag
|
||||
Option* add_flag(
|
||||
std::string name, ///< The name, short,long
|
||||
std::string discription="" ///< Discription string
|
||||
std::string name,
|
||||
std::string discription=""
|
||||
) {
|
||||
CLI::callback_t fun = [](CLI::results_t){
|
||||
return true;
|
||||
};
|
||||
|
||||
return add_option(name, fun, discription, NOTHING);
|
||||
Option* opt = add_option(name, fun, discription, Nothing);
|
||||
if(opt->positional())
|
||||
throw IncorrectConstruction("Flags cannot be positional");
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// Add option for flag
|
||||
template<typename T,
|
||||
enable_if_t<std::is_integral<T>::value && !is_bool<T>::value, detail::enabler> = detail::dummy>
|
||||
Option* add_flag(
|
||||
std::string name, ///< The name, short,long
|
||||
std::string name,
|
||||
T &count, ///< A varaible holding the count
|
||||
std::string discription="" ///< Discription string
|
||||
std::string discription=""
|
||||
) {
|
||||
|
||||
count = 0;
|
||||
@ -782,16 +835,19 @@ public:
|
||||
return true;
|
||||
};
|
||||
|
||||
return add_option(name, fun, discription, NOTHING);
|
||||
Option* opt = add_option(name, fun, discription, Nothing);
|
||||
if(opt->positional())
|
||||
throw IncorrectConstruction("Flags cannot be positional");
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// Bool version only allows the flag once
|
||||
template<typename T,
|
||||
enable_if_t<is_bool<T>::value, detail::enabler> = detail::dummy>
|
||||
Option* add_flag(
|
||||
std::string name, ///< The name, short,long
|
||||
T &count, ///< A varaible holding true if passed
|
||||
std::string discription="" ///< Discription string
|
||||
std::string name,
|
||||
T &count, ///< A varaible holding true if passed
|
||||
std::string discription=""
|
||||
) {
|
||||
|
||||
count = false;
|
||||
@ -800,22 +856,25 @@ public:
|
||||
return res.size() == 1;
|
||||
};
|
||||
|
||||
return add_option(name, fun, discription, NOTHING);
|
||||
Option* opt = add_option(name, fun, discription, Nothing);
|
||||
if(opt->positional())
|
||||
throw IncorrectConstruction("Flags cannot be positional");
|
||||
return opt;
|
||||
}
|
||||
|
||||
|
||||
/// Add set of options
|
||||
template<typename T>
|
||||
Option* add_set(
|
||||
std::string name, ///< The name, short,long
|
||||
std::string name,
|
||||
T &member, ///< The selected member of the set
|
||||
std::set<T> options, ///< The set of posibilities
|
||||
std::string discription="", ///< Discription string
|
||||
detail::Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
|
||||
std::set<T> options, ///< The set of posibilities
|
||||
std::string discription="",
|
||||
detail::Combiner opts=Validators
|
||||
) {
|
||||
|
||||
if(opts.num!=1)
|
||||
throw IncorrectConstruction("Must have ARGS(1).");
|
||||
throw IncorrectConstruction("Must have Args(1).");
|
||||
|
||||
CLI::callback_t fun = [&member, options](CLI::results_t res){
|
||||
if(res.size()!=1) {
|
||||
@ -844,11 +903,11 @@ public:
|
||||
|
||||
template<typename T, typename... Args>
|
||||
Option* add_set(
|
||||
std::string name, ///< The name, short,long
|
||||
T &member, ///< The selected member of the set
|
||||
std::set<T> options, ///< The set of posibilities
|
||||
std::string discription, ///< Discription string
|
||||
detail::Combiner opts, ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
|
||||
std::string name,
|
||||
T &member,
|
||||
std::set<T> options, ///< The set of posibilities
|
||||
std::string discription,
|
||||
detail::Combiner opts,
|
||||
detail::Combiner opts2,
|
||||
Args... args
|
||||
) {
|
||||
@ -862,13 +921,13 @@ public:
|
||||
template<typename T = std::string,
|
||||
enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy>
|
||||
Value<T> make_option(
|
||||
std::string name, ///< The name, short,long
|
||||
std::string name,
|
||||
std::string discription="",
|
||||
detail::Combiner opts=VALIDATORS
|
||||
detail::Combiner opts=Validators
|
||||
) {
|
||||
|
||||
if(opts.num!=1)
|
||||
throw IncorrectConstruction("Must have ARGS(1).");
|
||||
throw IncorrectConstruction("Must have Args(1).");
|
||||
|
||||
Value<T> out(name);
|
||||
std::shared_ptr<std::unique_ptr<T>> ptr = out.value;
|
||||
@ -890,7 +949,7 @@ public:
|
||||
|
||||
template<typename T = std::string, typename... Args>
|
||||
Value<T> make_option(
|
||||
std::string name, ///< The name, short,long
|
||||
std::string name,
|
||||
std::string discription,
|
||||
detail::Combiner opts,
|
||||
detail::Combiner opts2,
|
||||
@ -903,14 +962,14 @@ public:
|
||||
template<typename T,
|
||||
enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy>
|
||||
Value<T> make_option(
|
||||
std::string name, ///< The name, short,long
|
||||
std::string name,
|
||||
const T& default_value,
|
||||
std::string discription="",
|
||||
detail::Combiner opts=VALIDATORS
|
||||
detail::Combiner opts=Validators
|
||||
) {
|
||||
|
||||
if(opts.num!=1)
|
||||
throw IncorrectConstruction("Must have ARGS(1).");
|
||||
throw IncorrectConstruction("Must have Args(1).");
|
||||
|
||||
Value<T> out(name);
|
||||
std::shared_ptr<std::unique_ptr<T>> ptr = out.value;
|
||||
@ -938,13 +997,13 @@ public:
|
||||
template<typename T,
|
||||
enable_if_t<is_vector<T>::value, detail::enabler> = detail::dummy>
|
||||
Value<T> make_option(
|
||||
std::string name, ///< The name, short,long
|
||||
std::string name,
|
||||
std::string discription="",
|
||||
detail::Combiner opts=VALIDATORS
|
||||
detail::Combiner opts=Args
|
||||
) {
|
||||
|
||||
if(opts.num==0)
|
||||
throw IncorrectConstruction("Must have ARGS or be a vector.");
|
||||
throw IncorrectConstruction("Must have Args or be a vector.");
|
||||
|
||||
Value<T> out(name);
|
||||
std::shared_ptr<std::unique_ptr<T>> ptr = out.value;
|
||||
@ -967,7 +1026,7 @@ public:
|
||||
|
||||
template<typename T, typename... Args>
|
||||
Value<T> make_option(
|
||||
std::string name, ///< The name, short,long
|
||||
std::string name,
|
||||
const T& default_value,
|
||||
std::string discription,
|
||||
detail::Combiner opts,
|
||||
@ -979,7 +1038,7 @@ public:
|
||||
|
||||
/// Prototype for new output style: flag
|
||||
Value<int> make_flag(
|
||||
std::string name, ///< The name, short,long
|
||||
std::string name,
|
||||
std::string discription=""
|
||||
) {
|
||||
|
||||
@ -992,24 +1051,27 @@ public:
|
||||
**ptr = (int) res.size();
|
||||
return true;
|
||||
};
|
||||
add_option(name, fun, discription, NOTHING);
|
||||
|
||||
Option* opt = add_option(name, fun, discription, Nothing);
|
||||
if(opt->positional())
|
||||
throw IncorrectConstruction("Flags cannot be positional");
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Add set of options
|
||||
template<typename T>
|
||||
Value<T> make_set(
|
||||
std::string name, ///< The name, short,long
|
||||
std::string name,
|
||||
std::set<T> options, ///< The set of posibilities
|
||||
std::string discription="", ///< Discription string
|
||||
detail::Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS())
|
||||
std::string discription="",
|
||||
detail::Combiner opts=Validators
|
||||
) {
|
||||
|
||||
Value<T> out(name);
|
||||
std::shared_ptr<std::unique_ptr<T>> ptr = out.value;
|
||||
|
||||
if(opts.num!=1)
|
||||
throw IncorrectConstruction("Must have ARGS(1).");
|
||||
throw IncorrectConstruction("Must have Args(1).");
|
||||
|
||||
CLI::callback_t fun = [ptr, options](CLI::results_t res){
|
||||
if(res.size()!=1) {
|
||||
@ -1046,6 +1108,7 @@ public:
|
||||
|
||||
/// Parses the command line - throws errors
|
||||
void parse(int argc, char **argv) {
|
||||
progname = argv[0];
|
||||
std::vector<std::string> args;
|
||||
for(int i=argc-1; i>0; i--)
|
||||
args.push_back(argv[i]);
|
||||
@ -1081,7 +1144,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if (count("help") > 0) {
|
||||
if (count("--help") > 0) {
|
||||
throw CallForHelp();
|
||||
}
|
||||
|
||||
@ -1259,12 +1322,50 @@ public:
|
||||
if(name != "")
|
||||
out << "Subcommand: " << name << " ";
|
||||
out << prog_discription << std::endl;
|
||||
out << "Usage: " << progname;
|
||||
|
||||
// Positionals
|
||||
bool pos=false;
|
||||
for(const Option &opt : options)
|
||||
if(opt.positional()) {
|
||||
out << " " << opt.help_positional();
|
||||
if(opt.has_discription())
|
||||
pos=true;
|
||||
}
|
||||
out << std::endl << std::endl;
|
||||
|
||||
// Positional discriptions
|
||||
if(pos) {
|
||||
out << "Positionals:" << std::endl;
|
||||
for(const Option &opt : options)
|
||||
if(opt.positional() && opt.has_discription()) {
|
||||
out << " " << std::setw(30) << std::right << opt.help_positional();
|
||||
out << opt.get_discription() << std::endl;
|
||||
}
|
||||
out << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Options
|
||||
int len = std::accumulate(std::begin(options), std::end(options), 0,
|
||||
[](int val, const Option &opt){
|
||||
return std::max(opt.help_len()+3, val);});
|
||||
|
||||
bool npos = false;
|
||||
for(const Option &opt : options) {
|
||||
out << opt.help(len) << std::endl;
|
||||
if(opt.nonpositional()) {
|
||||
if(!npos) {
|
||||
out << "Options:" << std::endl;
|
||||
npos=true;
|
||||
}
|
||||
out << opt.help(len) << std::endl;
|
||||
}
|
||||
if(npos)
|
||||
out << std::endl;
|
||||
}
|
||||
|
||||
// Subcommands
|
||||
if(subcommands.size()> 0) {
|
||||
out << "Subcommands:" << std::endl;
|
||||
int max = std::accumulate(std::begin(subcommands), std::end(subcommands), 0,
|
||||
|
@ -37,19 +37,19 @@ struct TApp : public ::testing::Test {
|
||||
};
|
||||
|
||||
TEST_F(TApp, OneFlagShort) {
|
||||
app.add_flag("c,count");
|
||||
app.add_flag("-c,--count");
|
||||
args = {"-c"};
|
||||
EXPECT_NO_THROW(run());
|
||||
EXPECT_EQ(1, app.count("c"));
|
||||
EXPECT_EQ(1, app.count("count"));
|
||||
EXPECT_EQ(1, app.count("-c"));
|
||||
EXPECT_EQ(1, app.count("--count"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, OneFlagLong) {
|
||||
app.add_flag("c,count");
|
||||
app.add_flag("-c,--count");
|
||||
args = {"--count"};
|
||||
EXPECT_NO_THROW(run());
|
||||
EXPECT_EQ(1, app.count("c"));
|
||||
EXPECT_EQ(1, app.count("count"));
|
||||
EXPECT_EQ(1, app.count("-c"));
|
||||
EXPECT_EQ(1, app.count("--count"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, DashedOptions) {
|
||||
@ -59,9 +59,9 @@ TEST_F(TApp, DashedOptions) {
|
||||
|
||||
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(1, app.count("-c"));
|
||||
EXPECT_EQ(1, app.count("--q"));
|
||||
EXPECT_EQ(2, app.count("--this"));
|
||||
EXPECT_EQ(2, app.count("--that"));
|
||||
|
||||
}
|
||||
@ -69,76 +69,76 @@ TEST_F(TApp, DashedOptions) {
|
||||
|
||||
TEST_F(TApp, OneFlagRef) {
|
||||
int ref;
|
||||
app.add_flag("c,count", ref);
|
||||
app.add_flag("-c,--count", ref);
|
||||
args = {"--count"};
|
||||
EXPECT_NO_THROW(run());
|
||||
EXPECT_EQ(1, app.count("c"));
|
||||
EXPECT_EQ(1, app.count("count"));
|
||||
EXPECT_EQ(1, app.count("-c"));
|
||||
EXPECT_EQ(1, app.count("--count"));
|
||||
EXPECT_EQ(1, ref);
|
||||
}
|
||||
|
||||
TEST_F(TApp, OneString) {
|
||||
std::string str;
|
||||
app.add_option("s,string", str);
|
||||
app.add_option("-s,--string", str);
|
||||
args = {"--string", "mystring"};
|
||||
EXPECT_NO_THROW(run());
|
||||
EXPECT_EQ(1, app.count("s"));
|
||||
EXPECT_EQ(1, app.count("string"));
|
||||
EXPECT_EQ(1, app.count("-s"));
|
||||
EXPECT_EQ(1, app.count("--string"));
|
||||
EXPECT_EQ(str, "mystring");
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, TogetherInt) {
|
||||
int i;
|
||||
app.add_option("i,int", i);
|
||||
app.add_option("-i,--int", i);
|
||||
args = {"-i4"};
|
||||
EXPECT_NO_THROW(run());
|
||||
EXPECT_EQ(1, app.count("int"));
|
||||
EXPECT_EQ(1, app.count("i"));
|
||||
EXPECT_EQ(1, app.count("--int"));
|
||||
EXPECT_EQ(1, app.count("-i"));
|
||||
EXPECT_EQ(i, 4);
|
||||
}
|
||||
|
||||
TEST_F(TApp, SepInt) {
|
||||
int i;
|
||||
app.add_option("i,int", i);
|
||||
app.add_option("-i,--int", i);
|
||||
args = {"-i","4"};
|
||||
EXPECT_NO_THROW(run());
|
||||
EXPECT_EQ(1, app.count("int"));
|
||||
EXPECT_EQ(1, app.count("i"));
|
||||
EXPECT_EQ(1, app.count("--int"));
|
||||
EXPECT_EQ(1, app.count("-i"));
|
||||
EXPECT_EQ(i, 4);
|
||||
}
|
||||
|
||||
TEST_F(TApp, OneStringAgain) {
|
||||
std::string str;
|
||||
app.add_option("s,string", str);
|
||||
app.add_option("-s,--string", str);
|
||||
args = {"--string", "mystring"};
|
||||
EXPECT_NO_THROW(run());
|
||||
EXPECT_EQ(1, app.count("s"));
|
||||
EXPECT_EQ(1, app.count("string"));
|
||||
EXPECT_EQ(1, app.count("-s"));
|
||||
EXPECT_EQ(1, app.count("--string"));
|
||||
EXPECT_EQ(str, "mystring");
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, DefaultStringAgain) {
|
||||
std::string str = "previous";
|
||||
app.add_option("s,string", str);
|
||||
app.add_option("-s,--string", str);
|
||||
EXPECT_NO_THROW(run());
|
||||
EXPECT_EQ(0, app.count("s"));
|
||||
EXPECT_EQ(0, app.count("string"));
|
||||
EXPECT_EQ(0, app.count("-s"));
|
||||
EXPECT_EQ(0, app.count("--string"));
|
||||
EXPECT_EQ(str, "previous");
|
||||
}
|
||||
|
||||
TEST_F(TApp, LotsOfFlags) {
|
||||
|
||||
app.add_flag("a");
|
||||
app.add_flag("A");
|
||||
app.add_flag("b");
|
||||
app.add_flag("-a");
|
||||
app.add_flag("-A");
|
||||
app.add_flag("-b");
|
||||
|
||||
args = {"-a","-b","-aA"};
|
||||
EXPECT_NO_THROW(run());
|
||||
EXPECT_EQ(2, app.count("a"));
|
||||
EXPECT_EQ(1, app.count("b"));
|
||||
EXPECT_EQ(1, app.count("A"));
|
||||
EXPECT_EQ(2, app.count("-a"));
|
||||
EXPECT_EQ(1, app.count("-b"));
|
||||
EXPECT_EQ(1, app.count("-A"));
|
||||
}
|
||||
|
||||
|
||||
@ -148,9 +148,9 @@ TEST_F(TApp, BoolAndIntFlags) {
|
||||
int iflag;
|
||||
unsigned int uflag;
|
||||
|
||||
app.add_flag("b", bflag);
|
||||
app.add_flag("i", iflag);
|
||||
app.add_flag("u", uflag);
|
||||
app.add_flag("-b", bflag);
|
||||
app.add_flag("-i", iflag);
|
||||
app.add_flag("-u", uflag);
|
||||
|
||||
args = {"-b", "-i", "-u"};
|
||||
EXPECT_NO_THROW(run());
|
||||
@ -177,15 +177,15 @@ TEST_F(TApp, ShortOpts) {
|
||||
|
||||
unsigned long long funnyint;
|
||||
std::string someopt;
|
||||
app.add_flag("z", funnyint);
|
||||
app.add_option("y", someopt);
|
||||
app.add_flag("-z", funnyint);
|
||||
app.add_option("-y", someopt);
|
||||
|
||||
args = {"-zzyzyz",};
|
||||
|
||||
EXPECT_NO_THROW(run());
|
||||
|
||||
EXPECT_EQ(2, app.count("z"));
|
||||
EXPECT_EQ(1, app.count("y"));
|
||||
EXPECT_EQ(2, app.count("-z"));
|
||||
EXPECT_EQ(1, app.count("-y"));
|
||||
EXPECT_EQ((unsigned long long) 2, funnyint);
|
||||
EXPECT_EQ("zyz", someopt);
|
||||
}
|
||||
@ -195,15 +195,15 @@ TEST_F(TApp, Flags) {
|
||||
int i = 3;
|
||||
std::string s = "HI";
|
||||
|
||||
app.add_option("-i", i, "", CLI::DEFAULT, CLI::POSITIONAL);
|
||||
app.add_option("-s", s, "", CLI::DEFAULT, CLI::POSITIONAL);
|
||||
app.add_option("-i,i", i, "", CLI::Default);
|
||||
app.add_option("-s,s", s, "", CLI::Default);
|
||||
|
||||
args = {"-i2", "9"};
|
||||
|
||||
EXPECT_NO_THROW(run());
|
||||
|
||||
EXPECT_EQ(1, app.count("i"));
|
||||
EXPECT_EQ(1, app.count("s"));
|
||||
EXPECT_EQ(1, app.count("-s"));
|
||||
EXPECT_EQ(2, i);
|
||||
EXPECT_EQ("9", s);
|
||||
}
|
||||
@ -212,8 +212,8 @@ TEST_F(TApp, Positionals) {
|
||||
|
||||
std::string posit1;
|
||||
std::string posit2;
|
||||
app.add_option("posit1", posit1, "", CLI::POSITIONAL);
|
||||
app.add_option("posit2", posit2, "", CLI::POSITIONAL);
|
||||
app.add_option("posit1", posit1);
|
||||
app.add_option("posit2", posit2);
|
||||
|
||||
args = {"thing1","thing2"};
|
||||
|
||||
@ -229,42 +229,42 @@ TEST_F(TApp, MixedPositionals) {
|
||||
|
||||
int positional_int;
|
||||
std::string positional_string;
|
||||
app.add_option("posit1", positional_int, "", CLI::POSITIONAL);
|
||||
app.add_option("posit2", positional_string, "", CLI::POSITIONAL);
|
||||
app.add_option("posit1,--posit1", positional_int, "");
|
||||
app.add_option("posit2,--posit2", positional_string, "");
|
||||
|
||||
args = {"--posit2","thing2","7"};
|
||||
|
||||
EXPECT_NO_THROW(run());
|
||||
|
||||
EXPECT_EQ(1, app.count("posit2"));
|
||||
EXPECT_EQ(1, app.count("posit1"));
|
||||
EXPECT_EQ(1, app.count("--posit1"));
|
||||
EXPECT_EQ(7, positional_int);
|
||||
EXPECT_EQ("thing2", positional_string);
|
||||
}
|
||||
|
||||
TEST_F(TApp, Reset) {
|
||||
|
||||
app.add_flag("simple");
|
||||
app.add_flag("--simple");
|
||||
double doub;
|
||||
app.add_option("d,double", doub);
|
||||
app.add_option("-d,--double", doub);
|
||||
|
||||
args = {"--simple", "--double", "1.2"};
|
||||
|
||||
EXPECT_NO_THROW(run());
|
||||
|
||||
EXPECT_EQ(1, app.count("simple"));
|
||||
EXPECT_EQ(1, app.count("d"));
|
||||
EXPECT_EQ(1, app.count("--simple"));
|
||||
EXPECT_EQ(1, app.count("-d"));
|
||||
EXPECT_FLOAT_EQ(1.2, doub);
|
||||
|
||||
app.reset();
|
||||
|
||||
EXPECT_EQ(0, app.count("simple"));
|
||||
EXPECT_EQ(0, app.count("d"));
|
||||
EXPECT_EQ(0, app.count("--simple"));
|
||||
EXPECT_EQ(0, app.count("-d"));
|
||||
|
||||
EXPECT_NO_THROW(run());
|
||||
|
||||
EXPECT_EQ(1, app.count("simple"));
|
||||
EXPECT_EQ(1, app.count("d"));
|
||||
EXPECT_EQ(1, app.count("--simple"));
|
||||
EXPECT_EQ(1, app.count("-d"));
|
||||
EXPECT_FLOAT_EQ(1.2, doub);
|
||||
|
||||
}
|
||||
@ -275,7 +275,7 @@ TEST_F(TApp, FileNotExists) {
|
||||
EXPECT_TRUE(CLI::detail::_NonexistentPath(myfile));
|
||||
|
||||
std::string filename;
|
||||
app.add_option("file", filename, "", CLI::NonexistentPath);
|
||||
app.add_option("--file", filename, "", CLI::NonexistentPath);
|
||||
args = {"--file", myfile};
|
||||
|
||||
EXPECT_NO_THROW(run());
|
||||
@ -297,7 +297,7 @@ TEST_F(TApp, FileExists) {
|
||||
EXPECT_FALSE(CLI::detail::_ExistingFile(myfile));
|
||||
|
||||
std::string filename = "Failed";
|
||||
app.add_option("file", filename, "", CLI::ExistingFile);
|
||||
app.add_option("--file", filename, "", CLI::ExistingFile);
|
||||
args = {"--file", myfile};
|
||||
|
||||
EXPECT_THROW(run(), CLI::ParseError);
|
||||
@ -317,7 +317,7 @@ TEST_F(TApp, FileExists) {
|
||||
TEST_F(TApp, InSet) {
|
||||
|
||||
std::string choice;
|
||||
app.add_set("q,quick", choice, {"one", "two", "three"});
|
||||
app.add_set("-q,--quick", choice, {"one", "two", "three"});
|
||||
|
||||
args = {"--quick", "two"};
|
||||
|
||||
@ -334,12 +334,12 @@ TEST_F(TApp, VectorFixedString) {
|
||||
std::vector<std::string> strvec;
|
||||
std::vector<std::string> answer{"mystring", "mystring2", "mystring3"};
|
||||
|
||||
CLI::Option* opt = app.add_option("s,string", strvec, "", CLI::ARGS(3));
|
||||
CLI::Option* opt = app.add_option("-s,--string", strvec, "", CLI::Args(3));
|
||||
EXPECT_EQ(3, opt->expected());
|
||||
|
||||
args = {"--string", "mystring", "mystring2", "mystring3"};
|
||||
run();
|
||||
EXPECT_EQ(3, app.count("string"));
|
||||
EXPECT_EQ(3, app.count("--string"));
|
||||
EXPECT_EQ(answer, strvec);
|
||||
}
|
||||
|
||||
@ -349,12 +349,12 @@ 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);
|
||||
CLI::Option* opt = app.add_option("-s,--string", strvec);
|
||||
EXPECT_EQ(-1, opt->expected());
|
||||
|
||||
args = {"--string", "mystring", "mystring2", "mystring3"};
|
||||
EXPECT_NO_THROW(run());
|
||||
EXPECT_EQ(3, app.count("string"));
|
||||
EXPECT_EQ(3, app.count("--string"));
|
||||
EXPECT_EQ(answer, strvec);
|
||||
}
|
||||
|
||||
@ -417,9 +417,9 @@ struct SubcommandProgram : public TApp {
|
||||
start = app.add_subcommand("start", "Start prog");
|
||||
stop = app.add_subcommand("stop", "Stop prog");
|
||||
|
||||
app.add_flag("d", dummy, "My dummy var");
|
||||
start->add_option("f,file", file, "File name");
|
||||
stop->add_flag("c,count", count, "Some flag opt");
|
||||
app.add_flag("-d", dummy, "My dummy var");
|
||||
start->add_option("-f,--file", file, "File name");
|
||||
stop->add_flag("-c,--count", count, "Some flag opt");
|
||||
}
|
||||
};
|
||||
|
||||
@ -449,7 +449,7 @@ TEST_F(SubcommandProgram, SpareSub) {
|
||||
class TAppValue : public TApp {};
|
||||
|
||||
TEST_F(TAppValue, OneString) {
|
||||
auto str = app.make_option("s,string");
|
||||
auto str = app.make_option("-s,--string");
|
||||
std::string v;
|
||||
args = {"--string", "mystring"};
|
||||
EXPECT_FALSE((bool) str);
|
||||
@ -461,15 +461,15 @@ TEST_F(TAppValue, OneString) {
|
||||
EXPECT_NO_THROW(v = *str);
|
||||
EXPECT_NO_THROW(v = str);
|
||||
|
||||
EXPECT_EQ(1, app.count("s"));
|
||||
EXPECT_EQ(1, app.count("string"));
|
||||
EXPECT_EQ(1, app.count("-s"));
|
||||
EXPECT_EQ(1, app.count("--string"));
|
||||
EXPECT_EQ(*str, "mystring");
|
||||
|
||||
}
|
||||
|
||||
TEST_F(TAppValue, SeveralInts) {
|
||||
auto value = app.make_option<int>("first");
|
||||
CLI::Value<int> value2 = app.make_option<int>("s");
|
||||
auto value = app.make_option<int>("--first");
|
||||
CLI::Value<int> value2 = app.make_option<int>("-s");
|
||||
int v;
|
||||
args = {"--first", "12", "-s", "19"};
|
||||
EXPECT_FALSE((bool) value);
|
||||
@ -482,16 +482,16 @@ TEST_F(TAppValue, SeveralInts) {
|
||||
EXPECT_NO_THROW(v = *value);
|
||||
EXPECT_NO_THROW(v = value);
|
||||
|
||||
EXPECT_EQ(1, app.count("s"));
|
||||
EXPECT_EQ(1, app.count("first"));
|
||||
EXPECT_EQ(1, app.count("-s"));
|
||||
EXPECT_EQ(1, app.count("--first"));
|
||||
EXPECT_EQ(*value, 12);
|
||||
EXPECT_EQ(*value2, 19);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(TAppValue, Vector) {
|
||||
auto value = app.make_option<std::vector<int>>("first", "", CLI::ARGS);
|
||||
auto value2 = app.make_option<std::vector<std::string>>("second", "", CLI::ARGS);
|
||||
auto value = app.make_option<std::vector<int>>("--first", "", CLI::Args);
|
||||
auto value2 = app.make_option<std::vector<std::string>>("--second");
|
||||
|
||||
std::vector<int> i;
|
||||
std::vector<std::string> s;
|
||||
@ -515,8 +515,8 @@ TEST_F(TAppValue, Vector) {
|
||||
EXPECT_NO_THROW(s = *value2);
|
||||
//EXPECT_NO_THROW(s = value2);
|
||||
|
||||
EXPECT_EQ(3, app.count("first"));
|
||||
EXPECT_EQ(2, app.count("second"));
|
||||
EXPECT_EQ(3, app.count("--first"));
|
||||
EXPECT_EQ(2, app.count("--second"));
|
||||
|
||||
EXPECT_EQ(std::vector<int>({12,3,9}), *value);
|
||||
EXPECT_EQ(std::vector<std::string>({"thing", "try"}), *value2);
|
||||
@ -524,7 +524,7 @@ TEST_F(TAppValue, Vector) {
|
||||
}
|
||||
|
||||
TEST_F(TAppValue, DoubleVector) {
|
||||
auto value = app.make_option<std::vector<double>>("simple", "", CLI::ARGS);
|
||||
auto value = app.make_option<std::vector<double>>("--simple");
|
||||
std::vector<double> d;
|
||||
|
||||
args = {"--simple", "1.2", "3.4", "-1"};
|
||||
@ -535,7 +535,7 @@ TEST_F(TAppValue, DoubleVector) {
|
||||
|
||||
EXPECT_NO_THROW(d = *value);
|
||||
|
||||
EXPECT_EQ(3, app.count("simple"));
|
||||
EXPECT_EQ(3, app.count("--simple"));
|
||||
EXPECT_EQ(std::vector<double>({1.2, 3.4, -1}), *value);
|
||||
}
|
||||
|
||||
|
@ -87,17 +87,20 @@ TEST(Regex, SplittingNew) {
|
||||
|
||||
std::vector<std::string> shorts;
|
||||
std::vector<std::string> longs;
|
||||
std::string pname;
|
||||
|
||||
EXPECT_NO_THROW(std::tie(shorts, longs) = CLI::detail::get_names({"--long", "s", "-q", "also-long"}));
|
||||
EXPECT_NO_THROW(std::tie(shorts, longs, pname) = CLI::detail::get_names({"--long", "-s", "-q", "--also-long"}));
|
||||
EXPECT_EQ(std::vector<std::string>({"long", "also-long"}), longs);
|
||||
EXPECT_EQ(std::vector<std::string>({"s", "q"}), shorts);
|
||||
EXPECT_EQ("", pname);
|
||||
|
||||
EXPECT_NO_THROW(std::tie(shorts, longs, pname) = CLI::detail::get_names({"--long", "", "-s", "-q", "", "--also-long"}));
|
||||
EXPECT_EQ(std::vector<std::string>({"long", "also-long"}), longs);
|
||||
EXPECT_EQ(std::vector<std::string>({"s", "q"}), shorts);
|
||||
|
||||
EXPECT_NO_THROW(std::tie(shorts, longs) = CLI::detail::get_names({"--long", "", "s", "-q", "", "also-long"}));
|
||||
EXPECT_EQ(std::vector<std::string>({"long", "also-long"}), longs);
|
||||
EXPECT_EQ(std::vector<std::string>({"s", "q"}), shorts);
|
||||
|
||||
EXPECT_THROW(std::tie(shorts, longs) = CLI::detail::get_names({"-"}), CLI::BadNameString);
|
||||
EXPECT_THROW(std::tie(shorts, longs) = CLI::detail::get_names({"--"}), CLI::BadNameString);
|
||||
EXPECT_THROW(std::tie(shorts, longs) = CLI::detail::get_names({"-hi"}), CLI::BadNameString);
|
||||
EXPECT_THROW(std::tie(shorts, longs, pname) = CLI::detail::get_names({"-"}), CLI::BadNameString);
|
||||
EXPECT_THROW(std::tie(shorts, longs, pname) = CLI::detail::get_names({"--"}), CLI::BadNameString);
|
||||
EXPECT_THROW(std::tie(shorts, longs, pname) = CLI::detail::get_names({"-hi"}), CLI::BadNameString);
|
||||
EXPECT_THROW(std::tie(shorts, longs, pname) = CLI::detail::get_names({"one","two"}), CLI::BadNameString);
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user