This commit is contained in:
zrshonor 2021-07-07 15:05:02 +08:00
parent 174510285a
commit e453d2c79d
3 changed files with 1958 additions and 2123 deletions

View File

@ -1,17 +1,14 @@
/*
Copyright (c) 2014, 2015, 2016, 2017 Jarryd Beck
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,7 +16,6 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef CXXOPTS_HPP_INCLUDED
@ -665,7 +661,7 @@ namespace cxxopts
void stringstream_parser(const std::string& text, T& value)
{
std::stringstream in(text);
in >> value;
in >> value; //!!!!niubi!
if (!in) {
throw_or_mimic<argument_incorrect_type>(text);
}
@ -778,7 +774,6 @@ namespace cxxopts
value.emplace_back(std::move(v));
}
}
#ifdef CXXOPTS_HAS_OPTIONAL
template <typename T>
void
@ -1136,7 +1131,7 @@ namespace cxxopts
#if defined(__GNUC__)
#if __GNUC__ <= 10 && __GNUC_MINOR__ <= 1
#pragma GCC diagnostic push
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Werror=null-dereference"
#endif
#endif
@ -1580,7 +1575,7 @@ namespace cxxopts
constexpr size_t OPTION_DESC_GAP = 2;
std::basic_regex<char> option_matcher
("--([[:alnum:]][-_[:alnum:]]+)(=(.*))?|-([[:alnum:]]+)");
("-([[:alnum:]][-_[:alnum:]]+)(=(.*))?|-([[:alnum:]]{1})(=(.*))?");
std::basic_regex<char> option_specifier
("(([[:alnum:]]),)?[ ]*([[:alnum:]][-_[:alnum:]]*)?");
@ -1762,38 +1757,38 @@ namespace cxxopts
}
} // namespace
inline
void
Options::add_options
(
inline
void
Options::add_options
(
const std::string &group,
std::initializer_list<Option> options
)
{
)
{
OptionAdder option_adder(*this, group);
for (const auto &option: options)
{
option_adder(option.opts_, option.desc_, option.value_, option.arg_help_);
}
}
}
inline
OptionAdder
Options::add_options(std::string group)
{
inline
OptionAdder
Options::add_options(std::string group)
{
return OptionAdder(*this, std::move(group));
}
}
inline
OptionAdder&
OptionAdder::operator()
(
inline
OptionAdder&
OptionAdder::operator()
(
const std::string& opts,
const std::string& desc,
const std::shared_ptr<const Value>& value,
std::string arg_help
)
{
)
{
std::match_results<const char*> result;
std::regex_match(opts.c_str(), result, option_specifier);
@ -1837,44 +1832,44 @@ OptionAdder::operator()
);
return *this;
}
}
inline
void
OptionParser::parse_default(const std::shared_ptr<OptionDetails>& details)
{
// TODO: remove the duplicate code here
inline
void
OptionParser::parse_default(const std::shared_ptr<OptionDetails>& details)
{
// ggTODO: remove the duplicate code here
auto& store = m_parsed[details->hash()];
store.parse_default(details);
}
}
inline
void
OptionParser::parse_option
(
inline
void
OptionParser::parse_option
(
const std::shared_ptr<OptionDetails>& value,
const std::string& /*name*/,
const std::string& arg
)
{
)
{
auto hash = value->hash();
auto& result = m_parsed[hash];
result.parse(value, arg);
m_sequential.emplace_back(value->long_name(), arg);
}
}
inline
void
OptionParser::checked_parse_arg
(
inline
void
OptionParser::checked_parse_arg
(
int argc,
const char* const* argv,
int& current,
const std::shared_ptr<OptionDetails>& value,
const std::string& name
)
{
)
{
if (current + 1 >= argc)
{
if (value->value().has_implicit())
@ -1898,19 +1893,19 @@ OptionParser::checked_parse_arg
++current;
}
}
}
}
inline
void
OptionParser::add_to_option(OptionMap::const_iterator iter, const std::string& option, const std::string& arg)
{
inline
void
OptionParser::add_to_option(OptionMap::const_iterator iter, const std::string& option, const std::string& arg)
{
parse_option(iter->second, option, arg);
}
}
inline
bool
OptionParser::consume_positional(const std::string& a, PositionalListIterator& next)
{
inline
bool
OptionParser::consume_positional(const std::string& a, PositionalListIterator& next)
{
while (next != m_positional.end())
{
auto iter = m_options.find(*next);
@ -1935,43 +1930,43 @@ OptionParser::consume_positional(const std::string& a, PositionalListIterator& n
}
return false;
}
}
inline
void
Options::parse_positional(std::string option)
{
inline
void
Options::parse_positional(std::string option)
{
parse_positional(std::vector<std::string>{std::move(option)});
}
}
inline
void
Options::parse_positional(std::vector<std::string> options)
{
inline
void
Options::parse_positional(std::vector<std::string> options)
{
m_positional = std::move(options);
m_positional_set.insert(m_positional.begin(), m_positional.end());
}
}
inline
void
Options::parse_positional(std::initializer_list<std::string> options)
{
inline
void
Options::parse_positional(std::initializer_list<std::string> options)
{
parse_positional(std::vector<std::string>(options));
}
}
inline
ParseResult
Options::parse(int argc, const char* const* argv)
{
inline
ParseResult
Options::parse(int argc, const char* const* argv)
{
OptionParser parser(*m_options, m_positional, m_allow_unrecognised);
return parser.parse(argc, argv);
}
}
inline ParseResult
OptionParser::parse(int argc, const char* const* argv)
{
inline ParseResult
OptionParser::parse(int argc, const char* const* argv)
{
int current = 1;
bool consume_remaining = false;
auto next_positional = m_positional.begin();
@ -1980,7 +1975,7 @@ OptionParser::parse(int argc, const char* const* argv)
while (current != argc)
{
if (strcmp(argv[current], "--") == 0)
if (strcmp(argv[current], "-") == 0)
{
consume_remaining = true;
++current;
@ -2018,38 +2013,21 @@ OptionParser::parse(int argc, const char* const* argv)
if (result[4].length() != 0)
{
const std::string& s = result[4];
for (std::size_t i = 0; i != s.size(); ++i)
{
std::string name(1, s[i]);
auto iter = m_options.find(name);
if (iter == m_options.end())
{
if (m_allow_unrecognised)
{
auto iter = m_options.find(s);
if(iter==m_options.end()){
if(!m_allow_unrecognised){
throw_or_mimic<option_not_exists_exception>(s);
}
++current;
continue;
}
//error
throw_or_mimic<option_not_exists_exception>(name);
}
auto value = iter->second;
if (i + 1 == s.size())
{
//it must be the last argument
checked_parse_arg(argc, argv, current, value, name);
}
else if (value->value().has_implicit())
{
parse_option(value, name, value->value().get_implicit_value());
}
else
{
//error
throw_or_mimic<option_requires_argument_exception>(name);
}
if(result[5].length()!=0){
parse_option(value,s,result[6]);
std::cout<<"The value is"<<result[6].str()<<std::endl;
}else{
checked_parse_arg(argc,argv,current,value,s);
}
}
else if (result[1].length() != 0)
@ -2077,7 +2055,6 @@ OptionParser::parse(int argc, const char* const* argv)
if (result[2].length() != 0)
{
//parse the option given
parse_option(opt, name, result[3]);
}
else
@ -2088,7 +2065,6 @@ OptionParser::parse(int argc, const char* const* argv)
}
}
++current;
}
@ -2125,12 +2101,12 @@ OptionParser::parse(int argc, const char* const* argv)
ParseResult parsed(std::move(m_keys), std::move(m_parsed), std::move(m_sequential), std::move(unmatched));
return parsed;
}
}
inline
void
OptionParser::finalise_aliases()
{
inline
void
OptionParser::finalise_aliases()
{
for (auto& option: m_options)
{
auto& detail = *option.second;
@ -2140,31 +2116,31 @@ OptionParser::finalise_aliases()
m_parsed.emplace(hash, OptionValue());
}
}
}
inline
void
Options::add_option
(
inline
void
Options::add_option
(
const std::string& group,
const Option& option
)
{
)
{
add_options(group, {option});
}
}
inline
void
Options::add_option
(
inline
void
Options::add_option
(
const std::string& group,
const std::string& s,
const std::string& l,
std::string desc,
const std::shared_ptr<const Value>& value,
std::string arg_help
)
{
)
{
auto stringDesc = toLocalString(std::move(desc));
auto option = std::make_shared<OptionDetails>(s, l, stringDesc, value);
@ -2192,28 +2168,28 @@ Options::add_option
std::move(arg_help),
value->is_container(),
value->is_boolean()});
}
}
inline
void
Options::add_one_option
(
inline
void
Options::add_one_option
(
const std::string& option,
const std::shared_ptr<OptionDetails>& details
)
{
)
{
auto in = m_options->emplace(option, details);
if (!in.second)
{
throw_or_mimic<option_exists_error>(option);
}
}
}
inline
String
Options::help_one_group(const std::string& g) const
{
inline
String
Options::help_one_group(const std::string& g) const
{
using OptionHelp = std::vector<std::pair<String, String>>;
auto group = m_help.find(g);
@ -2284,16 +2260,16 @@ Options::help_one_group(const std::string& g) const
}
return result;
}
}
inline
void
Options::generate_group_help
(
inline
void
Options::generate_group_help
(
String& result,
const std::vector<std::string>& print_groups
) const
{
) const
{
for (size_t i = 0; i != print_groups.size(); ++i)
{
const String& group_help_text = help_one_group(print_groups[i]);
@ -2307,12 +2283,12 @@ Options::generate_group_help
result += '\n';
}
}
}
}
inline
void
Options::generate_all_groups_help(String& result) const
{
inline
void
Options::generate_all_groups_help(String& result) const
{
std::vector<std::string> all_groups;
std::transform(
@ -2326,12 +2302,12 @@ Options::generate_all_groups_help(String& result) const
);
generate_group_help(result, all_groups);
}
}
inline
std::string
Options::help(const std::vector<std::string>& help_groups) const
{
inline
std::string
Options::help(const std::vector<std::string>& help_groups) const
{
String result = m_help_string + "\nUsage:\n " +
toLocalString(m_program) + " " + toLocalString(m_custom_help);
@ -2351,12 +2327,12 @@ Options::help(const std::vector<std::string>& help_groups) const
}
return toUTF8String(result);
}
}
inline
std::vector<std::string>
Options::groups() const
{
inline
std::vector<std::string>
Options::groups() const
{
std::vector<std::string> g;
std::transform(
@ -2370,15 +2346,16 @@ Options::groups() const
);
return g;
}
}
inline
const HelpGroupDetails&
Options::group_help(const std::string& group) const
{
inline
const HelpGroupDetails&
Options::group_help(const std::string& group) const
{
return m_help.at(group);
}
}
} // namespace cxxopts
#endif //CXXOPTS_HPP_INCLUDED

View File

@ -1,171 +1,57 @@
/*
Copyright (c) 2014 Jarryd Beck
#include<cxxopts.hpp>
#include<iostream>
#include<vector>
using namespace std;
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
void parse(int argc,const char* argv[]){
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
try{
cxxopts::Options options(argv[0],"My test example");
options.allow_unrecognised_options();
options.show_positional_help();
options.set_width(70).set_tab_expansion().add_options("MyOption")
("f,float","a float variable",cxxopts::value<float>()->implicit_value("10"),"file")
("i,int","a integer variable",cxxopts::value<int>())
("l,float_list","a float list",cxxopts::value<vector<float>>())
("help","print help");
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
auto result = options.parse(argc,argv);
*/
#include <iostream>
#include "cxxopts.hpp"
void
parse(int argc, const char* argv[])
{
try
{
cxxopts::Options options(argv[0], " - example command line options");
options
.positional_help("[optional args]")
.show_positional_help();
bool apple = false;
options
.set_width(70)
.set_tab_expansion()
.allow_unrecognised_options()
.add_options()
("a,apple", "an apple", cxxopts::value<bool>(apple))
("b,bob", "Bob")
("char", "A character", cxxopts::value<char>())
("t,true", "True", cxxopts::value<bool>()->default_value("true"))
("f, file", "File", cxxopts::value<std::vector<std::string>>(), "FILE")
("i,input", "Input", cxxopts::value<std::string>())
("o,output", "Output file", cxxopts::value<std::string>()
->default_value("a.out")->implicit_value("b.def"), "BIN")
("x", "A short-only option", cxxopts::value<std::string>())
("positional",
"Positional arguments: these are the arguments that are entered "
"without an option", cxxopts::value<std::vector<std::string>>())
("long-description",
"thisisareallylongwordthattakesupthewholelineandcannotbebrokenataspace")
("help", "Print help")
("tab-expansion", "Tab\texpansion")
("int", "An integer", cxxopts::value<int>(), "N")
("float", "A floating point number", cxxopts::value<float>())
("vector", "A list of doubles", cxxopts::value<std::vector<double>>())
("option_that_is_too_long_for_the_help", "A very long option")
#ifdef CXXOPTS_USE_UNICODE
("unicode", u8"A help option with non-ascii: à. Here the size of the"
" string should be correct")
#endif
;
options.add_options("Group")
("c,compile", "compile")
("d,drop", "drop", cxxopts::value<std::vector<std::string>>());
options.parse_positional({"input", "output", "positional"});
auto result = options.parse(argc, argv);
if (result.count("help"))
{
std::cout << options.help({"", "Group"}) << std::endl;
if(result.count("help")){
cout<<options.help({"MyOption"})<<endl;
exit(0);
}
if (apple)
{
std::cout << "Saw option a " << result.count("a") << " times " <<
std::endl;
if(result.count("i")){
cout<<"Saw the argument of int "<<result.count("i")<<" times"<<endl;
cout<<"The last value is "<<result["i"].as<int>()<<endl;
}
if (result.count("b"))
{
std::cout << "Saw option b" << std::endl;
if(result.count("f")){
cout<<"Saw the argument of float "<<result.count("f")<<" times"<<endl;
cout<<"The last value is "<<result["f"].as<float>()<<endl;
}
if (result.count("char"))
{
std::cout << "Saw a character " << result["char"].as<char>() << "" << std::endl;
if(result.count("l")){
auto list = result["l"].as<vector<float>>();
for(auto data:list){
cout<<data<<" ";
}
if (result.count("f"))
{
auto& ff = result["f"].as<std::vector<std::string>>();
std::cout << "Files" << std::endl;
for (const auto& f : ff)
{
std::cout << f << std::endl;
cout<<endl;
}
auto unmatched = result.unmatched();
for(auto data:unmatched){
cout<<data<<" ";
}
if (result.count("input"))
{
std::cout << "Input = " << result["input"].as<std::string>()
<< std::endl;
}
if (result.count("output"))
{
std::cout << "Output = " << result["output"].as<std::string>()
<< std::endl;
}
if (result.count("positional"))
{
std::cout << "Positional = {";
auto& v = result["positional"].as<std::vector<std::string>>();
for (const auto& s : v) {
std::cout << s << ", ";
}
std::cout << "}" << std::endl;
}
if (result.count("int"))
{
std::cout << "int = " << result["int"].as<int>() << std::endl;
}
if (result.count("float"))
{
std::cout << "float = " << result["float"].as<float>() << std::endl;
}
if (result.count("vector"))
{
std::cout << "vector = ";
const auto values = result["vector"].as<std::vector<double>>();
for (const auto& v : values) {
std::cout << v << ", ";
}
std::cout << std::endl;
}
std::cout << "Arguments remain = " << argc << std::endl;
auto arguments = result.arguments();
std::cout << "Saw " << arguments.size() << " arguments" << std::endl;
}
catch (const cxxopts::OptionException& e)
{
std::cout << "error parsing options: " << e.what() << std::endl;
exit(1);
cout<<endl;
}catch (cxxopts::OptionException &e){
e.what();
}
}
int main(int argc, const char* argv[])
{
parse(argc, argv);
int main(){
int argc = 11;
const char* argv[] = {"My_Group","-int","10","-i=30","20","-f","30","-help","40","-l","30,20,30,40,50,60"};
parse(argc,argv);
return 0;
}

View File

@ -58,15 +58,15 @@ TEST_CASE("Basic options", "[options]")
Argv argv({
"tester",
"--long",
"-long",
"-s",
"--value",
"-value",
"value",
"-a",
"b",
"-6",
"-p",
"--space",
"-space",
});
auto** actual_argv = argv.argv();
@ -175,7 +175,7 @@ TEST_CASE("Some positional explicit", "[positional]")
options.parse_positional({"input", "output", "positional"});
Argv av({"tester", "--output", "a", "b", "c", "d"});
Argv av({"tester", "-output", "a", "b", "c", "d"});
auto** argv = av.argv();
auto argc = av.argc();
@ -201,7 +201,7 @@ TEST_CASE("No positional with extras", "[positional]")
("dummy", "oh no", cxxopts::value<std::string>())
;
Argv av({"extras", "--", "a", "b", "c", "d"});
Argv av({"extras", "-", "a", "b", "c", "d"});
auto** argv = av.argv();
auto argc = av.argc();
@ -238,7 +238,7 @@ TEST_CASE("Empty with implicit value", "[implicit]")
("implicit", "Has implicit", cxxopts::value<std::string>()
->implicit_value("foo"));
Argv av({"implicit", "--implicit="});
Argv av({"implicit", "-implicit="});
auto** argv = av.argv();
auto argc = av.argc();
@ -257,7 +257,7 @@ TEST_CASE("Boolean without implicit value", "[implicit]")
->no_implicit_value());
SECTION("When no value provided") {
Argv av({"no_implicit", "--bool"});
Argv av({"no_implicit", "-bool"});
auto** argv = av.argv();
auto argc = av.argc();
@ -266,7 +266,7 @@ TEST_CASE("Boolean without implicit value", "[implicit]")
}
SECTION("With equal-separated true") {
Argv av({"no_implicit", "--bool=true"});
Argv av({"no_implicit", "-bool=true"});
auto** argv = av.argv();
auto argc = av.argc();
@ -277,7 +277,7 @@ TEST_CASE("Boolean without implicit value", "[implicit]")
}
SECTION("With equal-separated false") {
Argv av({"no_implicit", "--bool=false"});
Argv av({"no_implicit", "-bool=false"});
auto** argv = av.argv();
auto argc = av.argc();
@ -288,7 +288,7 @@ TEST_CASE("Boolean without implicit value", "[implicit]")
}
SECTION("With space-separated true") {
Argv av({"no_implicit", "--bool", "true"});
Argv av({"no_implicit", "-bool", "true"});
auto** argv = av.argv();
auto argc = av.argc();
@ -299,7 +299,7 @@ TEST_CASE("Boolean without implicit value", "[implicit]")
}
SECTION("With space-separated false") {
Argv av({"no_implicit", "--bool", "false"});
Argv av({"no_implicit", "-bool", "false"});
auto** argv = av.argv();
auto argc = av.argc();
@ -336,7 +336,7 @@ TEST_CASE("Default values", "[default]")
}
SECTION("When values provided") {
Argv av({"implicit", "--default", "5"});
Argv av({"implicit", "-default", "5"});
auto** argv = av.argv();
auto argc = av.argc();
@ -355,7 +355,7 @@ TEST_CASE("Parse into a reference", "[reference]")
options.add_options()
("ref", "A reference", cxxopts::value(value));
Argv av({"into_reference", "--ref", "42"});
Argv av({"into_reference", "-ref", "42"});
auto argv = av.argv();
auto argc = av.argc();
@ -371,7 +371,7 @@ TEST_CASE("Integers", "[options]")
options.add_options()
("positional", "Integers", cxxopts::value<std::vector<int>>());
Argv av({"ints", "--", "5", "6", "-6", "0", "0xab", "0xAf", "0x0"});
Argv av({"ints", "-", "5", "6", "-6", "0", "0xab", "0xAf", "0x0"});
auto** argv = av.argv();
auto argc = av.argc();
@ -398,7 +398,7 @@ TEST_CASE("Leading zero integers", "[options]")
options.add_options()
("positional", "Integers", cxxopts::value<std::vector<int>>());
Argv av({"ints", "--", "05", "06", "0x0ab", "0x0001"});
Argv av({"ints", "-", "05", "06", "0x0ab", "0x0001"});
auto** argv = av.argv();
auto argc = av.argc();
@ -422,7 +422,7 @@ TEST_CASE("Unsigned integers", "[options]")
options.add_options()
("positional", "Integers", cxxopts::value<std::vector<unsigned int>>());
Argv av({"ints", "--", "-2"});
Argv av({"ints", "-", "-2"});
auto** argv = av.argv();
auto argc = av.argc();
@ -439,7 +439,7 @@ TEST_CASE("Integer bounds", "[integer]")
SECTION("No overflow")
{
Argv av({"ints", "--", "127", "-128", "0x7f", "-0x80", "0x7e"});
Argv av({"ints", "-", "127", "-128", "0x7f", "-0x80", "0x7e"});
auto argv = av.argv();
auto argc = av.argc();
@ -481,7 +481,7 @@ TEST_CASE("Integer overflow", "[options]")
options.add_options()
("positional", "Integers", cxxopts::value<std::vector<int8_t>>());
Argv av({"ints", "--", "128"});
Argv av({"ints", "-", "128"});
auto argv = av.argv();
auto argc = av.argc();
@ -501,7 +501,7 @@ TEST_CASE("Floats", "[options]")
("double", "Double precision", cxxopts::value<double>())
("positional", "Floats", cxxopts::value<std::vector<float>>());
Argv av({"floats", "--double", "0.5", "--", "4", "-4", "1.5e6", "-1.5e6"});
Argv av({"floats", "-double", "0.5", "-", "4", "-4", "1.5e6", "-1.5e6"});
auto** argv = av.argv();
auto argc = av.argc();
@ -526,7 +526,7 @@ TEST_CASE("Invalid integers", "[integer]") {
options.add_options()
("positional", "Integers", cxxopts::value<std::vector<int>>());
Argv av({"ints", "--", "Ae"});
Argv av({"ints", "-", "Ae"});
auto** argv = av.argv();
auto argc = av.argc();
@ -551,7 +551,7 @@ TEST_CASE("Booleans", "[boolean]") {
options.parse_positional("others");
Argv av({"booleans", "--bool=false", "--debug=true", "--timing", "--verbose=1", "--dry-run=0", "extra"});
Argv av({"booleans", "-bool=false", "-debug=true", "-timing", "-verbose=1", "-dry-run=0", "extra"});
auto** argv = av.argv();
auto argc = av.argc();
@ -585,7 +585,7 @@ TEST_CASE("std::vector", "[vector]") {
options.add_options()
("vector", "an vector option", cxxopts::value<std::vector<double>>(vector));
Argv av({"vector", "--vector", "1,-2.1,3,4.5"});
Argv av({"vector", "-vector", "1,-2.1,3,4.5"});
auto** argv = av.argv();
auto argc = av.argc();
@ -622,15 +622,13 @@ TEST_CASE("Unrecognised options", "[options]") {
cxxopts::Options options("unknown_options", " - test unknown options");
options.add_options()
("long", "a long option")
("s,short", "a short option");
("long", "a long option");
Argv av({
"unknown_options",
"--unknown",
"--long",
"-su",
"--another_unknown",
"-unknown",
"-long",
"-another_unknown",
});
auto** argv = av.argv();
@ -644,36 +642,10 @@ TEST_CASE("Unrecognised options", "[options]") {
options.allow_unrecognised_options();
auto result = options.parse(argc, argv);
auto& unmatched = result.unmatched();
CHECK((unmatched == std::vector<std::string>{"--unknown", "--another_unknown"}));
CHECK((unmatched == std::vector<std::string>{"-unknown", "-another_unknown"}));
}
}
TEST_CASE("Allow bad short syntax", "[options]") {
cxxopts::Options options("unknown_options", " - test unknown options");
options.add_options()
("long", "a long option")
("s,short", "a short option");
Argv av({
"unknown_options",
"-some_bad_short",
});
auto** argv = av.argv();
auto argc = av.argc();
SECTION("Default behaviour") {
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_syntax_exception&);
}
SECTION("After allowing unrecognised options") {
options.allow_unrecognised_options();
CHECK_NOTHROW(options.parse(argc, argv));
REQUIRE(argc == 2);
CHECK_THAT(argv[1], Catch::Equals("-some_bad_short"));
}
}
TEST_CASE("Invalid option syntax", "[options]") {
cxxopts::Options options("invalid_syntax", " - test invalid syntax");
@ -700,7 +672,7 @@ TEST_CASE("Options empty", "[options]") {
Argv argv_({
"test",
"--unknown"
"-unknown"
});
auto argc = argv_.argc();
auto** argv = argv_.argv();
@ -726,7 +698,7 @@ TEST_CASE("Initializer list with group", "[options]") {
Argv argv({
"test",
"--address",
"-address",
"10.0.0.1",
"-p",
"8000",
@ -756,7 +728,7 @@ TEST_CASE("Option add with add_option(string, Option)", "[options]") {
Argv argv_({
"test",
"--test",
"-test",
"5",
"-a",
"4"