start option description
This commit is contained in:
parent
db5477ddd8
commit
b89953f42b
61
src/cxxopts.cpp
Normal file
61
src/cxxopts.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include "cxxopts.hpp"
|
||||||
|
|
||||||
|
namespace cxxopts
|
||||||
|
{
|
||||||
|
|
||||||
|
std::basic_regex<char> option_matcher
|
||||||
|
("--([[:alpha:]][-_[:alpha:]]+)(=(.*))?|-([a-zA-Z]+)");
|
||||||
|
|
||||||
|
std::basic_regex<char> 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<const char*> 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<OptionDetails>(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
#include <regex>
|
#include <regex>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
namespace cxxopts
|
namespace cxxopts
|
||||||
{
|
{
|
||||||
@ -7,8 +9,60 @@ namespace cxxopts
|
|||||||
|
|
||||||
extern std::basic_regex<char> option_specifier;
|
extern std::basic_regex<char> 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 OptionAdder;
|
||||||
|
|
||||||
|
class OptionDetails
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OptionDetails(const std::string& description)
|
||||||
|
: m_desc(description)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_desc;
|
||||||
|
};
|
||||||
|
|
||||||
class Options
|
class Options
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -22,8 +76,8 @@ namespace cxxopts
|
|||||||
private:
|
private:
|
||||||
friend class OptionAdder;
|
friend class OptionAdder;
|
||||||
|
|
||||||
std::set<char32_t> m_short;
|
std::map<char, std::shared_ptr<OptionDetails>> m_short;
|
||||||
std::set<std::string> m_long;
|
std::map<std::string, std::shared_ptr<OptionDetails>> m_long;
|
||||||
};
|
};
|
||||||
|
|
||||||
class OptionAdder
|
class OptionAdder
|
||||||
|
|||||||
17
src/main.cpp
17
src/main.cpp
@ -1,21 +1,15 @@
|
|||||||
|
#include <codecvt>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "cxxopts.hpp"
|
#include "cxxopts.hpp"
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
std::locale::global(std::locale(""));
|
|
||||||
try
|
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<const char*> result;
|
std::match_results<const char*> result;
|
||||||
|
|
||||||
for (int i = 1; i < argc; ++i)
|
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)
|
} catch (const std::regex_error& e)
|
||||||
{
|
{
|
||||||
std::cout << "regex_error: " << e.what() << std::endl;
|
std::cout << "regex_error: " << e.what() << std::endl;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user