* Fixes #345, fixes #346, regards #340: Put exceptions in a sub-namespace and renamed them accordingly. * Also fixed some "loose ends" regarding namespace indentation which were missing in PR #350. * Dropped `required_option_missing` as it is unused.
This commit is contained in:
parent
548d6196f5
commit
628dc9202b
@ -109,9 +109,9 @@ result.unmatched()
|
|||||||
|
|
||||||
Exceptional situations throw C++ exceptions. There are two types of
|
Exceptional situations throw C++ exceptions. There are two types of
|
||||||
exceptions: errors defining the options, and errors when parsing a list of
|
exceptions: errors defining the options, and errors when parsing a list of
|
||||||
arguments. All exceptions derive from `cxxopts::OptionException`. Errors
|
arguments. All exceptions derive from `cxxopts::exceptions::exception`. Errors
|
||||||
defining options derive from `cxxopts::OptionSpecException` and errors
|
defining options derive from `cxxopts::exceptions::specification` and errors
|
||||||
parsing arguments derive from `cxxopts::OptionParseException`.
|
parsing arguments derive from `cxxopts::exceptions::parsing`.
|
||||||
|
|
||||||
All exceptions define a `what()` function to get a printable string
|
All exceptions define a `what()` function to get a printable string
|
||||||
explaining the error.
|
explaining the error.
|
||||||
|
|||||||
@ -227,6 +227,7 @@ empty(const String& s)
|
|||||||
} // namespace cxxopts
|
} // namespace cxxopts
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
|
|
||||||
inline
|
inline
|
||||||
cxxopts::UnicodeStringIterator
|
cxxopts::UnicodeStringIterator
|
||||||
begin(const icu::UnicodeString& s)
|
begin(const icu::UnicodeString& s)
|
||||||
@ -304,6 +305,7 @@ empty(const std::string& s)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace cxxopts {
|
namespace cxxopts {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
const std::string LQUOTE("\'");
|
const std::string LQUOTE("\'");
|
||||||
@ -368,164 +370,155 @@ class Value : public std::enable_shared_from_this<Value>
|
|||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
class OptionException : public std::exception
|
namespace exceptions {
|
||||||
{
|
class exception : public std::exception
|
||||||
public:
|
|
||||||
explicit OptionException(std::string message)
|
|
||||||
: m_message(std::move(message))
|
|
||||||
{
|
{
|
||||||
}
|
public:
|
||||||
|
explicit exception(std::string message)
|
||||||
|
: m_message(std::move(message))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
CXXOPTS_NODISCARD
|
CXXOPTS_NODISCARD
|
||||||
const char*
|
const char*
|
||||||
what() const noexcept override
|
what() const noexcept override
|
||||||
|
{
|
||||||
|
return m_message.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_message;
|
||||||
|
};
|
||||||
|
|
||||||
|
class specification : public exception
|
||||||
{
|
{
|
||||||
return m_message.c_str();
|
public:
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
explicit specification(const std::string& message)
|
||||||
std::string m_message;
|
: exception(message)
|
||||||
};
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class OptionSpecException : public OptionException
|
class parsing : public exception
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit OptionSpecException(const std::string& message)
|
|
||||||
: OptionException(message)
|
|
||||||
{
|
{
|
||||||
}
|
public:
|
||||||
};
|
explicit parsing(const std::string& message)
|
||||||
|
: exception(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class OptionParseException : public OptionException
|
class option_already_exists : public specification
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit OptionParseException(const std::string& message)
|
|
||||||
: OptionException(message)
|
|
||||||
{
|
{
|
||||||
}
|
public:
|
||||||
};
|
explicit option_already_exists(const std::string& option)
|
||||||
|
: specification("Option " + LQUOTE + option + RQUOTE + " already exists")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class option_exists_error : public OptionSpecException
|
class invalid_option_format : public specification
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit option_exists_error(const std::string& option)
|
|
||||||
: OptionSpecException("Option " + LQUOTE + option + RQUOTE + " already exists")
|
|
||||||
{
|
{
|
||||||
}
|
public:
|
||||||
};
|
explicit invalid_option_format(const std::string& format)
|
||||||
|
: specification("Invalid option format " + LQUOTE + format + RQUOTE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class invalid_option_format_error : public OptionSpecException
|
class invalid_option_syntax : public parsing {
|
||||||
{
|
public:
|
||||||
public:
|
explicit invalid_option_syntax(const std::string& text)
|
||||||
explicit invalid_option_format_error(const std::string& format)
|
: parsing("Argument " + LQUOTE + text + RQUOTE +
|
||||||
: OptionSpecException("Invalid option format " + LQUOTE + format + RQUOTE)
|
" starts with a - but has incorrect syntax")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class no_such_option : public parsing
|
||||||
{
|
{
|
||||||
}
|
public:
|
||||||
};
|
explicit no_such_option(const std::string& option)
|
||||||
|
: parsing("Option " + LQUOTE + option + RQUOTE + " does not exist")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class option_syntax_exception : public OptionParseException {
|
class missing_argument : public parsing
|
||||||
public:
|
|
||||||
explicit option_syntax_exception(const std::string& text)
|
|
||||||
: OptionParseException("Argument " + LQUOTE + text + RQUOTE +
|
|
||||||
" starts with a - but has incorrect syntax")
|
|
||||||
{
|
{
|
||||||
}
|
public:
|
||||||
};
|
explicit missing_argument(const std::string& option)
|
||||||
|
: parsing(
|
||||||
|
"Option " + LQUOTE + option + RQUOTE + " is missing an argument"
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class option_not_exists_exception : public OptionParseException
|
class option_requires_argument : public parsing
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit option_not_exists_exception(const std::string& option)
|
|
||||||
: OptionParseException("Option " + LQUOTE + option + RQUOTE + " does not exist")
|
|
||||||
{
|
{
|
||||||
}
|
public:
|
||||||
};
|
explicit option_requires_argument(const std::string& option)
|
||||||
|
: parsing(
|
||||||
|
"Option " + LQUOTE + option + RQUOTE + " requires an argument"
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class missing_argument_exception : public OptionParseException
|
class gratuitous_argument_for_option : public parsing
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit missing_argument_exception(const std::string& option)
|
gratuitous_argument_for_option
|
||||||
: OptionParseException(
|
(
|
||||||
"Option " + LQUOTE + option + RQUOTE + " is missing an argument"
|
const std::string& option,
|
||||||
|
const std::string& arg
|
||||||
)
|
)
|
||||||
{
|
: parsing(
|
||||||
}
|
"Option " + LQUOTE + option + RQUOTE +
|
||||||
};
|
" does not take an argument, but argument " +
|
||||||
|
LQUOTE + arg + RQUOTE + " given"
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class option_requires_argument_exception : public OptionParseException
|
class requested_option_not_present : public parsing
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit option_requires_argument_exception(const std::string& option)
|
explicit requested_option_not_present(const std::string& option)
|
||||||
: OptionParseException(
|
: parsing("Option " + LQUOTE + option + RQUOTE + " not present")
|
||||||
"Option " + LQUOTE + option + RQUOTE + " requires an argument"
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class option_has_no_value : public exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit option_has_no_value(const std::string& option)
|
||||||
|
: exception(
|
||||||
|
!option.empty() ?
|
||||||
|
("Option " + LQUOTE + option + RQUOTE + " has no value") :
|
||||||
|
"Option has no value")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class incorrect_argument_type : public parsing
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit incorrect_argument_type
|
||||||
|
(
|
||||||
|
const std::string& arg
|
||||||
)
|
)
|
||||||
{
|
: parsing(
|
||||||
}
|
"Argument " + LQUOTE + arg + RQUOTE + " failed to parse"
|
||||||
};
|
)
|
||||||
|
{
|
||||||
class option_not_has_argument_exception : public OptionParseException
|
}
|
||||||
{
|
};
|
||||||
public:
|
}
|
||||||
option_not_has_argument_exception
|
|
||||||
(
|
|
||||||
const std::string& option,
|
|
||||||
const std::string& arg
|
|
||||||
)
|
|
||||||
: OptionParseException(
|
|
||||||
"Option " + LQUOTE + option + RQUOTE +
|
|
||||||
" does not take an argument, but argument " +
|
|
||||||
LQUOTE + arg + RQUOTE + " given"
|
|
||||||
)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class option_not_present_exception : public OptionParseException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit option_not_present_exception(const std::string& option)
|
|
||||||
: OptionParseException("Option " + LQUOTE + option + RQUOTE + " not present")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class option_has_no_value_exception : public OptionException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit option_has_no_value_exception(const std::string& option)
|
|
||||||
: OptionException(
|
|
||||||
!option.empty() ?
|
|
||||||
("Option " + LQUOTE + option + RQUOTE + " has no value") :
|
|
||||||
"Option has no value")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class argument_incorrect_type : public OptionParseException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit argument_incorrect_type
|
|
||||||
(
|
|
||||||
const std::string& arg
|
|
||||||
)
|
|
||||||
: OptionParseException(
|
|
||||||
"Argument " + LQUOTE + arg + RQUOTE + " failed to parse"
|
|
||||||
)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class option_required_exception : public OptionParseException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit option_required_exception(const std::string& option)
|
|
||||||
: OptionParseException(
|
|
||||||
"Option " + LQUOTE + option + RQUOTE + " is required but not present"
|
|
||||||
)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void throw_or_mimic(const std::string& text)
|
void throw_or_mimic(const std::string& text)
|
||||||
@ -547,7 +540,9 @@ void throw_or_mimic(const std::string& text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace values {
|
namespace values {
|
||||||
|
|
||||||
namespace parser_tool {
|
namespace parser_tool {
|
||||||
|
|
||||||
struct IntegerDesc
|
struct IntegerDesc
|
||||||
{
|
{
|
||||||
std::string negative = "";
|
std::string negative = "";
|
||||||
@ -560,12 +555,13 @@ struct ArguDesc {
|
|||||||
bool set_value = false;
|
bool set_value = false;
|
||||||
std::string value = "";
|
std::string value = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CXXOPTS_NO_REGEX
|
#ifdef CXXOPTS_NO_REGEX
|
||||||
inline IntegerDesc SplitInteger(const std::string &text)
|
inline IntegerDesc SplitInteger(const std::string &text)
|
||||||
{
|
{
|
||||||
if (text.empty())
|
if (text.empty())
|
||||||
{
|
{
|
||||||
throw_or_mimic<argument_incorrect_type>(text);
|
throw_or_mimic<exceptions::incorrect_argument_type>(text);
|
||||||
}
|
}
|
||||||
IntegerDesc desc;
|
IntegerDesc desc;
|
||||||
const char *pdata = text.c_str();
|
const char *pdata = text.c_str();
|
||||||
@ -585,7 +581,7 @@ inline IntegerDesc SplitInteger(const std::string &text)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw_or_mimic<argument_incorrect_type>(text);
|
throw_or_mimic<exceptions::incorrect_argument_type>(text);
|
||||||
}
|
}
|
||||||
return desc;
|
return desc;
|
||||||
}
|
}
|
||||||
@ -644,7 +640,7 @@ inline std::pair<std::string, std::string> SplitSwitchDef(const std::string &tex
|
|||||||
if (*pdata == '\0') {
|
if (*pdata == '\0') {
|
||||||
long_sw = std::string(store, pdata - store);
|
long_sw = std::string(store, pdata - store);
|
||||||
} else {
|
} else {
|
||||||
throw_or_mimic<invalid_option_format_error>(text);
|
throw_or_mimic<exceptions::invalid_option_format>(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return std::pair<std::string, std::string>(short_sw, long_sw);
|
return std::pair<std::string, std::string>(short_sw, long_sw);
|
||||||
@ -725,7 +721,7 @@ inline IntegerDesc SplitInteger(const std::string &text)
|
|||||||
|
|
||||||
if (match.length() == 0)
|
if (match.length() == 0)
|
||||||
{
|
{
|
||||||
throw_or_mimic<argument_incorrect_type>(text);
|
throw_or_mimic<exceptions::incorrect_argument_type>(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
IntegerDesc desc;
|
IntegerDesc desc;
|
||||||
@ -741,7 +737,6 @@ inline IntegerDesc SplitInteger(const std::string &text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return desc;
|
return desc;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsTrueText(const std::string &text)
|
inline bool IsTrueText(const std::string &text)
|
||||||
@ -764,7 +759,7 @@ inline std::pair<std::string, std::string> SplitSwitchDef(const std::string &tex
|
|||||||
std::regex_match(text.c_str(), result, option_specifier);
|
std::regex_match(text.c_str(), result, option_specifier);
|
||||||
if (result.empty())
|
if (result.empty())
|
||||||
{
|
{
|
||||||
throw_or_mimic<invalid_option_format_error>(text);
|
throw_or_mimic<exceptions::invalid_option_format>(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& short_sw = result[2];
|
const std::string& short_sw = result[2];
|
||||||
@ -799,6 +794,7 @@ inline ArguDesc ParseArgument(const char *arg, bool &matched)
|
|||||||
} // namespace parser_tool
|
} // namespace parser_tool
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template <typename T, bool B>
|
template <typename T, bool B>
|
||||||
struct SignedCheck;
|
struct SignedCheck;
|
||||||
|
|
||||||
@ -813,14 +809,14 @@ struct SignedCheck<T, true>
|
|||||||
{
|
{
|
||||||
if (u > static_cast<U>((std::numeric_limits<T>::min)()))
|
if (u > static_cast<U>((std::numeric_limits<T>::min)()))
|
||||||
{
|
{
|
||||||
throw_or_mimic<argument_incorrect_type>(text);
|
throw_or_mimic<exceptions::incorrect_argument_type>(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (u > static_cast<U>((std::numeric_limits<T>::max)()))
|
if (u > static_cast<U>((std::numeric_limits<T>::max)()))
|
||||||
{
|
{
|
||||||
throw_or_mimic<argument_incorrect_type>(text);
|
throw_or_mimic<exceptions::incorrect_argument_type>(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -857,7 +853,7 @@ template <typename R, typename T>
|
|||||||
void
|
void
|
||||||
checked_negate(R&, T&&, const std::string& text, std::false_type)
|
checked_negate(R&, T&&, const std::string& text, std::false_type)
|
||||||
{
|
{
|
||||||
throw_or_mimic<argument_incorrect_type>(text);
|
throw_or_mimic<exceptions::incorrect_argument_type>(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -893,13 +889,13 @@ integer_parser(const std::string& text, T& value)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw_or_mimic<argument_incorrect_type>(text);
|
throw_or_mimic<exceptions::incorrect_argument_type>(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
const US next = static_cast<US>(result * base + digit);
|
const US next = static_cast<US>(result * base + digit);
|
||||||
if (result > next)
|
if (result > next)
|
||||||
{
|
{
|
||||||
throw_or_mimic<argument_incorrect_type>(text);
|
throw_or_mimic<exceptions::incorrect_argument_type>(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = next;
|
result = next;
|
||||||
@ -923,7 +919,7 @@ void stringstream_parser(const std::string& text, T& value)
|
|||||||
std::stringstream in(text);
|
std::stringstream in(text);
|
||||||
in >> value;
|
in >> value;
|
||||||
if (!in) {
|
if (!in) {
|
||||||
throw_or_mimic<argument_incorrect_type>(text);
|
throw_or_mimic<exceptions::incorrect_argument_type>(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -951,7 +947,7 @@ parse_value(const std::string& text, bool& value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw_or_mimic<argument_incorrect_type>(text);
|
throw_or_mimic<exceptions::incorrect_argument_type>(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
@ -1007,7 +1003,7 @@ void parse_value(const std::string& text, char& c)
|
|||||||
{
|
{
|
||||||
if (text.length() != 1)
|
if (text.length() != 1)
|
||||||
{
|
{
|
||||||
throw_or_mimic<argument_incorrect_type>(text);
|
throw_or_mimic<exceptions::incorrect_argument_type>(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
c = text[0];
|
c = text[0];
|
||||||
@ -1204,6 +1200,7 @@ class standard_value<bool> : public abstract_value<bool>
|
|||||||
m_implicit_value = "true";
|
m_implicit_value = "true";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace values
|
} // namespace values
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -1388,7 +1385,7 @@ class OptionValue
|
|||||||
as() const
|
as() const
|
||||||
{
|
{
|
||||||
if (m_value == nullptr) {
|
if (m_value == nullptr) {
|
||||||
throw_or_mimic<option_has_no_value_exception>(
|
throw_or_mimic<exceptions::option_has_no_value>(
|
||||||
m_long_name == nullptr ? "" : *m_long_name);
|
m_long_name == nullptr ? "" : *m_long_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1576,14 +1573,14 @@ class ParseResult
|
|||||||
|
|
||||||
if (iter == m_keys.end())
|
if (iter == m_keys.end())
|
||||||
{
|
{
|
||||||
throw_or_mimic<option_not_present_exception>(option);
|
throw_or_mimic<exceptions::requested_option_not_present>(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto viter = m_values.find(iter->second);
|
auto viter = m_values.find(iter->second);
|
||||||
|
|
||||||
if (viter == m_values.end())
|
if (viter == m_values.end())
|
||||||
{
|
{
|
||||||
throw_or_mimic<option_not_present_exception>(option);
|
throw_or_mimic<exceptions::requested_option_not_present>(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
return viter->second;
|
return viter->second;
|
||||||
@ -1898,184 +1895,186 @@ class OptionAdder
|
|||||||
};
|
};
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr size_t OPTION_LONGEST = 30;
|
|
||||||
constexpr size_t OPTION_DESC_GAP = 2;
|
|
||||||
|
|
||||||
String
|
constexpr size_t OPTION_LONGEST = 30;
|
||||||
format_option
|
constexpr size_t OPTION_DESC_GAP = 2;
|
||||||
(
|
|
||||||
const HelpOptionDetails& o
|
String
|
||||||
)
|
format_option
|
||||||
|
(
|
||||||
|
const HelpOptionDetails& o
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const auto& s = o.s;
|
||||||
|
const auto& l = o.l;
|
||||||
|
|
||||||
|
String result = " ";
|
||||||
|
|
||||||
|
if (!s.empty())
|
||||||
{
|
{
|
||||||
const auto& s = o.s;
|
result += "-" + toLocalString(s);
|
||||||
const auto& l = o.l;
|
if (!l.empty())
|
||||||
|
|
||||||
String result = " ";
|
|
||||||
|
|
||||||
if (!s.empty())
|
|
||||||
{
|
{
|
||||||
result += "-" + toLocalString(s);
|
result += ",";
|
||||||
if (!l.empty())
|
}
|
||||||
{
|
}
|
||||||
result += ",";
|
else
|
||||||
}
|
{
|
||||||
|
result += " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!l.empty())
|
||||||
|
{
|
||||||
|
result += " --" + toLocalString(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto arg = !o.arg_help.empty() ? toLocalString(o.arg_help) : "arg";
|
||||||
|
|
||||||
|
if (!o.is_boolean)
|
||||||
|
{
|
||||||
|
if (o.has_implicit)
|
||||||
|
{
|
||||||
|
result += " [=" + arg + "(=" + toLocalString(o.implicit_value) + ")]";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result += " ";
|
result += " " + arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!l.empty())
|
|
||||||
{
|
|
||||||
result += " --" + toLocalString(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto arg = !o.arg_help.empty() ? toLocalString(o.arg_help) : "arg";
|
|
||||||
|
|
||||||
if (!o.is_boolean)
|
|
||||||
{
|
|
||||||
if (o.has_implicit)
|
|
||||||
{
|
|
||||||
result += " [=" + arg + "(=" + toLocalString(o.implicit_value) + ")]";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result += " " + arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String
|
return result;
|
||||||
format_description
|
}
|
||||||
(
|
|
||||||
const HelpOptionDetails& o,
|
String
|
||||||
size_t start,
|
format_description
|
||||||
size_t allowed,
|
(
|
||||||
bool tab_expansion
|
const HelpOptionDetails& o,
|
||||||
)
|
size_t start,
|
||||||
|
size_t allowed,
|
||||||
|
bool tab_expansion
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto desc = o.desc;
|
||||||
|
|
||||||
|
if (o.has_default && (!o.is_boolean || o.default_value != "false"))
|
||||||
{
|
{
|
||||||
auto desc = o.desc;
|
if(!o.default_value.empty())
|
||||||
|
|
||||||
if (o.has_default && (!o.is_boolean || o.default_value != "false"))
|
|
||||||
{
|
{
|
||||||
if(!o.default_value.empty())
|
desc += toLocalString(" (default: " + o.default_value + ")");
|
||||||
{
|
|
||||||
desc += toLocalString(" (default: " + o.default_value + ")");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
desc += toLocalString(" (default: \"\")");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
String result;
|
|
||||||
|
|
||||||
if (tab_expansion)
|
|
||||||
{
|
{
|
||||||
String desc2;
|
desc += toLocalString(" (default: \"\")");
|
||||||
auto size = size_t{ 0 };
|
|
||||||
for (auto c = std::begin(desc); c != std::end(desc); ++c)
|
|
||||||
{
|
|
||||||
if (*c == '\n')
|
|
||||||
{
|
|
||||||
desc2 += *c;
|
|
||||||
size = 0;
|
|
||||||
}
|
|
||||||
else if (*c == '\t')
|
|
||||||
{
|
|
||||||
auto skip = 8 - size % 8;
|
|
||||||
stringAppend(desc2, skip, ' ');
|
|
||||||
size += skip;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
desc2 += *c;
|
|
||||||
++size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
desc = desc2;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
desc += " ";
|
String result;
|
||||||
|
|
||||||
auto current = std::begin(desc);
|
if (tab_expansion)
|
||||||
auto previous = current;
|
{
|
||||||
auto startLine = current;
|
String desc2;
|
||||||
auto lastSpace = current;
|
auto size = size_t{ 0 };
|
||||||
|
for (auto c = std::begin(desc); c != std::end(desc); ++c)
|
||||||
auto size = size_t{};
|
|
||||||
|
|
||||||
bool appendNewLine;
|
|
||||||
bool onlyWhiteSpace = true;
|
|
||||||
|
|
||||||
while (current != std::end(desc))
|
|
||||||
{
|
{
|
||||||
appendNewLine = false;
|
if (*c == '\n')
|
||||||
|
|
||||||
if (std::isblank(*previous))
|
|
||||||
{
|
{
|
||||||
lastSpace = current;
|
desc2 += *c;
|
||||||
}
|
|
||||||
|
|
||||||
if (!std::isblank(*current))
|
|
||||||
{
|
|
||||||
onlyWhiteSpace = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*current == '\n')
|
|
||||||
{
|
|
||||||
previous = current;
|
|
||||||
++current;
|
|
||||||
appendNewLine = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!appendNewLine && size >= allowed)
|
|
||||||
{
|
|
||||||
if (lastSpace != startLine)
|
|
||||||
{
|
|
||||||
current = lastSpace;
|
|
||||||
previous = current;
|
|
||||||
}
|
|
||||||
appendNewLine = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (appendNewLine)
|
|
||||||
{
|
|
||||||
stringAppend(result, startLine, current);
|
|
||||||
startLine = current;
|
|
||||||
lastSpace = current;
|
|
||||||
|
|
||||||
if (*previous != '\n')
|
|
||||||
{
|
|
||||||
stringAppend(result, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
stringAppend(result, start, ' ');
|
|
||||||
|
|
||||||
if (*previous != '\n')
|
|
||||||
{
|
|
||||||
stringAppend(result, lastSpace, current);
|
|
||||||
}
|
|
||||||
|
|
||||||
onlyWhiteSpace = true;
|
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
|
else if (*c == '\t')
|
||||||
|
{
|
||||||
|
auto skip = 8 - size % 8;
|
||||||
|
stringAppend(desc2, skip, ' ');
|
||||||
|
size += skip;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
desc2 += *c;
|
||||||
|
++size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
desc = desc2;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc += " ";
|
||||||
|
|
||||||
|
auto current = std::begin(desc);
|
||||||
|
auto previous = current;
|
||||||
|
auto startLine = current;
|
||||||
|
auto lastSpace = current;
|
||||||
|
|
||||||
|
auto size = size_t{};
|
||||||
|
|
||||||
|
bool appendNewLine;
|
||||||
|
bool onlyWhiteSpace = true;
|
||||||
|
|
||||||
|
while (current != std::end(desc))
|
||||||
|
{
|
||||||
|
appendNewLine = false;
|
||||||
|
|
||||||
|
if (std::isblank(*previous))
|
||||||
|
{
|
||||||
|
lastSpace = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!std::isblank(*current))
|
||||||
|
{
|
||||||
|
onlyWhiteSpace = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*current == '\n')
|
||||||
|
{
|
||||||
previous = current;
|
previous = current;
|
||||||
++current;
|
++current;
|
||||||
++size;
|
appendNewLine = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//append whatever is left but ignore whitespace
|
if (!appendNewLine && size >= allowed)
|
||||||
if (!onlyWhiteSpace)
|
|
||||||
{
|
{
|
||||||
stringAppend(result, startLine, previous);
|
if (lastSpace != startLine)
|
||||||
|
{
|
||||||
|
current = lastSpace;
|
||||||
|
previous = current;
|
||||||
|
}
|
||||||
|
appendNewLine = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
if (appendNewLine)
|
||||||
|
{
|
||||||
|
stringAppend(result, startLine, current);
|
||||||
|
startLine = current;
|
||||||
|
lastSpace = current;
|
||||||
|
|
||||||
|
if (*previous != '\n')
|
||||||
|
{
|
||||||
|
stringAppend(result, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
stringAppend(result, start, ' ');
|
||||||
|
|
||||||
|
if (*previous != '\n')
|
||||||
|
{
|
||||||
|
stringAppend(result, lastSpace, current);
|
||||||
|
}
|
||||||
|
|
||||||
|
onlyWhiteSpace = true;
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
previous = current;
|
||||||
|
++current;
|
||||||
|
++size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//append whatever is left but ignore whitespace
|
||||||
|
if (!onlyWhiteSpace)
|
||||||
|
{
|
||||||
|
stringAppend(result, startLine, previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
inline
|
inline
|
||||||
@ -2115,11 +2114,11 @@ OptionAdder::operator()
|
|||||||
|
|
||||||
if (!short_sw.length() && !long_sw.length())
|
if (!short_sw.length() && !long_sw.length())
|
||||||
{
|
{
|
||||||
throw_or_mimic<invalid_option_format_error>(opts);
|
throw_or_mimic<exceptions::invalid_option_format>(opts);
|
||||||
}
|
}
|
||||||
else if (long_sw.length() == 1 && short_sw.length())
|
else if (long_sw.length() == 1 && short_sw.length())
|
||||||
{
|
{
|
||||||
throw_or_mimic<invalid_option_format_error>(opts);
|
throw_or_mimic<exceptions::invalid_option_format>(opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto option_names = []
|
auto option_names = []
|
||||||
@ -2201,7 +2200,7 @@ OptionParser::checked_parse_arg
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw_or_mimic<missing_argument_exception>(name);
|
throw_or_mimic<exceptions::missing_argument>(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2249,7 +2248,7 @@ OptionParser::consume_positional(const std::string& a, PositionalListIterator& n
|
|||||||
add_to_option(iter, *next, a);
|
add_to_option(iter, *next, a);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
throw_or_mimic<option_not_exists_exception>(*next);
|
throw_or_mimic<exceptions::no_such_option>(*next);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -2315,7 +2314,7 @@ OptionParser::parse(int argc, const char* const* argv)
|
|||||||
// but if it starts with a `-`, then it's an error
|
// but if it starts with a `-`, then it's an error
|
||||||
if (argv[current][0] == '-' && argv[current][1] != '\0') {
|
if (argv[current][0] == '-' && argv[current][1] != '\0') {
|
||||||
if (!m_allow_unrecognised) {
|
if (!m_allow_unrecognised) {
|
||||||
throw_or_mimic<option_syntax_exception>(argv[current]);
|
throw_or_mimic<exceptions::invalid_option_syntax>(argv[current]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2350,7 +2349,7 @@ OptionParser::parse(int argc, const char* const* argv)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//error
|
//error
|
||||||
throw_or_mimic<option_not_exists_exception>(name);
|
throw_or_mimic<exceptions::no_such_option>(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto value = iter->second;
|
auto value = iter->second;
|
||||||
@ -2373,7 +2372,7 @@ OptionParser::parse(int argc, const char* const* argv)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
//error
|
//error
|
||||||
throw_or_mimic<option_requires_argument_exception>(name);
|
throw_or_mimic<exceptions::option_requires_argument>(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2393,7 +2392,7 @@ OptionParser::parse(int argc, const char* const* argv)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//error
|
//error
|
||||||
throw_or_mimic<option_not_exists_exception>(name);
|
throw_or_mimic<exceptions::no_such_option>(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto opt = iter->second;
|
auto opt = iter->second;
|
||||||
@ -2531,7 +2530,7 @@ Options::add_one_option
|
|||||||
|
|
||||||
if (!in.second)
|
if (!in.second)
|
||||||
{
|
{
|
||||||
throw_or_mimic<option_exists_error>(option);
|
throw_or_mimic<exceptions::option_already_exists>(option);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -182,7 +182,7 @@ parse(int argc, const char* argv[])
|
|||||||
}
|
}
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
catch (const cxxopts::OptionException& e)
|
catch (const cxxopts::exceptions::exception& e)
|
||||||
{
|
{
|
||||||
std::cout << "error parsing options: " << e.what() << std::endl;
|
std::cout << "error parsing options: " << e.what() << std::endl;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -9188,7 +9188,7 @@ namespace Catch {
|
|||||||
// And... Print a result applicable to each result type.
|
// And... Print a result applicable to each result type.
|
||||||
switch( assertionResult.getResultType() ) {
|
switch( assertionResult.getResultType() ) {
|
||||||
case ResultWas::ThrewException:
|
case ResultWas::ThrewException:
|
||||||
m_xml.scopedElement( "Exception" )
|
m_xml.scopedElement( "exception" )
|
||||||
.writeAttribute( "filename", assertionResult.getSourceInfo().file )
|
.writeAttribute( "filename", assertionResult.getSourceInfo().file )
|
||||||
.writeAttribute( "line", assertionResult.getSourceInfo().line )
|
.writeAttribute( "line", assertionResult.getSourceInfo().line )
|
||||||
.writeText( assertionResult.getMessage() );
|
.writeText( assertionResult.getMessage() );
|
||||||
|
|||||||
@ -94,7 +94,7 @@ TEST_CASE("Basic options", "[options]")
|
|||||||
CHECK(arguments[2].key() == "value");
|
CHECK(arguments[2].key() == "value");
|
||||||
CHECK(arguments[3].key() == "av");
|
CHECK(arguments[3].key() == "av");
|
||||||
|
|
||||||
CHECK_THROWS_AS(result["nothing"].as<std::string>(), cxxopts::option_has_no_value_exception&);
|
CHECK_THROWS_AS(result["nothing"].as<std::string>(), cxxopts::exceptions::option_has_no_value&);
|
||||||
|
|
||||||
CHECK(options.program() == "tester");
|
CHECK(options.program() == "tester");
|
||||||
}
|
}
|
||||||
@ -122,7 +122,7 @@ TEST_CASE("Short options", "[options]")
|
|||||||
CHECK(arguments[0].value() == "value");
|
CHECK(arguments[0].value() == "value");
|
||||||
|
|
||||||
REQUIRE_THROWS_AS(options.add_options()("", "nothing option"),
|
REQUIRE_THROWS_AS(options.add_options()("", "nothing option"),
|
||||||
cxxopts::invalid_option_format_error&);
|
cxxopts::exceptions::invalid_option_format&);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("No positional", "[positional]")
|
TEST_CASE("No positional", "[positional]")
|
||||||
@ -235,7 +235,7 @@ TEST_CASE("Positional not valid", "[positional]") {
|
|||||||
auto** argv = av.argv();
|
auto** argv = av.argv();
|
||||||
auto argc = av.argc();
|
auto argc = av.argc();
|
||||||
|
|
||||||
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_not_exists_exception&);
|
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::no_such_option&);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Positional with empty arguments", "[positional]") {
|
TEST_CASE("Positional with empty arguments", "[positional]") {
|
||||||
@ -294,7 +294,7 @@ TEST_CASE("Boolean without implicit value", "[implicit]")
|
|||||||
auto** argv = av.argv();
|
auto** argv = av.argv();
|
||||||
auto argc = av.argc();
|
auto argc = av.argc();
|
||||||
|
|
||||||
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::missing_argument_exception&);
|
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::missing_argument&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("With equal-separated true") {
|
SECTION("With equal-separated true") {
|
||||||
@ -460,7 +460,7 @@ TEST_CASE("Unsigned integers", "[options]")
|
|||||||
auto argc = av.argc();
|
auto argc = av.argc();
|
||||||
|
|
||||||
options.parse_positional("positional");
|
options.parse_positional("positional");
|
||||||
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::argument_incorrect_type&);
|
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::incorrect_argument_type&);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Integer bounds", "[integer]")
|
TEST_CASE("Integer bounds", "[integer]")
|
||||||
@ -497,12 +497,12 @@ TEST_CASE("Overflow on boundary", "[integer]")
|
|||||||
int8_t si;
|
int8_t si;
|
||||||
uint8_t ui;
|
uint8_t ui;
|
||||||
|
|
||||||
CHECK_THROWS_AS((integer_parser("128", si)), cxxopts::argument_incorrect_type&);
|
CHECK_THROWS_AS((integer_parser("128", si)), cxxopts::exceptions::incorrect_argument_type&);
|
||||||
CHECK_THROWS_AS((integer_parser("-129", si)), cxxopts::argument_incorrect_type&);
|
CHECK_THROWS_AS((integer_parser("-129", si)), cxxopts::exceptions::incorrect_argument_type&);
|
||||||
CHECK_THROWS_AS((integer_parser("256", ui)), cxxopts::argument_incorrect_type&);
|
CHECK_THROWS_AS((integer_parser("256", ui)), cxxopts::exceptions::incorrect_argument_type&);
|
||||||
CHECK_THROWS_AS((integer_parser("-0x81", si)), cxxopts::argument_incorrect_type&);
|
CHECK_THROWS_AS((integer_parser("-0x81", si)), cxxopts::exceptions::incorrect_argument_type&);
|
||||||
CHECK_THROWS_AS((integer_parser("0x80", si)), cxxopts::argument_incorrect_type&);
|
CHECK_THROWS_AS((integer_parser("0x80", si)), cxxopts::exceptions::incorrect_argument_type&);
|
||||||
CHECK_THROWS_AS((integer_parser("0x100", ui)), cxxopts::argument_incorrect_type&);
|
CHECK_THROWS_AS((integer_parser("0x100", ui)), cxxopts::exceptions::incorrect_argument_type&);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Integer overflow", "[options]")
|
TEST_CASE("Integer overflow", "[options]")
|
||||||
@ -519,11 +519,11 @@ TEST_CASE("Integer overflow", "[options]")
|
|||||||
auto argc = av.argc();
|
auto argc = av.argc();
|
||||||
|
|
||||||
options.parse_positional("positional");
|
options.parse_positional("positional");
|
||||||
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::argument_incorrect_type&);
|
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::incorrect_argument_type&);
|
||||||
|
|
||||||
int integer = 0;
|
int integer = 0;
|
||||||
CHECK_THROWS_AS((integer_parser("23423423423", integer)), cxxopts::argument_incorrect_type&);
|
CHECK_THROWS_AS((integer_parser("23423423423", integer)), cxxopts::exceptions::incorrect_argument_type&);
|
||||||
CHECK_THROWS_AS((integer_parser("234234234234", integer)), cxxopts::argument_incorrect_type&);
|
CHECK_THROWS_AS((integer_parser("234234234234", integer)), cxxopts::exceptions::incorrect_argument_type&);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Floats", "[options]")
|
TEST_CASE("Floats", "[options]")
|
||||||
@ -564,7 +564,7 @@ TEST_CASE("Invalid integers", "[integer]") {
|
|||||||
auto argc = av.argc();
|
auto argc = av.argc();
|
||||||
|
|
||||||
options.parse_positional("positional");
|
options.parse_positional("positional");
|
||||||
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::argument_incorrect_type&);
|
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::incorrect_argument_type&);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Booleans", "[boolean]") {
|
TEST_CASE("Booleans", "[boolean]") {
|
||||||
@ -670,7 +670,7 @@ TEST_CASE("Unrecognised options", "[options]") {
|
|||||||
auto argc = av.argc();
|
auto argc = av.argc();
|
||||||
|
|
||||||
SECTION("Default behaviour") {
|
SECTION("Default behaviour") {
|
||||||
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_not_exists_exception&);
|
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::no_such_option&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("After allowing unrecognised options") {
|
SECTION("After allowing unrecognised options") {
|
||||||
@ -697,7 +697,7 @@ TEST_CASE("Allow bad short syntax", "[options]") {
|
|||||||
auto argc = av.argc();
|
auto argc = av.argc();
|
||||||
|
|
||||||
SECTION("Default behaviour") {
|
SECTION("Default behaviour") {
|
||||||
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_syntax_exception&);
|
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::invalid_option_syntax&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("After allowing unrecognised options") {
|
SECTION("After allowing unrecognised options") {
|
||||||
@ -720,7 +720,7 @@ TEST_CASE("Invalid option syntax", "[options]") {
|
|||||||
auto argc = av.argc();
|
auto argc = av.argc();
|
||||||
|
|
||||||
SECTION("Default behaviour") {
|
SECTION("Default behaviour") {
|
||||||
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_syntax_exception&);
|
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::invalid_option_syntax&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -739,7 +739,7 @@ TEST_CASE("Options empty", "[options]") {
|
|||||||
auto** argv = argv_.argv();
|
auto** argv = argv_.argv();
|
||||||
|
|
||||||
CHECK(options.groups().empty());
|
CHECK(options.groups().empty());
|
||||||
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_not_exists_exception&);
|
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::no_such_option&);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Initializer list with group", "[options]") {
|
TEST_CASE("Initializer list with group", "[options]") {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user