mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-04-29 20:23:55 +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,6 +1,5 @@
|
||||
#include "CLI/CLI.hpp"
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
CLI::App app("K3Pi goofit fitter");
|
||||
@ -20,14 +19,10 @@ int main (int argc, char** argv) {
|
||||
return app.exit(e);
|
||||
}
|
||||
|
||||
std::cout << "Working on file: " << file
|
||||
<< ", direct count: " << app.count("--file")
|
||||
<< ", opt count: " << opt->count()
|
||||
<< std::endl;
|
||||
std::cout << "Working on count: " << count
|
||||
<< ", direct count: " << app.count("--count")
|
||||
<< ", opt count: " << copt->count()
|
||||
<< std::endl;
|
||||
std::cout << "Working on file: " << file << ", direct count: " << app.count("--file")
|
||||
<< ", opt count: " << opt->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;
|
||||
|
||||
return 0;
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "CLI/CLI.hpp"
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
CLI::App app("K3Pi goofit fitter");
|
||||
|
@ -1,23 +1,19 @@
|
||||
#include "CLI/CLI.hpp"
|
||||
#include "CLI/Timer.hpp"
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CLI::AutoTimer("This is a timer");
|
||||
|
||||
CLI::App app("K3Pi goofit fitter");
|
||||
|
||||
std::string file;
|
||||
CLI::Option* opt = app.add_option("-f,--file,file", file, "File name")
|
||||
->required()->group("Important");
|
||||
CLI::Option *opt = app.add_option("-f,--file,file", file, "File name")->required()->group("Important");
|
||||
|
||||
int count;
|
||||
CLI::Option* copt = app.add_flag("-c,--count", count, "Counter")
|
||||
->required()->group("Important");
|
||||
CLI::Option *copt = app.add_flag("-c,--count", count, "Counter")->required()->group("Important");
|
||||
|
||||
double value; // = 3.14;
|
||||
app.add_option("-d,--double", value, "Some Value")
|
||||
->group("Other");
|
||||
app.add_option("-d,--double", value, "Some Value")->group("Other");
|
||||
|
||||
try {
|
||||
app.parse(argc, argv);
|
||||
@ -25,14 +21,10 @@ int main (int argc, char** argv) {
|
||||
return app.exit(e);
|
||||
}
|
||||
|
||||
std::cout << "Working on file: " << file
|
||||
<< ", direct count: " << app.count("--file")
|
||||
<< ", opt count: " << opt->count()
|
||||
<< std::endl;
|
||||
std::cout << "Working on count: " << count
|
||||
<< ", direct count: " << app.count("--count")
|
||||
<< ", opt count: " << copt->count()
|
||||
<< std::endl;
|
||||
std::cout << "Working on file: " << file << ", direct count: " << app.count("--file")
|
||||
<< ", opt count: " << opt->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;
|
||||
|
||||
return 0;
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
||||
// CLI Library includes
|
||||
#include "CLI/Error.hpp"
|
||||
#include "CLI/Ini.hpp"
|
||||
@ -33,7 +32,6 @@ struct AppFriend;
|
||||
|
||||
class App;
|
||||
|
||||
|
||||
using App_p = std::unique_ptr<App>;
|
||||
|
||||
/// Creates a command line program, with very few defaults.
|
||||
@ -43,8 +41,8 @@ using App_p = std::unique_ptr<App>;
|
||||
class App {
|
||||
friend Option;
|
||||
friend detail::AppFriend;
|
||||
protected:
|
||||
|
||||
protected:
|
||||
// This library follows the Google style guide for member names ending in underscores
|
||||
|
||||
/// @name Basics
|
||||
@ -118,16 +116,13 @@ protected:
|
||||
/// Pointer to the config option
|
||||
Option *config_ptr_{nullptr};
|
||||
|
||||
|
||||
///@}
|
||||
|
||||
/// Special private constructor for subcommand
|
||||
App(std::string description_, bool help, detail::enabler)
|
||||
: description_(std::move(description_)) {
|
||||
App(std::string description_, bool help, detail::enabler) : description_(std::move(description_)) {
|
||||
|
||||
if(help)
|
||||
help_ptr_ = add_flag("-h,--help", "Print this help message and exit");
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
@ -135,10 +130,7 @@ public:
|
||||
///@{
|
||||
|
||||
/// Create a new program. Pass in the same arguments as main(), along with a help string.
|
||||
App(std::string description_="", bool help=true)
|
||||
: App(description_, help, detail::dummy) {
|
||||
|
||||
}
|
||||
App(std::string description_ = "", bool help = true) : App(description_, help, detail::dummy) {}
|
||||
|
||||
/// Set a callback for the end of parsing.
|
||||
///
|
||||
@ -190,7 +182,6 @@ public:
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
///@}
|
||||
/// @name Adding options
|
||||
///@{
|
||||
@ -209,34 +200,26 @@ public:
|
||||
/// std::string filename;
|
||||
/// program.add_option("filename", filename, "description of filename");
|
||||
///
|
||||
Option* add_option(
|
||||
std::string name,
|
||||
callback_t callback,
|
||||
std::string description="",
|
||||
bool defaulted=false
|
||||
) {
|
||||
Option *add_option(std::string name, callback_t callback, std::string description = "", bool defaulted = false) {
|
||||
Option myopt{name, description, callback, defaulted, this};
|
||||
|
||||
if(std::find_if(std::begin(options_), std::end(options_),
|
||||
[&myopt](const Option_p &v){return *v == myopt;}) == std::end(options_)) {
|
||||
if(std::find_if(std::begin(options_), std::end(options_), [&myopt](const Option_p &v) {
|
||||
return *v == myopt;
|
||||
}) == std::end(options_)) {
|
||||
options_.emplace_back();
|
||||
Option_p &option = options_.back();
|
||||
option.reset(new Option(name, description, callback, defaulted, this));
|
||||
return option.get();
|
||||
} else
|
||||
throw OptionAlreadyAdded(myopt.get_name());
|
||||
|
||||
}
|
||||
|
||||
/// Add option for non-vectors
|
||||
template <typename T, enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy>
|
||||
Option* add_option(
|
||||
std::string name,
|
||||
Option *add_option(std::string name,
|
||||
T &variable, ///< The variable to set
|
||||
std::string description = "",
|
||||
bool defaulted=false
|
||||
) {
|
||||
|
||||
bool defaulted = false) {
|
||||
|
||||
CLI::callback_t fun = [&variable](CLI::results_t res) {
|
||||
if(res.size() != 1)
|
||||
@ -256,12 +239,10 @@ public:
|
||||
|
||||
/// Add option for vectors
|
||||
template <typename T>
|
||||
Option* add_option(
|
||||
std::string name,
|
||||
Option *add_option(std::string name,
|
||||
std::vector<T> &variable, ///< The variable vector to set
|
||||
std::string description = "",
|
||||
bool defaulted=false
|
||||
) {
|
||||
bool defaulted = false) {
|
||||
|
||||
CLI::callback_t fun = [&variable](CLI::results_t res) {
|
||||
bool retval = true;
|
||||
@ -281,13 +262,8 @@ public:
|
||||
}
|
||||
|
||||
/// Add option for flag
|
||||
Option* add_flag(
|
||||
std::string name,
|
||||
std::string description=""
|
||||
) {
|
||||
CLI::callback_t fun = [](CLI::results_t){
|
||||
return true;
|
||||
};
|
||||
Option *add_flag(std::string name, std::string description = "") {
|
||||
CLI::callback_t fun = [](CLI::results_t) { return true; };
|
||||
|
||||
Option *opt = add_option(name, fun, description, false);
|
||||
if(opt->get_positional())
|
||||
@ -299,11 +275,9 @@ public:
|
||||
/// Add option for flag integer
|
||||
template <typename T,
|
||||
enable_if_t<std::is_integral<T>::value && !is_bool<T>::value, detail::enabler> = detail::dummy>
|
||||
Option* add_flag(
|
||||
std::string name,
|
||||
Option *add_flag(std::string name,
|
||||
T &count, ///< A varaible holding the count
|
||||
std::string description=""
|
||||
) {
|
||||
std::string description = "") {
|
||||
|
||||
count = 0;
|
||||
CLI::callback_t fun = [&count](CLI::results_t res) {
|
||||
@ -319,13 +293,10 @@ public:
|
||||
}
|
||||
|
||||
/// Bool version only allows the flag once
|
||||
template<typename T,
|
||||
enable_if_t<is_bool<T>::value, detail::enabler> = detail::dummy>
|
||||
Option* add_flag(
|
||||
std::string name,
|
||||
template <typename T, enable_if_t<is_bool<T>::value, detail::enabler> = detail::dummy>
|
||||
Option *add_flag(std::string name,
|
||||
T &count, ///< A varaible holding true if passed
|
||||
std::string description=""
|
||||
) {
|
||||
std::string description = "") {
|
||||
|
||||
count = false;
|
||||
CLI::callback_t fun = [&count](CLI::results_t res) {
|
||||
@ -340,16 +311,13 @@ public:
|
||||
return opt;
|
||||
}
|
||||
|
||||
|
||||
/// Add set of options
|
||||
template <typename T>
|
||||
Option* add_set(
|
||||
std::string name,
|
||||
Option *add_set(std::string name,
|
||||
T &member, ///< The selected member of the set
|
||||
std::set<T> options, ///< The set of posibilities
|
||||
std::string description = "",
|
||||
bool defaulted=false
|
||||
) {
|
||||
bool defaulted = false) {
|
||||
|
||||
CLI::callback_t fun = [&member, options](CLI::results_t res) {
|
||||
if(res.size() != 1) {
|
||||
@ -374,21 +342,20 @@ public:
|
||||
}
|
||||
|
||||
/// Add set of options, string only, ignore case
|
||||
Option* add_set_ignore_case(
|
||||
std::string name,
|
||||
Option *add_set_ignore_case(std::string name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
std::set<std::string> options, ///< The set of posibilities
|
||||
std::string description = "",
|
||||
bool defaulted=false
|
||||
) {
|
||||
bool defaulted = false) {
|
||||
|
||||
CLI::callback_t fun = [&member, options](CLI::results_t res) {
|
||||
if(res.size() != 1) {
|
||||
return false;
|
||||
}
|
||||
member = detail::to_lower(res[0]);
|
||||
auto iter = std::find_if(std::begin(options), std::end(options),
|
||||
[&member](std::string val){return detail::to_lower(val) == member;});
|
||||
auto iter = std::find_if(std::begin(options), std::end(options), [&member](std::string val) {
|
||||
return detail::to_lower(val) == member;
|
||||
});
|
||||
if(iter == std::end(options))
|
||||
return false;
|
||||
else {
|
||||
@ -409,16 +376,16 @@ public:
|
||||
|
||||
/// Add a complex number
|
||||
template <typename T>
|
||||
Option* add_complex(
|
||||
std::string name, T& variable,
|
||||
std::string description="", bool defaulted=false,
|
||||
Option *add_complex(std::string name,
|
||||
T &variable,
|
||||
std::string description = "",
|
||||
bool defaulted = false,
|
||||
std::string label = "COMPLEX") {
|
||||
CLI::callback_t fun = [&variable](results_t res) {
|
||||
if(res.size() != 2)
|
||||
return false;
|
||||
double x, y;
|
||||
bool worked = detail::lexical_cast(res[0], x)
|
||||
&& detail::lexical_cast(res[1], y);
|
||||
bool worked = detail::lexical_cast(res[0], x) && detail::lexical_cast(res[1], y);
|
||||
if(worked)
|
||||
variable = T(x, y);
|
||||
return worked;
|
||||
@ -434,7 +401,6 @@ public:
|
||||
return opt;
|
||||
}
|
||||
|
||||
|
||||
/// Add a configuration ini file option
|
||||
Option *add_config(std::string name = "--config",
|
||||
std::string default_filename = "",
|
||||
@ -452,8 +418,8 @@ public:
|
||||
|
||||
/// Removes an option from the App. Takes an option pointer. Returns true if found and removed.
|
||||
bool remove_option(Option *opt) {
|
||||
auto iterator = std::find_if(std::begin(options_), std::end(options_),
|
||||
[opt](const Option_p &v){return v.get() == opt;});
|
||||
auto iterator =
|
||||
std::find_if(std::begin(options_), std::end(options_), [opt](const Option_p &v) { return v.get() == opt; });
|
||||
if(iterator != std::end(options_)) {
|
||||
options_.erase(iterator);
|
||||
return true;
|
||||
@ -517,7 +483,6 @@ public:
|
||||
for(int i = argc - 1; i > 0; i--)
|
||||
args.emplace_back(argv[i]);
|
||||
return parse(args);
|
||||
|
||||
}
|
||||
|
||||
/// The real work is done here. Expects a reversed vector.
|
||||
@ -580,7 +545,6 @@ public:
|
||||
return subcomms;
|
||||
}
|
||||
|
||||
|
||||
/// Check to see if given subcommand was selected
|
||||
bool got_subcommand(App *subcom) const {
|
||||
// get subcom needed to verify that this was a real subcommand
|
||||
@ -588,15 +552,14 @@ public:
|
||||
}
|
||||
|
||||
/// Check with name instead of pointer to see if subcommand was selected
|
||||
bool got_subcommand(std::string name) const {
|
||||
return get_subcommand(name)->parsed_;
|
||||
}
|
||||
bool got_subcommand(std::string name) const { return get_subcommand(name)->parsed_; }
|
||||
|
||||
///@}
|
||||
/// @name Help
|
||||
///@{
|
||||
|
||||
/// Produce a string that could be read in as a config of the current values of the App. Set default_also to include default arguments. Prefix will add a string to the beginning of each option.
|
||||
/// Produce a string that could be read in as a config of the current values of the App. Set default_also to include
|
||||
/// default arguments. Prefix will add a string to the beginning of each option.
|
||||
std::string config_to_str(bool default_also = false, std::string prefix = "") const {
|
||||
std::stringstream out;
|
||||
for(const Option_p &opt : options_) {
|
||||
@ -627,7 +590,6 @@ public:
|
||||
} else if(opt->count() == 0 && default_also && opt.get() != get_help_ptr()) {
|
||||
out << name << "=false" << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
for(const App_p &subcom : subcommands_)
|
||||
@ -695,10 +657,8 @@ public:
|
||||
detail::format_help(out, opt->help_pname(), opt->get_description(), wid);
|
||||
}
|
||||
out << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Options
|
||||
if(npos) {
|
||||
for(const std::string &group : groups) {
|
||||
@ -708,7 +668,6 @@ public:
|
||||
for(const Option_p &opt : options_) {
|
||||
if(opt->nonpositional() && opt->get_group() == group)
|
||||
detail::format_help(out, opt->help_name(), opt->get_description(), wid);
|
||||
|
||||
}
|
||||
out << std::endl;
|
||||
}
|
||||
@ -728,28 +687,18 @@ public:
|
||||
///@{
|
||||
|
||||
/// Get a pointer to the help flag.
|
||||
Option* get_help_ptr() {
|
||||
return help_ptr_;
|
||||
}
|
||||
Option *get_help_ptr() { return help_ptr_; }
|
||||
|
||||
/// Get a pointer to the help flag. (const)
|
||||
const Option* get_help_ptr() const {
|
||||
return help_ptr_;
|
||||
}
|
||||
const Option *get_help_ptr() const { return help_ptr_; }
|
||||
|
||||
/// Get a pointer to the config option.
|
||||
Option* get_config_ptr() {
|
||||
return config_ptr_;
|
||||
}
|
||||
Option *get_config_ptr() { return config_ptr_; }
|
||||
|
||||
/// Get a pointer to the config option. (const)
|
||||
const Option* get_config_ptr() const {
|
||||
return config_ptr_;
|
||||
}
|
||||
const Option *get_config_ptr() const { return config_ptr_; }
|
||||
/// Get the name of the current app
|
||||
std::string get_name() const {
|
||||
return name_;
|
||||
}
|
||||
std::string get_name() const { return name_; }
|
||||
|
||||
/// Check the name, case insensitive if set
|
||||
bool check_name(std::string name_to_check) const {
|
||||
@ -764,22 +713,20 @@ public:
|
||||
|
||||
///@}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/// Check the options to make sure there are no conficts.
|
||||
///
|
||||
/// Currenly checks to see if mutiple positionals exist with -1 args
|
||||
void _validate() const {
|
||||
auto count = std::count_if(std::begin(options_), std::end(options_),
|
||||
[](const Option_p& opt){return opt->get_expected() == -1 && opt->get_positional();});
|
||||
auto count = std::count_if(std::begin(options_), std::end(options_), [](const Option_p &opt) {
|
||||
return opt->get_expected() == -1 && opt->get_positional();
|
||||
});
|
||||
if(count > 1)
|
||||
throw InvalidError(name_ + ": Too many positional arguments with unlimited expected args");
|
||||
for(const App_p &app : subcommands_)
|
||||
app->_validate();
|
||||
}
|
||||
|
||||
|
||||
/// Return missing from the master
|
||||
missing_t *missing() {
|
||||
if(parent_ != nullptr)
|
||||
@ -807,7 +754,6 @@ protected:
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// Selects a Classifer enum based on the type of the current argument
|
||||
detail::Classifer _recognize(const std::string ¤t) const {
|
||||
std::string dummy1, dummy2;
|
||||
@ -823,7 +769,6 @@ protected:
|
||||
return detail::Classifer::NONE;
|
||||
}
|
||||
|
||||
|
||||
/// Internal parse function
|
||||
void _parse(std::vector<std::string> &args) {
|
||||
parsed_ = true;
|
||||
@ -837,7 +782,6 @@ protected:
|
||||
throw CallForHelp();
|
||||
}
|
||||
|
||||
|
||||
// Process an INI file
|
||||
if(config_ptr_ != nullptr && config_name_ != "") {
|
||||
try {
|
||||
@ -853,7 +797,6 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Get envname options if not yet passed
|
||||
for(const Option_p &opt : options_) {
|
||||
if(opt->count() == 0 && opt->envname_ != "") {
|
||||
@ -874,8 +817,7 @@ protected:
|
||||
// Verify required options
|
||||
for(const Option_p &opt : options_) {
|
||||
// Required
|
||||
if (opt->get_required()
|
||||
&& (static_cast<int>( opt->count()) < opt->get_expected() || opt->count() == 0))
|
||||
if(opt->get_required() && (static_cast<int>(opt->count()) < opt->get_expected() || opt->count() == 0))
|
||||
throw RequiredError(opt->get_name());
|
||||
// Requires
|
||||
for(const Option *opt_req : opt->requires_)
|
||||
@ -896,12 +838,16 @@ protected:
|
||||
// Convert missing (pairs) to extras (string only)
|
||||
if(parent_ == nullptr) {
|
||||
args.resize(missing()->size());
|
||||
std::transform(std::begin(*missing()), std::end(*missing()), std::begin(args),
|
||||
std::transform(std::begin(*missing()),
|
||||
std::end(*missing()),
|
||||
std::begin(args),
|
||||
[](const std::pair<detail::Classifer, std::string> &val) { return val.second; });
|
||||
std::reverse(std::begin(args), std::end(args));
|
||||
|
||||
size_t num_left_over = std::count_if(std::begin(*missing()), std::end(*missing()),
|
||||
[](std::pair<detail::Classifer, std::string>& val){return val.first != detail::Classifer::POSITIONAL_MARK;});
|
||||
size_t num_left_over = std::count_if(
|
||||
std::begin(*missing()), std::end(*missing()), [](std::pair<detail::Classifer, std::string> &val) {
|
||||
return val.first != detail::Classifer::POSITIONAL_MARK;
|
||||
});
|
||||
|
||||
if(num_left_over > 0 && !allow_extras_)
|
||||
throw ExtrasError("[" + detail::rjoin(args, " ") + "]");
|
||||
@ -926,8 +872,8 @@ protected:
|
||||
return false;
|
||||
}
|
||||
|
||||
auto op_ptr = std::find_if(std::begin(options_), std::end(options_),
|
||||
[name](const Option_p &v){return v->check_lname(name);});
|
||||
auto op_ptr = std::find_if(
|
||||
std::begin(options_), std::end(options_), [name](const Option_p &v) { return v->check_lname(name); });
|
||||
|
||||
if(op_ptr == std::end(options_))
|
||||
return false;
|
||||
@ -935,7 +881,6 @@ protected:
|
||||
// Let's not go crazy with pointer syntax
|
||||
Option_p &op = *op_ptr;
|
||||
|
||||
|
||||
if(op->results_.empty()) {
|
||||
// Flag parsing
|
||||
if(op->get_expected() == 0) {
|
||||
@ -966,7 +911,8 @@ protected:
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Parse "one" argument (some may eat more than one), delegate to parent if fails, add to missing if missing from master
|
||||
/// Parse "one" argument (some may eat more than one), delegate to parent if fails, add to missing if missing from
|
||||
/// master
|
||||
void _parse_single(std::vector<std::string> &args, bool &positional_only) {
|
||||
|
||||
detail::Classifer classifer = positional_only ? detail::Classifer::NONE : _recognize(args.back());
|
||||
@ -991,8 +937,6 @@ protected:
|
||||
// Probably a positional or something for a parent (sub)command
|
||||
_parse_positional(args);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// Parse a positional, go up the tree to check
|
||||
@ -1001,10 +945,8 @@ protected:
|
||||
std::string positional = args.back();
|
||||
for(const Option_p &opt : options_) {
|
||||
// Eat options, one by one, until done
|
||||
if ( opt->get_positional()
|
||||
&& (static_cast<int>( opt->count()) < opt->get_expected()
|
||||
|| opt->get_expected() < 0)
|
||||
) {
|
||||
if(opt->get_positional() &&
|
||||
(static_cast<int>(opt->count()) < opt->get_expected() || opt->get_expected() < 0)) {
|
||||
|
||||
opt->add_result(positional);
|
||||
args.pop_back();
|
||||
@ -1046,8 +988,8 @@ protected:
|
||||
if(!detail::split_short(current, name, rest))
|
||||
throw HorribleError("Short");
|
||||
|
||||
auto op_ptr = std::find_if(std::begin(options_), std::end(options_), [name](const Option_p &opt){return opt->check_sname(name);});
|
||||
|
||||
auto op_ptr = std::find_if(
|
||||
std::begin(options_), std::end(options_), [name](const Option_p &opt) { return opt->check_sname(name); });
|
||||
|
||||
// Option not found
|
||||
if(op_ptr == std::end(options_)) {
|
||||
@ -1064,7 +1006,6 @@ protected:
|
||||
|
||||
args.pop_back();
|
||||
|
||||
|
||||
// Get a reference to the pointer to make syntax bearable
|
||||
Option_p &op = *op_ptr;
|
||||
|
||||
@ -1079,13 +1020,13 @@ protected:
|
||||
rest = "";
|
||||
}
|
||||
|
||||
|
||||
if(num == -1) {
|
||||
while(!args.empty() && _recognize(args.back()) == detail::Classifer::NONE) {
|
||||
op->add_result(args.back());
|
||||
args.pop_back();
|
||||
}
|
||||
} else while(num>0 && !args.empty()) {
|
||||
} else
|
||||
while(num > 0 && !args.empty()) {
|
||||
num--;
|
||||
std::string current_ = args.back();
|
||||
args.pop_back();
|
||||
@ -1107,7 +1048,8 @@ protected:
|
||||
if(!detail::split_long(current, name, value))
|
||||
throw HorribleError("Long:" + args.back());
|
||||
|
||||
auto op_ptr = std::find_if(std::begin(options_), std::end(options_), [name](const Option_p &v){return v->check_lname(name);});
|
||||
auto op_ptr = std::find_if(
|
||||
std::begin(options_), std::end(options_), [name](const Option_p &v) { return v->check_lname(name); });
|
||||
|
||||
// Option not found
|
||||
if(op_ptr == std::end(options_)) {
|
||||
@ -1130,7 +1072,8 @@ protected:
|
||||
int num = op->get_expected();
|
||||
|
||||
if(value != "") {
|
||||
if(num!=-1) num--;
|
||||
if(num != -1)
|
||||
num--;
|
||||
op->add_result(value);
|
||||
} else if(num == 0) {
|
||||
op->add_result("");
|
||||
@ -1141,14 +1084,14 @@ protected:
|
||||
op->add_result(args.back());
|
||||
args.pop_back();
|
||||
}
|
||||
} else while(num>0 && !args.empty()) {
|
||||
} else
|
||||
while(num > 0 && !args.empty()) {
|
||||
num--;
|
||||
op->add_result(args.back());
|
||||
args.pop_back();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
@ -1157,28 +1100,25 @@ struct AppFriend {
|
||||
|
||||
/// Wrap _parse_short, perfectly forward arguments and return
|
||||
template <typename... Args>
|
||||
static auto parse_short(App* app, Args && ...args)
|
||||
-> typename std::result_of<decltype(&App::_parse_short)(App, Args...)>::type {
|
||||
static auto parse_short(App *app, Args &&... args) ->
|
||||
typename std::result_of<decltype (&App::_parse_short)(App, Args...)>::type {
|
||||
return app->_parse_short(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
/// Wrap _parse_long, perfectly forward arguments and return
|
||||
template <typename... Args>
|
||||
static auto parse_long(App* app, Args && ...args)
|
||||
-> typename std::result_of<decltype(&App::_parse_long)(App, Args...)>::type {
|
||||
static auto parse_long(App *app, Args &&... args) ->
|
||||
typename std::result_of<decltype (&App::_parse_long)(App, Args...)>::type {
|
||||
return app->_parse_long(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/// Wrap _parse_subcommand, perfectly forward arguments and return
|
||||
template <typename... Args>
|
||||
static auto parse_subcommand(App* app, Args && ...args)
|
||||
-> typename std::result_of<decltype(&App::_parse_subcommand)(App, Args...)>::type {
|
||||
static auto parse_subcommand(App *app, Args &&... args) ->
|
||||
typename std::result_of<decltype (&App::_parse_subcommand)(App, Args...)>::type {
|
||||
return app->_parse_subcommand(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
} // namespace CLI
|
||||
|
||||
|
@ -12,4 +12,3 @@
|
||||
#include "CLI/StringTools.hpp"
|
||||
#include "CLI/TypeTools.hpp"
|
||||
#include "CLI/Validators.hpp"
|
||||
|
||||
|
@ -9,7 +9,8 @@
|
||||
|
||||
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 {
|
||||
Success = 0,
|
||||
IncorrectConstruction = 100,
|
||||
@ -44,14 +45,20 @@ struct Error : public std::runtime_error {
|
||||
int get_exit_code() const { return exit_code; }
|
||||
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) {}
|
||||
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) {}
|
||||
};
|
||||
|
||||
/// Construction errors (not in parsing)
|
||||
struct ConstructionError : public Error {
|
||||
// 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) {}
|
||||
};
|
||||
|
||||
@ -63,8 +70,7 @@ struct IncorrectConstruction : public ConstructionError {
|
||||
|
||||
/// Thrown on construction of a bad name
|
||||
struct BadNameString : public ConstructionError {
|
||||
BadNameString(std::string name)
|
||||
: ConstructionError("BadNameString", name, ExitCodes::BadNameString) {}
|
||||
BadNameString(std::string name) : ConstructionError("BadNameString", name, ExitCodes::BadNameString) {}
|
||||
};
|
||||
|
||||
/// Thrown when an option already exists
|
||||
@ -85,8 +91,7 @@ struct ParseError : public Error {
|
||||
|
||||
/// This is a successful completion on parsing, supposed to exit
|
||||
struct Success : public ParseError {
|
||||
Success()
|
||||
: ParseError("Success", "Successfully completed, should be caught and quit", ExitCodes::Success, false) {}
|
||||
Success() : ParseError("Success", "Successfully completed, should be caught and quit", ExitCodes::Success, false) {}
|
||||
};
|
||||
|
||||
/// -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) {}
|
||||
};
|
||||
|
||||
|
||||
/// Thrown when parsing an INI file and it is missing
|
||||
struct FileError : public ParseError {
|
||||
FileError (std::string name)
|
||||
: ParseError("FileError", name, ExitCodes::File) {}
|
||||
FileError(std::string name) : ParseError("FileError", name, ExitCodes::File) {}
|
||||
};
|
||||
|
||||
/// Thrown when conversion call back fails, such as when an int fails to coerse to a string
|
||||
struct ConversionError : public ParseError {
|
||||
ConversionError(std::string name)
|
||||
: ParseError("ConversionError", name, ExitCodes::Conversion) {}
|
||||
ConversionError(std::string name) : ParseError("ConversionError", name, ExitCodes::Conversion) {}
|
||||
};
|
||||
|
||||
/// Thrown when validation of results fails
|
||||
struct ValidationError : public ParseError {
|
||||
ValidationError(std::string name)
|
||||
: ParseError("ValidationError", name, ExitCodes::Validation) {}
|
||||
ValidationError(std::string name) : ParseError("ValidationError", name, ExitCodes::Validation) {}
|
||||
};
|
||||
|
||||
/// Thrown when a required option is missing
|
||||
struct RequiredError : public ParseError {
|
||||
RequiredError(std::string name)
|
||||
: ParseError("RequiredError", name, ExitCodes::Required) {}
|
||||
RequiredError(std::string name) : ParseError("RequiredError", name, ExitCodes::Required) {}
|
||||
};
|
||||
|
||||
/// Thrown when a requires option is missing
|
||||
@ -134,20 +134,17 @@ struct ExcludesError : public ParseError {
|
||||
|
||||
/// Thrown when too many positionals or options are found
|
||||
struct ExtrasError : public ParseError {
|
||||
ExtrasError(std::string name)
|
||||
: ParseError("ExtrasError", name, ExitCodes::Extras) {}
|
||||
ExtrasError(std::string name) : ParseError("ExtrasError", name, ExitCodes::Extras) {}
|
||||
};
|
||||
|
||||
/// Thrown when extra values are found in an INI file
|
||||
struct ExtrasINIError : public ParseError {
|
||||
ExtrasINIError(std::string name)
|
||||
: ParseError("ExtrasINIError", name, ExitCodes::ExtrasINI) {}
|
||||
ExtrasINIError(std::string name) : ParseError("ExtrasINIError", name, ExitCodes::ExtrasINI) {}
|
||||
};
|
||||
|
||||
/// Thrown when validation fails before parsing
|
||||
struct InvalidError : public ParseError {
|
||||
InvalidError(std::string name)
|
||||
: ParseError("InvalidError", name, ExitCodes::Invalid) {}
|
||||
InvalidError(std::string name) : ParseError("InvalidError", name, ExitCodes::Invalid) {}
|
||||
};
|
||||
|
||||
/// 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
|
||||
struct OptionNotFound : public Error {
|
||||
OptionNotFound(std::string name)
|
||||
: Error("OptionNotFound", name, ExitCodes::OptionNotFound) {}
|
||||
OptionNotFound(std::string name) : Error("OptionNotFound", name, ExitCodes::OptionNotFound) {}
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
#include "CLI/StringTools.hpp"
|
||||
|
||||
|
||||
namespace CLI {
|
||||
namespace detail {
|
||||
|
||||
@ -112,6 +111,5 @@ inline std::vector<ini_ret_t> parse_ini(const std::string &name) {
|
||||
return parse_ini(input);
|
||||
}
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace CLI
|
||||
|
@ -26,9 +26,9 @@ class App;
|
||||
|
||||
using Option_p = std::unique_ptr<Option>;
|
||||
|
||||
|
||||
class Option {
|
||||
friend App;
|
||||
|
||||
protected:
|
||||
/// @name Names
|
||||
///@{
|
||||
@ -99,7 +99,6 @@ protected:
|
||||
/// Options store a callback to do all the work
|
||||
callback_t callback_;
|
||||
|
||||
|
||||
///@}
|
||||
/// @name Parsing results
|
||||
///@{
|
||||
@ -113,31 +112,27 @@ protected:
|
||||
///@}
|
||||
|
||||
/// 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) :
|
||||
description_(std::move(description)), default_(default_), parent_(parent), callback_(std::move(callback)) {
|
||||
Option(std::string name,
|
||||
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));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// @name Basic
|
||||
///@{
|
||||
|
||||
/// Count the total number of times an option was passed
|
||||
size_t count() const {
|
||||
return results_.size();
|
||||
}
|
||||
|
||||
size_t count() const { return results_.size(); }
|
||||
|
||||
/// This class is true if option is passed.
|
||||
operator bool() const {
|
||||
return count() > 0;
|
||||
}
|
||||
operator bool() const { return count() > 0; }
|
||||
|
||||
/// Clear the parsed results (mostly for testing)
|
||||
void clear() {
|
||||
results_.clear();
|
||||
}
|
||||
void clear() { results_.clear(); }
|
||||
|
||||
///@}
|
||||
/// @name Setting options
|
||||
@ -150,9 +145,7 @@ public:
|
||||
}
|
||||
|
||||
/// Support Plubmum term
|
||||
Option* mandatory(bool value = true) {
|
||||
return required(value);
|
||||
}
|
||||
Option *mandatory(bool value = true) { return required(value); }
|
||||
|
||||
/// Set the number of expected arguments (Flags bypass this)
|
||||
Option *expected(int value) {
|
||||
@ -179,7 +172,6 @@ public:
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/// Sets required options
|
||||
Option *requires(Option *opt) {
|
||||
auto tup = requires_.insert(opt);
|
||||
@ -189,18 +181,15 @@ public:
|
||||
}
|
||||
|
||||
/// Can find a string if needed
|
||||
template<typename T=App>
|
||||
Option* requires(std::string opt_name) {
|
||||
template <typename T = App> Option *requires(std::string opt_name) {
|
||||
for(const Option_p &opt : dynamic_cast<T *>(parent_)->options_)
|
||||
if(opt.get() != this && opt->check_name(opt_name))
|
||||
return requires(opt.get());
|
||||
throw IncorrectConstruction("Option " + opt_name + " is not defined");
|
||||
|
||||
}
|
||||
|
||||
/// Any number supported, any mix of string and Opt
|
||||
template<typename A, typename B, typename... ARG>
|
||||
Option* requires(A opt, B opt1, ARG... args) {
|
||||
template <typename A, typename B, typename... ARG> Option *requires(A opt, B opt1, ARG... args) {
|
||||
requires(opt);
|
||||
return requires(opt1, args...);
|
||||
}
|
||||
@ -214,17 +203,14 @@ public:
|
||||
}
|
||||
|
||||
/// Can find a string if needed
|
||||
template<typename T=App>
|
||||
Option* excludes(std::string opt_name) {
|
||||
template <typename T = App> Option *excludes(std::string opt_name) {
|
||||
for(const Option_p &opt : dynamic_cast<T *>(parent_)->options_)
|
||||
if(opt.get() != this && opt->check_name(opt_name))
|
||||
return excludes(opt.get());
|
||||
throw IncorrectConstruction("Option " + opt_name + " is not defined");
|
||||
|
||||
}
|
||||
/// Any number supported, any mix of string and Opt
|
||||
template<typename A, typename B, typename... ARG>
|
||||
Option* excludes(A opt, B opt1, ARG... args) {
|
||||
template <typename A, typename B, typename... ARG> Option *excludes(A opt, B opt1, ARG... args) {
|
||||
excludes(opt);
|
||||
return excludes(opt1, args...);
|
||||
}
|
||||
@ -239,8 +225,7 @@ public:
|
||||
///
|
||||
/// 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.
|
||||
template<typename T=App>
|
||||
Option* ignore_case(bool value = true) {
|
||||
template <typename T = App> Option *ignore_case(bool value = true) {
|
||||
ignore_case_ = value;
|
||||
for(const Option_p &opt : dynamic_cast<T *>(parent_)->options_)
|
||||
if(opt.get() != this && *opt == *this)
|
||||
@ -253,49 +238,31 @@ public:
|
||||
///@{
|
||||
|
||||
/// True if this is a required option
|
||||
bool get_required() const {
|
||||
return required_;
|
||||
}
|
||||
bool get_required() const { return required_; }
|
||||
|
||||
/// The number of arguments the option expects
|
||||
int get_expected() const {
|
||||
return expected_;
|
||||
}
|
||||
int get_expected() const { return expected_; }
|
||||
|
||||
/// True if this has a default value
|
||||
int get_default() const {
|
||||
return default_;
|
||||
}
|
||||
int get_default() const { return default_; }
|
||||
|
||||
/// True if the argument can be given directly
|
||||
bool get_positional() const {
|
||||
return pname_.length() > 0;
|
||||
}
|
||||
bool get_positional() const { return pname_.length() > 0; }
|
||||
|
||||
/// True if option has at least one non-positional name
|
||||
bool nonpositional() const {
|
||||
return (snames_.size() + lnames_.size()) > 0;
|
||||
}
|
||||
bool nonpositional() const { return (snames_.size() + lnames_.size()) > 0; }
|
||||
|
||||
/// True if option has description
|
||||
bool has_description() const {
|
||||
return description_.length() > 0;
|
||||
}
|
||||
bool has_description() const { return description_.length() > 0; }
|
||||
|
||||
/// Get the group of this option
|
||||
const std::string& get_group() const {
|
||||
return group_;
|
||||
}
|
||||
const std::string &get_group() const { return group_; }
|
||||
|
||||
/// Get the description
|
||||
const std::string& get_description() const {
|
||||
return description_;
|
||||
}
|
||||
const std::string &get_description() const { return description_; }
|
||||
|
||||
// Just the pname
|
||||
std::string get_pname() const {
|
||||
return pname_;
|
||||
}
|
||||
std::string get_pname() const { return pname_; }
|
||||
|
||||
///@}
|
||||
/// @name Help tools
|
||||
@ -365,10 +332,8 @@ public:
|
||||
out << " " << opt->get_name();
|
||||
}
|
||||
return out.str();
|
||||
|
||||
}
|
||||
|
||||
|
||||
///@}
|
||||
/// @name Parser tools
|
||||
///@{
|
||||
@ -424,9 +389,9 @@ public:
|
||||
bool check_sname(std::string name) const {
|
||||
if(ignore_case_) {
|
||||
name = detail::to_lower(name);
|
||||
return std::find_if(std::begin(snames_), std::end(snames_),
|
||||
[&name](std::string local_sname){return detail::to_lower(local_sname) == name;})
|
||||
!= std::end(snames_);
|
||||
return std::find_if(std::begin(snames_), std::end(snames_), [&name](std::string local_sname) {
|
||||
return detail::to_lower(local_sname) == name;
|
||||
}) != std::end(snames_);
|
||||
} else
|
||||
return std::find(std::begin(snames_), std::end(snames_), name) != std::end(snames_);
|
||||
}
|
||||
@ -435,30 +400,24 @@ public:
|
||||
bool check_lname(std::string name) const {
|
||||
if(ignore_case_) {
|
||||
name = detail::to_lower(name);
|
||||
return std::find_if(std::begin(lnames_), std::end(lnames_),
|
||||
[&name](std::string local_sname){return detail::to_lower(local_sname) == name;})
|
||||
!= std::end(lnames_);
|
||||
return std::find_if(std::begin(lnames_), std::end(lnames_), [&name](std::string local_sname) {
|
||||
return detail::to_lower(local_sname) == name;
|
||||
}) != std::end(lnames_);
|
||||
} else
|
||||
return std::find(std::begin(lnames_), std::end(lnames_), name) != std::end(lnames_);
|
||||
}
|
||||
|
||||
|
||||
/// Puts a result at position r
|
||||
void add_result(std::string s) {
|
||||
results_.push_back(s);
|
||||
callback_run_ = false;
|
||||
}
|
||||
|
||||
|
||||
/// Get a copy of the results
|
||||
std::vector<std::string> results() const {
|
||||
return results_;
|
||||
}
|
||||
std::vector<std::string> results() const { return results_; }
|
||||
|
||||
/// See if the callback has been run already
|
||||
bool get_callback_run() const {
|
||||
return callback_run_;
|
||||
}
|
||||
bool get_callback_run() const { return callback_run_; }
|
||||
|
||||
///@}
|
||||
/// @name Custom options
|
||||
@ -472,16 +431,11 @@ public:
|
||||
}
|
||||
|
||||
/// Set the default value string representation
|
||||
void set_default_val(std::string val) {
|
||||
defaultval_ = val;
|
||||
}
|
||||
void set_default_val(std::string val) { defaultval_ = val; }
|
||||
|
||||
///@}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
/// @name App Helpers
|
||||
///@{
|
||||
/// Can print positional name detailed option if true
|
||||
@ -491,6 +445,4 @@ public:
|
||||
///@}
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace CLI
|
||||
|
@ -49,7 +49,6 @@ inline std::vector<std::string> split_names(std::string current) {
|
||||
}
|
||||
output.push_back(current);
|
||||
return output;
|
||||
|
||||
}
|
||||
|
||||
/// Get a vector of short names, one of long names, and a single name
|
||||
@ -80,14 +79,12 @@ inline std::tuple<std::vector<std::string>,std::vector<std::string>, std::string
|
||||
if(pos_name.length() > 0)
|
||||
throw BadNameString("Only one positional name allowed, remove: " + name);
|
||||
pos_name = name;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return std::tuple<std::vector<std::string>,std::vector<std::string>, 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 CLI
|
||||
|
@ -13,7 +13,6 @@
|
||||
namespace CLI {
|
||||
namespace detail {
|
||||
|
||||
|
||||
// Based on http://stackoverflow.com/questions/236129/split-a-string-in-c
|
||||
/// Split a string by a delim
|
||||
inline std::vector<std::string> split(const std::string &s, char delim) {
|
||||
@ -32,10 +31,8 @@ inline std::vector<std::string> split(const std::string &s, char delim) {
|
||||
return elems;
|
||||
}
|
||||
|
||||
|
||||
/// Simple function to join a string
|
||||
template <typename T>
|
||||
std::string join(const T& v, std::string delim = ",") {
|
||||
template <typename T> std::string join(const T &v, std::string delim = ",") {
|
||||
std::ostringstream s;
|
||||
size_t start = 0;
|
||||
for(const auto &i : v) {
|
||||
@ -47,8 +44,7 @@ std::string join(const T& v, std::string delim = ",") {
|
||||
}
|
||||
|
||||
/// Join a string in reverse order
|
||||
template<typename T>
|
||||
std::string rjoin(const T& v, std::string delim = ",") {
|
||||
template <typename T> std::string rjoin(const T &v, std::string delim = ",") {
|
||||
std::ostringstream s;
|
||||
for(size_t start = 0; start < v.size(); start++) {
|
||||
if(start > 0)
|
||||
@ -74,7 +70,6 @@ inline std::string& ltrim(std::string &str, const std::string &filter) {
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/// Trim whitespace from right of string
|
||||
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()); });
|
||||
@ -84,20 +79,17 @@ inline std::string& rtrim(std::string &str) {
|
||||
|
||||
/// Trim anything from right of string
|
||||
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());
|
||||
return str;
|
||||
}
|
||||
|
||||
/// Trim whitespace from string
|
||||
inline std::string& trim(std::string &str) {
|
||||
return ltrim(rtrim(str));
|
||||
}
|
||||
inline std::string &trim(std::string &str) { return ltrim(rtrim(str)); }
|
||||
|
||||
/// Trim anything from string
|
||||
inline std::string& trim(std::string &str, const std::string filter) {
|
||||
return ltrim(rtrim(str, filter), filter);
|
||||
}
|
||||
inline std::string &trim(std::string &str, const std::string filter) { return ltrim(rtrim(str, filter), filter); }
|
||||
|
||||
/// Make a copy of the string and then trim it
|
||||
inline std::string trim_copy(const std::string &str) {
|
||||
@ -123,14 +115,10 @@ inline void format_help(std::stringstream &out, std::string name, std::string de
|
||||
}
|
||||
|
||||
/// Verify the first character of an option
|
||||
template<typename T>
|
||||
bool valid_first_char(T c) {
|
||||
return std::isalpha(c, std::locale()) || c=='_';
|
||||
}
|
||||
template <typename T> bool valid_first_char(T c) { return std::isalpha(c, std::locale()) || c == '_'; }
|
||||
|
||||
/// Verify following characters of an option
|
||||
template<typename T>
|
||||
bool valid_later_char(T c) {
|
||||
template <typename T> bool valid_later_char(T c) {
|
||||
return std::isalnum(c, std::locale()) || c == '_' || c == '.' || c == '-';
|
||||
}
|
||||
|
||||
@ -146,8 +134,9 @@ inline bool valid_name_string(const std::string &str) {
|
||||
|
||||
/// Return a lower case version of a string
|
||||
inline std::string to_lower(std::string str) {
|
||||
std::transform(std::begin(str), std::end(str), std::begin(str),
|
||||
[](const std::string::value_type &x){return std::tolower(x,std::locale());});
|
||||
std::transform(std::begin(str), std::end(str), std::begin(str), [](const std::string::value_type &x) {
|
||||
return std::tolower(x, std::locale());
|
||||
});
|
||||
return str;
|
||||
}
|
||||
|
||||
|
@ -35,17 +35,13 @@ protected:
|
||||
size_t cycles{1};
|
||||
|
||||
public:
|
||||
|
||||
/// Standard print function, this one is set by default
|
||||
static std::string Simple(std::string title, std::string time) {
|
||||
return title + ": " + time;
|
||||
}
|
||||
static std::string Simple(std::string title, std::string time) { return title + ": " + time; }
|
||||
|
||||
/// This is a fancy print function with --- headers
|
||||
static std::string Big(std::string title, std::string time) {
|
||||
return std::string("-----------------------------------------\n")
|
||||
+ "| " + title + " | Time = " + time + "\n"
|
||||
+ "-----------------------------------------";
|
||||
return std::string("-----------------------------------------\n") + "| " + title + " | Time = " + time + "\n" +
|
||||
"-----------------------------------------";
|
||||
}
|
||||
|
||||
public:
|
||||
@ -99,33 +95,27 @@ public:
|
||||
// LCOV_EXCL_END
|
||||
|
||||
/// This is the main function, it creates a string
|
||||
std::string to_string() const {
|
||||
return time_print_(title_, make_time_str());
|
||||
}
|
||||
std::string to_string() const { return time_print_(title_, make_time_str()); }
|
||||
|
||||
/// 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
|
||||
class AutoTimer : public Timer {
|
||||
public:
|
||||
/// Reimplementing the constructor is required in GCC 4.7
|
||||
AutoTimer(std::string title="Timer", time_print_t time_print = Simple)
|
||||
: Timer(title, time_print) {}
|
||||
AutoTimer(std::string title = "Timer", time_print_t time_print = Simple) : Timer(title, time_print) {}
|
||||
// GCC 4.7 does not support using inheriting constructors.
|
||||
|
||||
/// This desctructor prints the string
|
||||
~AutoTimer () {
|
||||
std::cout << to_string() << std::endl;
|
||||
}
|
||||
~AutoTimer() { std::cout << to_string() << std::endl; }
|
||||
};
|
||||
|
||||
} // namespace CLI
|
||||
|
||||
/// This prints out the time if shifted into a std::cout like stream.
|
||||
inline std::ostream & operator<< (std::ostream& in, const CLI::Timer& timer) {
|
||||
return in << timer.to_string();
|
||||
}
|
||||
inline std::ostream &operator<<(std::ostream &in, const CLI::Timer &timer) { return in << timer.to_string(); }
|
||||
|
@ -14,34 +14,19 @@ namespace CLI {
|
||||
|
||||
// Copied from C++14
|
||||
#if __cplusplus < 201402L
|
||||
template< bool B, class T = void >
|
||||
using enable_if_t = typename std::enable_if<B,T>::type;
|
||||
template <bool B, class T = void> using enable_if_t = typename std::enable_if<B, T>::type;
|
||||
#else
|
||||
// If your compiler supports C++14, you can use that definition instead
|
||||
using std::enable_if_t;
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct is_vector {
|
||||
static const bool value = false;
|
||||
};
|
||||
template <typename T> 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>
|
||||
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 <typename T> struct is_bool { static const bool value = false; };
|
||||
|
||||
template <> struct is_bool<bool> { static bool const value = true; };
|
||||
|
||||
namespace detail {
|
||||
// Based generally on https://rmf.io/cxx11/almost-static-if
|
||||
@ -51,7 +36,6 @@ namespace detail {
|
||||
/// An instance to use in EnableIf
|
||||
constexpr enabler dummy = {};
|
||||
|
||||
|
||||
// Type name print
|
||||
|
||||
/// Was going to be based on
|
||||
@ -70,34 +54,26 @@ namespace detail {
|
||||
return "UINT";
|
||||
}
|
||||
|
||||
|
||||
template<typename T,
|
||||
enable_if_t<std::is_floating_point<T>::value, detail::enabler> = detail::dummy>
|
||||
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>
|
||||
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 && !std::is_integral<T>::value && !is_vector<T>::value
|
||||
, detail::enabler> = detail::dummy>
|
||||
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
|
||||
|
||||
|
||||
/// Integers
|
||||
template <typename T, enable_if_t<std::is_integral<T>::value, detail::enabler> = detail::dummy>
|
||||
bool lexical_cast(std::string input, T &output) {
|
||||
@ -124,16 +100,14 @@ namespace detail {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// String and similar
|
||||
template<typename T,
|
||||
enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value
|
||||
, detail::enabler> = detail::dummy>
|
||||
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 CLI
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
namespace CLI {
|
||||
|
||||
|
||||
/// @defgroup validator_group Validators
|
||||
/// @brief Some validators that are provided
|
||||
///
|
||||
@ -55,7 +54,6 @@ inline bool ExistingDirectory(std::string filename) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Check for a non-existing path
|
||||
inline bool NonexistentPath(std::string filename) {
|
||||
struct stat buffer;
|
||||
@ -69,8 +67,7 @@ inline bool NonexistentPath(std::string filename) {
|
||||
}
|
||||
|
||||
/// Produce a range validator function
|
||||
template<typename T>
|
||||
std::function<bool(std::string)> Range(T min, T max) {
|
||||
template <typename T> std::function<bool(std::string)> Range(T min, T max) {
|
||||
return [min, max](std::string input) {
|
||||
T val;
|
||||
detail::lexical_cast(input, val);
|
||||
@ -79,10 +76,7 @@ std::function<bool(std::string)> Range(T min, T max) {
|
||||
}
|
||||
|
||||
/// Range of one value is 0 to value
|
||||
template<typename T>
|
||||
std::function<bool(std::string)> Range(T max) {
|
||||
return Range(static_cast<T>(0), max);
|
||||
}
|
||||
template <typename T> 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/googlemock/include/
|
||||
- I../ build / googletest - src / googletest / include / -I../ build / googletest - src / googlemock / include /
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "app_helper.hpp"
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
TEST_F(TApp, OneFlagShort) {
|
||||
app.add_flag("-c,--count");
|
||||
args = {"-c"};
|
||||
@ -36,7 +35,6 @@ TEST_F(TApp, DashedOptions) {
|
||||
EXPECT_EQ((size_t)1, app.count("--q"));
|
||||
EXPECT_EQ((size_t)2, app.count("--this"));
|
||||
EXPECT_EQ((size_t)2, app.count("--that"));
|
||||
|
||||
}
|
||||
|
||||
TEST_F(TApp, OneFlagRef) {
|
||||
@ -69,7 +67,6 @@ TEST_F(TApp, OneStringEqualVersion) {
|
||||
EXPECT_EQ(str, "mystring");
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, TogetherInt) {
|
||||
int i;
|
||||
app.add_option("-i,--int", i);
|
||||
@ -100,7 +97,6 @@ TEST_F(TApp, OneStringAgain) {
|
||||
EXPECT_EQ(str, "mystring");
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, DefaultStringAgain) {
|
||||
std::string str = "previous";
|
||||
app.add_option("-s,--string", str);
|
||||
@ -139,7 +135,6 @@ TEST_F(TApp, LotsOfFlags) {
|
||||
EXPECT_EQ((size_t)1, app.count("-A"));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, BoolAndIntFlags) {
|
||||
|
||||
bool bflag;
|
||||
@ -178,7 +173,9 @@ TEST_F(TApp, ShortOpts) {
|
||||
app.add_flag("-z", funnyint);
|
||||
app.add_option("-y", someopt);
|
||||
|
||||
args = {"-zzyzyz",};
|
||||
args = {
|
||||
"-zzyzyz",
|
||||
};
|
||||
|
||||
run();
|
||||
|
||||
@ -224,7 +221,6 @@ TEST_F(TApp, RequiredFlags) {
|
||||
app.reset();
|
||||
args = {"-a", "-b"};
|
||||
run();
|
||||
|
||||
}
|
||||
|
||||
TEST_F(TApp, Positionals) {
|
||||
@ -244,7 +240,6 @@ TEST_F(TApp, Positionals) {
|
||||
EXPECT_EQ("thing2", posit2);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, ForcedPositional) {
|
||||
std::vector<std::string> posit;
|
||||
auto one = app.add_flag("--one");
|
||||
@ -266,7 +261,6 @@ TEST_F(TApp, ForcedPositional) {
|
||||
EXPECT_EQ(answers2, posit);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, MixedPositionals) {
|
||||
|
||||
int positional_int;
|
||||
@ -325,10 +319,8 @@ TEST_F(TApp, Reset) {
|
||||
EXPECT_EQ((size_t)1, app.count("--simple"));
|
||||
EXPECT_EQ((size_t)1, app.count("-d"));
|
||||
EXPECT_DOUBLE_EQ(1.2, doub);
|
||||
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, RemoveOption) {
|
||||
app.add_flag("--one");
|
||||
auto opt = app.add_flag("--two");
|
||||
@ -354,7 +346,6 @@ TEST_F(TApp, FileNotExists) {
|
||||
|
||||
app.reset();
|
||||
|
||||
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
EXPECT_TRUE(ok);
|
||||
EXPECT_THROW(run(), CLI::ValidationError);
|
||||
@ -430,7 +421,6 @@ TEST_F(TApp, FailSet) {
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, InSetIgnoreCase) {
|
||||
|
||||
std::string choice;
|
||||
@ -450,7 +440,6 @@ TEST_F(TApp, InSetIgnoreCase) {
|
||||
run();
|
||||
EXPECT_EQ("THREE", choice); // Keeps caps from set
|
||||
|
||||
|
||||
app.reset();
|
||||
args = {"--quick", "four"};
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
@ -458,7 +447,6 @@ TEST_F(TApp, InSetIgnoreCase) {
|
||||
app.reset();
|
||||
args = {"--quick=one", "--quick=two"};
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(TApp, VectorFixedString) {
|
||||
@ -474,8 +462,6 @@ TEST_F(TApp, VectorFixedString) {
|
||||
EXPECT_EQ(answer, strvec);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_F(TApp, VectorUnlimString) {
|
||||
std::vector<std::string> strvec;
|
||||
std::vector<std::string> answer{"mystring", "mystring2", "mystring3"};
|
||||
@ -495,7 +481,6 @@ TEST_F(TApp, VectorUnlimString) {
|
||||
EXPECT_EQ(answer, strvec);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, VectorFancyOpts) {
|
||||
std::vector<std::string> strvec;
|
||||
std::vector<std::string> answer{"mystring", "mystring2", "mystring3"};
|
||||
@ -535,7 +520,6 @@ TEST_F(TApp, RequiresFlags) {
|
||||
EXPECT_THROW(run(), CLI::RequiresError);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, ExcludesFlags) {
|
||||
CLI::Option *opt = app.add_flag("-s,--string");
|
||||
app.add_flag("--nostr")->excludes(opt);
|
||||
@ -771,7 +755,6 @@ TEST_F(TApp, AllowExtras) {
|
||||
EXPECT_NO_THROW({ left_over = run(); });
|
||||
EXPECT_TRUE(val);
|
||||
EXPECT_EQ(std::vector<std::string>({"-x"}), left_over);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(TApp, AllowExtrasOrder) {
|
||||
@ -787,7 +770,6 @@ TEST_F(TApp, AllowExtrasOrder) {
|
||||
std::vector<std::string> left_over_2;
|
||||
left_over_2 = app.parse(left_over);
|
||||
EXPECT_EQ(left_over, left_over_2);
|
||||
|
||||
}
|
||||
|
||||
// Test horrible error
|
||||
|
@ -53,7 +53,6 @@ TEST_F(TApp, AddingMultipleInfPositionals) {
|
||||
EXPECT_THROW(run(), CLI::InvalidError);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, AddingMultipleInfPositionalsSubcom) {
|
||||
std::vector<std::string> one, two;
|
||||
CLI::App *below = app.add_subcommand("below");
|
||||
@ -103,9 +102,7 @@ TEST_F(TApp, MultipleSubcomNoMatchingInplace2) {
|
||||
EXPECT_NO_THROW(second->ignore_case());
|
||||
}
|
||||
|
||||
TEST_F(TApp, IncorrectConstructionFlagPositional1) {
|
||||
EXPECT_THROW(app.add_flag("cat"), CLI::IncorrectConstruction);
|
||||
}
|
||||
TEST_F(TApp, IncorrectConstructionFlagPositional1) { EXPECT_THROW(app.add_flag("cat"), CLI::IncorrectConstruction); }
|
||||
|
||||
TEST_F(TApp, IncorrectConstructionFlagPositional2) {
|
||||
int x;
|
||||
|
@ -20,7 +20,6 @@ TEST(THelp, Basic) {
|
||||
EXPECT_THAT(help, HasSubstr("-h,--help"));
|
||||
EXPECT_THAT(help, HasSubstr("Options:"));
|
||||
EXPECT_THAT(help, HasSubstr("Usage:"));
|
||||
|
||||
}
|
||||
|
||||
TEST(THelp, OptionalPositional) {
|
||||
@ -44,11 +43,9 @@ TEST(THelp, Hidden) {
|
||||
CLI::App app{"My prog"};
|
||||
|
||||
std::string x;
|
||||
app.add_option("something", x, "My option here")
|
||||
->group("Hidden");
|
||||
app.add_option("something", x, "My option here")->group("Hidden");
|
||||
std::string y;
|
||||
app.add_option("--another", y)
|
||||
->group("Hidden");
|
||||
app.add_option("--another", y)->group("Hidden");
|
||||
|
||||
std::string help = app.help();
|
||||
|
||||
@ -73,7 +70,6 @@ TEST(THelp, OptionalPositionalAndOptions) {
|
||||
EXPECT_THAT(help, HasSubstr("-h,--help"));
|
||||
EXPECT_THAT(help, HasSubstr("Options:"));
|
||||
EXPECT_THAT(help, HasSubstr("Usage: program [OPTIONS] [something]"));
|
||||
|
||||
}
|
||||
|
||||
TEST(THelp, RequiredPositionalAndOptions) {
|
||||
@ -81,8 +77,7 @@ TEST(THelp, RequiredPositionalAndOptions) {
|
||||
app.add_flag("-q,--quick");
|
||||
|
||||
std::string x;
|
||||
app.add_option("something", x, "My option here")
|
||||
->required();
|
||||
app.add_option("something", x, "My option here")->required();
|
||||
|
||||
std::string help = app.help();
|
||||
|
||||
@ -93,7 +88,6 @@ TEST(THelp, RequiredPositionalAndOptions) {
|
||||
EXPECT_THAT(help, HasSubstr("Usage: program [OPTIONS] something"));
|
||||
}
|
||||
|
||||
|
||||
TEST(THelp, MultiOpts) {
|
||||
CLI::App app{"My prog"};
|
||||
std::vector<int> x, y;
|
||||
@ -136,8 +130,6 @@ TEST(THelp, MultiPosOpts) {
|
||||
EXPECT_THAT(help, HasSubstr("[vals...]"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST(THelp, EnvName) {
|
||||
CLI::App app{"My prog"};
|
||||
std::string input;
|
||||
@ -239,7 +231,6 @@ TEST(THelp, IntDefaults) {
|
||||
EXPECT_THAT(help, HasSubstr("1"));
|
||||
EXPECT_THAT(help, HasSubstr("=2"));
|
||||
EXPECT_THAT(help, HasSubstr("2,3,4"));
|
||||
|
||||
}
|
||||
|
||||
TEST(THelp, SetLower) {
|
||||
@ -255,7 +246,6 @@ TEST(THelp, SetLower) {
|
||||
EXPECT_THAT(help, HasSubstr("oNe"));
|
||||
EXPECT_THAT(help, HasSubstr("twO"));
|
||||
EXPECT_THAT(help, HasSubstr("THREE"));
|
||||
|
||||
}
|
||||
|
||||
TEST(Exit, ErrorWithHelp) {
|
||||
@ -287,5 +277,4 @@ TEST(Exit, ExitCodes) {
|
||||
EXPECT_EQ(0, app.exit(CLI::Success()));
|
||||
EXPECT_EQ(0, app.exit(CLI::CallForHelp()));
|
||||
EXPECT_EQ(i, app.exit(CLI::ExtrasError("Thing")));
|
||||
|
||||
}
|
||||
|
@ -51,7 +51,6 @@ TEST(Trim, Various) {
|
||||
EXPECT_EQ("a b", CLI::detail::trim(s4));
|
||||
}
|
||||
|
||||
|
||||
TEST(Trim, VariousFilters) {
|
||||
std::string s1{" sdlfkj sdflk sd s "};
|
||||
std::string a1{"sdlfkj sdflk sd s"};
|
||||
@ -84,10 +83,8 @@ TEST(Trim, TrimCopy) {
|
||||
EXPECT_NE(orig, trimmed);
|
||||
CLI::detail::trim(orig, "ab");
|
||||
EXPECT_EQ(trimmed, orig);
|
||||
|
||||
}
|
||||
|
||||
|
||||
TEST(Validators, FileExists) {
|
||||
std::string myfile{"TestFileNotUsed.txt"};
|
||||
EXPECT_FALSE(CLI::ExistingFile(myfile));
|
||||
@ -176,7 +173,6 @@ TEST(AppHelper, Ofstream) {
|
||||
EXPECT_TRUE(CLI::ExistingFile(myfile));
|
||||
}
|
||||
EXPECT_FALSE(CLI::ExistingFile(name));
|
||||
|
||||
}
|
||||
|
||||
TEST(Split, StringList) {
|
||||
@ -232,7 +228,6 @@ TEST(RegEx, Longs) {
|
||||
EXPECT_FALSE(CLI::detail::split_long("-things", name, value));
|
||||
EXPECT_FALSE(CLI::detail::split_long("Q", name, value));
|
||||
EXPECT_FALSE(CLI::detail::split_long("--", name, value));
|
||||
|
||||
}
|
||||
|
||||
TEST(RegEx, SplittingNew) {
|
||||
@ -246,7 +241,8 @@ TEST(RegEx, SplittingNew) {
|
||||
EXPECT_EQ(std::vector<std::string>({"s", "q"}), shorts);
|
||||
EXPECT_EQ("", pname);
|
||||
|
||||
EXPECT_NO_THROW(std::tie(shorts, longs, pname) = CLI::detail::get_names({"--long", "", "-s", "-q", "", "--also-long"}));
|
||||
EXPECT_NO_THROW(std::tie(shorts, longs, pname) =
|
||||
CLI::detail::get_names({"--long", "", "-s", "-q", "", "--also-long"}));
|
||||
EXPECT_EQ(std::vector<std::string>({"long", "also-long"}), longs);
|
||||
EXPECT_EQ(std::vector<std::string>({"s", "q"}), shorts);
|
||||
|
||||
@ -255,13 +251,9 @@ TEST(RegEx, SplittingNew) {
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
TEST(String, ToLower) {
|
||||
|
||||
EXPECT_EQ("one and two", CLI::detail::to_lower("one And TWO"));
|
||||
}
|
||||
TEST(String, ToLower) { EXPECT_EQ("one and two", CLI::detail::to_lower("one And TWO")); }
|
||||
|
||||
TEST(Join, Forward) {
|
||||
std::vector<std::string> val{{"one", "two", "three"}};
|
||||
@ -269,7 +261,6 @@ TEST(Join, Forward) {
|
||||
EXPECT_EQ("one;two;three", CLI::detail::join(val, ";"));
|
||||
}
|
||||
|
||||
|
||||
TEST(Join, Backward) {
|
||||
std::vector<std::string> val{{"three", "two", "one"}};
|
||||
EXPECT_EQ("one,two,three", CLI::detail::rjoin(val));
|
||||
@ -365,4 +356,3 @@ TEST(Types, LexicalCastString) {
|
||||
CLI::detail::lexical_cast(input, output);
|
||||
EXPECT_EQ(input, output);
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,6 @@ TEST(StringBased, First) {
|
||||
EXPECT_EQ("two", output.at(1).name());
|
||||
EXPECT_EQ((size_t)1, output.at(1).inputs.size());
|
||||
EXPECT_EQ("four", output.at(1).inputs.at(0));
|
||||
|
||||
}
|
||||
|
||||
TEST(StringBased, FirstWithComments) {
|
||||
@ -96,7 +95,6 @@ TEST(StringBased, Vector) {
|
||||
EXPECT_EQ("seven", output.at(2).inputs.at(2));
|
||||
}
|
||||
|
||||
|
||||
TEST(StringBased, Spaces) {
|
||||
std::stringstream ofile;
|
||||
|
||||
@ -137,7 +135,6 @@ TEST(StringBased, Sections) {
|
||||
EXPECT_EQ("four", output.at(1).inputs.at(0));
|
||||
}
|
||||
|
||||
|
||||
TEST(StringBased, SpacesSections) {
|
||||
std::stringstream ofile;
|
||||
|
||||
@ -196,7 +193,6 @@ TEST_F(TApp, IniNotRequired) {
|
||||
EXPECT_EQ(1, one);
|
||||
EXPECT_EQ(2, two);
|
||||
EXPECT_EQ(3, three);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniRequiredNotFound) {
|
||||
@ -205,7 +201,6 @@ TEST_F(TApp, IniRequiredNotFound) {
|
||||
app.add_config("--config", noini, "", true);
|
||||
|
||||
EXPECT_THROW(run(), CLI::FileError);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOverwrite) {
|
||||
@ -267,7 +262,6 @@ TEST_F(TApp, IniRequired) {
|
||||
args = {"--two=2"};
|
||||
|
||||
EXPECT_THROW(run(), CLI::RequiredError);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniVector) {
|
||||
@ -291,10 +285,8 @@ TEST_F(TApp, IniVector) {
|
||||
|
||||
EXPECT_EQ(std::vector<int>({2, 3}), two);
|
||||
EXPECT_EQ(std::vector<int>({1, 2, 3}), three);
|
||||
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, IniLayered) {
|
||||
|
||||
TempFile tmpini{"TestIniTmp.ini"};
|
||||
@ -322,7 +314,6 @@ TEST_F(TApp, IniLayered) {
|
||||
EXPECT_EQ(1, one);
|
||||
EXPECT_EQ(2, two);
|
||||
EXPECT_EQ(3, three);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniFailure) {
|
||||
@ -340,7 +331,6 @@ TEST_F(TApp, IniFailure) {
|
||||
EXPECT_THROW(run(), CLI::ExtrasINIError);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, IniSubFailure) {
|
||||
|
||||
TempFile tmpini{"TestIniTmp.ini"};
|
||||
@ -357,7 +347,6 @@ TEST_F(TApp, IniSubFailure) {
|
||||
EXPECT_THROW(run(), CLI::ExtrasINIError);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, IniNoSubFailure) {
|
||||
|
||||
TempFile tmpini{"TestIniTmp.ini"};
|
||||
@ -388,7 +377,6 @@ TEST_F(TApp, IniFlagConvertFailure) {
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, IniFlagNumbers) {
|
||||
|
||||
TempFile tmpini{"TestIniTmp.ini"};
|
||||
@ -474,7 +462,6 @@ TEST_F(TApp, IniFlags) {
|
||||
EXPECT_EQ(true, three);
|
||||
EXPECT_EQ(true, four);
|
||||
EXPECT_EQ(true, five);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputSimple) {
|
||||
@ -538,7 +525,6 @@ TEST_F(TApp, IniOutputSet) {
|
||||
EXPECT_THAT(str, HasSubstr("simple=2"));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, IniOutputDefault) {
|
||||
|
||||
int v = 7;
|
||||
@ -585,5 +571,4 @@ TEST_F(TApp, IniQuotedOutput) {
|
||||
std::string str = app.config_to_str();
|
||||
EXPECT_THAT(str, HasSubstr("val1=\"I am a string\""));
|
||||
EXPECT_THAT(str, HasSubstr("val2='I am a \"confusing\" string'"));
|
||||
|
||||
}
|
||||
|
@ -6,15 +6,13 @@ using ::testing::HasSubstr;
|
||||
|
||||
using cx = std::complex<double>;
|
||||
|
||||
CLI::Option* add_option(CLI::App& app,
|
||||
std::string name, cx& variable,
|
||||
std::string description="", bool defaulted=false) {
|
||||
CLI::Option *
|
||||
add_option(CLI::App &app, std::string name, cx &variable, std::string description = "", bool defaulted = false) {
|
||||
CLI::callback_t fun = [&variable](CLI::results_t res) {
|
||||
if(res.size() != 2)
|
||||
return false;
|
||||
double x, y;
|
||||
bool worked = CLI::detail::lexical_cast(res[0], x)
|
||||
&& CLI::detail::lexical_cast(res[1], y);
|
||||
bool worked = CLI::detail::lexical_cast(res[0], x) && CLI::detail::lexical_cast(res[1], y);
|
||||
if(worked)
|
||||
variable = cx(x, y);
|
||||
return worked;
|
||||
@ -32,7 +30,6 @@ CLI::Option* add_option(CLI::App& app,
|
||||
|
||||
TEST_F(TApp, AddingComplexParser) {
|
||||
|
||||
|
||||
cx comp{0, 0};
|
||||
add_option(app, "-c,--complex", comp);
|
||||
args = {"-c", "1.5", "2.5"};
|
||||
@ -75,10 +72,8 @@ TEST_F(TApp, BuiltinComplex) {
|
||||
run();
|
||||
|
||||
EXPECT_EQ(cx(4, 3), comp);
|
||||
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, BuiltinComplexIgnoreI) {
|
||||
cx comp{1, 2};
|
||||
app.add_complex("-c,--complex", comp);
|
||||
|
@ -26,5 +26,3 @@ TEST(Basic, Empty) {
|
||||
app.parse(simpleput);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,7 +34,6 @@ TEST_F(TApp, MultiSubFallthrough) {
|
||||
auto sub1 = app.add_subcommand("sub1");
|
||||
auto sub2 = app.add_subcommand("sub2");
|
||||
|
||||
|
||||
args = {"sub1", "sub2"};
|
||||
run();
|
||||
EXPECT_TRUE(app.got_subcommand("sub1"));
|
||||
@ -75,23 +74,17 @@ TEST_F(TApp, MultiSubFallthrough) {
|
||||
EXPECT_THROW(app.got_subcommand("sub3"), CLI::OptionNotFound);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, Callbacks) {
|
||||
auto sub1 = app.add_subcommand("sub1");
|
||||
sub1->set_callback([](){
|
||||
throw CLI::Success();
|
||||
});
|
||||
sub1->set_callback([]() { throw CLI::Success(); });
|
||||
auto sub2 = app.add_subcommand("sub2");
|
||||
bool val = false;
|
||||
sub2->set_callback([&val](){
|
||||
val = true;
|
||||
});
|
||||
sub2->set_callback([&val]() { val = true; });
|
||||
|
||||
args = {"sub2"};
|
||||
EXPECT_FALSE(val);
|
||||
run();
|
||||
EXPECT_TRUE(val);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(TApp, NoFallThroughOpts) {
|
||||
@ -104,7 +97,6 @@ TEST_F(TApp, NoFallThroughOpts) {
|
||||
EXPECT_THROW(run(), CLI::ExtrasError);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, NoFallThroughPositionals) {
|
||||
int val = 1;
|
||||
app.add_option("val", val);
|
||||
@ -127,7 +119,6 @@ TEST_F(TApp, FallThroughRegular) {
|
||||
run();
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, FallThroughShort) {
|
||||
app.fallthrough();
|
||||
int val = 1;
|
||||
@ -140,7 +131,6 @@ TEST_F(TApp, FallThroughShort) {
|
||||
run();
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, FallThroughPositional) {
|
||||
app.fallthrough();
|
||||
int val = 1;
|
||||
@ -165,7 +155,6 @@ TEST_F(TApp, FallThroughEquals) {
|
||||
run();
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, EvilParseFallthrough) {
|
||||
app.fallthrough();
|
||||
int val1 = 0, val2 = 0;
|
||||
@ -188,9 +177,7 @@ TEST_F(TApp, CallbackOrdering) {
|
||||
app.add_option("--val", val);
|
||||
|
||||
auto sub = app.add_subcommand("sub");
|
||||
sub->set_callback([&val, &sub_val](){
|
||||
sub_val = val;
|
||||
});
|
||||
sub->set_callback([&val, &sub_val]() { sub_val = val; });
|
||||
|
||||
args = {"sub", "--val=2"};
|
||||
run();
|
||||
@ -202,7 +189,6 @@ TEST_F(TApp, CallbackOrdering) {
|
||||
run();
|
||||
EXPECT_EQ(2, val);
|
||||
EXPECT_EQ(2, sub_val);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(TApp, RequiredSubCom) {
|
||||
@ -218,7 +204,6 @@ TEST_F(TApp, RequiredSubCom) {
|
||||
args = {"sub1"};
|
||||
|
||||
run();
|
||||
|
||||
}
|
||||
|
||||
TEST_F(TApp, Required1SubCom) {
|
||||
@ -275,7 +260,6 @@ TEST_F(SubcommandProgram, Working) {
|
||||
EXPECT_EQ("filename", file);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(SubcommandProgram, Spare) {
|
||||
args = {"extra", "-d", "start", "-ffilename"};
|
||||
|
||||
@ -309,19 +293,16 @@ TEST_F(SubcommandProgram, MultipleArgs) {
|
||||
run();
|
||||
|
||||
EXPECT_EQ((size_t)2, app.get_subcommands().size());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(SubcommandProgram, CaseCheck) {
|
||||
args = {"Start"};
|
||||
EXPECT_THROW(run(), CLI::ExtrasError);
|
||||
|
||||
|
||||
app.reset();
|
||||
args = {"start"};
|
||||
run();
|
||||
|
||||
|
||||
app.reset();
|
||||
start->ignore_case();
|
||||
run();
|
||||
@ -366,9 +347,7 @@ TEST_F(SubcommandProgram, HelpOrder) {
|
||||
|
||||
TEST_F(SubcommandProgram, Callbacks) {
|
||||
|
||||
start->set_callback([](){
|
||||
throw CLI::Success();
|
||||
});
|
||||
start->set_callback([]() { throw CLI::Success(); });
|
||||
|
||||
run();
|
||||
|
||||
@ -377,5 +356,4 @@ TEST_F(SubcommandProgram, Callbacks) {
|
||||
args = {"start"};
|
||||
|
||||
EXPECT_THROW(run(), CLI::Success);
|
||||
|
||||
}
|
||||
|
@ -58,8 +58,7 @@ TEST(Timer, PrintTimer) {
|
||||
|
||||
TEST(Timer, TimeItTimer) {
|
||||
CLI::Timer timer;
|
||||
std::string output = timer.time_it([](){
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));}, .1);
|
||||
std::string output = timer.time_it([]() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }, .1);
|
||||
std::cout << output << std::endl;
|
||||
EXPECT_THAT(output, HasSubstr("ms"));
|
||||
}
|
||||
|
@ -20,19 +20,15 @@ struct TApp : public ::testing::Test {
|
||||
std::reverse(std::begin(newargs), std::end(newargs));
|
||||
return app.parse(newargs);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class TempFile {
|
||||
std::string _name;
|
||||
|
||||
public:
|
||||
|
||||
TempFile(std::string name) : _name(name) {
|
||||
if(!CLI::NonexistentPath(_name))
|
||||
throw std::runtime_error(_name);
|
||||
|
||||
}
|
||||
|
||||
~TempFile() {
|
||||
@ -58,4 +54,3 @@ inline void unset_env(std::string name) {
|
||||
unsetenv(name.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,4 @@
|
||||
#include "CLI/CLI.hpp"
|
||||
#include "CLI/Timer.hpp"
|
||||
|
||||
int do_nothing() {
|
||||
return 7;
|
||||
}
|
||||
int do_nothing() { return 7; }
|
||||
|
@ -9,4 +9,3 @@ TEST(Link, DoNothing) {
|
||||
int a = do_nothing();
|
||||
EXPECT_EQ(7, a);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user