Changes following CR by @jarro2783:
* Added a `CHANGELOG.md` entry about the multiple-long-names feature. * Simplified the separation of the short name from the long names using `std::partition` * Using C-style logical operators: `!`, `&&`, `||` rather than `not`, `and`, `or` * `std::move()`ing from a vector of strings instead of just copying it. * `constexpr const` -> just `constexpr`, since that implies const, weirdly enough.
This commit is contained in:
parent
d994b9b2b7
commit
8e525e26f9
@ -7,6 +7,7 @@ options. The project adheres to semantic versioning.
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
* Support for multiple long names for the same option (= multiple long aliases)
|
||||||
* Add a `program()` function to retrieve the program name.
|
* Add a `program()` function to retrieve the program name.
|
||||||
* Added a .clang-format file.
|
* Added a .clang-format file.
|
||||||
|
|
||||||
|
|||||||
@ -659,7 +659,7 @@ inline OptionNames split_option_names(const std::string &text)
|
|||||||
"abcdefghijklmnopqrstuvwxyz"
|
"abcdefghijklmnopqrstuvwxyz"
|
||||||
"0123456789"
|
"0123456789"
|
||||||
"_-";
|
"_-";
|
||||||
if (not std::isalnum(text[token_start_pos]) or
|
if (!std::isalnum(text[token_start_pos]) ||
|
||||||
text.find_first_not_of(option_name_valid_chars, token_start_pos) < next_delimiter_pos) {
|
text.find_first_not_of(option_name_valid_chars, token_start_pos) < next_delimiter_pos) {
|
||||||
throw_or_mimic<exceptions::invalid_option_format>(text);
|
throw_or_mimic<exceptions::invalid_option_format>(text);
|
||||||
}
|
}
|
||||||
@ -783,14 +783,14 @@ inline bool IsFalseText(const std::string &text)
|
|||||||
// (without considering which or how many are single-character)
|
// (without considering which or how many are single-character)
|
||||||
inline OptionNames split_option_names(const std::string &text)
|
inline OptionNames split_option_names(const std::string &text)
|
||||||
{
|
{
|
||||||
if (not std::regex_match(text.c_str(), option_specifier))
|
if (!std::regex_match(text.c_str(), option_specifier))
|
||||||
{
|
{
|
||||||
throw_or_mimic<exceptions::invalid_option_format>(text);
|
throw_or_mimic<exceptions::invalid_option_format>(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionNames split_names;
|
OptionNames split_names;
|
||||||
|
|
||||||
constexpr const int use_non_matches { -1 };
|
constexpr int use_non_matches { -1 };
|
||||||
auto token_iterator = std::sregex_token_iterator(
|
auto token_iterator = std::sregex_token_iterator(
|
||||||
text.begin(), text.end(), option_specifier_separator, use_non_matches);
|
text.begin(), text.end(), option_specifier_separator, use_non_matches);
|
||||||
std::copy(token_iterator, std::sregex_token_iterator(), std::back_inserter(split_names));
|
std::copy(token_iterator, std::sregex_token_iterator(), std::back_inserter(split_names));
|
||||||
@ -2169,34 +2169,30 @@ OptionAdder::operator()
|
|||||||
std::string arg_help
|
std::string arg_help
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
OptionNames all_option_names = values::parser_tool::split_option_names(opts);
|
OptionNames option_names = values::parser_tool::split_option_names(opts);
|
||||||
// Note: All names will be non-empty!
|
// Note: All names will be non-empty; but we must separate the short
|
||||||
std::string short_sw {""};
|
// (length-1) and longer names
|
||||||
OptionNames long_option_names = all_option_names;
|
std::string short_name {""};
|
||||||
auto first_length_1_name_it = std::find_if(long_option_names.cbegin(), long_option_names.cend(),
|
auto first_short_name_iter =
|
||||||
[&](const std::string& name) { return name.length() == 1; }
|
std::partition(option_names.begin(), option_names.end(),
|
||||||
);
|
[&](const std::string& name) { return name.length() > 1; }
|
||||||
if (first_length_1_name_it != long_option_names.cend()) {
|
|
||||||
auto have_second_length_1_name = std::any_of(first_length_1_name_it + 1, long_option_names.cend(),
|
|
||||||
[&](const std::string& name) { return name.length() == 1; }
|
|
||||||
);
|
);
|
||||||
if (have_second_length_1_name) {
|
auto num_length_1_names = (option_names.end() - first_short_name_iter);
|
||||||
throw_or_mimic<exceptions::invalid_option_format>(opts);
|
switch(num_length_1_names) {
|
||||||
}
|
case 1:
|
||||||
short_sw = *first_length_1_name_it;
|
short_name = *first_short_name_iter;
|
||||||
long_option_names.erase(first_length_1_name_it);
|
option_names.erase(first_short_name_iter);
|
||||||
}
|
case 0:
|
||||||
if (short_sw.empty() && long_option_names.empty())
|
break;
|
||||||
{
|
default:
|
||||||
throw_or_mimic<exceptions::invalid_option_format>(opts);
|
throw_or_mimic<exceptions::invalid_option_format>(opts);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
m_options.add_option
|
m_options.add_option
|
||||||
(
|
(
|
||||||
m_group,
|
m_group,
|
||||||
short_sw,
|
short_name,
|
||||||
long_option_names,
|
option_names,
|
||||||
desc,
|
desc,
|
||||||
value,
|
value,
|
||||||
std::move(arg_help)
|
std::move(arg_help)
|
||||||
@ -2618,7 +2614,7 @@ Options::help_one_group(const std::string& g) const
|
|||||||
|
|
||||||
for (const auto& o : group->second.options)
|
for (const auto& o : group->second.options)
|
||||||
{
|
{
|
||||||
assert(not o.l.empty());
|
assert(!o.l.empty());
|
||||||
if (m_positional_set.find(o.l.front()) != m_positional_set.end() &&
|
if (m_positional_set.find(o.l.front()) != m_positional_set.end() &&
|
||||||
!m_show_positional)
|
!m_show_positional)
|
||||||
{
|
{
|
||||||
@ -2641,7 +2637,7 @@ Options::help_one_group(const std::string& g) const
|
|||||||
auto fiter = format.begin();
|
auto fiter = format.begin();
|
||||||
for (const auto& o : group->second.options)
|
for (const auto& o : group->second.options)
|
||||||
{
|
{
|
||||||
assert(not o.l.empty());
|
assert(!o.l.empty());
|
||||||
if (m_positional_set.find(o.l.front()) != m_positional_set.end() &&
|
if (m_positional_set.find(o.l.front()) != m_positional_set.end() &&
|
||||||
!m_show_positional)
|
!m_show_positional)
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user