|
|
@@ -10,6 +10,7 @@ namespace program {
|
|
|
template <typename Impl> class Arguments {
|
|
|
private:
|
|
|
using option_id = std::string;
|
|
|
+ struct Action;
|
|
|
struct Argument;
|
|
|
struct Flag;
|
|
|
struct Option;
|
|
|
@@ -24,6 +25,7 @@ public:
|
|
|
}
|
|
|
|
|
|
protected:
|
|
|
+ auto action(std::string const &name, std::string const &description = "");
|
|
|
auto argument(size_t index, std::string const & name,
|
|
|
std::string const & description = "");
|
|
|
auto flag(std::string const & name, std::string const & description = "");
|
|
|
@@ -46,6 +48,12 @@ private:
|
|
|
bool is_flag(char arg) const { return is_flag({'-', arg}); }
|
|
|
|
|
|
private:
|
|
|
+ friend struct ArgumentTestHelper;
|
|
|
+ friend int main(int, char const * const *);
|
|
|
+
|
|
|
+private:
|
|
|
+ using main_callback_t = std::function<int(Arguments const &)>;
|
|
|
+ using make_hook_t = std::function<main_callback_t(size_t, char const * const *)>;
|
|
|
// Metadata variables
|
|
|
bool primed_{false};
|
|
|
std::map<option_id, std::string> argument_descriptions;
|
|
|
@@ -53,9 +61,12 @@ private:
|
|
|
std::map<option_id, std::string> option_descriptions;
|
|
|
std::map<std::string, option_id> option_names;
|
|
|
std::set<option_id> flag_names;
|
|
|
+ std::map<std::string, make_hook_t> actions;
|
|
|
+ std::map<std::string, std::string> action_descriptions;
|
|
|
|
|
|
// Data/Output variables
|
|
|
std::string program;
|
|
|
+ main_callback_t main_callback{nullptr};
|
|
|
constexpr static size_t const no_optional_args{~0ul};
|
|
|
size_t optional_from{no_optional_args};
|
|
|
std::vector<std::string> arguments;
|
|
|
@@ -63,6 +74,16 @@ private:
|
|
|
std::map<std::string, int> flags;
|
|
|
};
|
|
|
|
|
|
+template <typename Impl> struct Arguments<Impl>::Action {
|
|
|
+ Arguments<Impl> * self;
|
|
|
+ std::string name;
|
|
|
+ std::string description;
|
|
|
+
|
|
|
+ template <typename T> operator T() const;
|
|
|
+ bool primed() const;
|
|
|
+ explicit operator bool() const;
|
|
|
+};
|
|
|
+
|
|
|
template <typename Impl> struct Arguments<Impl>::Argument {
|
|
|
Arguments<Impl> * self;
|
|
|
size_t index;
|
|
|
@@ -113,11 +134,17 @@ struct Arguments<Impl>::WithDefault {
|
|
|
|
|
|
#include "arguments_impl.hpp"
|
|
|
|
|
|
+
|
|
|
+template <typename Args, typename Action>
|
|
|
+int typed_main(Args const &, Action const &);
|
|
|
+
|
|
|
#define TYPED_MAIN(tname) \
|
|
|
int typed_main(tname const & args); \
|
|
|
int main(int argc, char const * const * const argv) try { \
|
|
|
- return typed_main(tname(argc, argv)); \
|
|
|
+ tname args(argc, argv); \
|
|
|
+ return (args.main_callback) ? args.main_callback(args) : typed_main(args); \
|
|
|
} catch (program::ProgramArgumentsError const & pae) { \
|
|
|
std::cerr << "Error in program argument handling: " << pae.what() << "\n"; \
|
|
|
} \
|
|
|
int typed_main(tname const & args)
|
|
|
+
|