mirror of
https://github.com/KeqingMoe/argparse.git
synced 2025-07-04 15:14:39 +00:00
Stop sharing argument values with parent parsers
See also: p-ranav/argparse#50
This commit is contained in:
parent
2208ec5b2d
commit
3f949fc3f1
@ -349,7 +349,7 @@ Here's what's happening:
|
|||||||
|
|
||||||
### Parent Parsers
|
### Parent Parsers
|
||||||
|
|
||||||
Sometimes, several parsers share a common set of arguments. Rather than repeating the definitions of these arguments, a single parser with all the shared arguments can be added as a parent to another ArgumentParser instance. The ```.add_parents``` method takes a list of ArgumentParser objects, collects all the positional and optional actions from them, and adds these actions to the ArgumentParser object being constructed:
|
Sometimes, several parsers share a common set of arguments. Rather than repeating the definitions of these arguments, a single parser with all the common arguments can be added as a parent to another ArgumentParser instance. The ```.add_parents``` method takes a list of ArgumentParser objects, collects all the positional and optional actions from them, and adds these actions to the ArgumentParser object being constructed:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
argparse::ArgumentParser parent_parser("main");
|
argparse::ArgumentParser parent_parser("main");
|
||||||
|
@ -35,7 +35,6 @@ SOFTWARE.
|
|||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@ -383,37 +382,30 @@ public:
|
|||||||
// Parameter packing
|
// Parameter packing
|
||||||
// Call add_argument with variadic number of string arguments
|
// Call add_argument with variadic number of string arguments
|
||||||
template <typename... Targs> Argument &add_argument(Targs... Fargs) {
|
template <typename... Targs> Argument &add_argument(Targs... Fargs) {
|
||||||
std::shared_ptr<Argument> tArgument =
|
auto tArgument = mOptionalArguments.emplace(cend(mOptionalArguments),
|
||||||
std::make_shared<Argument>(std::move(Fargs)...);
|
std::move(Fargs)...);
|
||||||
|
|
||||||
if (tArgument->mIsOptional)
|
if (!tArgument->mIsOptional)
|
||||||
mOptionalArguments.emplace_back(tArgument);
|
mPositionalArguments.splice(cend(mPositionalArguments),
|
||||||
else
|
mOptionalArguments, tArgument);
|
||||||
mPositionalArguments.emplace_back(tArgument);
|
|
||||||
|
|
||||||
for (const auto &mName : tArgument->mNames) {
|
index_argument(tArgument);
|
||||||
mArgumentMap.insert_or_assign(mName, tArgument);
|
|
||||||
}
|
|
||||||
return *tArgument;
|
return *tArgument;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parameter packed add_parents method
|
// Parameter packed add_parents method
|
||||||
// Accepts a variadic number of ArgumentParser objects
|
// Accepts a variadic number of ArgumentParser objects
|
||||||
template <typename... Targs> void add_parents(Targs... Fargs) {
|
template <typename... Targs> void add_parents(const Targs &... Fargs) {
|
||||||
const auto tNewParentParsers = {Fargs...};
|
for (auto &tParentParser : {Fargs...}) {
|
||||||
for (const auto &tParentParser : tNewParentParsers) {
|
for (auto &tArgument : tParentParser.mPositionalArguments) {
|
||||||
const auto &tPositionalArguments = tParentParser.mPositionalArguments;
|
auto it =
|
||||||
std::copy(std::begin(tPositionalArguments),
|
mPositionalArguments.insert(cend(mPositionalArguments), tArgument);
|
||||||
std::end(tPositionalArguments),
|
index_argument(it);
|
||||||
std::back_inserter(mPositionalArguments));
|
}
|
||||||
|
for (auto &tArgument : tParentParser.mOptionalArguments) {
|
||||||
const auto &tOptionalArguments = tParentParser.mOptionalArguments;
|
auto it =
|
||||||
std::copy(std::begin(tOptionalArguments), std::end(tOptionalArguments),
|
mOptionalArguments.insert(cend(mOptionalArguments), tArgument);
|
||||||
std::back_inserter(mOptionalArguments));
|
index_argument(it);
|
||||||
|
|
||||||
const auto &tArgumentMap = tParentParser.mArgumentMap;
|
|
||||||
for (const auto &[tKey, tValue] : tArgumentMap) {
|
|
||||||
mArgumentMap.insert_or_assign(tKey, tValue);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -471,7 +463,7 @@ public:
|
|||||||
size_t tLongestArgumentLength = parser.get_length_of_longest_argument();
|
size_t tLongestArgumentLength = parser.get_length_of_longest_argument();
|
||||||
|
|
||||||
for (const auto &argument : parser.mPositionalArguments) {
|
for (const auto &argument : parser.mPositionalArguments) {
|
||||||
stream << argument->mNames.front() << " ";
|
stream << argument.mNames.front() << " ";
|
||||||
}
|
}
|
||||||
stream << "\n\n";
|
stream << "\n\n";
|
||||||
|
|
||||||
@ -480,7 +472,7 @@ public:
|
|||||||
|
|
||||||
for (const auto &mPositionalArgument : parser.mPositionalArguments) {
|
for (const auto &mPositionalArgument : parser.mPositionalArguments) {
|
||||||
stream.width(tLongestArgumentLength);
|
stream.width(tLongestArgumentLength);
|
||||||
stream << *mPositionalArgument;
|
stream << mPositionalArgument;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parser.mOptionalArguments.empty())
|
if (!parser.mOptionalArguments.empty())
|
||||||
@ -489,7 +481,7 @@ public:
|
|||||||
|
|
||||||
for (const auto &mOptionalArgument : parser.mOptionalArguments) {
|
for (const auto &mOptionalArgument : parser.mOptionalArguments) {
|
||||||
stream.width(tLongestArgumentLength);
|
stream.width(tLongestArgumentLength);
|
||||||
stream << *mOptionalArgument;
|
stream << mOptionalArgument;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,7 +525,7 @@ private:
|
|||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"Maximum number of positional arguments exceeded");
|
"Maximum number of positional arguments exceeded");
|
||||||
}
|
}
|
||||||
auto tArgument = *(positionalArgumentIt++);
|
auto tArgument = positionalArgumentIt++;
|
||||||
it = tArgument->consume(it, end);
|
it = tArgument->consume(it, end);
|
||||||
} else if (auto tIterator = mArgumentMap.find(tCurrentArgument);
|
} else if (auto tIterator = mArgumentMap.find(tCurrentArgument);
|
||||||
tIterator != mArgumentMap.end()) {
|
tIterator != mArgumentMap.end()) {
|
||||||
@ -585,10 +577,17 @@ private:
|
|||||||
std::end(argumentLengths));
|
std::end(argumentLengths));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using list_iterator = std::list<Argument>::iterator;
|
||||||
|
|
||||||
|
void index_argument(list_iterator argIt) {
|
||||||
|
for (auto &mName : std::as_const(argIt->mNames))
|
||||||
|
mArgumentMap.insert_or_assign(mName, argIt);
|
||||||
|
}
|
||||||
|
|
||||||
std::string mProgramName;
|
std::string mProgramName;
|
||||||
std::vector<std::shared_ptr<Argument>> mPositionalArguments;
|
std::list<Argument> mPositionalArguments;
|
||||||
std::vector<std::shared_ptr<Argument>> mOptionalArguments;
|
std::list<Argument> mOptionalArguments;
|
||||||
std::map<std::string, std::shared_ptr<Argument>> mArgumentMap;
|
std::map<std::string, list_iterator, std::less<>> mArgumentMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace argparse
|
} // namespace argparse
|
||||||
|
@ -12,6 +12,7 @@ TEST_CASE("Add parent parsers", "[parent_parsers]") {
|
|||||||
child_parser.add_parents(parent_parser);
|
child_parser.add_parents(parent_parser);
|
||||||
child_parser.parse_args({ "./main", "--verbose"});
|
child_parser.parse_args({ "./main", "--verbose"});
|
||||||
REQUIRE(child_parser["--verbose"] == true);
|
REQUIRE(child_parser["--verbose"] == true);
|
||||||
|
REQUIRE(parent_parser["--verbose"] == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Add parent to multiple parent parsers", "[parent_parsers]") {
|
TEST_CASE("Add parent to multiple parent parsers", "[parent_parsers]") {
|
||||||
@ -26,6 +27,7 @@ TEST_CASE("Add parent to multiple parent parsers", "[parent_parsers]") {
|
|||||||
foo_parser.parse_args({ "./main", "--parent", "2", "XXX" });
|
foo_parser.parse_args({ "./main", "--parent", "2", "XXX" });
|
||||||
REQUIRE(foo_parser["--parent"] == 2);
|
REQUIRE(foo_parser["--parent"] == 2);
|
||||||
REQUIRE(foo_parser["foo"] == std::string("XXX"));
|
REQUIRE(foo_parser["foo"] == std::string("XXX"));
|
||||||
|
REQUIRE(parent_parser["--parent"] == 0);
|
||||||
|
|
||||||
argparse::ArgumentParser bar_parser("bar");
|
argparse::ArgumentParser bar_parser("bar");
|
||||||
bar_parser.add_argument("--bar");
|
bar_parser.add_argument("--bar");
|
||||||
|
Loading…
Reference in New Issue
Block a user