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