From b89953f42bd89ba3701aad88b79508036ff35ab6 Mon Sep 17 00:00:00 2001 From: Jarryd Beck Date: Sat, 27 Sep 2014 17:04:58 +1000 Subject: [PATCH] start option description --- src/cxxopts.cpp | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ src/cxxopts.hpp | 58 ++++++++++++++++++++++++++++++++++++++++++++-- src/main.cpp | 17 +++++++------- 3 files changed, 126 insertions(+), 10 deletions(-) create mode 100644 src/cxxopts.cpp diff --git a/src/cxxopts.cpp b/src/cxxopts.cpp new file mode 100644 index 0000000..f505504 --- /dev/null +++ b/src/cxxopts.cpp @@ -0,0 +1,61 @@ +#include "cxxopts.hpp" + +namespace cxxopts +{ + + std::basic_regex option_matcher + ("--([[:alpha:]][-_[:alpha:]]+)(=(.*))?|-([a-zA-Z]+)"); + + std::basic_regex option_specifier + ("(([a-zA-Z]),)?([a-zA-Z][-_a-zA-Z]+)"); + +OptionAdder +Options::add_options() +{ + return OptionAdder(*this); +} + +OptionAdder& +OptionAdder::operator() +( + const std::string& opts, + const std::string& desc +) +{ + std::match_results result; + std::regex_match(opts.c_str(), result, option_specifier); + + if (result.empty()) + { + throw invalid_option_format_error(opts); + } + + const auto& s = result[2]; + const auto& l = result[3]; + + auto option = std::make_shared(desc); + + if (s.length() != 0) + { + auto result = m_options.m_short.insert(std::make_pair(s.str()[0], option)); + + if (!result.second) + { + throw option_exists_error(s.str()); + } + } + + if (l.length() != 0) + { + auto result = m_options.m_long.insert(std::make_pair(l, option)); + + if (!result.second) + { + throw option_exists_error(l.str()); + } + } + + return *this; +} + +} diff --git a/src/cxxopts.hpp b/src/cxxopts.hpp index 4f08cf6..8e64f4c 100644 --- a/src/cxxopts.hpp +++ b/src/cxxopts.hpp @@ -1,5 +1,7 @@ #include #include +#include +#include namespace cxxopts { @@ -7,8 +9,60 @@ namespace cxxopts extern std::basic_regex option_specifier; + class OptionException : public std::exception + { + }; + + class option_exists_error : public OptionException + { + public: + option_exists_error(const std::string& option) + { + m_message = u8"Option ‘" + option + u8"’ already exists"; + } + + const char* + what() const noexcept + { + return m_message.c_str(); + } + + private: + std::string m_message; + }; + + class invalid_option_format_error : public OptionException + { + public: + invalid_option_format_error(const std::string& format) + { + m_message = u8"Invalid option format ‘" + format + u8"’"; + } + + const char* + what() const noexcept + { + return m_message.c_str(); + } + + private: + std::string m_message; + }; + class OptionAdder; + class OptionDetails + { + public: + OptionDetails(const std::string& description) + : m_desc(description) + { + } + + private: + std::string m_desc; + }; + class Options { public: @@ -22,8 +76,8 @@ namespace cxxopts private: friend class OptionAdder; - std::set m_short; - std::set m_long; + std::map> m_short; + std::map> m_long; }; class OptionAdder diff --git a/src/main.cpp b/src/main.cpp index 9cf4368..4505075 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,21 +1,15 @@ +#include #include #include +#include #include "cxxopts.hpp" int main(int argc, char* argv[]) { - std::locale::global(std::locale("")); try { - cxxopts::option_matcher.imbue(std::locale("")); - cxxopts::option_matcher.assign - ("--([[:alpha:]][-_[:alpha:]]+)(=(.*))?|-([a-zA-Z]+)", - std::regex_constants::extended | std::regex_constants::ECMAScript | - std::regex_constants::collate); - std::cout << cxxopts::option_matcher.getloc().name() << std::endl; - std::match_results result; for (int i = 1; i < argc; ++i) @@ -32,6 +26,13 @@ int main(int argc, char* argv[]) } } + cxxopts::Options options; + + options.add_options() + ("a,apple", "an apple") + ("b,bob", "Bob") + ; + } catch (const std::regex_error& e) { std::cout << "regex_error: " << e.what() << std::endl;