From 80254a8e5e588751e93a2bdb04557b22b961389f Mon Sep 17 00:00:00 2001 From: gen740 Date: Wed, 6 Dec 2023 22:44:20 +0900 Subject: [PATCH] Fix constructor --- Argo/ArgoMetaParse.cc | 3 + Argo/ArgoParser.cc | 26 +++---- Argo/ArgoParserImpl.cc | 16 +++-- Taskfile.yml | 5 +- generator/generate.py | 1 - include/Argo.hh | 44 +++++++----- tests/ExampleCode.cc | 5 +- tests/parser.cc | 151 +++++++++++++++++++++++++++++------------ 8 files changed, 166 insertions(+), 85 deletions(-) diff --git a/Argo/ArgoMetaParse.cc b/Argo/ArgoMetaParse.cc index ddc80ee..0092ab6 100644 --- a/Argo/ArgoMetaParse.cc +++ b/Argo/ArgoMetaParse.cc @@ -3,6 +3,7 @@ module; export module Argo:MetaParse; import :std_module; import :Arg; +import :TypeTraits; // generator start here @@ -16,6 +17,7 @@ struct SubParser { }; template + requires(is_tuple_v) auto MetaParse(SubParsers sub_parsers, int index, int argc, char** argv) -> bool { return std::apply( @@ -29,6 +31,7 @@ auto MetaParse(SubParsers sub_parsers, int index, int argc, }; template + requires(is_tuple_v) constexpr auto ParserIndex(SubParsers sub_parsers, // std::string_view key) -> std::int64_t { return std::apply( diff --git a/Argo/ArgoParser.cc b/Argo/ArgoParser.cc index 236d40b..274dd22 100644 --- a/Argo/ArgoParser.cc +++ b/Argo/ArgoParser.cc @@ -47,7 +47,8 @@ struct ParserInfo { }; export template , class PArg = void, - class HArg = void, class SubParserTuple = std::tuple<>> + class HArg = void, class SubParsers = std::tuple<>> + requires(is_tuple_v && is_tuple_v) class Parser { private: bool parsed_ = false; @@ -78,12 +79,11 @@ class Parser { Parser(const Parser&) = delete; Parser(Parser&&) = delete; - SubParserTuple subParsers; + SubParsers subParsers; - constexpr explicit Parser(SubParserTuple tuple) : subParsers(tuple) {} + constexpr explicit Parser(SubParsers tuple) : subParsers(tuple) {} - constexpr explicit Parser(std::unique_ptr info, - SubParserTuple tuple) + constexpr explicit Parser(std::unique_ptr info, SubParsers tuple) : info_(std::move(info)), subParsers(tuple){}; template , PArg, HArg, - SubParserTuple>(std::move(this->info_), subParsers); + SubParsers>(std::move(this->info_), subParsers); } template (std::forward(args)...); - return Parser( + return Parser( std::move(this->info_), subParsers); } @@ -223,7 +223,7 @@ class Parser { tuple_append_t>, PArg, HArg, - SubParserTuple>(std::move(this->info_), subParsers); + SubParsers>(std::move(this->info_), subParsers); } template @@ -232,7 +232,7 @@ class Parser { "Duplicated short name"); static_assert(Argo::SearchIndex::value == -1, "Duplicated name"); - return Parser, SubParserTuple>( + return Parser, SubParsers>( std::move(this->info_), subParsers); } @@ -246,7 +246,7 @@ class Parser { static_assert(Name.hasValidNameLength(), "Short name can't be more than one charactor"); this->info_->help = help; - return Parser, SubParserTuple>( + return Parser, SubParsers>( std::move(this->info_), subParsers); } @@ -272,12 +272,12 @@ class Parser { template auto& getParser() { - if constexpr (std::is_same_v>) { + if constexpr (std::is_same_v>) { static_assert(false, "Parser has no sub parser"); } - static_assert(!(SearchIndex::value == -1), + static_assert(!(SearchIndex::value == -1), "Could not find subparser"); - return std::get::value>(subParsers) + return std::get::value>(subParsers) .parser.get(); } diff --git a/Argo/ArgoParserImpl.cc b/Argo/ArgoParserImpl.cc index a4e4aef..65fb5e0 100644 --- a/Argo/ArgoParserImpl.cc +++ b/Argo/ArgoParserImpl.cc @@ -33,11 +33,13 @@ inline auto splitStringView(std::string_view str, } template + requires(is_tuple_v && is_tuple_v) auto Parser::resetArgs() -> void { ValueReset(); } template + requires(is_tuple_v && is_tuple_v) auto Parser::setArg( std::string_view key, std::span val) const -> void { if constexpr (!std::is_same_v) { @@ -50,6 +52,7 @@ auto Parser::setArg( } template + requires(is_tuple_v && is_tuple_v) auto Parser::setArg( std::span key, std::span val) const -> void { if constexpr (!std::is_same_v) { @@ -66,6 +69,7 @@ auto Parser::setArg( } template + requires(is_tuple_v && is_tuple_v) auto Parser::parse(int argc, char* argv[]) -> void { if (this->parsed_) [[unlikely]] { @@ -210,9 +214,9 @@ struct AnsiEscapeCode { } }; -auto createUsageSection(const auto& program_name, - [[maybe_unused]] const auto& help_info, - const auto& sub_commands) { +inline auto createUsageSection(const auto& program_name, + [[maybe_unused]] const auto& help_info, + const auto& sub_commands) { std::string ret; ret.append(program_name); @@ -247,7 +251,8 @@ auto createUsageSection(const auto& program_name, return ret; } -auto createSubcommandSection(const auto& ansi, const auto& sub_commands) { +inline auto createSubcommandSection(const auto& ansi, + const auto& sub_commands) { std::string ret; std::size_t max_command_length = 0; for (const auto& command : sub_commands) { @@ -282,7 +287,7 @@ auto createSubcommandSection(const auto& ansi, const auto& sub_commands) { return ret; } -auto createOptionsSection(const auto& ansi, const auto& help_info) { +inline auto createOptionsSection(const auto& ansi, const auto& help_info) { std::string ret; std::size_t max_name_len = 0; for (const auto& option : help_info) { @@ -339,6 +344,7 @@ auto createPositionalArgumentSection(const auto& ansi) { } template + requires(is_tuple_v && is_tuple_v) auto Parser::formatHelp(bool no_color) const -> std::string { std::string ret; diff --git a/Taskfile.yml b/Taskfile.yml index 72673c4..f6f824e 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -3,14 +3,11 @@ version: '3' tasks: cmake: cmds: - # - cmake -B build -S . -GNinja -DARGO_BENCHMARKS_ENABLE=true - - cmake -B build -S . -GNinja -DARGO_TESTS_ENABLE=true -DCMAKE_INSTALL_PREFIX=/Users/gen/.local + - cmake -B build -S . -GNinja -DARGO_TESTS_ENABLE=true compile: cmds: - cmake --build build execute: cmds: - # - ./build/main --arg1=42 --arg2="Hello,World" - ./build/test-argo-release - # - ./build/bench-parser-release silent: true diff --git a/generator/generate.py b/generator/generate.py index 2e783d0..e843627 100644 --- a/generator/generate.py +++ b/generator/generate.py @@ -1,6 +1,5 @@ import re - base = "./Argo.hh" diff --git a/include/Argo.hh b/include/Argo.hh index c92ef05..6c07124 100644 --- a/include/Argo.hh +++ b/include/Argo.hh @@ -1234,6 +1234,7 @@ struct SubParser { }; template + requires(is_tuple_v) auto MetaParse(SubParsers sub_parsers, int index, int argc, char** argv) -> bool { return std::apply( @@ -1247,6 +1248,7 @@ auto MetaParse(SubParsers sub_parsers, int index, int argc, }; template + requires(is_tuple_v) constexpr auto ParserIndex(SubParsers sub_parsers, // std::string_view key) -> std::int64_t { return std::apply( @@ -1295,7 +1297,8 @@ struct ParserInfo { }; template , class PArg = void, - class HArg = void, class SubParserTuple = std::tuple<>> + class HArg = void, class SubParsers = std::tuple<>> + requires(is_tuple_v && is_tuple_v) class Parser { private: bool parsed_ = false; @@ -1326,12 +1329,11 @@ class Parser { Parser(const Parser&) = delete; Parser(Parser&&) = delete; - SubParserTuple subParsers; + SubParsers subParsers; - constexpr explicit Parser(SubParserTuple tuple) : subParsers(tuple) {} + constexpr explicit Parser(SubParsers tuple) : subParsers(tuple) {} - constexpr explicit Parser(std::unique_ptr info, - SubParserTuple tuple) + constexpr explicit Parser(std::unique_ptr info, SubParsers tuple) : info_(std::move(info)), subParsers(tuple){}; template , PArg, HArg, - SubParserTuple>(std::move(this->info_), subParsers); + SubParsers>(std::move(this->info_), subParsers); } template (std::forward(args)...); - return Parser( + return Parser( std::move(this->info_), subParsers); } @@ -1471,7 +1473,7 @@ class Parser { tuple_append_t>, PArg, HArg, - SubParserTuple>(std::move(this->info_), subParsers); + SubParsers>(std::move(this->info_), subParsers); } template @@ -1480,7 +1482,7 @@ class Parser { "Duplicated short name"); static_assert(Argo::SearchIndex::value == -1, "Duplicated name"); - return Parser, SubParserTuple>( + return Parser, SubParsers>( std::move(this->info_), subParsers); } @@ -1494,7 +1496,7 @@ class Parser { static_assert(Name.hasValidNameLength(), "Short name can't be more than one charactor"); this->info_->help = help; - return Parser, SubParserTuple>( + return Parser, SubParsers>( std::move(this->info_), subParsers); } @@ -1520,12 +1522,12 @@ class Parser { template auto& getParser() { - if constexpr (std::is_same_v>) { + if constexpr (std::is_same_v>) { static_assert(false, "Parser has no sub parser"); } - static_assert(!(SearchIndex::value == -1), + static_assert(!(SearchIndex::value == -1), "Could not find subparser"); - return std::get::value>(subParsers) + return std::get::value>(subParsers) .parser.get(); } @@ -1612,11 +1614,13 @@ inline auto splitStringView(std::string_view str, } template + requires(is_tuple_v && is_tuple_v) auto Parser::resetArgs() -> void { ValueReset(); } template + requires(is_tuple_v && is_tuple_v) auto Parser::setArg( std::string_view key, std::span val) const -> void { if constexpr (!std::is_same_v) { @@ -1629,6 +1633,7 @@ auto Parser::setArg( } template + requires(is_tuple_v && is_tuple_v) auto Parser::setArg( std::span key, std::span val) const -> void { if constexpr (!std::is_same_v) { @@ -1645,6 +1650,7 @@ auto Parser::setArg( } template + requires(is_tuple_v && is_tuple_v) auto Parser::parse(int argc, char* argv[]) -> void { if (this->parsed_) [[unlikely]] { @@ -1789,9 +1795,9 @@ struct AnsiEscapeCode { } }; -auto createUsageSection(const auto& program_name, - [[maybe_unused]] const auto& help_info, - const auto& sub_commands) { +inline auto createUsageSection(const auto& program_name, + [[maybe_unused]] const auto& help_info, + const auto& sub_commands) { std::string ret; ret.append(program_name); @@ -1826,7 +1832,8 @@ auto createUsageSection(const auto& program_name, return ret; } -auto createSubcommandSection(const auto& ansi, const auto& sub_commands) { +inline auto createSubcommandSection(const auto& ansi, + const auto& sub_commands) { std::string ret; std::size_t max_command_length = 0; for (const auto& command : sub_commands) { @@ -1861,7 +1868,7 @@ auto createSubcommandSection(const auto& ansi, const auto& sub_commands) { return ret; } -auto createOptionsSection(const auto& ansi, const auto& help_info) { +inline auto createOptionsSection(const auto& ansi, const auto& help_info) { std::string ret; std::size_t max_name_len = 0; for (const auto& option : help_info) { @@ -1918,6 +1925,7 @@ auto createPositionalArgumentSection(const auto& ansi) { } template + requires(is_tuple_v && is_tuple_v) auto Parser::formatHelp(bool no_color) const -> std::string { std::string ret; diff --git a/tests/ExampleCode.cc b/tests/ExampleCode.cc index c5dfba9..81774e2 100644 --- a/tests/ExampleCode.cc +++ b/tests/ExampleCode.cc @@ -6,7 +6,8 @@ import Argo; #include "TestHelper.h" TEST(ArgoTest, ExampleCode) { - auto [argc, argv] = createArgcArgv("./main", "--arg1", "42", "--arg3", "Hello,World"); + auto [argc, argv] = + createArgcArgv("./main", "--arg1", "42", "--arg3", "Hello,World"); auto parser = Argo::Parser<0>("Program name") // .addArg<"arg1", int>() @@ -22,4 +23,4 @@ TEST(ArgoTest, ExampleCode) { EXPECT_TRUE((std::is_same_v()), int>)); EXPECT_TRUE((std::is_same_v()), float>)); EXPECT_TRUE((std::is_same_v()), std::string>)); -} +}; diff --git a/tests/parser.cc b/tests/parser.cc index ca0c247..8f2c5b8 100644 --- a/tests/parser.cc +++ b/tests/parser.cc @@ -19,7 +19,8 @@ TEST(ArgoTest, ExceptionThrow) { } TEST(ArgoTest, EqualAssign) { - auto [argc, argv] = createArgcArgv("./main", "--arg1=42", "--arg2=Hello,World"); + auto [argc, argv] = + createArgcArgv("./main", "--arg1=42", "--arg2=Hello,World"); auto argo = Argo::Parser<"Equal assign">(); auto parser = argo // @@ -33,10 +34,15 @@ TEST(ArgoTest, EqualAssign) { } TEST(ArgoTest, FlagArgument) { - auto [argc, argv] = createArgcArgv( // - "./main", // - "--arg1", "--arg2=true", "--arg3=1", // - "--arg4", "true", "--arg5", "1" // + auto [argc, argv] = createArgcArgv( // + "./main", // + "--arg1", + "--arg2=true", + "--arg3=1", // + "--arg4", + "true", + "--arg5", + "1" // ); auto argo = Argo::Parser<"Flag arguments">(); @@ -58,9 +64,12 @@ TEST(ArgoTest, FlagArgument) { TEST(ArgoTest, ShortArgument) { auto [argc, argv] = createArgcArgv( // "./main", // - "-a", "Hello,World", // - "--arg2", "42", // - "-c", "3.1415" // + "-a", + "Hello,World", // + "--arg2", + "42", // + "-c", + "3.1415" // ); auto argo = Argo::Parser<"Short argument">(); @@ -77,7 +86,9 @@ TEST(ArgoTest, ShortArgument) { TEST(ArgoTest, CombiningFlags) { auto [argc, argv] = createArgcArgv( // - "./main", "-abd", "-e" // + "./main", + "-abd", + "-e" // ); auto argo = Argo::Parser<"Combined flags">(); @@ -97,8 +108,10 @@ TEST(ArgoTest, CombiningFlags) { } TEST(ArgoTest, CombiningFlagsWithOptionalArg) { - auto [argc, argv] = createArgcArgv( // - "./main", "-abdc", "Hello,World" // + auto [argc, argv] = createArgcArgv( // + "./main", + "-abdc", + "Hello,World" // ); auto argo = Argo::Parser<"flag with optional args">(); @@ -118,7 +131,9 @@ TEST(ArgoTest, CombiningFlagsWithOptionalArg) { TEST(ArgoTest, Validation) { { auto [argc, argv] = createArgcArgv( // - "./main", "--arg", "42" // + "./main", + "--arg", + "42" // ); auto argo = Argo::Parser<"Validation 1">(); @@ -131,7 +146,9 @@ TEST(ArgoTest, Validation) { } { auto [argc, argv] = createArgcArgv( // - "./main", "--arg", "121" // + "./main", + "--arg", + "121" // ); auto argo = Argo::Parser<"Validation 2">(); @@ -148,7 +165,8 @@ TEST(ArgoTest, Validation) { // // auto argo = Argo::Parser<"Validation 3">(); // auto parser = argo // - // .addArg<"arg", int>(new Argo::Validation::Callback( + // .addArg<"arg", int>(new + // Argo::Validation::Callback( // [](auto value) { return value % 2 == 0; })) // .addFlag<"arg2">(); // EXPECT_THROW(parser.parse(argc, argv), Argo::ValidationError); @@ -161,7 +179,8 @@ TEST(ArgoTest, Validation) { // // auto argo = Argo::Parser<"Validation 4">(); // auto parser = argo // - // .addArg<"arg", int>(new Argo::Validation::Callback( + // .addArg<"arg", int>(new + // Argo::Validation::Callback( // [](auto value) { return value % 2 == 0; })) // .addFlag<"arg2">(); // parser.parse(argc, argv); @@ -170,12 +189,23 @@ TEST(ArgoTest, Validation) { TEST(ArgoTest, Narg) { { - auto [argc, argv] = createArgcArgv( // - "./main", // - "--arg1", "1", "2", "3", // - "--arg2", // - "--arg3", "6.0", "7.2", "8.4", "9.6", // - "--arg4", "11", "12", "8", "9" // + auto [argc, argv] = createArgcArgv( // + "./main", // + "--arg1", + "1", + "2", + "3", // + "--arg2", // + "--arg3", + "6.0", + "7.2", + "8.4", + "9.6", // + "--arg4", + "11", + "12", + "8", + "9" // ); auto argo = Argo::Parser<"Narg 1">(); @@ -190,12 +220,14 @@ TEST(ArgoTest, Narg) { EXPECT_THAT(parser.getArg<"arg1">(), testing::ElementsAre(1, 2, 3)); EXPECT_EQ(parser.getArg<"arg2">(), "Bar"); - EXPECT_THAT(parser.getArg<"arg3">(), testing::ElementsAre(6.0, 7.2, 8.4, 9.6)); + EXPECT_THAT(parser.getArg<"arg3">(), + testing::ElementsAre(6.0, 7.2, 8.4, 9.6)); } { auto [argc, argv] = createArgcArgv( // "./main", // - "--arg1", "1" // + "--arg1", + "1" // ); auto argo = Argo::Parser<"Narg 2">(); @@ -223,7 +255,8 @@ TEST(ArgoTest, NargException) { { auto [argc, argv] = createArgcArgv( // "./main", // - "--arg1", "--arg2" // + "--arg1", + "--arg2" // ); auto argo = Argo::Parser<"Narg exception 2">(); @@ -242,7 +275,8 @@ TEST(ArgoTest, NargException) { // auto parser = argo // // .addArg<"arg0,k", int>() // .addArg<"arg1,a", int, Argo::nargs('+')>() -// .addArg<"arg2", int, Argo::nargs('+')>(Argo::description("This is arg2")); +// .addArg<"arg2", int, +// Argo::nargs('+')>(Argo::description("This is arg2")); // // auto expect_help = R"(Options: // -k, --arg0 @@ -257,7 +291,10 @@ TEST(ArgoTest, Required) { { auto [argc, argv] = createArgcArgv( // "./main", // - "--arg1", "1", "--arg2", "2" // + "--arg1", + "1", + "--arg2", + "2" // ); auto argo = Argo::Parser<"Required argument">("Sample Program"); @@ -276,7 +313,9 @@ TEST(ArgoTest, Positional) { { auto [argc, argv] = createArgcArgv( // "./main", // - "1", "2", "3" // + "1", + "2", + "3" // ); auto argo = Argo::Parser<"Positional arguments">("Sample Program"); @@ -288,8 +327,12 @@ TEST(ArgoTest, Positional) { } { auto [argc, argv] = createArgcArgv( // - "./main", "1", "2", "3", // - "--arg2", "42.195" // + "./main", + "1", + "2", + "3", // + "--arg2", + "42.195" // ); auto argo = Argo::Parser<"positional argument2">("Sample Program"); @@ -305,8 +348,12 @@ TEST(ArgoTest, Positional) { { auto [argc, argv] = createArgcArgv( // - "./main", "--arg2", "42.195", // - "1", "2", "3" // + "./main", + "--arg2", + "42.195", // + "1", + "2", + "3" // ); auto argo = Argo::Parser<"positional argument3">("Sample Program"); @@ -322,8 +369,13 @@ TEST(ArgoTest, Positional) { { auto [argc, argv] = createArgcArgv( // - "./main", "--arg2", "42", "96", // - "1", "2", "3" // + "./main", + "--arg2", + "42", + "96", // + "1", + "2", + "3" // ); auto argo = Argo::Parser<"positonal argument 4">("Sample Program"); @@ -339,8 +391,11 @@ TEST(ArgoTest, Positional) { { auto [argc, argv] = createArgcArgv( // - "./main", "--arg2", // - "1", "2", "3" // + "./main", + "--arg2", // + "1", + "2", + "3" // ); auto argo = Argo::Parser<"positonal argument 5">("Sample Program"); @@ -357,7 +412,10 @@ TEST(ArgoTest, Positional) { { auto [argc, argv] = createArgcArgv( // "./main", // - "1", "2", "3", "-b" // + "1", + "2", + "3", + "-b" // ); auto argo = Argo::Parser<"positonal argument 6">("Sample Program"); @@ -374,7 +432,11 @@ TEST(ArgoTest, Positional) { { // error auto [argc, argv] = createArgcArgv( // "./main", // - "1", "2", "3", "-bc", "234.86" // + "1", + "2", + "3", + "-bc", + "234.86" // ); auto argo = Argo::Parser<"positonal argument 7">("Sample Program"); @@ -393,9 +455,12 @@ TEST(ArgoTest, Positional) { TEST(ArgoTest, IsAssigned) { { - auto [argc, argv] = createArgcArgv( // - "./main", // - "--arg1", "42", "--arg2", "--arg4" // + auto [argc, argv] = createArgcArgv( // + "./main", // + "--arg1", + "42", + "--arg2", + "--arg4" // ); auto argo = Argo::Parser<"Is assigned">("Sample Program"); @@ -416,8 +481,10 @@ TEST(ArgoTest, IsAssigned) { TEST(ArgoTest, CallBack) { { - auto [argc, argv] = createArgcArgv("./main", // - "1", "2", "3" // + auto [argc, argv] = createArgcArgv("./main", // + "1", + "2", + "3" // ); auto argo = Argo::Parser<150>("Sample Program");