arguments.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #pragma once
  2. #include <map>
  3. #include <set>
  4. #include <string>
  5. #include <vector>
  6. namespace program {
  7. template <typename Impl> class Arguments {
  8. private:
  9. using option_id = std::string;
  10. struct Argument;
  11. struct Flag;
  12. struct Option;
  13. template <typename, typename> struct WithDefault;
  14. public:
  15. Arguments() = default;
  16. Arguments(int argc, char const * const * const argv);
  17. protected:
  18. auto argument(size_t index, std::string const & name,
  19. std::string const & description = "");
  20. auto flag(std::string const & name, std::string const & description = "");
  21. auto flag(std::string const & name, char abbrev,
  22. std::string const & description = "");
  23. auto option(std::string const & name, std::string const & description = "");
  24. auto option(std::string const & name, char abbrev,
  25. std::string const & description = "");
  26. private:
  27. void usage() const;
  28. void add_options(std::string const & name, char abbrev,
  29. std::string const & description,
  30. std::vector<std::string> aliases = {});
  31. option_id id(std::string const & arg) const;
  32. option_id id(char arg) const { return id({'-', arg}); }
  33. bool is_option(std::string const & arg) const;
  34. bool is_option(char arg) const { return is_option({'-', arg}); }
  35. bool is_flag(std::string const & arg) const;
  36. bool is_flag(char arg) const { return is_flag({'-', arg}); }
  37. private:
  38. // Metadata variables
  39. bool primed_{false};
  40. std::map<option_id, std::string> argument_descriptions;
  41. std::map<size_t, option_id> argument_names;
  42. std::map<option_id, std::string> option_descriptions;
  43. std::map<std::string, option_id> option_names;
  44. std::set<option_id> flag_names;
  45. // Data/Output variables
  46. std::string program;
  47. size_t optional_from{std::numeric_limits<size_t>::max()};
  48. std::vector<std::string> arguments;
  49. std::map<std::string, std::vector<std::string>> options;
  50. std::map<std::string, int> flags;
  51. };
  52. template <typename Impl> struct Arguments<Impl>::Argument {
  53. Arguments<Impl> * self;
  54. size_t index;
  55. bool is_optional;
  56. std::string name;
  57. std::string description;
  58. template <typename T> auto operator=(T && value);
  59. template <typename T> operator T() const;
  60. bool primed() const;
  61. explicit operator bool() const;
  62. };
  63. template <typename Impl> struct Arguments<Impl>::Flag {
  64. Arguments<Impl> * self;
  65. std::string name;
  66. char abbrev;
  67. std::string description;
  68. bool default_value;
  69. auto operator=(bool && value);
  70. operator bool() const;
  71. template <typename T> operator T() const;
  72. bool primed(bool inv) const;
  73. };
  74. template <typename Impl> struct Arguments<Impl>::Option {
  75. Arguments<Impl> * self;
  76. std::string name;
  77. char abbrev;
  78. std::string description;
  79. template <typename T> auto operator=(T && value);
  80. template <typename T> operator T() const;
  81. bool primed() const;
  82. explicit operator bool() const;
  83. };
  84. template <typename Impl>
  85. template <typename B, typename V>
  86. struct Arguments<Impl>::WithDefault {
  87. B impl;
  88. V default_value;
  89. template <typename T> operator T() const { return impl ?: T(default_value); }
  90. };
  91. }
  92. #include "arguments_impl.hpp"
  93. #define TYPED_MAIN(tname) \
  94. int typed_main(tname const & args); \
  95. int main(int argc, char const * const * const argv) try { \
  96. return typed_main(tname(argc, argv)); \
  97. } catch (program::ProgramArgumentsError const & pae) { \
  98. std::cerr << "Error in program argument handling: " << pae.what() << "\n"; \
  99. } \
  100. int typed_main(tname const & args)