arguments.h 3.1 KB

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