mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-04-29 12:13:52 +00:00
Allow non standard option names like -option
(#1078)
This has been bounced around for a couple years now #474 and a few others have expressed desire to work with non-standard option names. We have been somewhat resistant to that but I think it can be done now. This PR adds a modifier `allow_non_standard_option_names()` It is purposely long, it is purposely off by default. But what it does is allow option names with a single `-` to act like a short option name. With this modifier enabled no single letter short option names are allowed to start with the same letter as a non-standard names. For example `-s` and `-single` would not be allowed. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com>
This commit is contained in:
parent
7bc90c7eb3
commit
5a03ee5838
@ -3,6 +3,7 @@ linelength=120 # As in .clang-format
|
|||||||
|
|
||||||
# Unused filters
|
# Unused filters
|
||||||
filter=-build/c++11 # Reports e.g. chrono and thread, which overlap with Chromium's API. Not applicable to general C++ projects.
|
filter=-build/c++11 # Reports e.g. chrono and thread, which overlap with Chromium's API. Not applicable to general C++ projects.
|
||||||
|
filter=-build/c++17 # google only restrictions not relevant
|
||||||
filter=-build/include_order # Requires unusual include order that encourages creating not self-contained headers
|
filter=-build/include_order # Requires unusual include order that encourages creating not self-contained headers
|
||||||
filter=-build/include_subdir # Prevents including files in current directory for whatever reason
|
filter=-build/include_subdir # Prevents including files in current directory for whatever reason
|
||||||
filter=-readability/nolint # Conflicts with clang-tidy
|
filter=-readability/nolint # Conflicts with clang-tidy
|
||||||
@ -13,3 +14,4 @@ filter=-runtime/string # Requires not using static const strings which makes th
|
|||||||
filter=-whitespace/blank_line # Unnecessarily strict with blank lines that otherwise help with readability
|
filter=-whitespace/blank_line # Unnecessarily strict with blank lines that otherwise help with readability
|
||||||
filter=-whitespace/indent # Requires strange 3-space indent of private/protected/public markers
|
filter=-whitespace/indent # Requires strange 3-space indent of private/protected/public markers
|
||||||
filter=-whitespace/parens,-whitespace/braces # Conflict with clang-format
|
filter=-whitespace/parens,-whitespace/braces # Conflict with clang-format
|
||||||
|
filter=-whitespace/newline # handled by clang-format
|
||||||
|
10
README.md
10
README.md
@ -158,8 +158,6 @@ installation fuss.
|
|||||||
There are some other possible "features" that are intentionally not supported by
|
There are some other possible "features" that are intentionally not supported by
|
||||||
this library:
|
this library:
|
||||||
|
|
||||||
- Non-standard variations on syntax, like `-long` options. This is non-standard
|
|
||||||
and should be avoided, so that is enforced by this library.
|
|
||||||
- Completion of partial options, such as Python's `argparse` supplies for
|
- Completion of partial options, such as Python's `argparse` supplies for
|
||||||
incomplete arguments. It's better not to guess. Most third party command line
|
incomplete arguments. It's better not to guess. Most third party command line
|
||||||
parsers for python actually reimplement command line parsing rather than using
|
parsers for python actually reimplement command line parsing rather than using
|
||||||
@ -904,6 +902,14 @@ option_groups. These are:
|
|||||||
the form of `/s /long /file:file_name.ext` This option does not change how
|
the form of `/s /long /file:file_name.ext` This option does not change how
|
||||||
options are specified in the `add_option` calls or the ability to process
|
options are specified in the `add_option` calls or the ability to process
|
||||||
options in the form of `-s --long --file=file_name.ext`.
|
options in the form of `-s --long --file=file_name.ext`.
|
||||||
|
- `.allow_non_standard_option_names()`:🚧 Allow specification of single `-` long
|
||||||
|
form option names. This is not recommended but is available to enable
|
||||||
|
reworking of existing interfaces. If this modifier is enabled on an app or
|
||||||
|
subcommand, options or flags can be specified like normal but instead of
|
||||||
|
throwing an exception, long form single dash option names will be allowed. It
|
||||||
|
is not allowed to have a single character short option starting with the same
|
||||||
|
character as a single dash long form name; for example, `-s` and `-single` are
|
||||||
|
not allowed in the same application.
|
||||||
- `.fallthrough()`: Allow extra unmatched options and positionals to "fall
|
- `.fallthrough()`: Allow extra unmatched options and positionals to "fall
|
||||||
through" and be matched on a parent option. Subcommands by default are allowed
|
through" and be matched on a parent option. Subcommands by default are allowed
|
||||||
to "fall through" as in they will first attempt to match on the current
|
to "fall through" as in they will first attempt to match on the current
|
||||||
|
@ -22,7 +22,7 @@ jobs:
|
|||||||
- job: CppLint
|
- job: CppLint
|
||||||
pool:
|
pool:
|
||||||
vmImage: "ubuntu-latest"
|
vmImage: "ubuntu-latest"
|
||||||
container: sharaku/cpplint:latest
|
container: helics/buildenv:cpplint
|
||||||
steps:
|
steps:
|
||||||
- bash: cpplint --counting=detailed --recursive examples include/CLI tests
|
- bash: cpplint --counting=detailed --recursive examples include/CLI tests
|
||||||
displayName: Checking against google style guide
|
displayName: Checking against google style guide
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <CLI/CLI.hpp>
|
#include <CLI/CLI.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
// example file to demonstrate a custom lexical cast function
|
// example file to demonstrate a custom lexical cast function
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <CLI/CLI.hpp>
|
#include <CLI/CLI.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class MyFormatter : public CLI::Formatter {
|
class MyFormatter : public CLI::Formatter {
|
||||||
public:
|
public:
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <CLI/CLI.hpp>
|
#include <CLI/CLI.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -260,6 +260,9 @@ class App {
|
|||||||
/// This is potentially useful as a modifier subcommand
|
/// This is potentially useful as a modifier subcommand
|
||||||
bool silent_{false};
|
bool silent_{false};
|
||||||
|
|
||||||
|
/// indicator that the subcommand should allow non-standard option arguments, such as -single_dash_flag
|
||||||
|
bool allow_non_standard_options_{false};
|
||||||
|
|
||||||
/// Counts the number of times this command/subcommand was parsed
|
/// Counts the number of times this command/subcommand was parsed
|
||||||
std::uint32_t parsed_{0U};
|
std::uint32_t parsed_{0U};
|
||||||
|
|
||||||
@ -392,6 +395,12 @@ class App {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// allow non standard option names
|
||||||
|
App *allow_non_standard_option_names(bool allowed = true) {
|
||||||
|
allow_non_standard_options_ = allowed;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the subcommand to be disabled by default, so on clear(), at the start of each parse it is disabled
|
/// Set the subcommand to be disabled by default, so on clear(), at the start of each parse it is disabled
|
||||||
App *disabled_by_default(bool disable = true) {
|
App *disabled_by_default(bool disable = true) {
|
||||||
if(disable) {
|
if(disable) {
|
||||||
@ -1146,6 +1155,9 @@ class App {
|
|||||||
/// Get the status of silence
|
/// Get the status of silence
|
||||||
CLI11_NODISCARD bool get_silent() const { return silent_; }
|
CLI11_NODISCARD bool get_silent() const { return silent_; }
|
||||||
|
|
||||||
|
/// Get the status of silence
|
||||||
|
CLI11_NODISCARD bool get_allow_non_standard_option_names() const { return allow_non_standard_options_; }
|
||||||
|
|
||||||
/// Get the status of disabled
|
/// Get the status of disabled
|
||||||
CLI11_NODISCARD bool get_immediate_callback() const { return immediate_callback_; }
|
CLI11_NODISCARD bool get_immediate_callback() const { return immediate_callback_; }
|
||||||
|
|
||||||
|
@ -341,9 +341,13 @@ class Option : public OptionBase<Option> {
|
|||||||
///@}
|
///@}
|
||||||
|
|
||||||
/// 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 option_name, std::string option_description, callback_t callback, App *parent)
|
Option(std::string option_name,
|
||||||
|
std::string option_description,
|
||||||
|
callback_t callback,
|
||||||
|
App *parent,
|
||||||
|
bool allow_non_standard = false)
|
||||||
: description_(std::move(option_description)), parent_(parent), callback_(std::move(callback)) {
|
: description_(std::move(option_description)), parent_(parent), callback_(std::move(callback)) {
|
||||||
std::tie(snames_, lnames_, pname_) = detail::get_names(detail::split_names(option_name));
|
std::tie(snames_, lnames_, pname_) = detail::get_names(detail::split_names(option_name), allow_non_standard);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -39,7 +39,7 @@ CLI11_INLINE std::vector<std::pair<std::string, std::string>> get_default_flag_v
|
|||||||
|
|
||||||
/// 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
|
||||||
CLI11_INLINE std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>
|
CLI11_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, bool allow_non_standard = false);
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
// [CLI11:split_hpp:end]
|
// [CLI11:split_hpp:end]
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <cstdio>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
// [CLI11:public_includes:set]
|
// [CLI11:public_includes:set]
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -161,7 +162,7 @@ CLI11_INLINE Option *App::add_option(std::string option_name,
|
|||||||
std::string option_description,
|
std::string option_description,
|
||||||
bool defaulted,
|
bool defaulted,
|
||||||
std::function<std::string()> func) {
|
std::function<std::string()> func) {
|
||||||
Option myopt{option_name, option_description, option_callback, this};
|
Option myopt{option_name, option_description, option_callback, this, allow_non_standard_options_};
|
||||||
|
|
||||||
if(std::find_if(std::begin(options_), std::end(options_), [&myopt](const Option_p &v) { return *v == myopt; }) ==
|
if(std::find_if(std::begin(options_), std::end(options_), [&myopt](const Option_p &v) { return *v == myopt; }) ==
|
||||||
std::end(options_)) {
|
std::end(options_)) {
|
||||||
@ -191,9 +192,34 @@ CLI11_INLINE Option *App::add_option(std::string option_name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(allow_non_standard_options_ && !myopt.snames_.empty()) {
|
||||||
|
for(auto &sname : myopt.snames_) {
|
||||||
|
if(sname.length() > 1) {
|
||||||
|
std::string test_name;
|
||||||
|
test_name.push_back('-');
|
||||||
|
test_name.push_back(sname.front());
|
||||||
|
auto *op = get_option_no_throw(test_name);
|
||||||
|
if(op != nullptr) {
|
||||||
|
throw(OptionAlreadyAdded("added option interferes with existing short option: " + sname));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(auto &opt : options_) {
|
||||||
|
for(const auto &osn : opt->snames_) {
|
||||||
|
if(osn.size() > 1) {
|
||||||
|
std::string test_name;
|
||||||
|
test_name.push_back(osn.front());
|
||||||
|
if(myopt.check_sname(test_name)) {
|
||||||
|
throw(OptionAlreadyAdded("added option interferes with existing non standard option: " +
|
||||||
|
osn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
options_.emplace_back();
|
options_.emplace_back();
|
||||||
Option_p &option = options_.back();
|
Option_p &option = options_.back();
|
||||||
option.reset(new Option(option_name, option_description, option_callback, this));
|
option.reset(new Option(option_name, option_description, option_callback, this, allow_non_standard_options_));
|
||||||
|
|
||||||
// Set the default string capture function
|
// Set the default string capture function
|
||||||
option->default_function(func);
|
option->default_function(func);
|
||||||
@ -1888,7 +1914,8 @@ App::_parse_arg(std::vector<std::string> &args, detail::Classifier current_type,
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Option not found
|
// Option not found
|
||||||
if(op_ptr == std::end(options_)) {
|
while(op_ptr == std::end(options_)) {
|
||||||
|
// using while so we can break
|
||||||
for(auto &subc : subcommands_) {
|
for(auto &subc : subcommands_) {
|
||||||
if(subc->name_.empty() && !subc->disabled_) {
|
if(subc->name_.empty() && !subc->disabled_) {
|
||||||
if(subc->_parse_arg(args, current_type, local_processing_only)) {
|
if(subc->_parse_arg(args, current_type, local_processing_only)) {
|
||||||
@ -1899,6 +1926,20 @@ App::_parse_arg(std::vector<std::string> &args, detail::Classifier current_type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(allow_non_standard_options_ && current_type == detail::Classifier::SHORT && current.size() > 2) {
|
||||||
|
std::string narg_name;
|
||||||
|
std::string nvalue;
|
||||||
|
detail::split_long(std::string{'-'} + current, narg_name, nvalue);
|
||||||
|
op_ptr = std::find_if(std::begin(options_), std::end(options_), [narg_name](const Option_p &opt) {
|
||||||
|
return opt->check_sname(narg_name);
|
||||||
|
});
|
||||||
|
if(op_ptr != std::end(options_)) {
|
||||||
|
arg_name = narg_name;
|
||||||
|
value = nvalue;
|
||||||
|
rest.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// don't capture missing if this is a nameless subcommand and nameless subcommands can't fallthrough
|
// don't capture missing if this is a nameless subcommand and nameless subcommands can't fallthrough
|
||||||
if(parent_ != nullptr && name_.empty()) {
|
if(parent_ != nullptr && name_.empty()) {
|
||||||
|
@ -103,7 +103,7 @@ CLI11_INLINE std::vector<std::pair<std::string, std::string>> get_default_flag_v
|
|||||||
}
|
}
|
||||||
|
|
||||||
CLI11_INLINE std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>
|
CLI11_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, bool allow_non_standard) {
|
||||||
|
|
||||||
std::vector<std::string> short_names;
|
std::vector<std::string> short_names;
|
||||||
std::vector<std::string> long_names;
|
std::vector<std::string> long_names;
|
||||||
@ -113,23 +113,35 @@ get_names(const std::vector<std::string> &input) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(name.length() > 1 && name[0] == '-' && name[1] != '-') {
|
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 if(name.length() > 2)
|
} else if(name.length() > 2) {
|
||||||
|
if(allow_non_standard) {
|
||||||
|
name = name.substr(1);
|
||||||
|
if(valid_name_string(name)) {
|
||||||
|
short_names.push_back(name);
|
||||||
|
} else {
|
||||||
|
throw BadNameString::BadLongName(name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
throw BadNameString::MissingDash(name);
|
throw BadNameString::MissingDash(name);
|
||||||
else
|
}
|
||||||
|
} else {
|
||||||
throw BadNameString::OneCharName(name);
|
throw BadNameString::OneCharName(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::BadLongName(name);
|
throw BadNameString::BadLongName(name);
|
||||||
|
}
|
||||||
} else if(name == "-" || name == "--" || name == "++") {
|
} else if(name == "-" || name == "--" || name == "++") {
|
||||||
throw BadNameString::ReservedName(name);
|
throw BadNameString::ReservedName(name);
|
||||||
} else {
|
} else {
|
||||||
if(!pos_name.empty())
|
if(!pos_name.empty()) {
|
||||||
throw BadNameString::MultiPositionalNames(name);
|
throw BadNameString::MultiPositionalNames(name);
|
||||||
|
}
|
||||||
if(valid_name_string(name)) {
|
if(valid_name_string(name)) {
|
||||||
pos_name = name;
|
pos_name = name;
|
||||||
} else {
|
} else {
|
||||||
|
@ -13,6 +13,9 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
TEST_CASE_METHOD(TApp, "OneFlagShort", "[app]") {
|
TEST_CASE_METHOD(TApp, "OneFlagShort", "[app]") {
|
||||||
app.add_flag("-c,--count");
|
app.add_flag("-c,--count");
|
||||||
@ -663,6 +666,15 @@ TEST_CASE_METHOD(TApp, "singledash", "[app]") {
|
|||||||
} catch(...) {
|
} catch(...) {
|
||||||
CHECK(false);
|
CHECK(false);
|
||||||
}
|
}
|
||||||
|
app.allow_non_standard_option_names();
|
||||||
|
try {
|
||||||
|
app.add_option("-!I{am}bad");
|
||||||
|
} catch(const CLI::BadNameString &e) {
|
||||||
|
std::string str = e.what();
|
||||||
|
CHECK_THAT(str, Contains("!I{am}bad"));
|
||||||
|
} catch(...) {
|
||||||
|
CHECK(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(TApp, "FlagLikeOption", "[app]") {
|
TEST_CASE_METHOD(TApp, "FlagLikeOption", "[app]") {
|
||||||
@ -2389,6 +2401,45 @@ TEST_CASE_METHOD(TApp, "OrderedModifyingTransforms", "[app]") {
|
|||||||
CHECK(std::vector<std::string>({"one21", "two21"}) == val);
|
CHECK(std::vector<std::string>({"one21", "two21"}) == val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// non standard options
|
||||||
|
TEST_CASE_METHOD(TApp, "nonStandardOptions", "[app]") {
|
||||||
|
std::string string1;
|
||||||
|
CHECK_THROWS_AS(app.add_option("-single", string1), CLI::BadNameString);
|
||||||
|
app.allow_non_standard_option_names();
|
||||||
|
CHECK(app.get_allow_non_standard_option_names());
|
||||||
|
app.add_option("-single", string1);
|
||||||
|
args = {"-single", "string1"};
|
||||||
|
|
||||||
|
run();
|
||||||
|
|
||||||
|
CHECK(string1 == "string1");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(TApp, "nonStandardOptions2", "[app]") {
|
||||||
|
std::vector<std::string> strings;
|
||||||
|
app.allow_non_standard_option_names();
|
||||||
|
app.add_option("-single,--single,-m", strings);
|
||||||
|
args = {"-single", "string1", "--single", "string2"};
|
||||||
|
|
||||||
|
run();
|
||||||
|
|
||||||
|
CHECK(strings == std::vector<std::string>{"string1", "string2"});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(TApp, "nonStandardOptionsIntersect", "[app]") {
|
||||||
|
std::vector<std::string> strings;
|
||||||
|
app.allow_non_standard_option_names();
|
||||||
|
app.add_option("-s,-t");
|
||||||
|
CHECK_THROWS_AS(app.add_option("-single,--single", strings), CLI::OptionAlreadyAdded);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(TApp, "nonStandardOptionsIntersect2", "[app]") {
|
||||||
|
std::vector<std::string> strings;
|
||||||
|
app.allow_non_standard_option_names();
|
||||||
|
app.add_option("-single,--single", strings);
|
||||||
|
CHECK_THROWS_AS(app.add_option("-s,-t"), CLI::OptionAlreadyAdded);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(TApp, "ThrowingTransform", "[app]") {
|
TEST_CASE_METHOD(TApp, "ThrowingTransform", "[app]") {
|
||||||
std::string val;
|
std::string val;
|
||||||
auto *m = app.add_option("-m,--mess", val);
|
auto *m = app.add_option("-m,--mess", val);
|
||||||
|
@ -13,17 +13,17 @@
|
|||||||
#include <boost/container/static_vector.hpp>
|
#include <boost/container/static_vector.hpp>
|
||||||
#include <boost/container/vector.hpp>
|
#include <boost/container/vector.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
using namespace boost::container;
|
|
||||||
|
|
||||||
TEMPLATE_TEST_CASE("Boost container single",
|
TEMPLATE_TEST_CASE("Boost container single",
|
||||||
"[boost][optional]",
|
"[boost][optional]",
|
||||||
(small_vector<int, 2>),
|
(boost::container::small_vector<int, 2>),
|
||||||
(small_vector<int, 3>),
|
(boost::container::small_vector<int, 3>),
|
||||||
flat_set<int>,
|
boost::container::flat_set<int>,
|
||||||
stable_vector<int>,
|
boost::container::stable_vector<int>,
|
||||||
slist<int>) {
|
boost::container::slist<int>) {
|
||||||
TApp tapp;
|
TApp tapp;
|
||||||
TestType cv;
|
TestType cv;
|
||||||
CLI::Option *opt = tapp.app.add_option("-v", cv);
|
CLI::Option *opt = tapp.app.add_option("-v", cv);
|
||||||
@ -45,12 +45,12 @@ using isp = std::pair<int, std::string>;
|
|||||||
|
|
||||||
TEMPLATE_TEST_CASE("Boost container pair",
|
TEMPLATE_TEST_CASE("Boost container pair",
|
||||||
"[boost][optional]",
|
"[boost][optional]",
|
||||||
stable_vector<isp>,
|
boost::container::stable_vector<isp>,
|
||||||
(small_vector<isp, 2>),
|
(boost::container::small_vector<isp, 2>),
|
||||||
flat_set<isp>,
|
boost::container::flat_set<isp>,
|
||||||
slist<isp>,
|
boost::container::slist<isp>,
|
||||||
vector<isp>,
|
boost::container::vector<isp>,
|
||||||
(flat_map<int, std::string>)) {
|
(boost::container::flat_map<int, std::string>)) {
|
||||||
|
|
||||||
TApp tapp;
|
TApp tapp;
|
||||||
TestType cv;
|
TestType cv;
|
||||||
@ -71,10 +71,10 @@ using tup_obj = std::tuple<int, std::string, double>;
|
|||||||
|
|
||||||
TEMPLATE_TEST_CASE("Boost container tuple",
|
TEMPLATE_TEST_CASE("Boost container tuple",
|
||||||
"[boost][optional]",
|
"[boost][optional]",
|
||||||
(small_vector<tup_obj, 3>),
|
(boost::container::small_vector<tup_obj, 3>),
|
||||||
stable_vector<tup_obj>,
|
boost::container::stable_vector<tup_obj>,
|
||||||
flat_set<tup_obj>,
|
boost::container::flat_set<tup_obj>,
|
||||||
slist<tup_obj>) {
|
boost::container::slist<tup_obj>) {
|
||||||
TApp tapp;
|
TApp tapp;
|
||||||
TestType cv;
|
TestType cv;
|
||||||
|
|
||||||
@ -90,24 +90,24 @@ TEMPLATE_TEST_CASE("Boost container tuple",
|
|||||||
CHECK(3u == cv.size());
|
CHECK(3u == cv.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
using icontainer1 = vector<int>;
|
using icontainer1 = boost::container::vector<int>;
|
||||||
using icontainer2 = flat_set<int>;
|
using icontainer2 = boost::container::flat_set<int>;
|
||||||
using icontainer3 = slist<int>;
|
using icontainer3 = boost::container::slist<int>;
|
||||||
|
|
||||||
TEMPLATE_TEST_CASE("Boost container container",
|
TEMPLATE_TEST_CASE("Boost container container",
|
||||||
"[boost][optional]",
|
"[boost][optional]",
|
||||||
std::vector<icontainer1>,
|
std::vector<icontainer1>,
|
||||||
slist<icontainer1>,
|
boost::container::slist<icontainer1>,
|
||||||
flat_set<icontainer1>,
|
boost::container::flat_set<icontainer1>,
|
||||||
(small_vector<icontainer1, 2>),
|
(boost::container::small_vector<icontainer1, 2>),
|
||||||
std::vector<icontainer2>,
|
std::vector<icontainer2>,
|
||||||
slist<icontainer2>,
|
boost::container::slist<icontainer2>,
|
||||||
flat_set<icontainer2>,
|
boost::container::flat_set<icontainer2>,
|
||||||
stable_vector<icontainer2>,
|
boost::container::stable_vector<icontainer2>,
|
||||||
(static_vector<icontainer2, 10>),
|
(boost::container::static_vector<icontainer2, 10>),
|
||||||
slist<icontainer3>,
|
boost::container::slist<icontainer3>,
|
||||||
flat_set<icontainer3>,
|
boost::container::flat_set<icontainer3>,
|
||||||
(static_vector<icontainer3, 10>)) {
|
(boost::container::static_vector<icontainer3, 10>)) {
|
||||||
|
|
||||||
TApp tapp;
|
TApp tapp;
|
||||||
TestType cv;
|
TestType cv;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <complex>
|
#include <complex>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
using cx = std::complex<double>;
|
using cx = std::complex<double>;
|
||||||
|
|
||||||
|
@ -7,7 +7,12 @@
|
|||||||
#include "app_helper.hpp"
|
#include "app_helper.hpp"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
TEST_CASE("StringBased: convert_arg_for_ini", "[config]") {
|
TEST_CASE("StringBased: convert_arg_for_ini", "[config]") {
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "app_helper.hpp"
|
#include "app_helper.hpp"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
TEST_CASE_METHOD(TApp, "AddingExistingShort", "[creation]") {
|
TEST_CASE_METHOD(TApp, "AddingExistingShort", "[creation]") {
|
||||||
CLI::Option *opt = app.add_flag("-c,--count");
|
CLI::Option *opt = app.add_flag("-c,--count");
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class SimpleFormatter : public CLI::FormatterBase {
|
class SimpleFormatter : public CLI::FormatterBase {
|
||||||
public:
|
public:
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "../fuzz/fuzzApp.hpp"
|
#include "../fuzz/fuzzApp.hpp"
|
||||||
#include "app_helper.hpp"
|
#include "app_helper.hpp"
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
std::string loadFailureFile(const std::string &type, int index) {
|
std::string loadFailureFile(const std::string &type, int index) {
|
||||||
std::string fileName(TEST_FILE_FOLDER "/fuzzFail/");
|
std::string fileName(TEST_FILE_FOLDER "/fuzzFail/");
|
||||||
|
@ -14,6 +14,10 @@
|
|||||||
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
TEST_CASE("THelp: Basic", "[help]") {
|
TEST_CASE("THelp: Basic", "[help]") {
|
||||||
CLI::App app{"My prog"};
|
CLI::App app{"My prog"};
|
||||||
@ -286,6 +290,20 @@ TEST_CASE("THelp: OptionalPositionalAndOptions", "[help]") {
|
|||||||
CHECK_THAT(help, Contains("AnotherProgram [OPTIONS] [something]"));
|
CHECK_THAT(help, Contains("AnotherProgram [OPTIONS] [something]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("THelp: NonStandardOptions", "[help]") {
|
||||||
|
CLI::App app{"My prog", "nonstandard"};
|
||||||
|
app.allow_non_standard_option_names();
|
||||||
|
app.add_flag("-q,--quick");
|
||||||
|
app.add_flag("-slow");
|
||||||
|
app.add_option("--fast,-not-slow", "a description of what is");
|
||||||
|
std::string x;
|
||||||
|
app.add_option("something", x, "My option here");
|
||||||
|
|
||||||
|
std::string help = app.help();
|
||||||
|
|
||||||
|
CHECK_THAT(help, Contains("-not-slow"));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("THelp: RequiredPositionalAndOptions", "[help]") {
|
TEST_CASE("THelp: RequiredPositionalAndOptions", "[help]") {
|
||||||
CLI::App app{"My prog"};
|
CLI::App app{"My prog"};
|
||||||
app.add_flag("-q,--quick");
|
app.add_flag("-q,--quick");
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class NotStreamable {};
|
class NotStreamable {};
|
||||||
|
|
||||||
|
@ -8,7 +8,9 @@
|
|||||||
|
|
||||||
#include <complex>
|
#include <complex>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using cx = std::complex<double>;
|
using cx = std::complex<double>;
|
||||||
|
|
||||||
|
@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
#include "app_helper.hpp"
|
#include "app_helper.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using vs_t = std::vector<std::string>;
|
using vs_t = std::vector<std::string>;
|
||||||
|
|
||||||
TEST_CASE_METHOD(TApp, "BasicOptionGroup", "[optiongroup]") {
|
TEST_CASE_METHOD(TApp, "BasicOptionGroup", "[optiongroup]") {
|
||||||
|
@ -16,10 +16,13 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <forward_list>
|
#include <forward_list>
|
||||||
|
#include <limits>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "app_helper.hpp"
|
#include "app_helper.hpp"
|
||||||
|
|
||||||
|
@ -7,6 +7,10 @@
|
|||||||
#include "app_helper.hpp"
|
#include "app_helper.hpp"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
static_assert(CLI::is_shared_ptr<std::shared_ptr<int>>::value == true, "is_shared_ptr should work on shared pointers");
|
static_assert(CLI::is_shared_ptr<std::shared_ptr<int>>::value == true, "is_shared_ptr should work on shared pointers");
|
||||||
static_assert(CLI::is_shared_ptr<int *>::value == false, "is_shared_ptr should work on pointers");
|
static_assert(CLI::is_shared_ptr<int *>::value == false, "is_shared_ptr should work on pointers");
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using input_t = std::vector<std::string>;
|
using input_t = std::vector<std::string>;
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
TEST_CASE_METHOD(TApp, "ExistingExeCheck", "[stringparse]") {
|
TEST_CASE_METHOD(TApp, "ExistingExeCheck", "[stringparse]") {
|
||||||
|
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
#include "app_helper.hpp"
|
#include "app_helper.hpp"
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using vs_t = std::vector<std::string>;
|
using vs_t = std::vector<std::string>;
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
@ -11,7 +11,12 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#if defined(CLI11_CPP17)
|
#if defined(CLI11_CPP17)
|
||||||
#if defined(__has_include)
|
#if defined(__has_include)
|
||||||
@ -78,7 +83,7 @@ TEST_CASE_METHOD(TApp, "EnumTransform", "[transform]") {
|
|||||||
// transformer doesn't do any checking so this still works
|
// transformer doesn't do any checking so this still works
|
||||||
args = {"-s", "5"};
|
args = {"-s", "5"};
|
||||||
run();
|
run();
|
||||||
CHECK(std::int16_t(5) == static_cast<std::int16_t>(value));
|
CHECK(static_cast<std::int16_t>(5) == static_cast<std::int16_t>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(TApp, "EnumCheckedTransform", "[transform]") {
|
TEST_CASE_METHOD(TApp, "EnumCheckedTransform", "[transform]") {
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
#include "app_helper.hpp"
|
#include "app_helper.hpp"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
TEST_CASE_METHOD(TApp, "True Bool Option", "[bool][flag]") {
|
TEST_CASE_METHOD(TApp, "True Bool Option", "[bool][flag]") {
|
||||||
// Strings needed here due to MSVC 2015.
|
// Strings needed here due to MSVC 2015.
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
#include <CLI/CLI.hpp>
|
#include <CLI/CLI.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
CLI::App app{"App description"};
|
CLI::App app{"App description"};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user