arguments.h 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. #pragma once
  2. #include <map>
  3. #include <string>
  4. #include <vector>
  5. namespace program {
  6. template <typename Impl> class Arguments {
  7. protected:
  8. struct Option;
  9. struct Positional;
  10. template <typename, typename> struct WithDefault;
  11. public:
  12. Arguments() = default;
  13. Arguments(int argc, char const * const * const argv);
  14. auto option(std::string const & name, std::string const & description = "");
  15. auto option(std::string const & name, char abbrev,
  16. std::string const & description = "");
  17. auto argument(size_t index, std::string const & name,
  18. std::string const & description = "");
  19. private:
  20. void usage() const;
  21. private:
  22. // Metadata variables
  23. bool primed_{false};
  24. std::map<std::string, std::string> option_descriptions;
  25. std::map<std::string, std::string> positional_descriptions;
  26. std::map<std::string, std::string> option_name_mapping;
  27. std::map<size_t, std::string> argument_names;
  28. // Data variables
  29. std::string program;
  30. size_t optional_from{std::numeric_limits<size_t>::max()};
  31. std::map<std::string, std::vector<std::string>> options;
  32. std::vector<std::string> arguments;
  33. };
  34. template <typename Impl>
  35. template <typename B, typename V>
  36. struct Arguments<Impl>::WithDefault {
  37. B impl;
  38. V default_value;
  39. template <typename T> operator T() const { return impl ?: T(default_value); }
  40. };
  41. template <typename Impl> struct Arguments<Impl>::Option {
  42. Arguments<Impl> * self;
  43. std::string name;
  44. char abbrev;
  45. std::string description;
  46. template <typename T> auto operator=(T && value);
  47. template <typename T> operator T() const;
  48. bool primed() const;
  49. explicit operator bool() const;
  50. };
  51. template <typename Impl> struct Arguments<Impl>::Positional {
  52. Arguments<Impl> * self;
  53. size_t index;
  54. bool is_optional;
  55. std::string name;
  56. std::string description;
  57. template <typename T> auto operator=(T && value);
  58. template <typename T> operator T() const;
  59. bool primed() const;
  60. explicit operator bool() const;
  61. };
  62. }
  63. #include "arguments_impl.hpp"
  64. #define TYPED_MAIN(tname) \
  65. int typed_main(tname const & args); \
  66. int main(int argc, char const * const * const argv) try { \
  67. return typed_main(tname(argc, argv)); \
  68. } catch (program::ProgramArgumentsError const & pae) { \
  69. std::cerr << "Error in program argument handling: " << pae.what() << "\n"; \
  70. } \
  71. int typed_main(tname const & args)