arguments.h 3.3 KB

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