mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-04-29 12:13:52 +00:00
Reformat with clang-format
This commit is contained in:
parent
f24561f460
commit
27f718125d
86
.clang-format
Normal file
86
.clang-format
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
# AccessModifierOffset: -2
|
||||||
|
# AlignAfterOpenBracket: Align
|
||||||
|
# AlignConsecutiveAssignments: false
|
||||||
|
# AlignConsecutiveDeclarations: false
|
||||||
|
# AlignEscapedNewlinesLeft: false
|
||||||
|
# AlignOperands: true
|
||||||
|
# AlignTrailingComments: true
|
||||||
|
# AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
# AllowShortBlocksOnASingleLine: false
|
||||||
|
# AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
# AllowShortFunctionsOnASingleLine: All
|
||||||
|
# AllowShortIfStatementsOnASingleLine: false
|
||||||
|
# AllowShortLoopsOnASingleLine: false
|
||||||
|
# AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
# AlwaysBreakAfterReturnType: None
|
||||||
|
# AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
# AlwaysBreakTemplateDeclarations: false
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
# BraceWrapping:
|
||||||
|
# AfterClass: false
|
||||||
|
# AfterControlStatement: false
|
||||||
|
# AfterEnum: false
|
||||||
|
# AfterFunction: false
|
||||||
|
# AfterNamespace: false
|
||||||
|
# AfterObjCDeclaration: false
|
||||||
|
# AfterStruct: false
|
||||||
|
# AfterUnion: false
|
||||||
|
# BeforeCatch: false
|
||||||
|
# BeforeElse: false
|
||||||
|
# IndentBraces: false
|
||||||
|
# BreakBeforeBinaryOperators: None
|
||||||
|
# BreakBeforeBraces: Attach
|
||||||
|
# BreakBeforeTernaryOperators: true
|
||||||
|
# BreakConstructorInitializersBeforeComma: false
|
||||||
|
# BreakAfterJavaFieldAnnotations: false
|
||||||
|
# BreakStringLiterals: true
|
||||||
|
ColumnLimit: 120
|
||||||
|
# CommentPragmas: '^ IWYU pragma:'
|
||||||
|
# ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
|
# ConstructorInitializerIndentWidth: 4
|
||||||
|
# ContinuationIndentWidth: 4
|
||||||
|
# Cpp11BracedListStyle: true
|
||||||
|
# DerivePointerAlignment: false
|
||||||
|
# DisableFormat: false
|
||||||
|
# ExperimentalAutoDetectBinPacking: false
|
||||||
|
# ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||||
|
# IncludeIsMainRegex: '$'
|
||||||
|
# IndentCaseLabels: false
|
||||||
|
IndentWidth: 4
|
||||||
|
# IndentWrappedFunctionNames: false
|
||||||
|
# JavaScriptQuotes: Leave
|
||||||
|
# JavaScriptWrapImports: true
|
||||||
|
# KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
|
# MacroBlockBegin: ''
|
||||||
|
# MacroBlockEnd: ''
|
||||||
|
# MaxEmptyLinesToKeep: 1
|
||||||
|
# NamespaceIndentation: None
|
||||||
|
# ObjCBlockIndentWidth: 2
|
||||||
|
# ObjCSpaceAfterProperty: false
|
||||||
|
# ObjCSpaceBeforeProtocolList: true
|
||||||
|
# PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
|
# PenaltyBreakComment: 300
|
||||||
|
# PenaltyBreakFirstLessLess: 120
|
||||||
|
# PenaltyBreakString: 1000
|
||||||
|
# PenaltyExcessCharacter: 1000000
|
||||||
|
# PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
# PointerAlignment: Right
|
||||||
|
# ReflowComments: true
|
||||||
|
SortIncludes: false
|
||||||
|
# SpaceAfterCStyleCast: false
|
||||||
|
# SpaceAfterTemplateKeyword: true
|
||||||
|
# SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeParens: Never
|
||||||
|
# SpaceInEmptyParentheses: false
|
||||||
|
# SpacesBeforeTrailingComments: 1
|
||||||
|
# SpacesInAngles: false
|
||||||
|
# SpacesInContainerLiterals: true
|
||||||
|
# SpacesInCStyleCastParentheses: false
|
||||||
|
# SpacesInParentheses: false
|
||||||
|
# SpacesInSquareBrackets: false
|
||||||
|
Standard: Cpp11
|
||||||
|
TabWidth: 4
|
||||||
|
UseTab: Never
|
@ -1,33 +1,28 @@
|
|||||||
#include "CLI/CLI.hpp"
|
#include "CLI/CLI.hpp"
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
int main (int argc, char** argv) {
|
|
||||||
|
|
||||||
CLI::App app("K3Pi goofit fitter");
|
CLI::App app("K3Pi goofit fitter");
|
||||||
|
|
||||||
std::string file;
|
std::string file;
|
||||||
CLI::Option* opt = app.add_option("-f,--file,file", file, "File name");
|
CLI::Option *opt = app.add_option("-f,--file,file", file, "File name");
|
||||||
|
|
||||||
int count;
|
|
||||||
CLI::Option* copt = app.add_flag("-c,--count", count, "Counter");
|
|
||||||
|
|
||||||
double value;// = 3.14;
|
int count;
|
||||||
|
CLI::Option *copt = app.add_flag("-c,--count", count, "Counter");
|
||||||
|
|
||||||
|
double value; // = 3.14;
|
||||||
app.add_option("-d,--double", value, "Some Value");
|
app.add_option("-d,--double", value, "Some Value");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
app.parse(argc, argv);
|
app.parse(argc, argv);
|
||||||
} catch (const CLI::Error &e) {
|
} catch(const CLI::Error &e) {
|
||||||
return app.exit(e);
|
return app.exit(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Working on file: " << file
|
std::cout << "Working on file: " << file << ", direct count: " << app.count("--file")
|
||||||
<< ", direct count: " << app.count("--file")
|
<< ", opt count: " << opt->count() << std::endl;
|
||||||
<< ", opt count: " << opt->count()
|
std::cout << "Working on count: " << count << ", direct count: " << app.count("--count")
|
||||||
<< std::endl;
|
<< ", opt count: " << copt->count() << std::endl;
|
||||||
std::cout << "Working on count: " << count
|
|
||||||
<< ", direct count: " << app.count("--count")
|
|
||||||
<< ", opt count: " << copt->count()
|
|
||||||
<< std::endl;
|
|
||||||
std::cout << "Some value: " << value << std::endl;
|
std::cout << "Some value: " << value << std::endl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,21 +1,20 @@
|
|||||||
#include "CLI/CLI.hpp"
|
#include "CLI/CLI.hpp"
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
int main (int argc, char** argv) {
|
|
||||||
|
|
||||||
CLI::App app("K3Pi goofit fitter");
|
CLI::App app("K3Pi goofit fitter");
|
||||||
app.add_flag("--random", "Some random flag");
|
app.add_flag("--random", "Some random flag");
|
||||||
CLI::App* start = app.add_subcommand("start", "A great subcommand");
|
CLI::App *start = app.add_subcommand("start", "A great subcommand");
|
||||||
CLI::App* stop = app.add_subcommand("stop", "Do you really want to stop?");
|
CLI::App *stop = app.add_subcommand("stop", "Do you really want to stop?");
|
||||||
|
|
||||||
std::string file;
|
std::string file;
|
||||||
start->add_option("-f,--file", file, "File name");
|
start->add_option("-f,--file", file, "File name");
|
||||||
|
|
||||||
CLI::Option* s = stop->add_flag("-c,--count", "Counter");
|
CLI::Option *s = stop->add_flag("-c,--count", "Counter");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
app.parse(argc, argv);
|
app.parse(argc, argv);
|
||||||
} catch (const CLI::Error &e) {
|
} catch(const CLI::Error &e) {
|
||||||
return app.exit(e);
|
return app.exit(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,38 +1,30 @@
|
|||||||
#include "CLI/CLI.hpp"
|
#include "CLI/CLI.hpp"
|
||||||
#include "CLI/Timer.hpp"
|
#include "CLI/Timer.hpp"
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
int main (int argc, char** argv) {
|
|
||||||
CLI::AutoTimer("This is a timer");
|
CLI::AutoTimer("This is a timer");
|
||||||
|
|
||||||
CLI::App app("K3Pi goofit fitter");
|
CLI::App app("K3Pi goofit fitter");
|
||||||
|
|
||||||
std::string file;
|
std::string file;
|
||||||
CLI::Option* opt = app.add_option("-f,--file,file", file, "File name")
|
CLI::Option *opt = app.add_option("-f,--file,file", file, "File name")->required()->group("Important");
|
||||||
->required()->group("Important");
|
|
||||||
|
|
||||||
int count;
|
|
||||||
CLI::Option* copt = app.add_flag("-c,--count", count, "Counter")
|
|
||||||
->required()->group("Important");
|
|
||||||
|
|
||||||
double value;// = 3.14;
|
int count;
|
||||||
app.add_option("-d,--double", value, "Some Value")
|
CLI::Option *copt = app.add_flag("-c,--count", count, "Counter")->required()->group("Important");
|
||||||
->group("Other");
|
|
||||||
|
double value; // = 3.14;
|
||||||
|
app.add_option("-d,--double", value, "Some Value")->group("Other");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
app.parse(argc, argv);
|
app.parse(argc, argv);
|
||||||
} catch (const CLI::Error &e) {
|
} catch(const CLI::Error &e) {
|
||||||
return app.exit(e);
|
return app.exit(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Working on file: " << file
|
std::cout << "Working on file: " << file << ", direct count: " << app.count("--file")
|
||||||
<< ", direct count: " << app.count("--file")
|
<< ", opt count: " << opt->count() << std::endl;
|
||||||
<< ", opt count: " << opt->count()
|
std::cout << "Working on count: " << count << ", direct count: " << app.count("--count")
|
||||||
<< std::endl;
|
<< ", opt count: " << copt->count() << std::endl;
|
||||||
std::cout << "Working on count: " << count
|
|
||||||
<< ", direct count: " << app.count("--count")
|
|
||||||
<< ", opt count: " << copt->count()
|
|
||||||
<< std::endl;
|
|
||||||
std::cout << "Some value: " << value << std::endl;
|
std::cout << "Some value: " << value << std::endl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -12,4 +12,3 @@
|
|||||||
#include "CLI/StringTools.hpp"
|
#include "CLI/StringTools.hpp"
|
||||||
#include "CLI/TypeTools.hpp"
|
#include "CLI/TypeTools.hpp"
|
||||||
#include "CLI/Validators.hpp"
|
#include "CLI/Validators.hpp"
|
||||||
|
|
||||||
|
@ -9,10 +9,11 @@
|
|||||||
|
|
||||||
namespace CLI {
|
namespace CLI {
|
||||||
|
|
||||||
/// These codes are part of every error in CLI. They can be obtained from e using e.exit_code or as a quick shortcut, int values from e.get_error_code().
|
/// These codes are part of every error in CLI. They can be obtained from e using e.exit_code or as a quick shortcut,
|
||||||
|
/// int values from e.get_error_code().
|
||||||
enum class ExitCodes {
|
enum class ExitCodes {
|
||||||
Success = 0,
|
Success = 0,
|
||||||
IncorrectConstruction=100,
|
IncorrectConstruction = 100,
|
||||||
BadNameString,
|
BadNameString,
|
||||||
OptionAlreadyAdded,
|
OptionAlreadyAdded,
|
||||||
File,
|
File,
|
||||||
@ -41,17 +42,23 @@ enum class ExitCodes {
|
|||||||
struct Error : public std::runtime_error {
|
struct Error : public std::runtime_error {
|
||||||
int exit_code;
|
int exit_code;
|
||||||
bool print_help;
|
bool print_help;
|
||||||
int get_exit_code() const {return exit_code;}
|
int get_exit_code() const { return exit_code; }
|
||||||
Error(std::string parent, std::string name, ExitCodes exit_code=ExitCodes::BaseClass, bool print_help=true)
|
Error(std::string parent, std::string name, ExitCodes exit_code = ExitCodes::BaseClass, bool print_help = true)
|
||||||
: runtime_error(parent + ": " + name), exit_code(static_cast<int>(exit_code)), print_help(print_help) {}
|
: runtime_error(parent + ": " + name), exit_code(static_cast<int>(exit_code)), print_help(print_help) {}
|
||||||
Error(std::string parent, std::string name, int exit_code=static_cast<int>(ExitCodes::BaseClass), bool print_help=true)
|
Error(std::string parent,
|
||||||
|
std::string name,
|
||||||
|
int exit_code = static_cast<int>(ExitCodes::BaseClass),
|
||||||
|
bool print_help = true)
|
||||||
: runtime_error(parent + ": " + name), exit_code(exit_code), print_help(print_help) {}
|
: runtime_error(parent + ": " + name), exit_code(exit_code), print_help(print_help) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Construction errors (not in parsing)
|
/// Construction errors (not in parsing)
|
||||||
struct ConstructionError : public Error {
|
struct ConstructionError : public Error {
|
||||||
// Using Error::Error constructors seem to not work on GCC 4.7
|
// Using Error::Error constructors seem to not work on GCC 4.7
|
||||||
ConstructionError(std::string parent, std::string name, ExitCodes exit_code=ExitCodes::BaseClass, bool print_help=true)
|
ConstructionError(std::string parent,
|
||||||
|
std::string name,
|
||||||
|
ExitCodes exit_code = ExitCodes::BaseClass,
|
||||||
|
bool print_help = true)
|
||||||
: Error(parent, name, exit_code, print_help) {}
|
: Error(parent, name, exit_code, print_help) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,8 +70,7 @@ struct IncorrectConstruction : public ConstructionError {
|
|||||||
|
|
||||||
/// Thrown on construction of a bad name
|
/// Thrown on construction of a bad name
|
||||||
struct BadNameString : public ConstructionError {
|
struct BadNameString : public ConstructionError {
|
||||||
BadNameString(std::string name)
|
BadNameString(std::string name) : ConstructionError("BadNameString", name, ExitCodes::BadNameString) {}
|
||||||
: ConstructionError("BadNameString", name, ExitCodes::BadNameString) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when an option already exists
|
/// Thrown when an option already exists
|
||||||
@ -77,7 +83,7 @@ struct OptionAlreadyAdded : public ConstructionError {
|
|||||||
|
|
||||||
/// Anything that can error in Parse
|
/// Anything that can error in Parse
|
||||||
struct ParseError : public Error {
|
struct ParseError : public Error {
|
||||||
ParseError(std::string parent, std::string name, ExitCodes exit_code=ExitCodes::BaseClass, bool print_help=true)
|
ParseError(std::string parent, std::string name, ExitCodes exit_code = ExitCodes::BaseClass, bool print_help = true)
|
||||||
: Error(parent, name, exit_code, print_help) {}
|
: Error(parent, name, exit_code, print_help) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -85,8 +91,7 @@ struct ParseError : public Error {
|
|||||||
|
|
||||||
/// This is a successful completion on parsing, supposed to exit
|
/// This is a successful completion on parsing, supposed to exit
|
||||||
struct Success : public ParseError {
|
struct Success : public ParseError {
|
||||||
Success()
|
Success() : ParseError("Success", "Successfully completed, should be caught and quit", ExitCodes::Success, false) {}
|
||||||
: ParseError("Success", "Successfully completed, should be caught and quit", ExitCodes::Success, false) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// -h or --help on command line
|
/// -h or --help on command line
|
||||||
@ -95,29 +100,24 @@ struct CallForHelp : public ParseError {
|
|||||||
: ParseError("CallForHelp", "This should be caught in your main function, see examples", ExitCodes::Success) {}
|
: ParseError("CallForHelp", "This should be caught in your main function, see examples", ExitCodes::Success) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Thrown when parsing an INI file and it is missing
|
/// Thrown when parsing an INI file and it is missing
|
||||||
struct FileError : public ParseError {
|
struct FileError : public ParseError {
|
||||||
FileError (std::string name)
|
FileError(std::string name) : ParseError("FileError", name, ExitCodes::File) {}
|
||||||
: ParseError("FileError", name, ExitCodes::File) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when conversion call back fails, such as when an int fails to coerse to a string
|
/// Thrown when conversion call back fails, such as when an int fails to coerse to a string
|
||||||
struct ConversionError : public ParseError {
|
struct ConversionError : public ParseError {
|
||||||
ConversionError(std::string name)
|
ConversionError(std::string name) : ParseError("ConversionError", name, ExitCodes::Conversion) {}
|
||||||
: ParseError("ConversionError", name, ExitCodes::Conversion) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when validation of results fails
|
/// Thrown when validation of results fails
|
||||||
struct ValidationError : public ParseError {
|
struct ValidationError : public ParseError {
|
||||||
ValidationError(std::string name)
|
ValidationError(std::string name) : ParseError("ValidationError", name, ExitCodes::Validation) {}
|
||||||
: ParseError("ValidationError", name, ExitCodes::Validation) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when a required option is missing
|
/// Thrown when a required option is missing
|
||||||
struct RequiredError : public ParseError {
|
struct RequiredError : public ParseError {
|
||||||
RequiredError(std::string name)
|
RequiredError(std::string name) : ParseError("RequiredError", name, ExitCodes::Required) {}
|
||||||
: ParseError("RequiredError", name, ExitCodes::Required) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when a requires option is missing
|
/// Thrown when a requires option is missing
|
||||||
@ -134,20 +134,17 @@ struct ExcludesError : public ParseError {
|
|||||||
|
|
||||||
/// Thrown when too many positionals or options are found
|
/// Thrown when too many positionals or options are found
|
||||||
struct ExtrasError : public ParseError {
|
struct ExtrasError : public ParseError {
|
||||||
ExtrasError(std::string name)
|
ExtrasError(std::string name) : ParseError("ExtrasError", name, ExitCodes::Extras) {}
|
||||||
: ParseError("ExtrasError", name, ExitCodes::Extras) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when extra values are found in an INI file
|
/// Thrown when extra values are found in an INI file
|
||||||
struct ExtrasINIError : public ParseError {
|
struct ExtrasINIError : public ParseError {
|
||||||
ExtrasINIError(std::string name)
|
ExtrasINIError(std::string name) : ParseError("ExtrasINIError", name, ExitCodes::ExtrasINI) {}
|
||||||
: ParseError("ExtrasINIError", name, ExitCodes::ExtrasINI) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when validation fails before parsing
|
/// Thrown when validation fails before parsing
|
||||||
struct InvalidError : public ParseError {
|
struct InvalidError : public ParseError {
|
||||||
InvalidError(std::string name)
|
InvalidError(std::string name) : ParseError("InvalidError", name, ExitCodes::Invalid) {}
|
||||||
: ParseError("InvalidError", name, ExitCodes::Invalid) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This is just a safety check to verify selection and parsing match
|
/// This is just a safety check to verify selection and parsing match
|
||||||
@ -160,8 +157,7 @@ struct HorribleError : public ParseError {
|
|||||||
|
|
||||||
/// Thrown when counting a non-existent option
|
/// Thrown when counting a non-existent option
|
||||||
struct OptionNotFound : public Error {
|
struct OptionNotFound : public Error {
|
||||||
OptionNotFound(std::string name)
|
OptionNotFound(std::string name) : Error("OptionNotFound", name, ExitCodes::OptionNotFound) {}
|
||||||
: Error("OptionNotFound", name, ExitCodes::OptionNotFound) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
@ -10,18 +10,17 @@
|
|||||||
|
|
||||||
#include "CLI/StringTools.hpp"
|
#include "CLI/StringTools.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace CLI {
|
namespace CLI {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
inline std::string inijoin(std::vector<std::string> args) {
|
inline std::string inijoin(std::vector<std::string> args) {
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
size_t start = 0;
|
size_t start = 0;
|
||||||
for (const auto& arg : args) {
|
for(const auto &arg : args) {
|
||||||
if(start++ > 0)
|
if(start++ > 0)
|
||||||
s << " ";
|
s << " ";
|
||||||
|
|
||||||
auto it = std::find_if(arg.begin(), arg.end(), [](char ch){ return std::isspace<char>(ch , std::locale());});
|
auto it = std::find_if(arg.begin(), arg.end(), [](char ch) { return std::isspace<char>(ch, std::locale()); });
|
||||||
if(it == arg.end())
|
if(it == arg.end())
|
||||||
s << arg;
|
s << arg;
|
||||||
else if(arg.find(R"(")") == std::string::npos)
|
else if(arg.find(R"(")") == std::string::npos)
|
||||||
@ -47,18 +46,18 @@ struct ini_ret_t {
|
|||||||
///
|
///
|
||||||
/// Level 0, a.b.c would return a
|
/// Level 0, a.b.c would return a
|
||||||
/// Level 1, a.b.c could return b
|
/// Level 1, a.b.c could return b
|
||||||
std::string parent () const {
|
std::string parent() const {
|
||||||
std::vector<std::string> plist = detail::split(fullname, '.');
|
std::vector<std::string> plist = detail::split(fullname, '.');
|
||||||
if(plist.size() > (level+1))
|
if(plist.size() > (level + 1))
|
||||||
return plist[level];
|
return plist[level];
|
||||||
else
|
else
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return name
|
/// Return name
|
||||||
std::string name () const {
|
std::string name() const {
|
||||||
std::vector<std::string> plist = detail::split(fullname, '.');
|
std::vector<std::string> plist = detail::split(fullname, '.');
|
||||||
return plist.at(plist.size()-1);
|
return plist.at(plist.size() - 1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -74,17 +73,17 @@ inline std::vector<ini_ret_t> parse_ini(std::istream &input) {
|
|||||||
|
|
||||||
detail::trim(line);
|
detail::trim(line);
|
||||||
size_t len = line.length();
|
size_t len = line.length();
|
||||||
if(len > 1 && line[0] == '[' && line[len-1] == ']') {
|
if(len > 1 && line[0] == '[' && line[len - 1] == ']') {
|
||||||
section = line.substr(1,len-2);
|
section = line.substr(1, len - 2);
|
||||||
} else if (len > 0 && line[0] != ';') {
|
} else if(len > 0 && line[0] != ';') {
|
||||||
output.emplace_back();
|
output.emplace_back();
|
||||||
ini_ret_t& out = output.back();
|
ini_ret_t &out = output.back();
|
||||||
|
|
||||||
// Find = in string, split and recombine
|
// Find = in string, split and recombine
|
||||||
auto pos = line.find("=");
|
auto pos = line.find("=");
|
||||||
if(pos != std::string::npos) {
|
if(pos != std::string::npos) {
|
||||||
name = detail::trim_copy(line.substr(0,pos));
|
name = detail::trim_copy(line.substr(0, pos));
|
||||||
std::string item = detail::trim_copy(line.substr(pos+1));
|
std::string item = detail::trim_copy(line.substr(pos + 1));
|
||||||
items = detail::split_up(item);
|
items = detail::split_up(item);
|
||||||
} else {
|
} else {
|
||||||
name = detail::trim_copy(line);
|
name = detail::trim_copy(line);
|
||||||
@ -112,6 +111,5 @@ inline std::vector<ini_ret_t> parse_ini(const std::string &name) {
|
|||||||
return parse_ini(input);
|
return parse_ini(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace CLI
|
} // namespace CLI
|
||||||
|
@ -19,17 +19,17 @@
|
|||||||
namespace CLI {
|
namespace CLI {
|
||||||
|
|
||||||
using results_t = std::vector<std::string>;
|
using results_t = std::vector<std::string>;
|
||||||
using callback_t = std::function<bool (results_t)>;
|
using callback_t = std::function<bool(results_t)>;
|
||||||
|
|
||||||
class Option;
|
class Option;
|
||||||
class App;
|
class App;
|
||||||
|
|
||||||
using Option_p = std::unique_ptr<Option>;
|
using Option_p = std::unique_ptr<Option>;
|
||||||
|
|
||||||
|
|
||||||
class Option {
|
class Option {
|
||||||
friend App;
|
friend App;
|
||||||
protected:
|
|
||||||
|
protected:
|
||||||
/// @name Names
|
/// @name Names
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ protected:
|
|||||||
///@}
|
///@}
|
||||||
/// @name Help
|
/// @name Help
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
/// The description for help strings
|
/// The description for help strings
|
||||||
std::string description_;
|
std::string description_;
|
||||||
|
|
||||||
@ -59,47 +59,46 @@ protected:
|
|||||||
std::string typeval_;
|
std::string typeval_;
|
||||||
|
|
||||||
/// The group membership
|
/// The group membership
|
||||||
std::string group_ {"Options"};
|
std::string group_{"Options"};
|
||||||
|
|
||||||
/// True if this option has a default
|
/// True if this option has a default
|
||||||
bool default_ {false};
|
bool default_{false};
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
/// @name Configuration
|
/// @name Configuration
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
/// True if this is a required option
|
/// True if this is a required option
|
||||||
bool required_ {false};
|
bool required_{false};
|
||||||
|
|
||||||
/// The number of expected values, 0 for flag, -1 for unlimited vector
|
/// The number of expected values, 0 for flag, -1 for unlimited vector
|
||||||
int expected_ {1};
|
int expected_{1};
|
||||||
|
|
||||||
/// A private setting to allow args to not be able to accept incorrect expected values
|
/// A private setting to allow args to not be able to accept incorrect expected values
|
||||||
bool changeable_ {false};
|
bool changeable_{false};
|
||||||
|
|
||||||
/// Ignore the case when matching (option, not value)
|
/// Ignore the case when matching (option, not value)
|
||||||
bool ignore_case_ {false};
|
bool ignore_case_{false};
|
||||||
|
|
||||||
/// A list of validators to run on each value parsed
|
/// A list of validators to run on each value parsed
|
||||||
std::vector<std::function<bool(std::string)>> validators_;
|
std::vector<std::function<bool(std::string)>> validators_;
|
||||||
|
|
||||||
/// A list of options that are required with this option
|
/// A list of options that are required with this option
|
||||||
std::set<Option*> requires_;
|
std::set<Option *> requires_;
|
||||||
|
|
||||||
/// A list of options that are excluded with this option
|
/// A list of options that are excluded with this option
|
||||||
std::set<Option*> excludes_;
|
std::set<Option *> excludes_;
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
/// @name Other
|
/// @name Other
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
/// Remember the parent app
|
/// Remember the parent app
|
||||||
App* parent_;
|
App *parent_;
|
||||||
|
|
||||||
/// Options store a callback to do all the work
|
/// Options store a callback to do all the work
|
||||||
callback_t callback_;
|
callback_t callback_;
|
||||||
|
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
/// @name Parsing results
|
/// @name Parsing results
|
||||||
///@{
|
///@{
|
||||||
@ -108,54 +107,48 @@ protected:
|
|||||||
results_t results_;
|
results_t results_;
|
||||||
|
|
||||||
/// Whether the callback has run (needed for INI parsing)
|
/// Whether the callback has run (needed for INI parsing)
|
||||||
bool callback_run_ {false};
|
bool callback_run_{false};
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
/// Making an option by hand is not defined, it must be made by the App class
|
/// Making an option by hand is not defined, it must be made by the App class
|
||||||
Option(std::string name, std::string description = "", std::function<bool(results_t)> callback=[](results_t){return true;}, bool default_=true, App* parent = nullptr) :
|
Option(std::string name,
|
||||||
description_(std::move(description)), default_(default_), parent_(parent), callback_(std::move(callback)) {
|
std::string description = "",
|
||||||
|
std::function<bool(results_t)> callback = [](results_t) { return true; },
|
||||||
|
bool default_ = true,
|
||||||
|
App *parent = nullptr)
|
||||||
|
: description_(std::move(description)), default_(default_), parent_(parent), callback_(std::move(callback)) {
|
||||||
std::tie(snames_, lnames_, pname_) = detail::get_names(detail::split_names(name));
|
std::tie(snames_, lnames_, pname_) = detail::get_names(detail::split_names(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// @name Basic
|
/// @name Basic
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
/// Count the total number of times an option was passed
|
/// Count the total number of times an option was passed
|
||||||
size_t count() const {
|
size_t count() const { return results_.size(); }
|
||||||
return results_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// This class is true if option is passed.
|
/// This class is true if option is passed.
|
||||||
operator bool() const {
|
operator bool() const { return count() > 0; }
|
||||||
return count() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Clear the parsed results (mostly for testing)
|
/// Clear the parsed results (mostly for testing)
|
||||||
void clear() {
|
void clear() { results_.clear(); }
|
||||||
results_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
/// @name Setting options
|
/// @name Setting options
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
/// Set the option as required
|
/// Set the option as required
|
||||||
Option* required(bool value = true) {
|
Option *required(bool value = true) {
|
||||||
required_ = value;
|
required_ = value;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Support Plubmum term
|
/// Support Plubmum term
|
||||||
Option* mandatory(bool value = true) {
|
Option *mandatory(bool value = true) { return required(value); }
|
||||||
return required(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the number of expected arguments (Flags bypass this)
|
/// Set the number of expected arguments (Flags bypass this)
|
||||||
Option* expected(int value) {
|
Option *expected(int value) {
|
||||||
if(value == 0)
|
if(value == 0)
|
||||||
throw IncorrectConstruction("Cannot set 0 expected, use a flag instead");
|
throw IncorrectConstruction("Cannot set 0 expected, use a flag instead");
|
||||||
else if(expected_ == 0)
|
else if(expected_ == 0)
|
||||||
@ -167,21 +160,20 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a validator
|
/// Adds a validator
|
||||||
Option* check(std::function<bool(std::string)> validator) {
|
Option *check(std::function<bool(std::string)> validator) {
|
||||||
|
|
||||||
validators_.push_back(validator);
|
validators_.push_back(validator);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Changes the group membership
|
/// Changes the group membership
|
||||||
Option* group(std::string name) {
|
Option *group(std::string name) {
|
||||||
group_ = name;
|
group_ = name;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Sets required options
|
/// Sets required options
|
||||||
Option* requires(Option* opt) {
|
Option *requires(Option *opt) {
|
||||||
auto tup = requires_.insert(opt);
|
auto tup = requires_.insert(opt);
|
||||||
if(!tup.second)
|
if(!tup.second)
|
||||||
throw OptionAlreadyAdded(get_name() + " requires " + opt->get_name());
|
throw OptionAlreadyAdded(get_name() + " requires " + opt->get_name());
|
||||||
@ -189,24 +181,21 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Can find a string if needed
|
/// Can find a string if needed
|
||||||
template<typename T=App>
|
template <typename T = App> Option *requires(std::string opt_name) {
|
||||||
Option* requires(std::string opt_name) {
|
for(const Option_p &opt : dynamic_cast<T *>(parent_)->options_)
|
||||||
for(const Option_p& opt : dynamic_cast<T*>(parent_)->options_)
|
|
||||||
if(opt.get() != this && opt->check_name(opt_name))
|
if(opt.get() != this && opt->check_name(opt_name))
|
||||||
return requires(opt.get());
|
return requires(opt.get());
|
||||||
throw IncorrectConstruction("Option " + opt_name + " is not defined");
|
throw IncorrectConstruction("Option " + opt_name + " is not defined");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Any number supported, any mix of string and Opt
|
/// Any number supported, any mix of string and Opt
|
||||||
template<typename A, typename B, typename... ARG>
|
template <typename A, typename B, typename... ARG> Option *requires(A opt, B opt1, ARG... args) {
|
||||||
Option* requires(A opt, B opt1, ARG... args) {
|
|
||||||
requires(opt);
|
requires(opt);
|
||||||
return requires(opt1, args...);
|
return requires(opt1, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets excluded options
|
/// Sets excluded options
|
||||||
Option* excludes(Option* opt) {
|
Option *excludes(Option *opt) {
|
||||||
auto tup = excludes_.insert(opt);
|
auto tup = excludes_.insert(opt);
|
||||||
if(!tup.second)
|
if(!tup.second)
|
||||||
throw OptionAlreadyAdded(get_name() + " excludes " + opt->get_name());
|
throw OptionAlreadyAdded(get_name() + " excludes " + opt->get_name());
|
||||||
@ -214,23 +203,20 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Can find a string if needed
|
/// Can find a string if needed
|
||||||
template<typename T=App>
|
template <typename T = App> Option *excludes(std::string opt_name) {
|
||||||
Option* excludes(std::string opt_name) {
|
for(const Option_p &opt : dynamic_cast<T *>(parent_)->options_)
|
||||||
for(const Option_p& opt : dynamic_cast<T*>(parent_)->options_)
|
|
||||||
if(opt.get() != this && opt->check_name(opt_name))
|
if(opt.get() != this && opt->check_name(opt_name))
|
||||||
return excludes(opt.get());
|
return excludes(opt.get());
|
||||||
throw IncorrectConstruction("Option " + opt_name + " is not defined");
|
throw IncorrectConstruction("Option " + opt_name + " is not defined");
|
||||||
|
|
||||||
}
|
}
|
||||||
/// Any number supported, any mix of string and Opt
|
/// Any number supported, any mix of string and Opt
|
||||||
template<typename A, typename B, typename... ARG>
|
template <typename A, typename B, typename... ARG> Option *excludes(A opt, B opt1, ARG... args) {
|
||||||
Option* excludes(A opt, B opt1, ARG... args) {
|
|
||||||
excludes(opt);
|
excludes(opt);
|
||||||
return excludes(opt1, args...);
|
return excludes(opt1, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets environment variable to read if no option given
|
/// Sets environment variable to read if no option given
|
||||||
Option* envname(std::string name) {
|
Option *envname(std::string name) {
|
||||||
envname_ = name;
|
envname_ = name;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -239,10 +225,9 @@ public:
|
|||||||
///
|
///
|
||||||
/// The template hides the fact that we don't have the definition of App yet.
|
/// The template hides the fact that we don't have the definition of App yet.
|
||||||
/// You are never expected to add an argument to the template here.
|
/// You are never expected to add an argument to the template here.
|
||||||
template<typename T=App>
|
template <typename T = App> Option *ignore_case(bool value = true) {
|
||||||
Option* ignore_case(bool value = true) {
|
|
||||||
ignore_case_ = value;
|
ignore_case_ = value;
|
||||||
for(const Option_p& opt : dynamic_cast<T*>(parent_)->options_)
|
for(const Option_p &opt : dynamic_cast<T *>(parent_)->options_)
|
||||||
if(opt.get() != this && *opt == *this)
|
if(opt.get() != this && *opt == *this)
|
||||||
throw OptionAlreadyAdded(opt->get_name());
|
throw OptionAlreadyAdded(opt->get_name());
|
||||||
return this;
|
return this;
|
||||||
@ -251,76 +236,58 @@ public:
|
|||||||
///@}
|
///@}
|
||||||
/// @name Accessors
|
/// @name Accessors
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
/// True if this is a required option
|
/// True if this is a required option
|
||||||
bool get_required() const {
|
bool get_required() const { return required_; }
|
||||||
return required_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The number of arguments the option expects
|
/// The number of arguments the option expects
|
||||||
int get_expected() const {
|
int get_expected() const { return expected_; }
|
||||||
return expected_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// True if this has a default value
|
/// True if this has a default value
|
||||||
int get_default() const {
|
int get_default() const { return default_; }
|
||||||
return default_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// True if the argument can be given directly
|
/// True if the argument can be given directly
|
||||||
bool get_positional() const {
|
bool get_positional() const { return pname_.length() > 0; }
|
||||||
return pname_.length() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// True if option has at least one non-positional name
|
/// True if option has at least one non-positional name
|
||||||
bool nonpositional() const {
|
bool nonpositional() const { return (snames_.size() + lnames_.size()) > 0; }
|
||||||
return (snames_.size() + lnames_.size()) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// True if option has description
|
/// True if option has description
|
||||||
bool has_description() const {
|
bool has_description() const { return description_.length() > 0; }
|
||||||
return description_.length() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the group of this option
|
/// Get the group of this option
|
||||||
const std::string& get_group() const {
|
const std::string &get_group() const { return group_; }
|
||||||
return group_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the description
|
/// Get the description
|
||||||
const std::string& get_description() const {
|
const std::string &get_description() const { return description_; }
|
||||||
return description_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Just the pname
|
// Just the pname
|
||||||
std::string get_pname() const {
|
std::string get_pname() const { return pname_; }
|
||||||
return pname_;
|
|
||||||
}
|
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
/// @name Help tools
|
/// @name Help tools
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
/// Gets a , sep list of names. Does not include the positional name if opt_only=true.
|
/// Gets a , sep list of names. Does not include the positional name if opt_only=true.
|
||||||
std::string get_name(bool opt_only=false) const {
|
std::string get_name(bool opt_only = false) const {
|
||||||
std::vector<std::string> name_list;
|
std::vector<std::string> name_list;
|
||||||
if(!opt_only && pname_.length() > 0)
|
if(!opt_only && pname_.length() > 0)
|
||||||
name_list.push_back(pname_);
|
name_list.push_back(pname_);
|
||||||
for(const std::string& sname : snames_)
|
for(const std::string &sname : snames_)
|
||||||
name_list.push_back("-"+sname);
|
name_list.push_back("-" + sname);
|
||||||
for(const std::string& lname : lnames_)
|
for(const std::string &lname : lnames_)
|
||||||
name_list.push_back("--"+lname);
|
name_list.push_back("--" + lname);
|
||||||
return detail::join(name_list);
|
return detail::join(name_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The name and any extras needed for positionals
|
/// The name and any extras needed for positionals
|
||||||
std::string help_positional() const {
|
std::string help_positional() const {
|
||||||
std::string out = pname_;
|
std::string out = pname_;
|
||||||
if(get_expected()>1)
|
if(get_expected() > 1)
|
||||||
out = out + "(" + std::to_string(get_expected()) + "x)";
|
out = out + "(" + std::to_string(get_expected()) + "x)";
|
||||||
else if(get_expected()==-1)
|
else if(get_expected() == -1)
|
||||||
out = out + "...";
|
out = out + "...";
|
||||||
out = get_required() ? out : "["+out+"]";
|
out = get_required() ? out : "[" + out + "]";
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,7 +297,7 @@ public:
|
|||||||
out << get_name(true) << help_aftername();
|
out << get_name(true) << help_aftername();
|
||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// pname with type info
|
/// pname with type info
|
||||||
std::string help_pname() const {
|
std::string help_pname() const {
|
||||||
std::stringstream out;
|
std::stringstream out;
|
||||||
@ -346,7 +313,7 @@ public:
|
|||||||
if(typeval_ != "")
|
if(typeval_ != "")
|
||||||
out << " " << typeval_;
|
out << " " << typeval_;
|
||||||
if(defaultval_ != "")
|
if(defaultval_ != "")
|
||||||
out << "=" << defaultval_;
|
out << "=" << defaultval_;
|
||||||
if(get_expected() > 1)
|
if(get_expected() > 1)
|
||||||
out << " x " << get_expected();
|
out << " x " << get_expected();
|
||||||
if(get_expected() == -1)
|
if(get_expected() == -1)
|
||||||
@ -356,29 +323,27 @@ public:
|
|||||||
out << " (env:" << envname_ << ")";
|
out << " (env:" << envname_ << ")";
|
||||||
if(!requires_.empty()) {
|
if(!requires_.empty()) {
|
||||||
out << " Requires:";
|
out << " Requires:";
|
||||||
for(const Option* opt : requires_)
|
for(const Option *opt : requires_)
|
||||||
out << " " << opt->get_name();
|
out << " " << opt->get_name();
|
||||||
}
|
}
|
||||||
if(!excludes_.empty()) {
|
if(!excludes_.empty()) {
|
||||||
out << " Excludes:";
|
out << " Excludes:";
|
||||||
for(const Option* opt : excludes_)
|
for(const Option *opt : excludes_)
|
||||||
out << " " << opt->get_name();
|
out << " " << opt->get_name();
|
||||||
}
|
}
|
||||||
return out.str();
|
return out.str();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
/// @name Parser tools
|
/// @name Parser tools
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
/// Process the callback
|
/// Process the callback
|
||||||
void run_callback() const {
|
void run_callback() const {
|
||||||
if(!callback_(results_))
|
if(!callback_(results_))
|
||||||
throw ConversionError(get_name() + "=" + detail::join(results_));
|
throw ConversionError(get_name() + "=" + detail::join(results_));
|
||||||
if(!validators_.empty()) {
|
if(!validators_.empty()) {
|
||||||
for(const std::string & result : results_)
|
for(const std::string &result : results_)
|
||||||
for(const std::function<bool(std::string)> &vali : validators_)
|
for(const std::function<bool(std::string)> &vali : validators_)
|
||||||
if(!vali(result))
|
if(!vali(result))
|
||||||
throw ValidationError(get_name() + "=" + result);
|
throw ValidationError(get_name() + "=" + result);
|
||||||
@ -386,7 +351,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// If options share any of the same names, they are equal (not counting positional)
|
/// 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_)
|
||||||
if(other.check_sname(sname))
|
if(other.check_sname(sname))
|
||||||
return true;
|
return true;
|
||||||
@ -406,9 +371,9 @@ public:
|
|||||||
/// Check a name. Requires "-" or "--" for short / long, supports positional name
|
/// 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 {
|
||||||
|
|
||||||
if(name.length()>2 && name.substr(0,2) == "--")
|
if(name.length() > 2 && name.substr(0, 2) == "--")
|
||||||
return check_lname(name.substr(2));
|
return check_lname(name.substr(2));
|
||||||
else if (name.length()>1 && name.substr(0,1) == "-")
|
else if(name.length() > 1 && name.substr(0, 1) == "-")
|
||||||
return check_sname(name.substr(1));
|
return check_sname(name.substr(1));
|
||||||
else {
|
else {
|
||||||
std::string local_pname = pname_;
|
std::string local_pname = pname_;
|
||||||
@ -424,73 +389,60 @@ public:
|
|||||||
bool check_sname(std::string name) const {
|
bool check_sname(std::string name) const {
|
||||||
if(ignore_case_) {
|
if(ignore_case_) {
|
||||||
name = detail::to_lower(name);
|
name = detail::to_lower(name);
|
||||||
return std::find_if(std::begin(snames_), std::end(snames_),
|
return std::find_if(std::begin(snames_), std::end(snames_), [&name](std::string local_sname) {
|
||||||
[&name](std::string local_sname){return detail::to_lower(local_sname) == name;})
|
return detail::to_lower(local_sname) == name;
|
||||||
!= std::end(snames_);
|
}) != std::end(snames_);
|
||||||
} else
|
} else
|
||||||
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
|
/// Requires "--" to be removed from string
|
||||||
bool check_lname(std::string name) const {
|
bool check_lname(std::string name) const {
|
||||||
if(ignore_case_) {
|
if(ignore_case_) {
|
||||||
name = detail::to_lower(name);
|
name = detail::to_lower(name);
|
||||||
return std::find_if(std::begin(lnames_), std::end(lnames_),
|
return std::find_if(std::begin(lnames_), std::end(lnames_), [&name](std::string local_sname) {
|
||||||
[&name](std::string local_sname){return detail::to_lower(local_sname) == name;})
|
return detail::to_lower(local_sname) == name;
|
||||||
!= std::end(lnames_);
|
}) != std::end(lnames_);
|
||||||
} else
|
} else
|
||||||
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
|
/// Puts a result at position r
|
||||||
void add_result(std::string s) {
|
void add_result(std::string s) {
|
||||||
results_.push_back(s);
|
results_.push_back(s);
|
||||||
callback_run_ = false;
|
callback_run_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Get a copy of the results
|
/// Get a copy of the results
|
||||||
std::vector<std::string> results() const {
|
std::vector<std::string> results() const { return results_; }
|
||||||
return results_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See if the callback has been run already
|
/// See if the callback has been run already
|
||||||
bool get_callback_run() const {
|
bool get_callback_run() const { return callback_run_; }
|
||||||
return callback_run_;
|
|
||||||
}
|
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
/// @name Custom options
|
/// @name Custom options
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
/// Set a custom option, typestring, expected, and changeable
|
/// Set a custom option, typestring, expected, and changeable
|
||||||
void set_custom_option(std::string typeval, int expected=1, bool changeable = false) {
|
void set_custom_option(std::string typeval, int expected = 1, bool changeable = false) {
|
||||||
typeval_ = typeval;
|
typeval_ = typeval;
|
||||||
expected_ = expected;
|
expected_ = expected;
|
||||||
changeable_ = changeable;
|
changeable_ = changeable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the default value string representation
|
/// Set the default value string representation
|
||||||
void set_default_val(std::string val) {
|
void set_default_val(std::string val) { defaultval_ = val; }
|
||||||
defaultval_ = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
|
protected:
|
||||||
protected:
|
|
||||||
|
|
||||||
|
|
||||||
/// @name App Helpers
|
/// @name App Helpers
|
||||||
///@{
|
///@{
|
||||||
/// Can print positional name detailed option if true
|
/// Can print positional name detailed option if true
|
||||||
bool _has_help_positional() const {
|
bool _has_help_positional() const {
|
||||||
return get_positional() && (has_description() || !requires_.empty() || !excludes_.empty() );
|
return get_positional() && (has_description() || !requires_.empty() || !excludes_.empty());
|
||||||
}
|
}
|
||||||
///@}
|
///@}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace CLI
|
} // namespace CLI
|
||||||
|
@ -15,8 +15,8 @@ namespace detail {
|
|||||||
|
|
||||||
// Returns false if not a short option. Otherwise, sets opt name and rest and returns true
|
// Returns false if not a short option. Otherwise, sets opt name and rest and returns true
|
||||||
inline bool split_short(const std::string ¤t, std::string &name, std::string &rest) {
|
inline bool split_short(const std::string ¤t, std::string &name, std::string &rest) {
|
||||||
if(current.size()>1 && current[0] == '-' && valid_first_char(current[1])) {
|
if(current.size() > 1 && current[0] == '-' && valid_first_char(current[1])) {
|
||||||
name = current.substr(1,1);
|
name = current.substr(1, 1);
|
||||||
rest = current.substr(2);
|
rest = current.substr(2);
|
||||||
return true;
|
return true;
|
||||||
} else
|
} else
|
||||||
@ -25,11 +25,11 @@ inline bool split_short(const std::string ¤t, std::string &name, std::stri
|
|||||||
|
|
||||||
// Returns false if not a long option. Otherwise, sets opt name and other side of = and returns true
|
// Returns false if not a long option. Otherwise, sets opt name and other side of = and returns true
|
||||||
inline bool split_long(const std::string ¤t, std::string &name, std::string &value) {
|
inline bool split_long(const std::string ¤t, std::string &name, std::string &value) {
|
||||||
if(current.size()>2 && current.substr(0,2) == "--" && valid_first_char(current[2])) {
|
if(current.size() > 2 && current.substr(0, 2) == "--" && valid_first_char(current[2])) {
|
||||||
auto loc = current.find("=");
|
auto loc = current.find("=");
|
||||||
if(loc != std::string::npos) {
|
if(loc != std::string::npos) {
|
||||||
name = current.substr(2,loc-2);
|
name = current.substr(2, loc - 2);
|
||||||
value = current.substr(loc+1);
|
value = current.substr(loc + 1);
|
||||||
} else {
|
} else {
|
||||||
name = current.substr(2);
|
name = current.substr(2);
|
||||||
value = "";
|
value = "";
|
||||||
@ -44,18 +44,17 @@ inline std::vector<std::string> split_names(std::string current) {
|
|||||||
std::vector<std::string> output;
|
std::vector<std::string> output;
|
||||||
size_t val;
|
size_t val;
|
||||||
while((val = current.find(",")) != std::string::npos) {
|
while((val = current.find(",")) != std::string::npos) {
|
||||||
output.push_back(current.substr(0,val));
|
output.push_back(current.substr(0, val));
|
||||||
current = current.substr(val+1);
|
current = current.substr(val + 1);
|
||||||
}
|
}
|
||||||
output.push_back(current);
|
output.push_back(current);
|
||||||
return output;
|
return output;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a vector of short names, one of long names, and a single name
|
/// Get a vector of short names, one of long names, and a single name
|
||||||
inline std::tuple<std::vector<std::string>,std::vector<std::string>, std::string>
|
inline std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>
|
||||||
get_names(const std::vector<std::string> &input) {
|
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;
|
std::string pos_name;
|
||||||
@ -64,30 +63,28 @@ inline std::tuple<std::vector<std::string>,std::vector<std::string>, std::string
|
|||||||
if(name.length() == 0)
|
if(name.length() == 0)
|
||||||
continue;
|
continue;
|
||||||
else if(name.length() > 1 && name[0] == '-' && name[1] != '-') {
|
else if(name.length() > 1 && name[0] == '-' && name[1] != '-') {
|
||||||
if(name.length()==2 && valid_first_char(name[1]))
|
if(name.length() == 2 && valid_first_char(name[1]))
|
||||||
short_names.emplace_back(1,name[1]);
|
short_names.emplace_back(1, name[1]);
|
||||||
else
|
else
|
||||||
throw BadNameString("Invalid one char name: "+name);
|
throw BadNameString("Invalid one char name: " + name);
|
||||||
} else if(name.length() > 2 && name.substr(0,2) == "--") {
|
} else if(name.length() > 2 && name.substr(0, 2) == "--") {
|
||||||
name = name.substr(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 == "--") {
|
} else if(name == "-" || name == "--") {
|
||||||
throw BadNameString("Must have a name, not just dashes");
|
throw BadNameString("Must have a name, not just dashes");
|
||||||
} else {
|
} else {
|
||||||
if(pos_name.length() > 0)
|
if(pos_name.length() > 0)
|
||||||
throw BadNameString("Only one positional name allowed, remove: "+name);
|
throw BadNameString("Only one positional name allowed, remove: " + name);
|
||||||
pos_name = name;
|
pos_name = name;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::tuple<std::vector<std::string>,std::vector<std::string>, std::string>
|
|
||||||
(short_names, long_names, pos_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>(
|
||||||
|
short_names, long_names, pos_name);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace CLI
|
} // namespace CLI
|
||||||
|
@ -13,32 +13,29 @@
|
|||||||
namespace CLI {
|
namespace CLI {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
|
||||||
// Based on http://stackoverflow.com/questions/236129/split-a-string-in-c
|
// Based on http://stackoverflow.com/questions/236129/split-a-string-in-c
|
||||||
///Split a string by a delim
|
/// Split a string by a delim
|
||||||
inline std::vector<std::string> split(const std::string &s, char delim) {
|
inline std::vector<std::string> split(const std::string &s, char delim) {
|
||||||
std::vector<std::string> elems;
|
std::vector<std::string> elems;
|
||||||
// Check to see if emtpy string, give consistent result
|
// Check to see if emtpy string, give consistent result
|
||||||
if(s=="")
|
if(s == "")
|
||||||
elems.emplace_back("");
|
elems.emplace_back("");
|
||||||
else {
|
else {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss.str(s);
|
ss.str(s);
|
||||||
std::string item;
|
std::string item;
|
||||||
while (std::getline(ss, item, delim)) {
|
while(std::getline(ss, item, delim)) {
|
||||||
elems.push_back(item);
|
elems.push_back(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return elems;
|
return elems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Simple function to join a string
|
/// Simple function to join a string
|
||||||
template <typename T>
|
template <typename T> std::string join(const T &v, std::string delim = ",") {
|
||||||
std::string join(const T& v, std::string delim = ",") {
|
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
size_t start = 0;
|
size_t start = 0;
|
||||||
for (const auto& i : v) {
|
for(const auto &i : v) {
|
||||||
if(start++ > 0)
|
if(start++ > 0)
|
||||||
s << delim;
|
s << delim;
|
||||||
s << i;
|
s << i;
|
||||||
@ -47,10 +44,9 @@ std::string join(const T& v, std::string delim = ",") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Join a string in reverse order
|
/// Join a string in reverse order
|
||||||
template<typename T>
|
template <typename T> std::string rjoin(const T &v, std::string delim = ",") {
|
||||||
std::string rjoin(const T& v, std::string delim = ",") {
|
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
for(size_t start=0; start<v.size(); start++) {
|
for(size_t start = 0; start < v.size(); start++) {
|
||||||
if(start > 0)
|
if(start > 0)
|
||||||
s << delim;
|
s << delim;
|
||||||
s << v[v.size() - start - 1];
|
s << v[v.size() - start - 1];
|
||||||
@ -61,43 +57,39 @@ std::string rjoin(const T& v, std::string delim = ",") {
|
|||||||
// Based roughly on http://stackoverflow.com/questions/25829143/c-trim-whitespace-from-a-string
|
// Based roughly on http://stackoverflow.com/questions/25829143/c-trim-whitespace-from-a-string
|
||||||
|
|
||||||
/// Trim whitespace from left of string
|
/// Trim whitespace from left of string
|
||||||
inline std::string& ltrim(std::string &str) {
|
inline std::string <rim(std::string &str) {
|
||||||
auto it = std::find_if(str.begin(), str.end(), [](char ch){ return !std::isspace<char>(ch , std::locale());});
|
auto it = std::find_if(str.begin(), str.end(), [](char ch) { return !std::isspace<char>(ch, std::locale()); });
|
||||||
str.erase(str.begin(), it);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trim anything from left of string
|
|
||||||
inline std::string& ltrim(std::string &str, const std::string &filter) {
|
|
||||||
auto it = std::find_if(str.begin(), str.end(), [&filter](char ch){return filter.find(ch) == std::string::npos;});
|
|
||||||
str.erase(str.begin(), it);
|
str.erase(str.begin(), it);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trim anything from left of string
|
||||||
|
inline std::string <rim(std::string &str, const std::string &filter) {
|
||||||
|
auto it = std::find_if(str.begin(), str.end(), [&filter](char ch) { return filter.find(ch) == std::string::npos; });
|
||||||
|
str.erase(str.begin(), it);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
/// Trim whitespace from right of string
|
/// Trim whitespace from right of string
|
||||||
inline std::string& rtrim(std::string &str) {
|
inline std::string &rtrim(std::string &str) {
|
||||||
auto it = std::find_if(str.rbegin(), str.rend(), [](char ch){ return !std::isspace<char>(ch, std::locale());});
|
auto it = std::find_if(str.rbegin(), str.rend(), [](char ch) { return !std::isspace<char>(ch, std::locale()); });
|
||||||
str.erase(it.base() , str.end() );
|
str.erase(it.base(), str.end());
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trim anything from right of string
|
/// Trim anything from right of string
|
||||||
inline std::string& rtrim(std::string &str, const std::string &filter) {
|
inline std::string &rtrim(std::string &str, const std::string &filter) {
|
||||||
auto it = std::find_if(str.rbegin(), str.rend(), [&filter](char ch){return filter.find(ch) == std::string::npos;});
|
auto it =
|
||||||
|
std::find_if(str.rbegin(), str.rend(), [&filter](char ch) { return filter.find(ch) == std::string::npos; });
|
||||||
str.erase(it.base(), str.end());
|
str.erase(it.base(), str.end());
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trim whitespace from string
|
/// Trim whitespace from string
|
||||||
inline std::string& trim(std::string &str) {
|
inline std::string &trim(std::string &str) { return ltrim(rtrim(str)); }
|
||||||
return ltrim(rtrim(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trim anything from string
|
/// Trim anything from string
|
||||||
inline std::string& trim(std::string &str, const std::string filter) {
|
inline std::string &trim(std::string &str, const std::string filter) { return ltrim(rtrim(str, filter), filter); }
|
||||||
return ltrim(rtrim(str, filter), filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Make a copy of the string and then trim it
|
/// Make a copy of the string and then trim it
|
||||||
inline std::string trim_copy(const std::string &str) {
|
inline std::string trim_copy(const std::string &str) {
|
||||||
@ -113,25 +105,21 @@ inline std::string trim_copy(const std::string &str, const std::string &filter)
|
|||||||
/// Print a two part "help" string
|
/// Print a two part "help" string
|
||||||
inline void format_help(std::stringstream &out, std::string name, std::string description, size_t wid) {
|
inline void format_help(std::stringstream &out, std::string name, std::string description, size_t wid) {
|
||||||
name = " " + name;
|
name = " " + name;
|
||||||
out << std::setw(static_cast<int>( wid)) << std::left << name;
|
out << std::setw(static_cast<int>(wid)) << std::left << name;
|
||||||
if(description != "") {
|
if(description != "") {
|
||||||
if(name.length()>=wid)
|
if(name.length() >= wid)
|
||||||
out << std::endl << std::setw(static_cast<int>( wid)) << "";
|
out << std::endl << std::setw(static_cast<int>(wid)) << "";
|
||||||
out << description;
|
out << description;
|
||||||
}
|
}
|
||||||
out << std::endl;
|
out << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verify the first character of an option
|
/// Verify the first character of an option
|
||||||
template<typename T>
|
template <typename T> bool valid_first_char(T c) { return std::isalpha(c, std::locale()) || c == '_'; }
|
||||||
bool valid_first_char(T c) {
|
|
||||||
return std::isalpha(c, std::locale()) || c=='_';
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Verify following characters of an option
|
/// Verify following characters of an option
|
||||||
template<typename T>
|
template <typename T> bool valid_later_char(T c) {
|
||||||
bool valid_later_char(T c) {
|
return std::isalnum(c, std::locale()) || c == '_' || c == '.' || c == '-';
|
||||||
return std::isalnum(c, std::locale()) || c=='_' || c=='.' || c=='-';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verify an option name
|
/// Verify an option name
|
||||||
@ -146,16 +134,17 @@ inline bool valid_name_string(const std::string &str) {
|
|||||||
|
|
||||||
/// Return a lower case version of a string
|
/// Return a lower case version of a string
|
||||||
inline std::string to_lower(std::string str) {
|
inline std::string to_lower(std::string str) {
|
||||||
std::transform(std::begin(str), std::end(str), std::begin(str),
|
std::transform(std::begin(str), std::end(str), std::begin(str), [](const std::string::value_type &x) {
|
||||||
[](const std::string::value_type &x){return std::tolower(x,std::locale());});
|
return std::tolower(x, std::locale());
|
||||||
|
});
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Split a string '"one two" "three"' into 'one two', 'three'
|
/// Split a string '"one two" "three"' into 'one two', 'three'
|
||||||
inline std::vector<std::string> split_up(std::string str) {
|
inline std::vector<std::string> split_up(std::string str) {
|
||||||
|
|
||||||
std::vector<char> delims = {'\'', '\"'};
|
std::vector<char> delims = {'\'', '\"'};
|
||||||
auto find_ws = [](char ch){ return std::isspace<char>(ch , std::locale());};
|
auto find_ws = [](char ch) { return std::isspace<char>(ch, std::locale()); };
|
||||||
trim(str);
|
trim(str);
|
||||||
|
|
||||||
std::vector<std::string> output;
|
std::vector<std::string> output;
|
||||||
@ -164,8 +153,8 @@ inline std::vector<std::string> split_up(std::string str) {
|
|||||||
if(str[0] == '\'') {
|
if(str[0] == '\'') {
|
||||||
auto end = str.find('\'', 1);
|
auto end = str.find('\'', 1);
|
||||||
if(end != std::string::npos) {
|
if(end != std::string::npos) {
|
||||||
output.push_back(str.substr(1,end-1));
|
output.push_back(str.substr(1, end - 1));
|
||||||
str = str.substr(end+1);
|
str = str.substr(end + 1);
|
||||||
} else {
|
} else {
|
||||||
output.push_back(str.substr(1));
|
output.push_back(str.substr(1));
|
||||||
str = "";
|
str = "";
|
||||||
@ -173,8 +162,8 @@ inline std::vector<std::string> split_up(std::string str) {
|
|||||||
} else if(str[0] == '\"') {
|
} else if(str[0] == '\"') {
|
||||||
auto end = str.find('\"', 1);
|
auto end = str.find('\"', 1);
|
||||||
if(end != std::string::npos) {
|
if(end != std::string::npos) {
|
||||||
output.push_back(str.substr(1,end-1));
|
output.push_back(str.substr(1, end - 1));
|
||||||
str = str.substr(end+1);
|
str = str.substr(end + 1);
|
||||||
} else {
|
} else {
|
||||||
output.push_back(str.substr(1));
|
output.push_back(str.substr(1));
|
||||||
str = "";
|
str = "";
|
||||||
@ -183,7 +172,7 @@ inline std::vector<std::string> split_up(std::string str) {
|
|||||||
} else {
|
} else {
|
||||||
auto it = std::find_if(std::begin(str), std::end(str), find_ws);
|
auto it = std::find_if(std::begin(str), std::end(str), find_ws);
|
||||||
if(it != std::end(str)) {
|
if(it != std::end(str)) {
|
||||||
std::string value = std::string(str.begin(),it);
|
std::string value = std::string(str.begin(), it);
|
||||||
output.push_back(value);
|
output.push_back(value);
|
||||||
str = std::string(it, str.end());
|
str = std::string(it, str.end());
|
||||||
} else {
|
} else {
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
namespace CLI {
|
namespace CLI {
|
||||||
|
|
||||||
class Timer {
|
class Timer {
|
||||||
protected:
|
protected:
|
||||||
/// This is a typedef to make clocks easier to use
|
/// This is a typedef to make clocks easier to use
|
||||||
using clock = std::chrono::steady_clock;
|
using clock = std::chrono::steady_clock;
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ protected:
|
|||||||
using time_point = std::chrono::time_point<clock>;
|
using time_point = std::chrono::time_point<clock>;
|
||||||
|
|
||||||
/// This is the type of a printing function, you can make your own
|
/// This is the type of a printing function, you can make your own
|
||||||
using time_print_t = std::function<std::string (std::string, std::string)>;
|
using time_print_t = std::function<std::string(std::string, std::string)>;
|
||||||
|
|
||||||
/// This is the title of the timer
|
/// This is the title of the timer
|
||||||
std::string title_;
|
std::string title_;
|
||||||
@ -30,31 +30,27 @@ protected:
|
|||||||
|
|
||||||
/// This is the starting point (when the timer was created)
|
/// This is the starting point (when the timer was created)
|
||||||
time_point start_;
|
time_point start_;
|
||||||
|
|
||||||
/// This is the number of times cycles (print divides by this number)
|
/// This is the number of times cycles (print divides by this number)
|
||||||
size_t cycles {1};
|
size_t cycles{1};
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
|
public:
|
||||||
/// Standard print function, this one is set by default
|
/// Standard print function, this one is set by default
|
||||||
static std::string Simple(std::string title, std::string time) {
|
static std::string Simple(std::string title, std::string time) { return title + ": " + time; }
|
||||||
return title + ": " + time;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This is a fancy print function with --- headers
|
/// This is a fancy print function with --- headers
|
||||||
static std::string Big(std::string title, std::string time) {
|
static std::string Big(std::string title, std::string time) {
|
||||||
return std::string("-----------------------------------------\n")
|
return std::string("-----------------------------------------\n") + "| " + title + " | Time = " + time + "\n" +
|
||||||
+ "| " + title + " | Time = " + time + "\n"
|
"-----------------------------------------";
|
||||||
+ "-----------------------------------------";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Standard constructor, can set title and print function
|
/// Standard constructor, can set title and print function
|
||||||
Timer(std::string title="Timer", time_print_t time_print = Simple)
|
Timer(std::string title = "Timer", time_print_t time_print = Simple)
|
||||||
: title_(std::move(title)), time_print_(std::move(time_print)), start_(clock::now()) {}
|
: title_(std::move(title)), time_print_(std::move(time_print)), start_(clock::now()) {}
|
||||||
|
|
||||||
/// Time a function by running it multiple times. Target time is the len to target.
|
/// Time a function by running it multiple times. Target time is the len to target.
|
||||||
std::string time_it(std::function<void()> f, double target_time=1) {
|
std::string time_it(std::function<void()> f, double target_time = 1) {
|
||||||
time_point start = start_;
|
time_point start = start_;
|
||||||
double total_time;
|
double total_time;
|
||||||
|
|
||||||
@ -62,11 +58,11 @@ public:
|
|||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
do {
|
do {
|
||||||
f();
|
f();
|
||||||
std::chrono::duration<double> elapsed = clock::now() - start_;
|
std::chrono::duration<double> elapsed = clock::now() - start_;
|
||||||
total_time = elapsed.count();
|
total_time = elapsed.count();
|
||||||
} while (n++ < 100 && total_time < target_time);
|
} while(n++ < 100 && total_time < target_time);
|
||||||
|
|
||||||
std::string out = make_time_str(total_time/n) + " for " + std::to_string(n) + " tries";
|
std::string out = make_time_str(total_time / n) + " for " + std::to_string(n) + " tries";
|
||||||
start_ = start;
|
start_ = start;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@ -78,54 +74,48 @@ public:
|
|||||||
double time = elapsed.count() / cycles;
|
double time = elapsed.count() / cycles;
|
||||||
return make_time_str(time);
|
return make_time_str(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
// LCOV_EXCL_START
|
// LCOV_EXCL_START
|
||||||
std::string make_time_str(double time) const {
|
std::string make_time_str(double time) const {
|
||||||
auto print_it = [](double x, std::string unit){
|
auto print_it = [](double x, std::string unit) {
|
||||||
char buffer[50];
|
char buffer[50];
|
||||||
std::snprintf(buffer, 50, "%.5g", x);
|
std::snprintf(buffer, 50, "%.5g", x);
|
||||||
return buffer + std::string(" ") + unit;
|
return buffer + std::string(" ") + unit;
|
||||||
};
|
};
|
||||||
|
|
||||||
if(time < .000001)
|
if(time < .000001)
|
||||||
return print_it(time*1000000000, "ns");
|
return print_it(time * 1000000000, "ns");
|
||||||
else if(time < .001)
|
else if(time < .001)
|
||||||
return print_it(time*1000000, "us");
|
return print_it(time * 1000000, "us");
|
||||||
else if(time < 1)
|
else if(time < 1)
|
||||||
return print_it(time*1000, "ms");
|
return print_it(time * 1000, "ms");
|
||||||
else
|
else
|
||||||
return print_it(time, "s");
|
return print_it(time, "s");
|
||||||
}
|
}
|
||||||
// LCOV_EXCL_END
|
// LCOV_EXCL_END
|
||||||
|
|
||||||
/// This is the main function, it creates a string
|
/// This is the main function, it creates a string
|
||||||
std::string to_string() const {
|
std::string to_string() const { return time_print_(title_, make_time_str()); }
|
||||||
return time_print_(title_, make_time_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Division sets the number of cycles to divide by (no graphical change)
|
/// Division sets the number of cycles to divide by (no graphical change)
|
||||||
Timer& operator / (size_t val) {cycles = val; return *this;}
|
Timer &operator/(size_t val) {
|
||||||
|
cycles = val;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// This class prints out the time upon destruction
|
/// This class prints out the time upon destruction
|
||||||
class AutoTimer : public Timer {
|
class AutoTimer : public Timer {
|
||||||
public:
|
public:
|
||||||
/// Reimplementing the constructor is required in GCC 4.7
|
/// Reimplementing the constructor is required in GCC 4.7
|
||||||
AutoTimer(std::string title="Timer", time_print_t time_print = Simple)
|
AutoTimer(std::string title = "Timer", time_print_t time_print = Simple) : Timer(title, time_print) {}
|
||||||
: Timer(title, time_print) {}
|
|
||||||
// GCC 4.7 does not support using inheriting constructors.
|
// GCC 4.7 does not support using inheriting constructors.
|
||||||
|
|
||||||
/// This desctructor prints the string
|
/// This desctructor prints the string
|
||||||
~AutoTimer () {
|
~AutoTimer() { std::cout << to_string() << std::endl; }
|
||||||
std::cout << to_string() << std::endl;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CLI
|
} // namespace CLI
|
||||||
|
|
||||||
/// This prints out the time if shifted into a std::cout like stream.
|
/// This prints out the time if shifted into a std::cout like stream.
|
||||||
inline std::ostream & operator<< (std::ostream& in, const CLI::Timer& timer) {
|
inline std::ostream &operator<<(std::ostream &in, const CLI::Timer &timer) { return in << timer.to_string(); }
|
||||||
return in << timer.to_string();
|
|
||||||
}
|
|
||||||
|
@ -14,126 +14,100 @@ namespace CLI {
|
|||||||
|
|
||||||
// Copied from C++14
|
// Copied from C++14
|
||||||
#if __cplusplus < 201402L
|
#if __cplusplus < 201402L
|
||||||
template< bool B, class T = void >
|
template <bool B, class T = void> using enable_if_t = typename std::enable_if<B, T>::type;
|
||||||
using enable_if_t = typename std::enable_if<B,T>::type;
|
|
||||||
#else
|
#else
|
||||||
// If your compiler supports C++14, you can use that definition instead
|
// If your compiler supports C++14, you can use that definition instead
|
||||||
using std::enable_if_t;
|
using std::enable_if_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> struct is_vector { static const bool value = false; };
|
||||||
struct is_vector {
|
|
||||||
static const bool value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
template <class T, class A> struct is_vector<std::vector<T, A>> { static bool const value = true; };
|
||||||
|
|
||||||
template<class T, class A>
|
template <typename T> struct is_bool { static const bool value = false; };
|
||||||
struct is_vector<std::vector<T, A> > {
|
|
||||||
static bool const value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct is_bool {
|
|
||||||
static const bool value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct is_bool<bool> {
|
|
||||||
static bool const value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
template <> struct is_bool<bool> { static bool const value = true; };
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
// Based generally on https://rmf.io/cxx11/almost-static-if
|
// Based generally on https://rmf.io/cxx11/almost-static-if
|
||||||
/// Simple empty scoped class
|
/// Simple empty scoped class
|
||||||
enum class enabler {};
|
enum class enabler {};
|
||||||
|
|
||||||
/// An instance to use in EnableIf
|
/// An instance to use in EnableIf
|
||||||
constexpr enabler dummy = {};
|
constexpr enabler dummy = {};
|
||||||
|
|
||||||
|
// Type name print
|
||||||
|
|
||||||
// Type name print
|
/// Was going to be based on
|
||||||
|
/// http://stackoverflow.com/questions/1055452/c-get-name-of-type-in-template
|
||||||
|
/// But this is cleaner and works better in this case
|
||||||
|
|
||||||
/// Was going to be based on
|
template <typename T,
|
||||||
/// http://stackoverflow.com/questions/1055452/c-get-name-of-type-in-template
|
enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value, detail::enabler> = detail::dummy>
|
||||||
/// But this is cleaner and works better in this case
|
constexpr const char *type_name() {
|
||||||
|
return "INT";
|
||||||
template<typename T,
|
}
|
||||||
enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value, detail::enabler> = detail::dummy>
|
|
||||||
constexpr const char* type_name() {
|
|
||||||
return "INT";
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T,
|
template <typename T,
|
||||||
enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value, detail::enabler> = detail::dummy>
|
enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value, detail::enabler> = detail::dummy>
|
||||||
constexpr const char* type_name() {
|
constexpr const char *type_name() {
|
||||||
return "UINT";
|
return "UINT";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename T,
|
|
||||||
enable_if_t<std::is_floating_point<T>::value, detail::enabler> = detail::dummy>
|
|
||||||
constexpr const char* type_name() {
|
|
||||||
return "FLOAT";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// This one should not be used, since vector types print the internal type
|
|
||||||
template<typename T,
|
|
||||||
enable_if_t<is_vector<T>::value, detail::enabler> = detail::dummy>
|
|
||||||
constexpr const char* type_name() {
|
|
||||||
return "VECTOR";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
template <typename T, enable_if_t<std::is_floating_point<T>::value, detail::enabler> = detail::dummy>
|
||||||
|
constexpr const char *type_name() {
|
||||||
|
return "FLOAT";
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T,
|
/// This one should not be used, since vector types print the internal type
|
||||||
enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value && !is_vector<T>::value
|
template <typename T, enable_if_t<is_vector<T>::value, detail::enabler> = detail::dummy>
|
||||||
, detail::enabler> = detail::dummy>
|
constexpr const char *type_name() {
|
||||||
constexpr const char* type_name() {
|
return "VECTOR";
|
||||||
return "TEXT";
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
template <typename T,
|
||||||
|
enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value && !is_vector<T>::value,
|
||||||
|
detail::enabler> = detail::dummy>
|
||||||
|
constexpr const char *type_name() {
|
||||||
|
return "TEXT";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lexical cast
|
||||||
|
|
||||||
// Lexical cast
|
/// Integers
|
||||||
|
template <typename T, enable_if_t<std::is_integral<T>::value, detail::enabler> = detail::dummy>
|
||||||
|
bool lexical_cast(std::string input, T &output) {
|
||||||
/// Integers
|
try {
|
||||||
template<typename T, enable_if_t<std::is_integral<T>::value, detail::enabler> = detail::dummy>
|
output = static_cast<T>(std::stoll(input));
|
||||||
bool lexical_cast(std::string input, T& output) {
|
|
||||||
try{
|
|
||||||
output = static_cast<T>(std::stoll(input));
|
|
||||||
return true;
|
|
||||||
} catch (const std::invalid_argument&) {
|
|
||||||
return false;
|
|
||||||
} catch (const std::out_of_range&) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Floats
|
|
||||||
template<typename T, enable_if_t<std::is_floating_point<T>::value, detail::enabler> = detail::dummy>
|
|
||||||
bool lexical_cast(std::string input, T& output) {
|
|
||||||
try{
|
|
||||||
output =static_cast<T>(std::stold(input));
|
|
||||||
return true;
|
|
||||||
} catch (const std::invalid_argument&) {
|
|
||||||
return false;
|
|
||||||
} catch (const std::out_of_range&) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// String and similar
|
|
||||||
template<typename T,
|
|
||||||
enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value
|
|
||||||
, detail::enabler> = detail::dummy>
|
|
||||||
bool lexical_cast(std::string input, T& output) {
|
|
||||||
output = input;
|
|
||||||
return true;
|
return true;
|
||||||
|
} catch(const std::invalid_argument &) {
|
||||||
|
return false;
|
||||||
|
} catch(const std::out_of_range &) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Floats
|
||||||
|
template <typename T, enable_if_t<std::is_floating_point<T>::value, detail::enabler> = detail::dummy>
|
||||||
|
bool lexical_cast(std::string input, T &output) {
|
||||||
|
try {
|
||||||
|
output = static_cast<T>(std::stold(input));
|
||||||
|
return true;
|
||||||
|
} catch(const std::invalid_argument &) {
|
||||||
|
return false;
|
||||||
|
} catch(const std::out_of_range &) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// String and similar
|
||||||
|
template <
|
||||||
|
typename T,
|
||||||
|
enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value, detail::enabler> = detail::dummy>
|
||||||
|
bool lexical_cast(std::string input, T &output) {
|
||||||
|
output = input;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace CLI
|
} // namespace CLI
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
namespace CLI {
|
namespace CLI {
|
||||||
|
|
||||||
|
|
||||||
/// @defgroup validator_group Validators
|
/// @defgroup validator_group Validators
|
||||||
/// @brief Some validators that are provided
|
/// @brief Some validators that are provided
|
||||||
///
|
///
|
||||||
@ -25,13 +24,13 @@ namespace CLI {
|
|||||||
|
|
||||||
/// Check for an existing file
|
/// Check for an existing file
|
||||||
inline bool ExistingFile(std::string filename) {
|
inline bool ExistingFile(std::string filename) {
|
||||||
struct stat buffer;
|
struct stat buffer;
|
||||||
bool exist = stat(filename.c_str(), &buffer) == 0;
|
bool exist = stat(filename.c_str(), &buffer) == 0;
|
||||||
bool is_dir = (buffer.st_mode & S_IFDIR) != 0;
|
bool is_dir = (buffer.st_mode & S_IFDIR) != 0;
|
||||||
if(!exist) {
|
if(!exist) {
|
||||||
std::cerr << "File does not exist: " << filename << std::endl;
|
std::cerr << "File does not exist: " << filename << std::endl;
|
||||||
return false;
|
return false;
|
||||||
} else if (is_dir) {
|
} else if(is_dir) {
|
||||||
std::cerr << "File is actually a directory: " << filename << std::endl;
|
std::cerr << "File is actually a directory: " << filename << std::endl;
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@ -41,13 +40,13 @@ inline bool ExistingFile(std::string filename) {
|
|||||||
|
|
||||||
/// Check for an existing directory
|
/// Check for an existing directory
|
||||||
inline bool ExistingDirectory(std::string filename) {
|
inline bool ExistingDirectory(std::string filename) {
|
||||||
struct stat buffer;
|
struct stat buffer;
|
||||||
bool exist = stat(filename.c_str(), &buffer) == 0;
|
bool exist = stat(filename.c_str(), &buffer) == 0;
|
||||||
bool is_dir = (buffer.st_mode & S_IFDIR) != 0;
|
bool is_dir = (buffer.st_mode & S_IFDIR) != 0;
|
||||||
if(!exist) {
|
if(!exist) {
|
||||||
std::cerr << "Directory does not exist: " << filename << std::endl;
|
std::cerr << "Directory does not exist: " << filename << std::endl;
|
||||||
return false;
|
return false;
|
||||||
} else if (is_dir) {
|
} else if(is_dir) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "Directory is actually a file: " << filename << std::endl;
|
std::cerr << "Directory is actually a file: " << filename << std::endl;
|
||||||
@ -55,11 +54,10 @@ inline bool ExistingDirectory(std::string filename) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Check for a non-existing path
|
/// Check for a non-existing path
|
||||||
inline bool NonexistentPath(std::string filename) {
|
inline bool NonexistentPath(std::string filename) {
|
||||||
struct stat buffer;
|
struct stat buffer;
|
||||||
bool exist = stat(filename.c_str(), &buffer) == 0;
|
bool exist = stat(filename.c_str(), &buffer) == 0;
|
||||||
if(!exist) {
|
if(!exist) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -69,9 +67,8 @@ inline bool NonexistentPath(std::string filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Produce a range validator function
|
/// Produce a range validator function
|
||||||
template<typename T>
|
template <typename T> std::function<bool(std::string)> Range(T min, T max) {
|
||||||
std::function<bool(std::string)> Range(T min, T max) {
|
return [min, max](std::string input) {
|
||||||
return [min, max](std::string input){
|
|
||||||
T val;
|
T val;
|
||||||
detail::lexical_cast(input, val);
|
detail::lexical_cast(input, val);
|
||||||
return val >= min && val <= max;
|
return val >= min && val <= max;
|
||||||
@ -79,10 +76,7 @@ std::function<bool(std::string)> Range(T min, T max) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Range of one value is 0 to value
|
/// Range of one value is 0 to value
|
||||||
template<typename T>
|
template <typename T> std::function<bool(std::string)> Range(T max) { return Range(static_cast<T>(0), max); }
|
||||||
std::function<bool(std::string)> Range(T max) {
|
|
||||||
return Range(static_cast<T>(0), max);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
@ -1,2 +1 @@
|
|||||||
-I../build/googletest-src/googletest/include/
|
- I../ build / googletest - src / googletest / include / -I../ build / googletest - src / googlemock / include /
|
||||||
-I../build/googletest-src/googlemock/include/
|
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
#include "app_helper.hpp"
|
#include "app_helper.hpp"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, OneFlagShort) {
|
TEST_F(TApp, OneFlagShort) {
|
||||||
app.add_flag("-c,--count");
|
app.add_flag("-c,--count");
|
||||||
args = {"-c"};
|
args = {"-c"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 1, app.count("-c"));
|
EXPECT_EQ((size_t)1, app.count("-c"));
|
||||||
EXPECT_EQ((size_t) 1, app.count("--count"));
|
EXPECT_EQ((size_t)1, app.count("--count"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, CountNonExist) {
|
TEST_F(TApp, CountNonExist) {
|
||||||
@ -21,8 +20,8 @@ TEST_F(TApp, OneFlagLong) {
|
|||||||
app.add_flag("-c,--count");
|
app.add_flag("-c,--count");
|
||||||
args = {"--count"};
|
args = {"--count"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 1, app.count("-c"));
|
EXPECT_EQ((size_t)1, app.count("-c"));
|
||||||
EXPECT_EQ((size_t) 1, app.count("--count"));
|
EXPECT_EQ((size_t)1, app.count("--count"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, DashedOptions) {
|
TEST_F(TApp, DashedOptions) {
|
||||||
@ -32,11 +31,10 @@ TEST_F(TApp, DashedOptions) {
|
|||||||
|
|
||||||
args = {"-c", "--q", "--this", "--that"};
|
args = {"-c", "--q", "--this", "--that"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 1, app.count("-c"));
|
EXPECT_EQ((size_t)1, app.count("-c"));
|
||||||
EXPECT_EQ((size_t) 1, app.count("--q"));
|
EXPECT_EQ((size_t)1, app.count("--q"));
|
||||||
EXPECT_EQ((size_t) 2, app.count("--this"));
|
EXPECT_EQ((size_t)2, app.count("--this"));
|
||||||
EXPECT_EQ((size_t) 2, app.count("--that"));
|
EXPECT_EQ((size_t)2, app.count("--that"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, OneFlagRef) {
|
TEST_F(TApp, OneFlagRef) {
|
||||||
@ -44,8 +42,8 @@ TEST_F(TApp, OneFlagRef) {
|
|||||||
app.add_flag("-c,--count", ref);
|
app.add_flag("-c,--count", ref);
|
||||||
args = {"--count"};
|
args = {"--count"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 1, app.count("-c"));
|
EXPECT_EQ((size_t)1, app.count("-c"));
|
||||||
EXPECT_EQ((size_t) 1, app.count("--count"));
|
EXPECT_EQ((size_t)1, app.count("--count"));
|
||||||
EXPECT_EQ(1, ref);
|
EXPECT_EQ(1, ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,8 +52,8 @@ TEST_F(TApp, OneString) {
|
|||||||
app.add_option("-s,--string", str);
|
app.add_option("-s,--string", str);
|
||||||
args = {"--string", "mystring"};
|
args = {"--string", "mystring"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 1, app.count("-s"));
|
EXPECT_EQ((size_t)1, app.count("-s"));
|
||||||
EXPECT_EQ((size_t) 1, app.count("--string"));
|
EXPECT_EQ((size_t)1, app.count("--string"));
|
||||||
EXPECT_EQ(str, "mystring");
|
EXPECT_EQ(str, "mystring");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,29 +62,28 @@ TEST_F(TApp, OneStringEqualVersion) {
|
|||||||
app.add_option("-s,--string", str);
|
app.add_option("-s,--string", str);
|
||||||
args = {"--string=mystring"};
|
args = {"--string=mystring"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 1, app.count("-s"));
|
EXPECT_EQ((size_t)1, app.count("-s"));
|
||||||
EXPECT_EQ((size_t) 1, app.count("--string"));
|
EXPECT_EQ((size_t)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"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 1, app.count("--int"));
|
EXPECT_EQ((size_t)1, app.count("--int"));
|
||||||
EXPECT_EQ((size_t) 1, app.count("-i"));
|
EXPECT_EQ((size_t)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"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 1, app.count("--int"));
|
EXPECT_EQ((size_t)1, app.count("--int"));
|
||||||
EXPECT_EQ((size_t) 1, app.count("-i"));
|
EXPECT_EQ((size_t)1, app.count("-i"));
|
||||||
EXPECT_EQ(i, 4);
|
EXPECT_EQ(i, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,18 +92,17 @@ TEST_F(TApp, OneStringAgain) {
|
|||||||
app.add_option("-s,--string", str);
|
app.add_option("-s,--string", str);
|
||||||
args = {"--string", "mystring"};
|
args = {"--string", "mystring"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 1, app.count("-s"));
|
EXPECT_EQ((size_t)1, app.count("-s"));
|
||||||
EXPECT_EQ((size_t) 1, app.count("--string"));
|
EXPECT_EQ((size_t)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);
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 0, app.count("-s"));
|
EXPECT_EQ((size_t)0, app.count("-s"));
|
||||||
EXPECT_EQ((size_t) 0, app.count("--string"));
|
EXPECT_EQ((size_t)0, app.count("--string"));
|
||||||
EXPECT_EQ(str, "previous");
|
EXPECT_EQ(str, "previous");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,14 +128,13 @@ TEST_F(TApp, LotsOfFlags) {
|
|||||||
app.add_flag("-A");
|
app.add_flag("-A");
|
||||||
app.add_flag("-b");
|
app.add_flag("-b");
|
||||||
|
|
||||||
args = {"-a","-b","-aA"};
|
args = {"-a", "-b", "-aA"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 2, app.count("-a"));
|
EXPECT_EQ((size_t)2, app.count("-a"));
|
||||||
EXPECT_EQ((size_t) 1, app.count("-b"));
|
EXPECT_EQ((size_t)1, app.count("-b"));
|
||||||
EXPECT_EQ((size_t) 1, app.count("-A"));
|
EXPECT_EQ((size_t)1, app.count("-A"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, BoolAndIntFlags) {
|
TEST_F(TApp, BoolAndIntFlags) {
|
||||||
|
|
||||||
bool bflag;
|
bool bflag;
|
||||||
@ -154,7 +149,7 @@ TEST_F(TApp, BoolAndIntFlags) {
|
|||||||
run();
|
run();
|
||||||
EXPECT_TRUE(bflag);
|
EXPECT_TRUE(bflag);
|
||||||
EXPECT_EQ(1, iflag);
|
EXPECT_EQ(1, iflag);
|
||||||
EXPECT_EQ((unsigned int) 1, uflag);
|
EXPECT_EQ((unsigned int)1, uflag);
|
||||||
|
|
||||||
app.reset();
|
app.reset();
|
||||||
|
|
||||||
@ -168,7 +163,7 @@ TEST_F(TApp, BoolAndIntFlags) {
|
|||||||
run();
|
run();
|
||||||
EXPECT_FALSE(bflag);
|
EXPECT_FALSE(bflag);
|
||||||
EXPECT_EQ(3, iflag);
|
EXPECT_EQ(3, iflag);
|
||||||
EXPECT_EQ((unsigned int) 2, uflag);
|
EXPECT_EQ((unsigned int)2, uflag);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, ShortOpts) {
|
TEST_F(TApp, ShortOpts) {
|
||||||
@ -178,13 +173,15 @@ TEST_F(TApp, ShortOpts) {
|
|||||||
app.add_flag("-z", funnyint);
|
app.add_flag("-z", funnyint);
|
||||||
app.add_option("-y", someopt);
|
app.add_option("-y", someopt);
|
||||||
|
|
||||||
args = {"-zzyzyz",};
|
args = {
|
||||||
|
"-zzyzyz",
|
||||||
|
};
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
EXPECT_EQ((size_t) 2, app.count("-z"));
|
EXPECT_EQ((size_t)2, app.count("-z"));
|
||||||
EXPECT_EQ((size_t) 1, app.count("-y"));
|
EXPECT_EQ((size_t)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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,8 +197,8 @@ TEST_F(TApp, DefaultOpts) {
|
|||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
EXPECT_EQ((size_t) 1, app.count("i"));
|
EXPECT_EQ((size_t)1, app.count("i"));
|
||||||
EXPECT_EQ((size_t) 1, app.count("-s"));
|
EXPECT_EQ((size_t)1, app.count("-s"));
|
||||||
EXPECT_EQ(2, i);
|
EXPECT_EQ(2, i);
|
||||||
EXPECT_EQ("9", s);
|
EXPECT_EQ("9", s);
|
||||||
}
|
}
|
||||||
@ -224,7 +221,6 @@ TEST_F(TApp, RequiredFlags) {
|
|||||||
app.reset();
|
app.reset();
|
||||||
args = {"-a", "-b"};
|
args = {"-a", "-b"};
|
||||||
run();
|
run();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, Positionals) {
|
TEST_F(TApp, Positionals) {
|
||||||
@ -234,17 +230,16 @@ TEST_F(TApp, Positionals) {
|
|||||||
app.add_option("posit1", posit1);
|
app.add_option("posit1", posit1);
|
||||||
app.add_option("posit2", posit2);
|
app.add_option("posit2", posit2);
|
||||||
|
|
||||||
args = {"thing1","thing2"};
|
args = {"thing1", "thing2"};
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
EXPECT_EQ((size_t) 1, app.count("posit1"));
|
EXPECT_EQ((size_t)1, app.count("posit1"));
|
||||||
EXPECT_EQ((size_t) 1, app.count("posit2"));
|
EXPECT_EQ((size_t)1, app.count("posit2"));
|
||||||
EXPECT_EQ("thing1", posit1);
|
EXPECT_EQ("thing1", posit1);
|
||||||
EXPECT_EQ("thing2", posit2);
|
EXPECT_EQ("thing2", posit2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, ForcedPositional) {
|
TEST_F(TApp, ForcedPositional) {
|
||||||
std::vector<std::string> posit;
|
std::vector<std::string> posit;
|
||||||
auto one = app.add_flag("--one");
|
auto one = app.add_flag("--one");
|
||||||
@ -266,7 +261,6 @@ TEST_F(TApp, ForcedPositional) {
|
|||||||
EXPECT_EQ(answers2, posit);
|
EXPECT_EQ(answers2, posit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, MixedPositionals) {
|
TEST_F(TApp, MixedPositionals) {
|
||||||
|
|
||||||
int positional_int;
|
int positional_int;
|
||||||
@ -274,12 +268,12 @@ TEST_F(TApp, MixedPositionals) {
|
|||||||
app.add_option("posit1,--posit1", positional_int, "");
|
app.add_option("posit1,--posit1", positional_int, "");
|
||||||
app.add_option("posit2,--posit2", positional_string, "");
|
app.add_option("posit2,--posit2", positional_string, "");
|
||||||
|
|
||||||
args = {"--posit2","thing2","7"};
|
args = {"--posit2", "thing2", "7"};
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
EXPECT_EQ((size_t) 1, app.count("posit2"));
|
EXPECT_EQ((size_t)1, app.count("posit2"));
|
||||||
EXPECT_EQ((size_t) 1, app.count("--posit1"));
|
EXPECT_EQ((size_t)1, app.count("--posit1"));
|
||||||
EXPECT_EQ(7, positional_int);
|
EXPECT_EQ(7, positional_int);
|
||||||
EXPECT_EQ("thing2", positional_string);
|
EXPECT_EQ("thing2", positional_string);
|
||||||
}
|
}
|
||||||
@ -311,24 +305,22 @@ TEST_F(TApp, Reset) {
|
|||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
EXPECT_EQ((size_t) 1, app.count("--simple"));
|
EXPECT_EQ((size_t)1, app.count("--simple"));
|
||||||
EXPECT_EQ((size_t) 1, app.count("-d"));
|
EXPECT_EQ((size_t)1, app.count("-d"));
|
||||||
EXPECT_DOUBLE_EQ(1.2, doub);
|
EXPECT_DOUBLE_EQ(1.2, doub);
|
||||||
|
|
||||||
app.reset();
|
app.reset();
|
||||||
|
|
||||||
EXPECT_EQ((size_t) 0, app.count("--simple"));
|
EXPECT_EQ((size_t)0, app.count("--simple"));
|
||||||
EXPECT_EQ((size_t) 0, app.count("-d"));
|
EXPECT_EQ((size_t)0, app.count("-d"));
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
EXPECT_EQ((size_t) 1, app.count("--simple"));
|
EXPECT_EQ((size_t)1, app.count("--simple"));
|
||||||
EXPECT_EQ((size_t) 1, app.count("-d"));
|
EXPECT_EQ((size_t)1, app.count("-d"));
|
||||||
EXPECT_DOUBLE_EQ(1.2, doub);
|
EXPECT_DOUBLE_EQ(1.2, doub);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, RemoveOption) {
|
TEST_F(TApp, RemoveOption) {
|
||||||
app.add_flag("--one");
|
app.add_flag("--one");
|
||||||
auto opt = app.add_flag("--two");
|
auto opt = app.add_flag("--two");
|
||||||
@ -354,7 +346,6 @@ TEST_F(TApp, FileNotExists) {
|
|||||||
|
|
||||||
app.reset();
|
app.reset();
|
||||||
|
|
||||||
|
|
||||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||||
EXPECT_TRUE(ok);
|
EXPECT_TRUE(ok);
|
||||||
EXPECT_THROW(run(), CLI::ValidationError);
|
EXPECT_THROW(run(), CLI::ValidationError);
|
||||||
@ -388,7 +379,7 @@ 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"};
|
||||||
|
|
||||||
run();
|
run();
|
||||||
@ -404,7 +395,7 @@ TEST_F(TApp, InIntSet) {
|
|||||||
|
|
||||||
int choice;
|
int choice;
|
||||||
app.add_set("-q,--quick", choice, {1, 2, 3});
|
app.add_set("-q,--quick", choice, {1, 2, 3});
|
||||||
|
|
||||||
args = {"--quick", "2"};
|
args = {"--quick", "2"};
|
||||||
|
|
||||||
run();
|
run();
|
||||||
@ -420,7 +411,7 @@ TEST_F(TApp, FailSet) {
|
|||||||
|
|
||||||
int choice;
|
int choice;
|
||||||
app.add_set("-q,--quick", choice, {1, 2, 3});
|
app.add_set("-q,--quick", choice, {1, 2, 3});
|
||||||
|
|
||||||
args = {"--quick", "3", "--quick=2"};
|
args = {"--quick", "3", "--quick=2"};
|
||||||
EXPECT_THROW(run(), CLI::ConversionError);
|
EXPECT_THROW(run(), CLI::ConversionError);
|
||||||
|
|
||||||
@ -430,12 +421,11 @@ TEST_F(TApp, FailSet) {
|
|||||||
EXPECT_THROW(run(), CLI::ConversionError);
|
EXPECT_THROW(run(), CLI::ConversionError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, InSetIgnoreCase) {
|
TEST_F(TApp, InSetIgnoreCase) {
|
||||||
|
|
||||||
std::string choice;
|
std::string choice;
|
||||||
app.add_set_ignore_case("-q,--quick", choice, {"one", "Two", "THREE"});
|
app.add_set_ignore_case("-q,--quick", choice, {"one", "Two", "THREE"});
|
||||||
|
|
||||||
args = {"--quick", "One"};
|
args = {"--quick", "One"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ("one", choice);
|
EXPECT_EQ("one", choice);
|
||||||
@ -450,7 +440,6 @@ TEST_F(TApp, InSetIgnoreCase) {
|
|||||||
run();
|
run();
|
||||||
EXPECT_EQ("THREE", choice); // Keeps caps from set
|
EXPECT_EQ("THREE", choice); // Keeps caps from set
|
||||||
|
|
||||||
|
|
||||||
app.reset();
|
app.reset();
|
||||||
args = {"--quick", "four"};
|
args = {"--quick", "four"};
|
||||||
EXPECT_THROW(run(), CLI::ConversionError);
|
EXPECT_THROW(run(), CLI::ConversionError);
|
||||||
@ -458,54 +447,50 @@ TEST_F(TApp, InSetIgnoreCase) {
|
|||||||
app.reset();
|
app.reset();
|
||||||
args = {"--quick=one", "--quick=two"};
|
args = {"--quick=one", "--quick=two"};
|
||||||
EXPECT_THROW(run(), CLI::ConversionError);
|
EXPECT_THROW(run(), CLI::ConversionError);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, VectorFixedString) {
|
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)->expected(3);
|
CLI::Option *opt = app.add_option("-s,--string", strvec)->expected(3);
|
||||||
EXPECT_EQ(3, opt->get_expected());
|
EXPECT_EQ(3, opt->get_expected());
|
||||||
|
|
||||||
args = {"--string", "mystring", "mystring2", "mystring3"};
|
args = {"--string", "mystring", "mystring2", "mystring3"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 3, app.count("--string"));
|
EXPECT_EQ((size_t)3, app.count("--string"));
|
||||||
EXPECT_EQ(answer, strvec);
|
EXPECT_EQ(answer, strvec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, VectorUnlimString) {
|
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::Option *opt = app.add_option("-s,--string", strvec);
|
||||||
EXPECT_EQ(-1, opt->get_expected());
|
EXPECT_EQ(-1, opt->get_expected());
|
||||||
|
|
||||||
args = {"--string", "mystring", "mystring2", "mystring3"};
|
args = {"--string", "mystring", "mystring2", "mystring3"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 3, app.count("--string"));
|
EXPECT_EQ((size_t)3, app.count("--string"));
|
||||||
EXPECT_EQ(answer, strvec);
|
EXPECT_EQ(answer, strvec);
|
||||||
|
|
||||||
app.reset();
|
app.reset();
|
||||||
args = {"-s", "mystring", "mystring2", "mystring3"};
|
args = {"-s", "mystring", "mystring2", "mystring3"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 3, app.count("--string"));
|
EXPECT_EQ((size_t)3, app.count("--string"));
|
||||||
EXPECT_EQ(answer, strvec);
|
EXPECT_EQ(answer, strvec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, VectorFancyOpts) {
|
TEST_F(TApp, VectorFancyOpts) {
|
||||||
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)->required()->expected(3);
|
CLI::Option *opt = app.add_option("-s,--string", strvec)->required()->expected(3);
|
||||||
EXPECT_EQ(3, opt->get_expected());
|
EXPECT_EQ(3, opt->get_expected());
|
||||||
|
|
||||||
args = {"--string", "mystring", "mystring2", "mystring3"};
|
args = {"--string", "mystring", "mystring2", "mystring3"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 3, app.count("--string"));
|
EXPECT_EQ((size_t)3, app.count("--string"));
|
||||||
EXPECT_EQ(answer, strvec);
|
EXPECT_EQ(answer, strvec);
|
||||||
|
|
||||||
app.reset();
|
app.reset();
|
||||||
@ -517,7 +502,7 @@ TEST_F(TApp, VectorFancyOpts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, RequiresFlags) {
|
TEST_F(TApp, RequiresFlags) {
|
||||||
CLI::Option* opt = app.add_flag("-s,--string");
|
CLI::Option *opt = app.add_flag("-s,--string");
|
||||||
app.add_flag("--both")->requires(opt);
|
app.add_flag("--both")->requires(opt);
|
||||||
|
|
||||||
run();
|
run();
|
||||||
@ -535,9 +520,8 @@ TEST_F(TApp, RequiresFlags) {
|
|||||||
EXPECT_THROW(run(), CLI::RequiresError);
|
EXPECT_THROW(run(), CLI::RequiresError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, ExcludesFlags) {
|
TEST_F(TApp, ExcludesFlags) {
|
||||||
CLI::Option* opt = app.add_flag("-s,--string");
|
CLI::Option *opt = app.add_flag("-s,--string");
|
||||||
app.add_flag("--nostr")->excludes(opt);
|
app.add_flag("--nostr")->excludes(opt);
|
||||||
|
|
||||||
run();
|
run();
|
||||||
@ -560,9 +544,9 @@ TEST_F(TApp, ExcludesFlags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, ExcludesMixedFlags) {
|
TEST_F(TApp, ExcludesMixedFlags) {
|
||||||
CLI::Option* opt1 = app.add_flag("--opt1");
|
CLI::Option *opt1 = app.add_flag("--opt1");
|
||||||
app.add_flag("--opt2");
|
app.add_flag("--opt2");
|
||||||
CLI::Option* opt3 = app.add_flag("--opt3");
|
CLI::Option *opt3 = app.add_flag("--opt3");
|
||||||
app.add_flag("--no")->excludes(opt1, "--opt2", opt3);
|
app.add_flag("--no")->excludes(opt1, "--opt2", opt3);
|
||||||
|
|
||||||
run();
|
run();
|
||||||
@ -585,9 +569,9 @@ TEST_F(TApp, ExcludesMixedFlags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, RequiresMultiFlags) {
|
TEST_F(TApp, RequiresMultiFlags) {
|
||||||
CLI::Option* opt1 = app.add_flag("--opt1");
|
CLI::Option *opt1 = app.add_flag("--opt1");
|
||||||
CLI::Option* opt2 = app.add_flag("--opt2");
|
CLI::Option *opt2 = app.add_flag("--opt2");
|
||||||
CLI::Option* opt3 = app.add_flag("--opt3");
|
CLI::Option *opt3 = app.add_flag("--opt3");
|
||||||
app.add_flag("--optall")->requires(opt1, opt2, opt3);
|
app.add_flag("--optall")->requires(opt1, opt2, opt3);
|
||||||
|
|
||||||
run();
|
run();
|
||||||
@ -618,7 +602,7 @@ TEST_F(TApp, RequiresMultiFlags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, RequiresMixedFlags) {
|
TEST_F(TApp, RequiresMixedFlags) {
|
||||||
CLI::Option* opt1 = app.add_flag("--opt1");
|
CLI::Option *opt1 = app.add_flag("--opt1");
|
||||||
app.add_flag("--opt2");
|
app.add_flag("--opt2");
|
||||||
app.add_flag("--opt3");
|
app.add_flag("--opt3");
|
||||||
app.add_flag("--optall")->requires(opt1, "--opt2", "--opt3");
|
app.add_flag("--optall")->requires(opt1, "--opt2", "--opt3");
|
||||||
@ -651,8 +635,8 @@ TEST_F(TApp, RequiresMixedFlags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, RequiresChainedFlags) {
|
TEST_F(TApp, RequiresChainedFlags) {
|
||||||
CLI::Option* opt1 = app.add_flag("--opt1");
|
CLI::Option *opt1 = app.add_flag("--opt1");
|
||||||
CLI::Option* opt2 = app.add_flag("--opt2")->requires(opt1);
|
CLI::Option *opt2 = app.add_flag("--opt2")->requires(opt1);
|
||||||
app.add_flag("--opt3")->requires(opt2);
|
app.add_flag("--opt3")->requires(opt2);
|
||||||
|
|
||||||
run();
|
run();
|
||||||
@ -690,13 +674,13 @@ TEST_F(TApp, Env) {
|
|||||||
|
|
||||||
put_env("CLI11_TEST_ENV_TMP", "2");
|
put_env("CLI11_TEST_ENV_TMP", "2");
|
||||||
|
|
||||||
int val=1;
|
int val = 1;
|
||||||
CLI::Option* vopt = app.add_option("--tmp", val)->envname("CLI11_TEST_ENV_TMP");
|
CLI::Option *vopt = app.add_option("--tmp", val)->envname("CLI11_TEST_ENV_TMP");
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
EXPECT_EQ(2, val);
|
EXPECT_EQ(2, val);
|
||||||
EXPECT_EQ((size_t) 1, vopt->count());
|
EXPECT_EQ((size_t)1, vopt->count());
|
||||||
|
|
||||||
app.reset();
|
app.reset();
|
||||||
vopt->required();
|
vopt->required();
|
||||||
@ -708,8 +692,8 @@ TEST_F(TApp, Env) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, RangeInt) {
|
TEST_F(TApp, RangeInt) {
|
||||||
int x=0;
|
int x = 0;
|
||||||
app.add_option("--one", x)->check(CLI::Range(3,6));
|
app.add_option("--one", x)->check(CLI::Range(3, 6));
|
||||||
|
|
||||||
args = {"--one=1"};
|
args = {"--one=1"};
|
||||||
EXPECT_THROW(run(), CLI::ValidationError);
|
EXPECT_THROW(run(), CLI::ValidationError);
|
||||||
@ -733,9 +717,9 @@ TEST_F(TApp, RangeInt) {
|
|||||||
|
|
||||||
TEST_F(TApp, RangeDouble) {
|
TEST_F(TApp, RangeDouble) {
|
||||||
|
|
||||||
double x=0;
|
double x = 0;
|
||||||
/// Note that this must be a double in Range, too
|
/// Note that this must be a double in Range, too
|
||||||
app.add_option("--one", x)->check(CLI::Range(3.0,6.0));
|
app.add_option("--one", x)->check(CLI::Range(3.0, 6.0));
|
||||||
|
|
||||||
args = {"--one=1"};
|
args = {"--one=1"};
|
||||||
EXPECT_THROW(run(), CLI::ValidationError);
|
EXPECT_THROW(run(), CLI::ValidationError);
|
||||||
@ -768,10 +752,9 @@ TEST_F(TApp, AllowExtras) {
|
|||||||
|
|
||||||
args = {"-x", "-f"};
|
args = {"-x", "-f"};
|
||||||
std::vector<std::string> left_over;
|
std::vector<std::string> left_over;
|
||||||
EXPECT_NO_THROW({left_over = run();});
|
EXPECT_NO_THROW({ left_over = run(); });
|
||||||
EXPECT_TRUE(val);
|
EXPECT_TRUE(val);
|
||||||
EXPECT_EQ(std::vector<std::string>({"-x"}), left_over);
|
EXPECT_EQ(std::vector<std::string>({"-x"}), left_over);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, AllowExtrasOrder) {
|
TEST_F(TApp, AllowExtrasOrder) {
|
||||||
@ -780,14 +763,13 @@ TEST_F(TApp, AllowExtrasOrder) {
|
|||||||
|
|
||||||
args = {"-x", "-f"};
|
args = {"-x", "-f"};
|
||||||
std::vector<std::string> left_over;
|
std::vector<std::string> left_over;
|
||||||
EXPECT_NO_THROW({left_over = run();});
|
EXPECT_NO_THROW({ left_over = run(); });
|
||||||
EXPECT_EQ(std::vector<std::string>({"-f", "-x"}), left_over);
|
EXPECT_EQ(std::vector<std::string>({"-f", "-x"}), left_over);
|
||||||
app.reset();
|
app.reset();
|
||||||
|
|
||||||
std::vector<std::string> left_over_2;
|
std::vector<std::string> left_over_2;
|
||||||
left_over_2 = app.parse(left_over);
|
left_over_2 = app.parse(left_over);
|
||||||
EXPECT_EQ(left_over, left_over_2);
|
EXPECT_EQ(left_over, left_over_2);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test horrible error
|
// Test horrible error
|
||||||
|
@ -53,10 +53,9 @@ TEST_F(TApp, AddingMultipleInfPositionals) {
|
|||||||
EXPECT_THROW(run(), CLI::InvalidError);
|
EXPECT_THROW(run(), CLI::InvalidError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, AddingMultipleInfPositionalsSubcom) {
|
TEST_F(TApp, AddingMultipleInfPositionalsSubcom) {
|
||||||
std::vector<std::string> one, two;
|
std::vector<std::string> one, two;
|
||||||
CLI::App* below = app.add_subcommand("below");
|
CLI::App *below = app.add_subcommand("below");
|
||||||
below->add_option("one", one);
|
below->add_option("one", one);
|
||||||
below->add_option("two", two);
|
below->add_option("two", two);
|
||||||
|
|
||||||
@ -84,28 +83,26 @@ TEST_F(TApp, MultipleSubcomMatchingWithCaseFirst) {
|
|||||||
TEST_F(TApp, MultipleSubcomMatchingWithCaseInplace) {
|
TEST_F(TApp, MultipleSubcomMatchingWithCaseInplace) {
|
||||||
app.add_subcommand("first");
|
app.add_subcommand("first");
|
||||||
auto first = app.add_subcommand("fIrst");
|
auto first = app.add_subcommand("fIrst");
|
||||||
|
|
||||||
EXPECT_THROW(first->ignore_case(), CLI::OptionAlreadyAdded);
|
EXPECT_THROW(first->ignore_case(), CLI::OptionAlreadyAdded);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, MultipleSubcomMatchingWithCaseInplace2) {
|
TEST_F(TApp, MultipleSubcomMatchingWithCaseInplace2) {
|
||||||
auto first = app.add_subcommand("first");
|
auto first = app.add_subcommand("first");
|
||||||
app.add_subcommand("fIrst");
|
app.add_subcommand("fIrst");
|
||||||
|
|
||||||
EXPECT_THROW(first->ignore_case(), CLI::OptionAlreadyAdded);
|
EXPECT_THROW(first->ignore_case(), CLI::OptionAlreadyAdded);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, MultipleSubcomNoMatchingInplace2) {
|
TEST_F(TApp, MultipleSubcomNoMatchingInplace2) {
|
||||||
auto first = app.add_subcommand("first");
|
auto first = app.add_subcommand("first");
|
||||||
auto second = app.add_subcommand("second");
|
auto second = app.add_subcommand("second");
|
||||||
|
|
||||||
EXPECT_NO_THROW(first->ignore_case());
|
EXPECT_NO_THROW(first->ignore_case());
|
||||||
EXPECT_NO_THROW(second->ignore_case());
|
EXPECT_NO_THROW(second->ignore_case());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, IncorrectConstructionFlagPositional1) {
|
TEST_F(TApp, IncorrectConstructionFlagPositional1) { EXPECT_THROW(app.add_flag("cat"), CLI::IncorrectConstruction); }
|
||||||
EXPECT_THROW(app.add_flag("cat"), CLI::IncorrectConstruction);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(TApp, IncorrectConstructionFlagPositional2) {
|
TEST_F(TApp, IncorrectConstructionFlagPositional2) {
|
||||||
int x;
|
int x;
|
||||||
@ -142,40 +139,40 @@ TEST_F(TApp, IncorrectConstructionVectorAsFlag) {
|
|||||||
|
|
||||||
TEST_F(TApp, IncorrectConstructionRequiresCannotFind) {
|
TEST_F(TApp, IncorrectConstructionRequiresCannotFind) {
|
||||||
auto cat = app.add_flag("--cat");
|
auto cat = app.add_flag("--cat");
|
||||||
EXPECT_THROW(cat->requires("--nothing"),CLI::IncorrectConstruction);
|
EXPECT_THROW(cat->requires("--nothing"), CLI::IncorrectConstruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, IncorrectConstructionExcludesCannotFind) {
|
TEST_F(TApp, IncorrectConstructionExcludesCannotFind) {
|
||||||
auto cat = app.add_flag("--cat");
|
auto cat = app.add_flag("--cat");
|
||||||
EXPECT_THROW(cat->excludes("--nothing"),CLI::IncorrectConstruction);
|
EXPECT_THROW(cat->excludes("--nothing"), CLI::IncorrectConstruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, IncorrectConstructionDuplicateRequires) {
|
TEST_F(TApp, IncorrectConstructionDuplicateRequires) {
|
||||||
auto cat = app.add_flag("--cat");
|
auto cat = app.add_flag("--cat");
|
||||||
auto other = app.add_flag("--other");
|
auto other = app.add_flag("--other");
|
||||||
ASSERT_NO_THROW(cat->requires(other));
|
ASSERT_NO_THROW(cat->requires(other));
|
||||||
EXPECT_THROW(cat->requires(other),CLI::OptionAlreadyAdded);
|
EXPECT_THROW(cat->requires(other), CLI::OptionAlreadyAdded);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, IncorrectConstructionDuplicateRequiresTxt) {
|
TEST_F(TApp, IncorrectConstructionDuplicateRequiresTxt) {
|
||||||
auto cat = app.add_flag("--cat");
|
auto cat = app.add_flag("--cat");
|
||||||
app.add_flag("--other");
|
app.add_flag("--other");
|
||||||
ASSERT_NO_THROW(cat->requires("--other"));
|
ASSERT_NO_THROW(cat->requires("--other"));
|
||||||
EXPECT_THROW(cat->requires("--other"),CLI::OptionAlreadyAdded);
|
EXPECT_THROW(cat->requires("--other"), CLI::OptionAlreadyAdded);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, IncorrectConstructionDuplicateExcludes) {
|
TEST_F(TApp, IncorrectConstructionDuplicateExcludes) {
|
||||||
auto cat = app.add_flag("--cat");
|
auto cat = app.add_flag("--cat");
|
||||||
auto other = app.add_flag("--other");
|
auto other = app.add_flag("--other");
|
||||||
ASSERT_NO_THROW(cat->excludes(other));
|
ASSERT_NO_THROW(cat->excludes(other));
|
||||||
EXPECT_THROW(cat->excludes(other),CLI::OptionAlreadyAdded);
|
EXPECT_THROW(cat->excludes(other), CLI::OptionAlreadyAdded);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, IncorrectConstructionDuplicateExcludesTxt) {
|
TEST_F(TApp, IncorrectConstructionDuplicateExcludesTxt) {
|
||||||
auto cat = app.add_flag("--cat");
|
auto cat = app.add_flag("--cat");
|
||||||
app.add_flag("--other");
|
app.add_flag("--other");
|
||||||
ASSERT_NO_THROW(cat->excludes("--other"));
|
ASSERT_NO_THROW(cat->excludes("--other"));
|
||||||
EXPECT_THROW(cat->excludes("--other"),CLI::OptionAlreadyAdded);
|
EXPECT_THROW(cat->excludes("--other"), CLI::OptionAlreadyAdded);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, CheckName) {
|
TEST_F(TApp, CheckName) {
|
||||||
@ -186,7 +183,7 @@ TEST_F(TApp, CheckName) {
|
|||||||
int x, y;
|
int x, y;
|
||||||
auto pos1 = app.add_option("pos1", x);
|
auto pos1 = app.add_option("pos1", x);
|
||||||
auto pos2 = app.add_option("pOs2", y);
|
auto pos2 = app.add_option("pOs2", y);
|
||||||
|
|
||||||
EXPECT_TRUE(long1->check_name("--long1"));
|
EXPECT_TRUE(long1->check_name("--long1"));
|
||||||
EXPECT_FALSE(long1->check_name("--lonG1"));
|
EXPECT_FALSE(long1->check_name("--lonG1"));
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ TEST(THelp, Basic) {
|
|||||||
EXPECT_THAT(help, HasSubstr("-h,--help"));
|
EXPECT_THAT(help, HasSubstr("-h,--help"));
|
||||||
EXPECT_THAT(help, HasSubstr("Options:"));
|
EXPECT_THAT(help, HasSubstr("Options:"));
|
||||||
EXPECT_THAT(help, HasSubstr("Usage:"));
|
EXPECT_THAT(help, HasSubstr("Usage:"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(THelp, OptionalPositional) {
|
TEST(THelp, OptionalPositional) {
|
||||||
@ -44,11 +43,9 @@ TEST(THelp, Hidden) {
|
|||||||
CLI::App app{"My prog"};
|
CLI::App app{"My prog"};
|
||||||
|
|
||||||
std::string x;
|
std::string x;
|
||||||
app.add_option("something", x, "My option here")
|
app.add_option("something", x, "My option here")->group("Hidden");
|
||||||
->group("Hidden");
|
|
||||||
std::string y;
|
std::string y;
|
||||||
app.add_option("--another", y)
|
app.add_option("--another", y)->group("Hidden");
|
||||||
->group("Hidden");
|
|
||||||
|
|
||||||
std::string help = app.help();
|
std::string help = app.help();
|
||||||
|
|
||||||
@ -73,7 +70,6 @@ TEST(THelp, OptionalPositionalAndOptions) {
|
|||||||
EXPECT_THAT(help, HasSubstr("-h,--help"));
|
EXPECT_THAT(help, HasSubstr("-h,--help"));
|
||||||
EXPECT_THAT(help, HasSubstr("Options:"));
|
EXPECT_THAT(help, HasSubstr("Options:"));
|
||||||
EXPECT_THAT(help, HasSubstr("Usage: program [OPTIONS] [something]"));
|
EXPECT_THAT(help, HasSubstr("Usage: program [OPTIONS] [something]"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(THelp, RequiredPositionalAndOptions) {
|
TEST(THelp, RequiredPositionalAndOptions) {
|
||||||
@ -81,8 +77,7 @@ TEST(THelp, RequiredPositionalAndOptions) {
|
|||||||
app.add_flag("-q,--quick");
|
app.add_flag("-q,--quick");
|
||||||
|
|
||||||
std::string x;
|
std::string x;
|
||||||
app.add_option("something", x, "My option here")
|
app.add_option("something", x, "My option here")->required();
|
||||||
->required();
|
|
||||||
|
|
||||||
std::string help = app.help();
|
std::string help = app.help();
|
||||||
|
|
||||||
@ -93,7 +88,6 @@ TEST(THelp, RequiredPositionalAndOptions) {
|
|||||||
EXPECT_THAT(help, HasSubstr("Usage: program [OPTIONS] something"));
|
EXPECT_THAT(help, HasSubstr("Usage: program [OPTIONS] something"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(THelp, MultiOpts) {
|
TEST(THelp, MultiOpts) {
|
||||||
CLI::App app{"My prog"};
|
CLI::App app{"My prog"};
|
||||||
std::vector<int> x, y;
|
std::vector<int> x, y;
|
||||||
@ -111,7 +105,7 @@ TEST(THelp, MultiOpts) {
|
|||||||
|
|
||||||
TEST(THelp, VectorOpts) {
|
TEST(THelp, VectorOpts) {
|
||||||
CLI::App app{"My prog"};
|
CLI::App app{"My prog"};
|
||||||
std::vector<int> x = {1,2};
|
std::vector<int> x = {1, 2};
|
||||||
app.add_option("-q,--quick", x, "", true);
|
app.add_option("-q,--quick", x, "", true);
|
||||||
|
|
||||||
std::string help = app.help();
|
std::string help = app.help();
|
||||||
@ -136,8 +130,6 @@ TEST(THelp, MultiPosOpts) {
|
|||||||
EXPECT_THAT(help, HasSubstr("[vals...]"));
|
EXPECT_THAT(help, HasSubstr("[vals...]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TEST(THelp, EnvName) {
|
TEST(THelp, EnvName) {
|
||||||
CLI::App app{"My prog"};
|
CLI::App app{"My prog"};
|
||||||
std::string input;
|
std::string input;
|
||||||
@ -151,7 +143,7 @@ TEST(THelp, EnvName) {
|
|||||||
TEST(THelp, Requires) {
|
TEST(THelp, Requires) {
|
||||||
CLI::App app{"My prog"};
|
CLI::App app{"My prog"};
|
||||||
|
|
||||||
CLI::Option* op1 = app.add_flag("--op1");
|
CLI::Option *op1 = app.add_flag("--op1");
|
||||||
app.add_flag("--op2")->requires(op1);
|
app.add_flag("--op2")->requires(op1);
|
||||||
|
|
||||||
std::string help = app.help();
|
std::string help = app.help();
|
||||||
@ -162,9 +154,9 @@ TEST(THelp, Requires) {
|
|||||||
TEST(THelp, RequiresPositional) {
|
TEST(THelp, RequiresPositional) {
|
||||||
CLI::App app{"My prog"};
|
CLI::App app{"My prog"};
|
||||||
|
|
||||||
int x,y;
|
int x, y;
|
||||||
|
|
||||||
CLI::Option* op1 = app.add_option("op1", x, "one");
|
CLI::Option *op1 = app.add_option("op1", x, "one");
|
||||||
app.add_option("op2", y, "two")->requires(op1);
|
app.add_option("op2", y, "two")->requires(op1);
|
||||||
|
|
||||||
std::string help = app.help();
|
std::string help = app.help();
|
||||||
@ -176,7 +168,7 @@ TEST(THelp, RequiresPositional) {
|
|||||||
TEST(THelp, Excludes) {
|
TEST(THelp, Excludes) {
|
||||||
CLI::App app{"My prog"};
|
CLI::App app{"My prog"};
|
||||||
|
|
||||||
CLI::Option* op1 = app.add_flag("--op1");
|
CLI::Option *op1 = app.add_flag("--op1");
|
||||||
app.add_flag("--op2")->excludes(op1);
|
app.add_flag("--op2")->excludes(op1);
|
||||||
|
|
||||||
std::string help = app.help();
|
std::string help = app.help();
|
||||||
@ -187,9 +179,9 @@ TEST(THelp, Excludes) {
|
|||||||
TEST(THelp, ExcludesPositional) {
|
TEST(THelp, ExcludesPositional) {
|
||||||
CLI::App app{"My prog"};
|
CLI::App app{"My prog"};
|
||||||
|
|
||||||
int x,y;
|
int x, y;
|
||||||
|
|
||||||
CLI::Option* op1 = app.add_option("op1", x);
|
CLI::Option *op1 = app.add_option("op1", x);
|
||||||
app.add_option("op2", y)->excludes(op1);
|
app.add_option("op2", y)->excludes(op1);
|
||||||
|
|
||||||
std::string help = app.help();
|
std::string help = app.help();
|
||||||
@ -211,15 +203,15 @@ TEST(THelp, Subcom) {
|
|||||||
|
|
||||||
help = app.help();
|
help = app.help();
|
||||||
EXPECT_THAT(help, HasSubstr("Usage: program [OPTIONS] SUBCOMMAND"));
|
EXPECT_THAT(help, HasSubstr("Usage: program [OPTIONS] SUBCOMMAND"));
|
||||||
|
|
||||||
help = sub1->help();
|
help = sub1->help();
|
||||||
EXPECT_THAT(help, HasSubstr("Usage: sub1"));
|
EXPECT_THAT(help, HasSubstr("Usage: sub1"));
|
||||||
|
|
||||||
char x[] = "./myprogram";
|
char x[] = "./myprogram";
|
||||||
char y[] = "sub2";
|
char y[] = "sub2";
|
||||||
|
|
||||||
std::vector<char*> args = {x,y};
|
std::vector<char *> args = {x, y};
|
||||||
app.parse((int) args.size(), args.data());
|
app.parse((int)args.size(), args.data());
|
||||||
|
|
||||||
help = app.help();
|
help = app.help();
|
||||||
EXPECT_THAT(help, HasSubstr("Usage: ./myprogram sub2"));
|
EXPECT_THAT(help, HasSubstr("Usage: ./myprogram sub2"));
|
||||||
@ -229,8 +221,8 @@ TEST(THelp, IntDefaults) {
|
|||||||
CLI::App app{"My prog"};
|
CLI::App app{"My prog"};
|
||||||
|
|
||||||
int one{1}, two{2};
|
int one{1}, two{2};
|
||||||
app.add_option("--one", one, "Help for one", true);
|
app.add_option("--one", one, "Help for one", true);
|
||||||
app.add_set("--set", two, {2,3,4}, "Help for set", true);
|
app.add_set("--set", two, {2, 3, 4}, "Help for set", true);
|
||||||
|
|
||||||
std::string help = app.help();
|
std::string help = app.help();
|
||||||
|
|
||||||
@ -239,14 +231,13 @@ TEST(THelp, IntDefaults) {
|
|||||||
EXPECT_THAT(help, HasSubstr("1"));
|
EXPECT_THAT(help, HasSubstr("1"));
|
||||||
EXPECT_THAT(help, HasSubstr("=2"));
|
EXPECT_THAT(help, HasSubstr("=2"));
|
||||||
EXPECT_THAT(help, HasSubstr("2,3,4"));
|
EXPECT_THAT(help, HasSubstr("2,3,4"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(THelp, SetLower) {
|
TEST(THelp, SetLower) {
|
||||||
CLI::App app{"My prog"};
|
CLI::App app{"My prog"};
|
||||||
|
|
||||||
std::string def{"One"};
|
std::string def{"One"};
|
||||||
app.add_set_ignore_case("--set",def, {"oNe", "twO", "THREE"}, "Help for set", true);
|
app.add_set_ignore_case("--set", def, {"oNe", "twO", "THREE"}, "Help for set", true);
|
||||||
|
|
||||||
std::string help = app.help();
|
std::string help = app.help();
|
||||||
|
|
||||||
@ -255,16 +246,15 @@ TEST(THelp, SetLower) {
|
|||||||
EXPECT_THAT(help, HasSubstr("oNe"));
|
EXPECT_THAT(help, HasSubstr("oNe"));
|
||||||
EXPECT_THAT(help, HasSubstr("twO"));
|
EXPECT_THAT(help, HasSubstr("twO"));
|
||||||
EXPECT_THAT(help, HasSubstr("THREE"));
|
EXPECT_THAT(help, HasSubstr("THREE"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Exit, ErrorWithHelp) {
|
TEST(Exit, ErrorWithHelp) {
|
||||||
CLI::App app{"My prog"};
|
CLI::App app{"My prog"};
|
||||||
|
|
||||||
std::vector<std::string> input {"-h"};
|
std::vector<std::string> input{"-h"};
|
||||||
try {
|
try {
|
||||||
app.parse(input);
|
app.parse(input);
|
||||||
} catch (const CLI::CallForHelp &e) {
|
} catch(const CLI::CallForHelp &e) {
|
||||||
EXPECT_EQ(static_cast<int>(CLI::ExitCodes::Success), e.get_exit_code());
|
EXPECT_EQ(static_cast<int>(CLI::ExitCodes::Success), e.get_exit_code());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -272,10 +262,10 @@ TEST(Exit, ErrorWithHelp) {
|
|||||||
TEST(Exit, ErrorWithoutHelp) {
|
TEST(Exit, ErrorWithoutHelp) {
|
||||||
CLI::App app{"My prog"};
|
CLI::App app{"My prog"};
|
||||||
|
|
||||||
std::vector<std::string> input {"--none"};
|
std::vector<std::string> input{"--none"};
|
||||||
try {
|
try {
|
||||||
app.parse(input);
|
app.parse(input);
|
||||||
} catch (const CLI::ParseError &e) {
|
} catch(const CLI::ParseError &e) {
|
||||||
EXPECT_EQ(static_cast<int>(CLI::ExitCodes::Extras), e.get_exit_code());
|
EXPECT_EQ(static_cast<int>(CLI::ExitCodes::Extras), e.get_exit_code());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -287,5 +277,4 @@ TEST(Exit, ExitCodes) {
|
|||||||
EXPECT_EQ(0, app.exit(CLI::Success()));
|
EXPECT_EQ(0, app.exit(CLI::Success()));
|
||||||
EXPECT_EQ(0, app.exit(CLI::CallForHelp()));
|
EXPECT_EQ(0, app.exit(CLI::CallForHelp()));
|
||||||
EXPECT_EQ(i, app.exit(CLI::ExtrasError("Thing")));
|
EXPECT_EQ(i, app.exit(CLI::ExtrasError("Thing")));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
TEST(Split, SimpleByToken) {
|
TEST(Split, SimpleByToken) {
|
||||||
auto out = CLI::detail::split("one.two.three", '.');
|
auto out = CLI::detail::split("one.two.three", '.');
|
||||||
ASSERT_EQ((size_t) 3, out.size());
|
ASSERT_EQ((size_t)3, out.size());
|
||||||
EXPECT_EQ("one", out.at(0));
|
EXPECT_EQ("one", out.at(0));
|
||||||
EXPECT_EQ("two", out.at(1));
|
EXPECT_EQ("two", out.at(1));
|
||||||
EXPECT_EQ("three", out.at(2));
|
EXPECT_EQ("three", out.at(2));
|
||||||
@ -15,13 +15,13 @@ TEST(Split, SimpleByToken) {
|
|||||||
|
|
||||||
TEST(Split, Single) {
|
TEST(Split, Single) {
|
||||||
auto out = CLI::detail::split("one", '.');
|
auto out = CLI::detail::split("one", '.');
|
||||||
ASSERT_EQ((size_t) 1, out.size());
|
ASSERT_EQ((size_t)1, out.size());
|
||||||
EXPECT_EQ("one", out.at(0));
|
EXPECT_EQ("one", out.at(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Split, Empty) {
|
TEST(Split, Empty) {
|
||||||
auto out = CLI::detail::split("", '.');
|
auto out = CLI::detail::split("", '.');
|
||||||
ASSERT_EQ((size_t) 1, out.size());
|
ASSERT_EQ((size_t)1, out.size());
|
||||||
EXPECT_EQ("", out.at(0));
|
EXPECT_EQ("", out.at(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ TEST(Trim, Various) {
|
|||||||
std::string a1{"sdlfkj sdflk sd s"};
|
std::string a1{"sdlfkj sdflk sd s"};
|
||||||
CLI::detail::trim(s1);
|
CLI::detail::trim(s1);
|
||||||
EXPECT_EQ(a1, s1);
|
EXPECT_EQ(a1, s1);
|
||||||
|
|
||||||
std::string s2{" a \t"};
|
std::string s2{" a \t"};
|
||||||
CLI::detail::trim(s2);
|
CLI::detail::trim(s2);
|
||||||
EXPECT_EQ("a", s2);
|
EXPECT_EQ("a", s2);
|
||||||
@ -51,13 +51,12 @@ TEST(Trim, Various) {
|
|||||||
EXPECT_EQ("a b", CLI::detail::trim(s4));
|
EXPECT_EQ("a b", CLI::detail::trim(s4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(Trim, VariousFilters) {
|
TEST(Trim, VariousFilters) {
|
||||||
std::string s1{" sdlfkj sdflk sd s "};
|
std::string s1{" sdlfkj sdflk sd s "};
|
||||||
std::string a1{"sdlfkj sdflk sd s"};
|
std::string a1{"sdlfkj sdflk sd s"};
|
||||||
CLI::detail::trim(s1, " ");
|
CLI::detail::trim(s1, " ");
|
||||||
EXPECT_EQ(a1, s1);
|
EXPECT_EQ(a1, s1);
|
||||||
|
|
||||||
std::string s2{" a \t"};
|
std::string s2{" a \t"};
|
||||||
CLI::detail::trim(s2, " ");
|
CLI::detail::trim(s2, " ");
|
||||||
EXPECT_EQ("a \t", s2);
|
EXPECT_EQ("a \t", s2);
|
||||||
@ -84,10 +83,8 @@ TEST(Trim, TrimCopy) {
|
|||||||
EXPECT_NE(orig, trimmed);
|
EXPECT_NE(orig, trimmed);
|
||||||
CLI::detail::trim(orig, "ab");
|
CLI::detail::trim(orig, "ab");
|
||||||
EXPECT_EQ(trimmed, orig);
|
EXPECT_EQ(trimmed, orig);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(Validators, FileExists) {
|
TEST(Validators, FileExists) {
|
||||||
std::string myfile{"TestFileNotUsed.txt"};
|
std::string myfile{"TestFileNotUsed.txt"};
|
||||||
EXPECT_FALSE(CLI::ExistingFile(myfile));
|
EXPECT_FALSE(CLI::ExistingFile(myfile));
|
||||||
@ -140,14 +137,14 @@ TEST(Validators, DirectoryIsFile) {
|
|||||||
TEST(AppHelper, TempfileCreated) {
|
TEST(AppHelper, TempfileCreated) {
|
||||||
std::string name = "TestFileNotUsed.txt";
|
std::string name = "TestFileNotUsed.txt";
|
||||||
{
|
{
|
||||||
TempFile myfile{name};
|
TempFile myfile{name};
|
||||||
|
|
||||||
EXPECT_FALSE(CLI::ExistingFile(myfile));
|
EXPECT_FALSE(CLI::ExistingFile(myfile));
|
||||||
|
|
||||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||||
EXPECT_TRUE(ok);
|
EXPECT_TRUE(ok);
|
||||||
EXPECT_TRUE(CLI::ExistingFile(name));
|
EXPECT_TRUE(CLI::ExistingFile(name));
|
||||||
EXPECT_THROW({TempFile otherfile(name);}, std::runtime_error);
|
EXPECT_THROW({ TempFile otherfile(name); }, std::runtime_error);
|
||||||
}
|
}
|
||||||
EXPECT_FALSE(CLI::ExistingFile(name));
|
EXPECT_FALSE(CLI::ExistingFile(name));
|
||||||
}
|
}
|
||||||
@ -155,9 +152,9 @@ TEST(AppHelper, TempfileCreated) {
|
|||||||
TEST(AppHelper, TempfileNotCreated) {
|
TEST(AppHelper, TempfileNotCreated) {
|
||||||
std::string name = "TestFileNotUsed.txt";
|
std::string name = "TestFileNotUsed.txt";
|
||||||
{
|
{
|
||||||
TempFile myfile{name};
|
TempFile myfile{name};
|
||||||
|
|
||||||
EXPECT_FALSE(CLI::ExistingFile(myfile));
|
EXPECT_FALSE(CLI::ExistingFile(myfile));
|
||||||
}
|
}
|
||||||
EXPECT_FALSE(CLI::ExistingFile(name));
|
EXPECT_FALSE(CLI::ExistingFile(name));
|
||||||
}
|
}
|
||||||
@ -166,22 +163,21 @@ TEST(AppHelper, Ofstream) {
|
|||||||
|
|
||||||
std::string name = "TestFileNotUsed.txt";
|
std::string name = "TestFileNotUsed.txt";
|
||||||
{
|
{
|
||||||
TempFile myfile(name);
|
TempFile myfile(name);
|
||||||
|
|
||||||
{
|
{
|
||||||
std::ofstream out{myfile};
|
std::ofstream out{myfile};
|
||||||
out << "this is output" << std::endl;
|
out << "this is output" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_TRUE(CLI::ExistingFile(myfile));
|
EXPECT_TRUE(CLI::ExistingFile(myfile));
|
||||||
}
|
}
|
||||||
EXPECT_FALSE(CLI::ExistingFile(name));
|
EXPECT_FALSE(CLI::ExistingFile(name));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Split, StringList) {
|
TEST(Split, StringList) {
|
||||||
|
|
||||||
std::vector<std::string> results {"a", "long", "--lone", "-q"};
|
std::vector<std::string> results{"a", "long", "--lone", "-q"};
|
||||||
EXPECT_EQ(results, CLI::detail::split_names("a,long,--lone,-q"));
|
EXPECT_EQ(results, CLI::detail::split_names("a,long,--lone,-q"));
|
||||||
|
|
||||||
EXPECT_EQ(std::vector<std::string>({"one"}), CLI::detail::split_names("one"));
|
EXPECT_EQ(std::vector<std::string>({"one"}), CLI::detail::split_names("one"));
|
||||||
@ -232,7 +228,6 @@ TEST(RegEx, Longs) {
|
|||||||
EXPECT_FALSE(CLI::detail::split_long("-things", name, value));
|
EXPECT_FALSE(CLI::detail::split_long("-things", name, value));
|
||||||
EXPECT_FALSE(CLI::detail::split_long("Q", name, value));
|
EXPECT_FALSE(CLI::detail::split_long("Q", name, value));
|
||||||
EXPECT_FALSE(CLI::detail::split_long("--", name, value));
|
EXPECT_FALSE(CLI::detail::split_long("--", name, value));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(RegEx, SplittingNew) {
|
TEST(RegEx, SplittingNew) {
|
||||||
@ -246,7 +241,8 @@ TEST(RegEx, SplittingNew) {
|
|||||||
EXPECT_EQ(std::vector<std::string>({"s", "q"}), shorts);
|
EXPECT_EQ(std::vector<std::string>({"s", "q"}), shorts);
|
||||||
EXPECT_EQ("", pname);
|
EXPECT_EQ("", pname);
|
||||||
|
|
||||||
EXPECT_NO_THROW(std::tie(shorts, longs, pname) = 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>({"long", "also-long"}), longs);
|
||||||
EXPECT_EQ(std::vector<std::string>({"s", "q"}), shorts);
|
EXPECT_EQ(std::vector<std::string>({"s", "q"}), shorts);
|
||||||
|
|
||||||
@ -254,57 +250,52 @@ TEST(RegEx, SplittingNew) {
|
|||||||
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({"-hi"}), 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({"---hi"}), CLI::BadNameString);
|
||||||
EXPECT_THROW(std::tie(shorts, longs, pname) = CLI::detail::get_names({"one","two"}), CLI::BadNameString);
|
EXPECT_THROW(std::tie(shorts, longs, pname) = CLI::detail::get_names({"one", "two"}), CLI::BadNameString);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(String, ToLower) {
|
TEST(String, ToLower) { EXPECT_EQ("one and two", CLI::detail::to_lower("one And TWO")); }
|
||||||
|
|
||||||
EXPECT_EQ("one and two", CLI::detail::to_lower("one And TWO"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Join, Forward) {
|
TEST(Join, Forward) {
|
||||||
std::vector<std::string> val {{"one", "two", "three"}};
|
std::vector<std::string> val{{"one", "two", "three"}};
|
||||||
EXPECT_EQ("one,two,three", CLI::detail::join(val));
|
EXPECT_EQ("one,two,three", CLI::detail::join(val));
|
||||||
EXPECT_EQ("one;two;three", CLI::detail::join(val, ";"));
|
EXPECT_EQ("one;two;three", CLI::detail::join(val, ";"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(Join, Backward) {
|
TEST(Join, Backward) {
|
||||||
std::vector<std::string> val {{"three", "two", "one"}};
|
std::vector<std::string> val{{"three", "two", "one"}};
|
||||||
EXPECT_EQ("one,two,three", CLI::detail::rjoin(val));
|
EXPECT_EQ("one,two,three", CLI::detail::rjoin(val));
|
||||||
EXPECT_EQ("one;two;three", CLI::detail::rjoin(val, ";"));
|
EXPECT_EQ("one;two;three", CLI::detail::rjoin(val, ";"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(SplitUp, Simple) {
|
TEST(SplitUp, Simple) {
|
||||||
std::vector<std::string> oput = {"one", "two three"};
|
std::vector<std::string> oput = {"one", "two three"};
|
||||||
std::string orig {R"(one "two three")"};
|
std::string orig{R"(one "two three")"};
|
||||||
std::vector<std::string> result = CLI::detail::split_up(orig);
|
std::vector<std::string> result = CLI::detail::split_up(orig);
|
||||||
EXPECT_EQ(oput, result);
|
EXPECT_EQ(oput, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(SplitUp, Layered) {
|
TEST(SplitUp, Layered) {
|
||||||
std::vector<std::string> output = {R"(one 'two three')"};
|
std::vector<std::string> output = {R"(one 'two three')"};
|
||||||
std::string orig {R"("one 'two three'")"};
|
std::string orig{R"("one 'two three'")"};
|
||||||
std::vector<std::string> result = CLI::detail::split_up(orig);
|
std::vector<std::string> result = CLI::detail::split_up(orig);
|
||||||
EXPECT_EQ(output, result);
|
EXPECT_EQ(output, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(SplitUp, Spaces) {
|
TEST(SplitUp, Spaces) {
|
||||||
std::vector<std::string> oput = {"one", " two three"};
|
std::vector<std::string> oput = {"one", " two three"};
|
||||||
std::string orig {R"( one " two three" )"};
|
std::string orig{R"( one " two three" )"};
|
||||||
std::vector<std::string> result = CLI::detail::split_up(orig);
|
std::vector<std::string> result = CLI::detail::split_up(orig);
|
||||||
EXPECT_EQ(oput, result);
|
EXPECT_EQ(oput, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(SplitUp, BadStrings) {
|
TEST(SplitUp, BadStrings) {
|
||||||
std::vector<std::string> oput = {"one", " two three"};
|
std::vector<std::string> oput = {"one", " two three"};
|
||||||
std::string orig {R"( one " two three )"};
|
std::string orig{R"( one " two three )"};
|
||||||
std::vector<std::string> result = CLI::detail::split_up(orig);
|
std::vector<std::string> result = CLI::detail::split_up(orig);
|
||||||
EXPECT_EQ(oput, result);
|
EXPECT_EQ(oput, result);
|
||||||
|
|
||||||
oput = {"one", " two three"};
|
oput = {"one", " two three"};
|
||||||
orig = R"( one ' two three )";
|
orig = R"( one ' two three )";
|
||||||
result = CLI::detail::split_up(orig);
|
result = CLI::detail::split_up(orig);
|
||||||
EXPECT_EQ(oput, result);
|
EXPECT_EQ(oput, result);
|
||||||
}
|
}
|
||||||
@ -327,8 +318,8 @@ TEST(Types, TypeName) {
|
|||||||
|
|
||||||
std::string text_name = CLI::detail::type_name<std::string>();
|
std::string text_name = CLI::detail::type_name<std::string>();
|
||||||
EXPECT_EQ("TEXT", text_name);
|
EXPECT_EQ("TEXT", text_name);
|
||||||
|
|
||||||
std::string text2_name = CLI::detail::type_name<char*>();
|
std::string text2_name = CLI::detail::type_name<char *>();
|
||||||
EXPECT_EQ("TEXT", text2_name);
|
EXPECT_EQ("TEXT", text2_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,11 +341,11 @@ TEST(Types, LexicalCastDouble) {
|
|||||||
std::string input = "9.12";
|
std::string input = "9.12";
|
||||||
long double x;
|
long double x;
|
||||||
EXPECT_TRUE(CLI::detail::lexical_cast(input, x));
|
EXPECT_TRUE(CLI::detail::lexical_cast(input, x));
|
||||||
EXPECT_FLOAT_EQ((float) 9.12, (float) x);
|
EXPECT_FLOAT_EQ((float)9.12, (float)x);
|
||||||
|
|
||||||
std::string bad_input = "hello";
|
std::string bad_input = "hello";
|
||||||
EXPECT_FALSE(CLI::detail::lexical_cast(bad_input, x));
|
EXPECT_FALSE(CLI::detail::lexical_cast(bad_input, x));
|
||||||
|
|
||||||
std::string overflow_input = "1" + std::to_string(LDBL_MAX);
|
std::string overflow_input = "1" + std::to_string(LDBL_MAX);
|
||||||
EXPECT_FALSE(CLI::detail::lexical_cast(overflow_input, x));
|
EXPECT_FALSE(CLI::detail::lexical_cast(overflow_input, x));
|
||||||
}
|
}
|
||||||
@ -365,4 +356,3 @@ TEST(Types, LexicalCastString) {
|
|||||||
CLI::detail::lexical_cast(input, output);
|
CLI::detail::lexical_cast(input, output);
|
||||||
EXPECT_EQ(input, output);
|
EXPECT_EQ(input, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
using ::testing::HasSubstr;
|
using ::testing::HasSubstr;
|
||||||
using ::testing::Not;
|
using ::testing::Not;
|
||||||
|
|
||||||
@ -17,14 +17,13 @@ TEST(StringBased, First) {
|
|||||||
|
|
||||||
std::vector<CLI::detail::ini_ret_t> output = CLI::detail::parse_ini(ofile);
|
std::vector<CLI::detail::ini_ret_t> output = CLI::detail::parse_ini(ofile);
|
||||||
|
|
||||||
EXPECT_EQ((size_t) 2, output.size());
|
EXPECT_EQ((size_t)2, output.size());
|
||||||
EXPECT_EQ("one", output.at(0).name());
|
EXPECT_EQ("one", output.at(0).name());
|
||||||
EXPECT_EQ((size_t) 1, output.at(0).inputs.size());
|
EXPECT_EQ((size_t)1, output.at(0).inputs.size());
|
||||||
EXPECT_EQ("three", output.at(0).inputs.at(0));
|
EXPECT_EQ("three", output.at(0).inputs.at(0));
|
||||||
EXPECT_EQ("two", output.at(1).name());
|
EXPECT_EQ("two", output.at(1).name());
|
||||||
EXPECT_EQ((size_t) 1, output.at(1).inputs.size());
|
EXPECT_EQ((size_t)1, output.at(1).inputs.size());
|
||||||
EXPECT_EQ("four", output.at(1).inputs.at(0));
|
EXPECT_EQ("four", output.at(1).inputs.at(0));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StringBased, FirstWithComments) {
|
TEST(StringBased, FirstWithComments) {
|
||||||
@ -39,12 +38,12 @@ TEST(StringBased, FirstWithComments) {
|
|||||||
|
|
||||||
auto output = CLI::detail::parse_ini(ofile);
|
auto output = CLI::detail::parse_ini(ofile);
|
||||||
|
|
||||||
EXPECT_EQ((size_t) 2, output.size());
|
EXPECT_EQ((size_t)2, output.size());
|
||||||
EXPECT_EQ("one", output.at(0).name());
|
EXPECT_EQ("one", output.at(0).name());
|
||||||
EXPECT_EQ((size_t) 1, output.at(0).inputs.size());
|
EXPECT_EQ((size_t)1, output.at(0).inputs.size());
|
||||||
EXPECT_EQ("three", output.at(0).inputs.at(0));
|
EXPECT_EQ("three", output.at(0).inputs.at(0));
|
||||||
EXPECT_EQ("two", output.at(1).name());
|
EXPECT_EQ("two", output.at(1).name());
|
||||||
EXPECT_EQ((size_t) 1, output.at(1).inputs.size());
|
EXPECT_EQ((size_t)1, output.at(1).inputs.size());
|
||||||
EXPECT_EQ("four", output.at(1).inputs.at(0));
|
EXPECT_EQ("four", output.at(1).inputs.at(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,15 +58,15 @@ TEST(StringBased, Quotes) {
|
|||||||
|
|
||||||
auto output = CLI::detail::parse_ini(ofile);
|
auto output = CLI::detail::parse_ini(ofile);
|
||||||
|
|
||||||
EXPECT_EQ((size_t) 3, output.size());
|
EXPECT_EQ((size_t)3, output.size());
|
||||||
EXPECT_EQ("one", output.at(0).name());
|
EXPECT_EQ("one", output.at(0).name());
|
||||||
EXPECT_EQ((size_t) 1, output.at(0).inputs.size());
|
EXPECT_EQ((size_t)1, output.at(0).inputs.size());
|
||||||
EXPECT_EQ("three", output.at(0).inputs.at(0));
|
EXPECT_EQ("three", output.at(0).inputs.at(0));
|
||||||
EXPECT_EQ("two", output.at(1).name());
|
EXPECT_EQ("two", output.at(1).name());
|
||||||
EXPECT_EQ((size_t) 1, output.at(1).inputs.size());
|
EXPECT_EQ((size_t)1, output.at(1).inputs.size());
|
||||||
EXPECT_EQ("four", output.at(1).inputs.at(0));
|
EXPECT_EQ("four", output.at(1).inputs.at(0));
|
||||||
EXPECT_EQ("five", output.at(2).name());
|
EXPECT_EQ("five", output.at(2).name());
|
||||||
EXPECT_EQ((size_t) 1, output.at(2).inputs.size());
|
EXPECT_EQ((size_t)1, output.at(2).inputs.size());
|
||||||
EXPECT_EQ("six and seven", output.at(2).inputs.at(0));
|
EXPECT_EQ("six and seven", output.at(2).inputs.at(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,21 +81,20 @@ TEST(StringBased, Vector) {
|
|||||||
|
|
||||||
auto output = CLI::detail::parse_ini(ofile);
|
auto output = CLI::detail::parse_ini(ofile);
|
||||||
|
|
||||||
EXPECT_EQ((size_t) 3, output.size());
|
EXPECT_EQ((size_t)3, output.size());
|
||||||
EXPECT_EQ("one", output.at(0).name());
|
EXPECT_EQ("one", output.at(0).name());
|
||||||
EXPECT_EQ((size_t) 1, output.at(0).inputs.size());
|
EXPECT_EQ((size_t)1, output.at(0).inputs.size());
|
||||||
EXPECT_EQ("three", output.at(0).inputs.at(0));
|
EXPECT_EQ("three", output.at(0).inputs.at(0));
|
||||||
EXPECT_EQ("two", output.at(1).name());
|
EXPECT_EQ("two", output.at(1).name());
|
||||||
EXPECT_EQ((size_t) 1, output.at(1).inputs.size());
|
EXPECT_EQ((size_t)1, output.at(1).inputs.size());
|
||||||
EXPECT_EQ("four", output.at(1).inputs.at(0));
|
EXPECT_EQ("four", output.at(1).inputs.at(0));
|
||||||
EXPECT_EQ("five", output.at(2).name());
|
EXPECT_EQ("five", output.at(2).name());
|
||||||
EXPECT_EQ((size_t) 3, output.at(2).inputs.size());
|
EXPECT_EQ((size_t)3, output.at(2).inputs.size());
|
||||||
EXPECT_EQ("six", output.at(2).inputs.at(0));
|
EXPECT_EQ("six", output.at(2).inputs.at(0));
|
||||||
EXPECT_EQ("and", output.at(2).inputs.at(1));
|
EXPECT_EQ("and", output.at(2).inputs.at(1));
|
||||||
EXPECT_EQ("seven", output.at(2).inputs.at(2));
|
EXPECT_EQ("seven", output.at(2).inputs.at(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(StringBased, Spaces) {
|
TEST(StringBased, Spaces) {
|
||||||
std::stringstream ofile;
|
std::stringstream ofile;
|
||||||
|
|
||||||
@ -107,12 +105,12 @@ TEST(StringBased, Spaces) {
|
|||||||
|
|
||||||
auto output = CLI::detail::parse_ini(ofile);
|
auto output = CLI::detail::parse_ini(ofile);
|
||||||
|
|
||||||
EXPECT_EQ((size_t) 2, output.size());
|
EXPECT_EQ((size_t)2, output.size());
|
||||||
EXPECT_EQ("one", output.at(0).name());
|
EXPECT_EQ("one", output.at(0).name());
|
||||||
EXPECT_EQ((size_t) 1, output.at(0).inputs.size());
|
EXPECT_EQ((size_t)1, output.at(0).inputs.size());
|
||||||
EXPECT_EQ("three", output.at(0).inputs.at(0));
|
EXPECT_EQ("three", output.at(0).inputs.at(0));
|
||||||
EXPECT_EQ("two", output.at(1).name());
|
EXPECT_EQ("two", output.at(1).name());
|
||||||
EXPECT_EQ((size_t) 1, output.at(1).inputs.size());
|
EXPECT_EQ((size_t)1, output.at(1).inputs.size());
|
||||||
EXPECT_EQ("four", output.at(1).inputs.at(0));
|
EXPECT_EQ("four", output.at(1).inputs.at(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,18 +124,17 @@ TEST(StringBased, Sections) {
|
|||||||
ofile.seekg(0, std::ios::beg);
|
ofile.seekg(0, std::ios::beg);
|
||||||
|
|
||||||
auto output = CLI::detail::parse_ini(ofile);
|
auto output = CLI::detail::parse_ini(ofile);
|
||||||
|
|
||||||
EXPECT_EQ((size_t) 2, output.size());
|
EXPECT_EQ((size_t)2, output.size());
|
||||||
EXPECT_EQ("one", output.at(0).name());
|
EXPECT_EQ("one", output.at(0).name());
|
||||||
EXPECT_EQ((size_t) 1, output.at(0).inputs.size());
|
EXPECT_EQ((size_t)1, output.at(0).inputs.size());
|
||||||
EXPECT_EQ("three", output.at(0).inputs.at(0));
|
EXPECT_EQ("three", output.at(0).inputs.at(0));
|
||||||
EXPECT_EQ("two", output.at(1).name());
|
EXPECT_EQ("two", output.at(1).name());
|
||||||
EXPECT_EQ("second", output.at(1).parent());
|
EXPECT_EQ("second", output.at(1).parent());
|
||||||
EXPECT_EQ((size_t) 1, output.at(1).inputs.size());
|
EXPECT_EQ((size_t)1, output.at(1).inputs.size());
|
||||||
EXPECT_EQ("four", output.at(1).inputs.at(0));
|
EXPECT_EQ("four", output.at(1).inputs.at(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(StringBased, SpacesSections) {
|
TEST(StringBased, SpacesSections) {
|
||||||
std::stringstream ofile;
|
std::stringstream ofile;
|
||||||
|
|
||||||
@ -151,13 +148,13 @@ TEST(StringBased, SpacesSections) {
|
|||||||
|
|
||||||
auto output = CLI::detail::parse_ini(ofile);
|
auto output = CLI::detail::parse_ini(ofile);
|
||||||
|
|
||||||
EXPECT_EQ((size_t) 2, output.size());
|
EXPECT_EQ((size_t)2, output.size());
|
||||||
EXPECT_EQ("one", output.at(0).name());
|
EXPECT_EQ("one", output.at(0).name());
|
||||||
EXPECT_EQ((size_t) 1, output.at(0).inputs.size());
|
EXPECT_EQ((size_t)1, output.at(0).inputs.size());
|
||||||
EXPECT_EQ("three", output.at(0).inputs.at(0));
|
EXPECT_EQ("three", output.at(0).inputs.at(0));
|
||||||
EXPECT_EQ("two", output.at(1).name());
|
EXPECT_EQ("two", output.at(1).name());
|
||||||
EXPECT_EQ("second", output.at(1).parent());
|
EXPECT_EQ("second", output.at(1).parent());
|
||||||
EXPECT_EQ((size_t) 1, output.at(1).inputs.size());
|
EXPECT_EQ((size_t)1, output.at(1).inputs.size());
|
||||||
EXPECT_EQ("four", output.at(1).inputs.at(0));
|
EXPECT_EQ("four", output.at(1).inputs.at(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +171,7 @@ TEST_F(TApp, IniNotRequired) {
|
|||||||
out << "three=3" << std::endl;
|
out << "three=3" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int one=0, two=0, three=0;
|
int one = 0, two = 0, three = 0;
|
||||||
app.add_option("--one", one);
|
app.add_option("--one", one);
|
||||||
app.add_option("--two", two);
|
app.add_option("--two", two);
|
||||||
app.add_option("--three", three);
|
app.add_option("--three", three);
|
||||||
@ -188,7 +185,7 @@ TEST_F(TApp, IniNotRequired) {
|
|||||||
EXPECT_EQ(3, three);
|
EXPECT_EQ(3, three);
|
||||||
|
|
||||||
app.reset();
|
app.reset();
|
||||||
one=two=three=0;
|
one = two = three = 0;
|
||||||
args = {"--one=1", "--two=2"};
|
args = {"--one=1", "--two=2"};
|
||||||
|
|
||||||
run();
|
run();
|
||||||
@ -196,7 +193,6 @@ TEST_F(TApp, IniNotRequired) {
|
|||||||
EXPECT_EQ(1, one);
|
EXPECT_EQ(1, one);
|
||||||
EXPECT_EQ(2, two);
|
EXPECT_EQ(2, two);
|
||||||
EXPECT_EQ(3, three);
|
EXPECT_EQ(3, three);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, IniRequiredNotFound) {
|
TEST_F(TApp, IniRequiredNotFound) {
|
||||||
@ -205,7 +201,6 @@ TEST_F(TApp, IniRequiredNotFound) {
|
|||||||
app.add_config("--config", noini, "", true);
|
app.add_config("--config", noini, "", true);
|
||||||
|
|
||||||
EXPECT_THROW(run(), CLI::FileError);
|
EXPECT_THROW(run(), CLI::FileError);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, IniOverwrite) {
|
TEST_F(TApp, IniOverwrite) {
|
||||||
@ -224,7 +219,7 @@ TEST_F(TApp, IniOverwrite) {
|
|||||||
app.add_config("--conf", next);
|
app.add_config("--conf", next);
|
||||||
int two = 7;
|
int two = 7;
|
||||||
app.add_option("--two", two);
|
app.add_option("--two", two);
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
EXPECT_EQ(99, two);
|
EXPECT_EQ(99, two);
|
||||||
@ -243,7 +238,7 @@ TEST_F(TApp, IniRequired) {
|
|||||||
out << "three=3" << std::endl;
|
out << "three=3" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int one=0, two=0, three=0;
|
int one = 0, two = 0, three = 0;
|
||||||
app.add_option("--one", one)->required();
|
app.add_option("--one", one)->required();
|
||||||
app.add_option("--two", two)->required();
|
app.add_option("--two", two)->required();
|
||||||
app.add_option("--three", three)->required();
|
app.add_option("--three", three)->required();
|
||||||
@ -253,7 +248,7 @@ TEST_F(TApp, IniRequired) {
|
|||||||
run();
|
run();
|
||||||
|
|
||||||
app.reset();
|
app.reset();
|
||||||
one=two=three=0;
|
one = two = three = 0;
|
||||||
args = {"--one=1", "--two=2"};
|
args = {"--one=1", "--two=2"};
|
||||||
|
|
||||||
run();
|
run();
|
||||||
@ -267,7 +262,6 @@ TEST_F(TApp, IniRequired) {
|
|||||||
args = {"--two=2"};
|
args = {"--two=2"};
|
||||||
|
|
||||||
EXPECT_THROW(run(), CLI::RequiredError);
|
EXPECT_THROW(run(), CLI::RequiredError);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, IniVector) {
|
TEST_F(TApp, IniVector) {
|
||||||
@ -289,12 +283,10 @@ TEST_F(TApp, IniVector) {
|
|||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
EXPECT_EQ(std::vector<int>({2,3}), two);
|
EXPECT_EQ(std::vector<int>({2, 3}), two);
|
||||||
EXPECT_EQ(std::vector<int>({1,2,3}), three);
|
EXPECT_EQ(std::vector<int>({1, 2, 3}), three);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, IniLayered) {
|
TEST_F(TApp, IniLayered) {
|
||||||
|
|
||||||
TempFile tmpini{"TestIniTmp.ini"};
|
TempFile tmpini{"TestIniTmp.ini"};
|
||||||
@ -310,7 +302,7 @@ TEST_F(TApp, IniLayered) {
|
|||||||
out << "subsubcom.val=3" << std::endl;
|
out << "subsubcom.val=3" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int one=0, two=0, three=0;
|
int one = 0, two = 0, three = 0;
|
||||||
app.add_option("--val", one);
|
app.add_option("--val", one);
|
||||||
auto subcom = app.add_subcommand("subcom");
|
auto subcom = app.add_subcommand("subcom");
|
||||||
subcom->add_option("--val", two);
|
subcom->add_option("--val", two);
|
||||||
@ -322,12 +314,11 @@ TEST_F(TApp, IniLayered) {
|
|||||||
EXPECT_EQ(1, one);
|
EXPECT_EQ(1, one);
|
||||||
EXPECT_EQ(2, two);
|
EXPECT_EQ(2, two);
|
||||||
EXPECT_EQ(3, three);
|
EXPECT_EQ(3, three);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, IniFailure) {
|
TEST_F(TApp, IniFailure) {
|
||||||
|
|
||||||
TempFile tmpini{"TestIniTmp.ini"};
|
TempFile tmpini{"TestIniTmp.ini"};
|
||||||
|
|
||||||
app.add_config("--config", tmpini);
|
app.add_config("--config", tmpini);
|
||||||
|
|
||||||
@ -340,7 +331,6 @@ TEST_F(TApp, IniFailure) {
|
|||||||
EXPECT_THROW(run(), CLI::ExtrasINIError);
|
EXPECT_THROW(run(), CLI::ExtrasINIError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, IniSubFailure) {
|
TEST_F(TApp, IniSubFailure) {
|
||||||
|
|
||||||
TempFile tmpini{"TestIniTmp.ini"};
|
TempFile tmpini{"TestIniTmp.ini"};
|
||||||
@ -357,7 +347,6 @@ TEST_F(TApp, IniSubFailure) {
|
|||||||
EXPECT_THROW(run(), CLI::ExtrasINIError);
|
EXPECT_THROW(run(), CLI::ExtrasINIError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, IniNoSubFailure) {
|
TEST_F(TApp, IniNoSubFailure) {
|
||||||
|
|
||||||
TempFile tmpini{"TestIniTmp.ini"};
|
TempFile tmpini{"TestIniTmp.ini"};
|
||||||
@ -388,7 +377,6 @@ TEST_F(TApp, IniFlagConvertFailure) {
|
|||||||
EXPECT_THROW(run(), CLI::ConversionError);
|
EXPECT_THROW(run(), CLI::ConversionError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, IniFlagNumbers) {
|
TEST_F(TApp, IniFlagNumbers) {
|
||||||
|
|
||||||
TempFile tmpini{"TestIniTmp.ini"};
|
TempFile tmpini{"TestIniTmp.ini"};
|
||||||
@ -474,7 +462,6 @@ TEST_F(TApp, IniFlags) {
|
|||||||
EXPECT_EQ(true, three);
|
EXPECT_EQ(true, three);
|
||||||
EXPECT_EQ(true, four);
|
EXPECT_EQ(true, four);
|
||||||
EXPECT_EQ(true, five);
|
EXPECT_EQ(true, five);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, IniOutputSimple) {
|
TEST_F(TApp, IniOutputSimple) {
|
||||||
@ -528,7 +515,7 @@ TEST_F(TApp, IniOutputFlag) {
|
|||||||
TEST_F(TApp, IniOutputSet) {
|
TEST_F(TApp, IniOutputSet) {
|
||||||
|
|
||||||
int v;
|
int v;
|
||||||
app.add_set("--simple", v, {1,2,3});
|
app.add_set("--simple", v, {1, 2, 3});
|
||||||
|
|
||||||
args = {"--simple=2"};
|
args = {"--simple=2"};
|
||||||
|
|
||||||
@ -538,10 +525,9 @@ TEST_F(TApp, IniOutputSet) {
|
|||||||
EXPECT_THAT(str, HasSubstr("simple=2"));
|
EXPECT_THAT(str, HasSubstr("simple=2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, IniOutputDefault) {
|
TEST_F(TApp, IniOutputDefault) {
|
||||||
|
|
||||||
int v=7;
|
int v = 7;
|
||||||
app.add_option("--simple", v, "", true);
|
app.add_option("--simple", v, "", true);
|
||||||
|
|
||||||
run();
|
run();
|
||||||
@ -574,7 +560,7 @@ TEST_F(TApp, IniQuotedOutput) {
|
|||||||
|
|
||||||
std::string val2;
|
std::string val2;
|
||||||
app.add_option("--val2", val2);
|
app.add_option("--val2", val2);
|
||||||
|
|
||||||
args = {"--val1", "I am a string", "--val2", R"(I am a "confusing" string)"};
|
args = {"--val1", "I am a string", "--val2", R"(I am a "confusing" string)"};
|
||||||
|
|
||||||
run();
|
run();
|
||||||
@ -585,5 +571,4 @@ TEST_F(TApp, IniQuotedOutput) {
|
|||||||
std::string str = app.config_to_str();
|
std::string str = app.config_to_str();
|
||||||
EXPECT_THAT(str, HasSubstr("val1=\"I am a string\""));
|
EXPECT_THAT(str, HasSubstr("val1=\"I am a string\""));
|
||||||
EXPECT_THAT(str, HasSubstr("val2='I am a \"confusing\" string'"));
|
EXPECT_THAT(str, HasSubstr("val2='I am a \"confusing\" string'"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,21 +6,19 @@ using ::testing::HasSubstr;
|
|||||||
|
|
||||||
using cx = std::complex<double>;
|
using cx = std::complex<double>;
|
||||||
|
|
||||||
CLI::Option* add_option(CLI::App& app,
|
CLI::Option *
|
||||||
std::string name, cx& variable,
|
add_option(CLI::App &app, std::string name, cx &variable, std::string description = "", bool defaulted = false) {
|
||||||
std::string description="", bool defaulted=false) {
|
CLI::callback_t fun = [&variable](CLI::results_t res) {
|
||||||
CLI::callback_t fun = [&variable](CLI::results_t res){
|
if(res.size() != 2)
|
||||||
if(res.size()!=2)
|
|
||||||
return false;
|
return false;
|
||||||
double x,y;
|
double x, y;
|
||||||
bool worked = CLI::detail::lexical_cast(res[0], x)
|
bool worked = CLI::detail::lexical_cast(res[0], x) && CLI::detail::lexical_cast(res[1], y);
|
||||||
&& CLI::detail::lexical_cast(res[1], y);
|
|
||||||
if(worked)
|
if(worked)
|
||||||
variable = cx(x,y);
|
variable = cx(x, y);
|
||||||
return worked;
|
return worked;
|
||||||
};
|
};
|
||||||
|
|
||||||
CLI::Option* opt = app.add_option(name, fun, description, defaulted);
|
CLI::Option *opt = app.add_option(name, fun, description, defaulted);
|
||||||
opt->set_custom_option("COMPLEX", 2);
|
opt->set_custom_option("COMPLEX", 2);
|
||||||
if(defaulted) {
|
if(defaulted) {
|
||||||
std::stringstream out;
|
std::stringstream out;
|
||||||
@ -32,19 +30,18 @@ CLI::Option* add_option(CLI::App& app,
|
|||||||
|
|
||||||
TEST_F(TApp, AddingComplexParser) {
|
TEST_F(TApp, AddingComplexParser) {
|
||||||
|
|
||||||
|
cx comp{0, 0};
|
||||||
cx comp {0, 0};
|
|
||||||
add_option(app, "-c,--complex", comp);
|
add_option(app, "-c,--complex", comp);
|
||||||
args = {"-c", "1.5", "2.5"};
|
args = {"-c", "1.5", "2.5"};
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
EXPECT_EQ(cx(1.5,2.5), comp);
|
EXPECT_EQ(cx(1.5, 2.5), comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, DefaultComplex) {
|
TEST_F(TApp, DefaultComplex) {
|
||||||
|
|
||||||
cx comp {1, 2};
|
cx comp{1, 2};
|
||||||
add_option(app, "-c,--complex", comp, "", true);
|
add_option(app, "-c,--complex", comp, "", true);
|
||||||
args = {"-c", "4", "3"};
|
args = {"-c", "4", "3"};
|
||||||
|
|
||||||
@ -52,15 +49,15 @@ TEST_F(TApp, DefaultComplex) {
|
|||||||
EXPECT_THAT(help, HasSubstr("1"));
|
EXPECT_THAT(help, HasSubstr("1"));
|
||||||
EXPECT_THAT(help, HasSubstr("2"));
|
EXPECT_THAT(help, HasSubstr("2"));
|
||||||
|
|
||||||
EXPECT_EQ(cx(1,2), comp);
|
EXPECT_EQ(cx(1, 2), comp);
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
EXPECT_EQ(cx(4,3), comp);
|
EXPECT_EQ(cx(4, 3), comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, BuiltinComplex) {
|
TEST_F(TApp, BuiltinComplex) {
|
||||||
cx comp {1, 2};
|
cx comp{1, 2};
|
||||||
app.add_complex("-c,--complex", comp, "", true);
|
app.add_complex("-c,--complex", comp, "", true);
|
||||||
|
|
||||||
args = {"-c", "4", "3"};
|
args = {"-c", "4", "3"};
|
||||||
@ -70,28 +67,26 @@ TEST_F(TApp, BuiltinComplex) {
|
|||||||
EXPECT_THAT(help, HasSubstr("2"));
|
EXPECT_THAT(help, HasSubstr("2"));
|
||||||
EXPECT_THAT(help, HasSubstr("COMPLEX"));
|
EXPECT_THAT(help, HasSubstr("COMPLEX"));
|
||||||
|
|
||||||
EXPECT_EQ(cx(1,2), comp);
|
EXPECT_EQ(cx(1, 2), comp);
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
EXPECT_EQ(cx(4,3), comp);
|
EXPECT_EQ(cx(4, 3), comp);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, BuiltinComplexIgnoreI) {
|
TEST_F(TApp, BuiltinComplexIgnoreI) {
|
||||||
cx comp {1, 2};
|
cx comp{1, 2};
|
||||||
app.add_complex("-c,--complex", comp);
|
app.add_complex("-c,--complex", comp);
|
||||||
|
|
||||||
args = {"-c", "4", "3i"};
|
args = {"-c", "4", "3i"};
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
EXPECT_EQ(cx(4,3), comp);
|
EXPECT_EQ(cx(4, 3), comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, BuiltinComplexFail) {
|
TEST_F(TApp, BuiltinComplexFail) {
|
||||||
cx comp {1, 2};
|
cx comp{1, 2};
|
||||||
app.add_complex("-c,--complex", comp);
|
app.add_complex("-c,--complex", comp);
|
||||||
|
|
||||||
args = {"-c", "4"};
|
args = {"-c", "4"};
|
||||||
|
@ -11,20 +11,18 @@ using input_t = std::vector<std::string>;
|
|||||||
TEST(Basic, Empty) {
|
TEST(Basic, Empty) {
|
||||||
|
|
||||||
{
|
{
|
||||||
CLI::App app;
|
CLI::App app;
|
||||||
input_t simpleput;
|
input_t simpleput;
|
||||||
app.parse(simpleput);
|
app.parse(simpleput);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
CLI::App app;
|
CLI::App app;
|
||||||
input_t spare = {"spare"};
|
input_t spare = {"spare"};
|
||||||
EXPECT_THROW(app.parse(spare), CLI::ExtrasError);
|
EXPECT_THROW(app.parse(spare), CLI::ExtrasError);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
CLI::App app;
|
CLI::App app;
|
||||||
input_t simpleput;
|
input_t simpleput;
|
||||||
app.parse(simpleput);
|
app.parse(simpleput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,15 +9,15 @@ TEST_F(TApp, BasicSubcommands) {
|
|||||||
EXPECT_THROW(app.get_subcommand("sub3"), CLI::OptionNotFound);
|
EXPECT_THROW(app.get_subcommand("sub3"), CLI::OptionNotFound);
|
||||||
|
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 0, app.get_subcommands().size());
|
EXPECT_EQ((size_t)0, app.get_subcommands().size());
|
||||||
|
|
||||||
app.reset();
|
app.reset();
|
||||||
args = {"sub1"};
|
args = {"sub1"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ(sub1, app.get_subcommands().at(0));
|
EXPECT_EQ(sub1, app.get_subcommands().at(0));
|
||||||
|
|
||||||
app.reset();
|
app.reset();
|
||||||
EXPECT_EQ((size_t) 0, app.get_subcommands().size());
|
EXPECT_EQ((size_t)0, app.get_subcommands().size());
|
||||||
|
|
||||||
args = {"sub2"};
|
args = {"sub2"};
|
||||||
run();
|
run();
|
||||||
@ -34,7 +34,6 @@ TEST_F(TApp, MultiSubFallthrough) {
|
|||||||
auto sub1 = app.add_subcommand("sub1");
|
auto sub1 = app.add_subcommand("sub1");
|
||||||
auto sub2 = app.add_subcommand("sub2");
|
auto sub2 = app.add_subcommand("sub2");
|
||||||
|
|
||||||
|
|
||||||
args = {"sub1", "sub2"};
|
args = {"sub1", "sub2"};
|
||||||
run();
|
run();
|
||||||
EXPECT_TRUE(app.got_subcommand("sub1"));
|
EXPECT_TRUE(app.got_subcommand("sub1"));
|
||||||
@ -71,27 +70,21 @@ TEST_F(TApp, MultiSubFallthrough) {
|
|||||||
EXPECT_TRUE(*sub1);
|
EXPECT_TRUE(*sub1);
|
||||||
EXPECT_FALSE(*sub2);
|
EXPECT_FALSE(*sub2);
|
||||||
EXPECT_FALSE(sub2->parsed());
|
EXPECT_FALSE(sub2->parsed());
|
||||||
|
|
||||||
EXPECT_THROW(app.got_subcommand("sub3"), CLI::OptionNotFound);
|
EXPECT_THROW(app.got_subcommand("sub3"), CLI::OptionNotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, Callbacks) {
|
TEST_F(TApp, Callbacks) {
|
||||||
auto sub1 = app.add_subcommand("sub1");
|
auto sub1 = app.add_subcommand("sub1");
|
||||||
sub1->set_callback([](){
|
sub1->set_callback([]() { throw CLI::Success(); });
|
||||||
throw CLI::Success();
|
|
||||||
});
|
|
||||||
auto sub2 = app.add_subcommand("sub2");
|
auto sub2 = app.add_subcommand("sub2");
|
||||||
bool val = false;
|
bool val = false;
|
||||||
sub2->set_callback([&val](){
|
sub2->set_callback([&val]() { val = true; });
|
||||||
val = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
args = {"sub2"};
|
args = {"sub2"};
|
||||||
EXPECT_FALSE(val);
|
EXPECT_FALSE(val);
|
||||||
run();
|
run();
|
||||||
EXPECT_TRUE(val);
|
EXPECT_TRUE(val);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, NoFallThroughOpts) {
|
TEST_F(TApp, NoFallThroughOpts) {
|
||||||
@ -99,18 +92,17 @@ TEST_F(TApp, NoFallThroughOpts) {
|
|||||||
app.add_option("--val", val);
|
app.add_option("--val", val);
|
||||||
|
|
||||||
app.add_subcommand("sub");
|
app.add_subcommand("sub");
|
||||||
|
|
||||||
args = {"sub", "--val", "2"};
|
args = {"sub", "--val", "2"};
|
||||||
EXPECT_THROW(run(), CLI::ExtrasError);
|
EXPECT_THROW(run(), CLI::ExtrasError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, NoFallThroughPositionals) {
|
TEST_F(TApp, NoFallThroughPositionals) {
|
||||||
int val = 1;
|
int val = 1;
|
||||||
app.add_option("val", val);
|
app.add_option("val", val);
|
||||||
|
|
||||||
app.add_subcommand("sub");
|
app.add_subcommand("sub");
|
||||||
|
|
||||||
args = {"sub", "2"};
|
args = {"sub", "2"};
|
||||||
EXPECT_THROW(run(), CLI::ExtrasError);
|
EXPECT_THROW(run(), CLI::ExtrasError);
|
||||||
}
|
}
|
||||||
@ -121,33 +113,31 @@ TEST_F(TApp, FallThroughRegular) {
|
|||||||
app.add_option("--val", val);
|
app.add_option("--val", val);
|
||||||
|
|
||||||
app.add_subcommand("sub");
|
app.add_subcommand("sub");
|
||||||
|
|
||||||
args = {"sub", "--val", "2"};
|
args = {"sub", "--val", "2"};
|
||||||
// Should not throw
|
// Should not throw
|
||||||
run();
|
run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, FallThroughShort) {
|
TEST_F(TApp, FallThroughShort) {
|
||||||
app.fallthrough();
|
app.fallthrough();
|
||||||
int val = 1;
|
int val = 1;
|
||||||
app.add_option("-v", val);
|
app.add_option("-v", val);
|
||||||
|
|
||||||
app.add_subcommand("sub");
|
app.add_subcommand("sub");
|
||||||
|
|
||||||
args = {"sub", "-v", "2"};
|
args = {"sub", "-v", "2"};
|
||||||
// Should not throw
|
// Should not throw
|
||||||
run();
|
run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, FallThroughPositional) {
|
TEST_F(TApp, FallThroughPositional) {
|
||||||
app.fallthrough();
|
app.fallthrough();
|
||||||
int val = 1;
|
int val = 1;
|
||||||
app.add_option("val", val);
|
app.add_option("val", val);
|
||||||
|
|
||||||
app.add_subcommand("sub");
|
app.add_subcommand("sub");
|
||||||
|
|
||||||
args = {"sub", "2"};
|
args = {"sub", "2"};
|
||||||
// Should not throw
|
// Should not throw
|
||||||
run();
|
run();
|
||||||
@ -159,13 +149,12 @@ TEST_F(TApp, FallThroughEquals) {
|
|||||||
app.add_option("--val", val);
|
app.add_option("--val", val);
|
||||||
|
|
||||||
app.add_subcommand("sub");
|
app.add_subcommand("sub");
|
||||||
|
|
||||||
args = {"sub", "--val=2"};
|
args = {"sub", "--val=2"};
|
||||||
// Should not throw
|
// Should not throw
|
||||||
run();
|
run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TApp, EvilParseFallthrough) {
|
TEST_F(TApp, EvilParseFallthrough) {
|
||||||
app.fallthrough();
|
app.fallthrough();
|
||||||
int val1 = 0, val2 = 0;
|
int val1 = 0, val2 = 0;
|
||||||
@ -173,7 +162,7 @@ TEST_F(TApp, EvilParseFallthrough) {
|
|||||||
|
|
||||||
auto sub = app.add_subcommand("sub");
|
auto sub = app.add_subcommand("sub");
|
||||||
sub->add_option("val2", val2);
|
sub->add_option("val2", val2);
|
||||||
|
|
||||||
args = {"sub", "--val1", "1", "2"};
|
args = {"sub", "--val1", "1", "2"};
|
||||||
// Should not throw
|
// Should not throw
|
||||||
run();
|
run();
|
||||||
@ -188,10 +177,8 @@ TEST_F(TApp, CallbackOrdering) {
|
|||||||
app.add_option("--val", val);
|
app.add_option("--val", val);
|
||||||
|
|
||||||
auto sub = app.add_subcommand("sub");
|
auto sub = app.add_subcommand("sub");
|
||||||
sub->set_callback([&val, &sub_val](){
|
sub->set_callback([&val, &sub_val]() { sub_val = val; });
|
||||||
sub_val = val;
|
|
||||||
});
|
|
||||||
|
|
||||||
args = {"sub", "--val=2"};
|
args = {"sub", "--val=2"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ(2, val);
|
EXPECT_EQ(2, val);
|
||||||
@ -202,7 +189,6 @@ TEST_F(TApp, CallbackOrdering) {
|
|||||||
run();
|
run();
|
||||||
EXPECT_EQ(2, val);
|
EXPECT_EQ(2, val);
|
||||||
EXPECT_EQ(2, sub_val);
|
EXPECT_EQ(2, sub_val);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, RequiredSubCom) {
|
TEST_F(TApp, RequiredSubCom) {
|
||||||
@ -218,7 +204,6 @@ TEST_F(TApp, RequiredSubCom) {
|
|||||||
args = {"sub1"};
|
args = {"sub1"};
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TApp, Required1SubCom) {
|
TEST_F(TApp, Required1SubCom) {
|
||||||
@ -248,8 +233,8 @@ TEST_F(TApp, BadSubcomSearch) {
|
|||||||
|
|
||||||
struct SubcommandProgram : public TApp {
|
struct SubcommandProgram : public TApp {
|
||||||
|
|
||||||
CLI::App* start;
|
CLI::App *start;
|
||||||
CLI::App* stop;
|
CLI::App *stop;
|
||||||
|
|
||||||
int dummy;
|
int dummy;
|
||||||
std::string file;
|
std::string file;
|
||||||
@ -258,7 +243,7 @@ struct SubcommandProgram : public TApp {
|
|||||||
SubcommandProgram() {
|
SubcommandProgram() {
|
||||||
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");
|
||||||
@ -275,7 +260,6 @@ TEST_F(SubcommandProgram, Working) {
|
|||||||
EXPECT_EQ("filename", file);
|
EXPECT_EQ("filename", file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(SubcommandProgram, Spare) {
|
TEST_F(SubcommandProgram, Spare) {
|
||||||
args = {"extra", "-d", "start", "-ffilename"};
|
args = {"extra", "-d", "start", "-ffilename"};
|
||||||
|
|
||||||
@ -292,7 +276,7 @@ TEST_F(SubcommandProgram, Multiple) {
|
|||||||
args = {"-d", "start", "-ffilename", "stop"};
|
args = {"-d", "start", "-ffilename", "stop"};
|
||||||
|
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 2, app.get_subcommands().size());
|
EXPECT_EQ((size_t)2, app.get_subcommands().size());
|
||||||
EXPECT_EQ(1, dummy);
|
EXPECT_EQ(1, dummy);
|
||||||
EXPECT_EQ("filename", file);
|
EXPECT_EQ("filename", file);
|
||||||
}
|
}
|
||||||
@ -308,20 +292,17 @@ TEST_F(SubcommandProgram, MultipleArgs) {
|
|||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
EXPECT_EQ((size_t) 2, app.get_subcommands().size());
|
EXPECT_EQ((size_t)2, app.get_subcommands().size());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SubcommandProgram, CaseCheck) {
|
TEST_F(SubcommandProgram, CaseCheck) {
|
||||||
args = {"Start"};
|
args = {"Start"};
|
||||||
EXPECT_THROW(run(), CLI::ExtrasError);
|
EXPECT_THROW(run(), CLI::ExtrasError);
|
||||||
|
|
||||||
|
|
||||||
app.reset();
|
app.reset();
|
||||||
args = {"start"};
|
args = {"start"};
|
||||||
run();
|
run();
|
||||||
|
|
||||||
|
|
||||||
app.reset();
|
app.reset();
|
||||||
start->ignore_case();
|
start->ignore_case();
|
||||||
run();
|
run();
|
||||||
@ -337,15 +318,15 @@ TEST_F(TApp, SubcomInheritCaseCheck) {
|
|||||||
auto sub2 = app.add_subcommand("sub2");
|
auto sub2 = app.add_subcommand("sub2");
|
||||||
|
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ((size_t) 0, app.get_subcommands().size());
|
EXPECT_EQ((size_t)0, app.get_subcommands().size());
|
||||||
|
|
||||||
app.reset();
|
app.reset();
|
||||||
args = {"SuB1"};
|
args = {"SuB1"};
|
||||||
run();
|
run();
|
||||||
EXPECT_EQ(sub1, app.get_subcommands().at(0));
|
EXPECT_EQ(sub1, app.get_subcommands().at(0));
|
||||||
|
|
||||||
app.reset();
|
app.reset();
|
||||||
EXPECT_EQ((size_t) 0, app.get_subcommands().size());
|
EXPECT_EQ((size_t)0, app.get_subcommands().size());
|
||||||
|
|
||||||
args = {"sUb2"};
|
args = {"sUb2"};
|
||||||
run();
|
run();
|
||||||
@ -366,9 +347,7 @@ TEST_F(SubcommandProgram, HelpOrder) {
|
|||||||
|
|
||||||
TEST_F(SubcommandProgram, Callbacks) {
|
TEST_F(SubcommandProgram, Callbacks) {
|
||||||
|
|
||||||
start->set_callback([](){
|
start->set_callback([]() { throw CLI::Success(); });
|
||||||
throw CLI::Success();
|
|
||||||
});
|
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
@ -377,5 +356,4 @@ TEST_F(SubcommandProgram, Callbacks) {
|
|||||||
args = {"start"};
|
args = {"start"};
|
||||||
|
|
||||||
EXPECT_THROW(run(), CLI::Success);
|
EXPECT_THROW(run(), CLI::Success);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ TEST(Timer, STimes) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Fails on Windows
|
// Fails on Windows
|
||||||
//TEST(Timer, UStimes) {
|
// TEST(Timer, UStimes) {
|
||||||
// CLI::Timer timer;
|
// CLI::Timer timer;
|
||||||
// std::this_thread::sleep_for(std::chrono::microseconds(2));
|
// std::this_thread::sleep_for(std::chrono::microseconds(2));
|
||||||
// std::string output = timer.to_string();
|
// std::string output = timer.to_string();
|
||||||
@ -58,8 +58,7 @@ TEST(Timer, PrintTimer) {
|
|||||||
|
|
||||||
TEST(Timer, TimeItTimer) {
|
TEST(Timer, TimeItTimer) {
|
||||||
CLI::Timer timer;
|
CLI::Timer timer;
|
||||||
std::string output = timer.time_it([](){
|
std::string output = timer.time_it([]() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }, .1);
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));}, .1);
|
|
||||||
std::cout << output << std::endl;
|
std::cout << output << std::endl;
|
||||||
EXPECT_THAT(output, HasSubstr("ms"));
|
EXPECT_THAT(output, HasSubstr("ms"));
|
||||||
}
|
}
|
||||||
|
@ -20,27 +20,23 @@ struct TApp : public ::testing::Test {
|
|||||||
std::reverse(std::begin(newargs), std::end(newargs));
|
std::reverse(std::begin(newargs), std::end(newargs));
|
||||||
return app.parse(newargs);
|
return app.parse(newargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TempFile {
|
class TempFile {
|
||||||
std::string _name;
|
std::string _name;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TempFile(std::string name) : _name(name) {
|
TempFile(std::string name) : _name(name) {
|
||||||
if(!CLI::NonexistentPath(_name))
|
if(!CLI::NonexistentPath(_name))
|
||||||
throw std::runtime_error(_name);
|
throw std::runtime_error(_name);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~TempFile() {
|
~TempFile() {
|
||||||
std::remove(_name.c_str()); // Doesn't matter if returns 0 or not
|
std::remove(_name.c_str()); // Doesn't matter if returns 0 or not
|
||||||
}
|
}
|
||||||
|
|
||||||
operator const std::string& () const {return _name;}
|
operator const std::string &() const { return _name; }
|
||||||
const char* c_str() const {return _name.c_str();}
|
const char *c_str() const { return _name.c_str(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void put_env(std::string name, std::string value) {
|
inline void put_env(std::string name, std::string value) {
|
||||||
@ -58,4 +54,3 @@ inline void unset_env(std::string name) {
|
|||||||
unsetenv(name.c_str());
|
unsetenv(name.c_str());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
#include "CLI/CLI.hpp"
|
#include "CLI/CLI.hpp"
|
||||||
#include "CLI/Timer.hpp"
|
#include "CLI/Timer.hpp"
|
||||||
|
|
||||||
int do_nothing() {
|
int do_nothing() { return 7; }
|
||||||
return 7;
|
|
||||||
}
|
|
||||||
|
@ -9,4 +9,3 @@ TEST(Link, DoNothing) {
|
|||||||
int a = do_nothing();
|
int a = do_nothing();
|
||||||
EXPECT_EQ(7, a);
|
EXPECT_EQ(7, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user