diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/argparser.h | 77 |
1 files changed, 57 insertions, 20 deletions
diff --git a/src/argparser.h b/src/argparser.h index 51d6745..ec7d5ce 100644 --- a/src/argparser.h +++ b/src/argparser.h @@ -10,8 +10,31 @@ #include <type_traits> #include <iostream> +namespace arg +{ +struct noarg {}; +template<typename T> +struct Opt +{ + std::string shortopt; + std::string longopt; + std::function<int(T)> cb; + std::string help; + T t{}; +}; + +template<> +struct Opt<noarg> +{ + std::string shortopt; + std::string longopt; + std::function<int()> cb; + std::string help; + noarg t{}; +}; + template<typename... Ts> -class ArgParser +class Parser { public: struct missing_arg{}; @@ -22,6 +45,7 @@ public: { return 1; } + for(int i = 1; i < argc; ++i) // skip argv[0] which is program name { bool was_handled{false}; @@ -38,20 +62,33 @@ public: } try { - auto arg = convert(argc, argv, i, opt.t); - return {opt.cb(arg), state::handled}; + using T = std::decay_t<decltype(opt)>; + if constexpr (std::is_same_v<T, Opt<noarg>>) + { + return {opt.cb(), state::handled}; + } + else + { + auto arg = convert(argc, argv, i, opt.t); + return {opt.cb(arg), state::handled}; + } } catch(std::invalid_argument&) { - std::cout << "Invalid " << opt.shortopt << - " argument.\n"; - std::cout << opt.help << "\n"; + std::cout << argv[0] << + ": invalid argument for option '" << + opt.shortopt << "'\n"; + std::cout << "Type '" << argv[0] << + " -h' for more information.\n"; return {1, state::handled}; } catch(missing_arg&) { - std::cout << "Missing " << opt.shortopt << - " argument.\n"; + std::cout << argv[0] << + ": option requires and argument '" << + opt.shortopt << "'\n"; + std::cout << "Type '" << argv[0] << + " -h' for more information.\n"; std::cout << opt.help << "\n"; return {1, state::handled}; } @@ -69,7 +106,8 @@ public: } if(!was_handled) { - std::cout << "Unknown argument " << argv[i] << '\n'; + std::cout << argv[0] << ": invalid option '" << argv[i] << "'\n"; + std::cout << "Type '" << argv[0] << " -h' for more information.\n"; return 1; } } @@ -85,18 +123,15 @@ public: options.emplace_back(Opt<T>{shortopt, longopt, cb, help}); } -private: - template<typename T> - struct Opt + void add(const std::string& shortopt, + const std::string& longopt, + std::function<int()> cb, + const std::string& help) { - //using contained_type = T; - std::string shortopt; - std::string longopt; - std::function<int(T)> cb; - std::string help; - T t{}; - }; + options.emplace_back(Opt<noarg>{shortopt, longopt, cb, help}); + } +private: template<typename T> T convert(int argc, const char* const argv[], int& i, T) { @@ -148,6 +183,8 @@ private: return {}; } - using Opts = std::variant<Opt<Ts>...>; + using Opts = std::variant<Opt<noarg>, Opt<Ts>...>; std::vector<Opts> options; }; + +} // arg:: |