summaryrefslogtreecommitdiff
path: root/src/argparser.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/argparser.h')
-rw-r--r--src/argparser.h77
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::