summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2022-07-20 19:15:51 (GMT)
committerBrad King <brad.king@kitware.com>2022-07-25 17:52:01 (GMT)
commitf7e81802f2fd3996983376dc2c3d638fdf35f396 (patch)
tree6631d5403913cd377f7123415d05c831de496122
parentf95a5832c7ce6e88bd623e818471fa8c23fa77f4 (diff)
downloadCMake-f7e81802f2fd3996983376dc2c3d638fdf35f396.zip
CMake-f7e81802f2fd3996983376dc2c3d638fdf35f396.tar.gz
CMake-f7e81802f2fd3996983376dc2c3d638fdf35f396.tar.bz2
cmArgumentParser: Offer binding for list of parsed keywords
Some clients ask for this list in their `Parse()` call. Offer them a way to express this request as a binding.
-rw-r--r--Source/cmArgumentParser.cxx3
-rw-r--r--Source/cmArgumentParser.h24
-rw-r--r--Tests/CMakeLib/testArgumentParser.cxx23
3 files changed, 50 insertions, 0 deletions
diff --git a/Source/cmArgumentParser.cxx b/Source/cmArgumentParser.cxx
index fafae13..d4a3c8a 100644
--- a/Source/cmArgumentParser.cxx
+++ b/Source/cmArgumentParser.cxx
@@ -86,6 +86,9 @@ void Instance::Consume(cm::string_view arg)
if (this->ParsedKeywords != nullptr) {
this->ParsedKeywords->emplace_back(it->first);
}
+ if (this->Bindings.ParsedKeyword) {
+ this->Bindings.ParsedKeyword(*this, it->first);
+ }
it->second(*this);
return;
}
diff --git a/Source/cmArgumentParser.h b/Source/cmArgumentParser.h
index 70deaa6..7e219ae 100644
--- a/Source/cmArgumentParser.h
+++ b/Source/cmArgumentParser.h
@@ -81,6 +81,7 @@ class ActionMap
public:
KeywordActionMap Keywords;
KeywordNameAction KeywordMissingValue;
+ KeywordNameAction ParsedKeyword;
};
class Base
@@ -103,6 +104,12 @@ public:
static_cast<void>(inserted);
}
+ void BindParsedKeyword(KeywordNameAction action)
+ {
+ assert(!this->Bindings.ParsedKeyword);
+ this->Bindings.ParsedKeyword = std::move(action);
+ }
+
void BindKeywordMissingValue(KeywordNameAction action)
{
assert(!this->Bindings.KeywordMissingValue);
@@ -187,6 +194,16 @@ public:
return *this;
}
+ cmArgumentParser& BindParsedKeywords(
+ std::vector<cm::string_view> Result::*member)
+ {
+ this->Base::BindParsedKeyword(
+ [member](Instance& instance, cm::string_view arg) {
+ (static_cast<Result*>(instance.Result)->*member).emplace_back(arg);
+ });
+ return *this;
+ }
+
template <typename Range>
bool Parse(Result& result, Range const& args,
std::vector<std::string>* unparsedArguments,
@@ -221,6 +238,13 @@ public:
return *this;
}
+ cmArgumentParser& BindParsedKeywords(std::vector<cm::string_view>& ref)
+ {
+ this->Base::BindParsedKeyword(
+ [&ref](Instance&, cm::string_view arg) { ref.emplace_back(arg); });
+ return *this;
+ }
+
template <typename Range>
ParseResult Parse(
Range const& args, std::vector<std::string>* unparsedArguments,
diff --git a/Tests/CMakeLib/testArgumentParser.cxx b/Tests/CMakeLib/testArgumentParser.cxx
index 9db7936..5460356 100644
--- a/Tests/CMakeLib/testArgumentParser.cxx
+++ b/Tests/CMakeLib/testArgumentParser.cxx
@@ -38,6 +38,8 @@ struct Result : public ArgumentParser::ParseResult
std::vector<std::vector<std::string>> Multi2;
cm::optional<std::vector<std::vector<std::string>>> Multi3;
cm::optional<std::vector<std::vector<std::string>>> Multi4;
+
+ std::vector<cm::string_view> ParsedKeywords;
};
std::initializer_list<cm::string_view> const args = {
@@ -67,6 +69,23 @@ bool verifyResult(Result const& result,
{
static std::vector<std::string> const foobar = { "foo", "bar" };
static std::vector<std::string> const barfoo = { "bar", "foo" };
+ static std::vector<cm::string_view> const parsedKeywords = {
+ /* clang-format off */
+ "OPTION_1",
+ "STRING_1",
+ "STRING_2",
+ "STRING_4",
+ "LIST_1",
+ "LIST_2",
+ "LIST_3",
+ "LIST_3",
+ "LIST_4",
+ "LIST_6",
+ "MULTI_2",
+ "MULTI_3",
+ "MULTI_3",
+ /* clang-format on */
+ };
static std::map<cm::string_view, std::string> const keywordErrors = {
{ "STRING_1"_s, " missing required value\n" },
{ "LIST_1"_s, " missing required value\n" },
@@ -114,6 +133,8 @@ bool verifyResult(Result const& result,
ASSERT_TRUE(unparsedArguments.size() == 1);
ASSERT_TRUE(unparsedArguments[0] == "bar");
+ ASSERT_TRUE(result.ParsedKeywords == parsedKeywords);
+
ASSERT_TRUE(result.GetKeywordErrors().size() == keywordErrors.size());
for (auto const& ke : result.GetKeywordErrors()) {
auto const ki = keywordErrors.find(ke.first);
@@ -147,6 +168,7 @@ bool testArgumentParserDynamic()
.Bind("MULTI_2"_s, result.Multi2)
.Bind("MULTI_3"_s, result.Multi3)
.Bind("MULTI_4"_s, result.Multi4)
+ .BindParsedKeywords(result.ParsedKeywords)
.Parse(args, &unparsedArguments);
return verifyResult(result, unparsedArguments);
@@ -170,6 +192,7 @@ static auto const parserStatic = //
.Bind("MULTI_2"_s, &Result::Multi2)
.Bind("MULTI_3"_s, &Result::Multi3)
.Bind("MULTI_4"_s, &Result::Multi4)
+ .BindParsedKeywords(&Result::ParsedKeywords)
/* keep semicolon on own line */;
bool testArgumentParserStatic()