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

File diff suppressed because it is too large Load Diff

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;
exit(0);
if(result.count("help")){
cout<<options.help({"MyOption"})<<endl;
exit(0);
}
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("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("l")){
auto list = result["l"].as<vector<float>>();
for(auto data:list){
cout<<data<<" ";
}
cout<<endl;
}
auto unmatched = result.unmatched();
for(auto data:unmatched){
cout<<data<<" ";
}
cout<<endl;
}catch (cxxopts::OptionException &e){
e.what();
}
if (apple)
{
std::cout << "Saw option a " << result.count("a") << " times " <<
std::endl;
}
if (result.count("b"))
{
std::cout << "Saw option b" << std::endl;
}
if (result.count("char"))
{
std::cout << "Saw a character " << result["char"].as<char>() << "" << std::endl;
}
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;
}
}
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);
}
}
int main(int argc, const char* argv[])
{
parse(argc, argv);
return 0;
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"