From 3d559d3a23cf8567b1f300a1e8e70b8d87f90f0c Mon Sep 17 00:00:00 2001 From: Yoshihiro Hokazono Date: Sun, 12 Sep 2021 03:36:05 +0900 Subject: [PATCH] Revive remaining method I reimplemented remaining() method for backward compatibility. It consumes "all" remaining args. So, I added mAcceptsOptionalLikeValue flag and handle it by using this flag. Currently, remaining() behavior is slightly different from the original when no args are provided and get>() method is called. Originally it raises an exception. But current implementation returns an empty container instead of exception. It is possible to implement complete backward compatibility by referencing mAcceptsOptionalLikeValue flag and raises an exception in get() method, but I did not do this. I think that is too much. --- include/argparse/argparse.hpp | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/include/argparse/argparse.hpp b/include/argparse/argparse.hpp index d855ee3..4789d7f 100644 --- a/include/argparse/argparse.hpp +++ b/include/argparse/argparse.hpp @@ -490,6 +490,11 @@ public: return *this; } + Argument &remaining() { + mAcceptsOptionalLikeValue = true; + return nargs(NArgsPattern::ANY); + } + template Iterator consume(Iterator start, Iterator end, std::string_view usedName = {}) { @@ -501,25 +506,21 @@ public: const auto numArgsMax = mNumArgsRange.get_max(); const auto numArgsMin = mNumArgsRange.get_min(); + std::size_t dist = 0; if (numArgsMax == 0) { mValues.emplace_back(mImplicitValue); return start; - } else if (static_cast(std::distance(start, end)) >= numArgsMin) { - - auto it = start; - for (std::size_t i = 0; it != end; ++it, ++i) { - if (Argument::is_optional(*it)) { - break; - } - if (i >= numArgsMax) { - break; + } else if ((dist = static_cast(std::distance(start, end))) >= numArgsMin) { + if (numArgsMax < dist) { + end = std::next(start, numArgsMax); + } + if (!mAcceptsOptionalLikeValue) { + end = std::find_if(start, end, Argument::is_optional); + dist = static_cast(std::distance(start, end)); + if (dist < numArgsMin) { + throw std::runtime_error("Too few arguments"); } } - auto dist = static_cast(std::distance(start, it)); - if (dist < numArgsMin) { - throw std::runtime_error("Too few arguments"); - } - end = it; struct action_apply { void operator()(valued_action &f) { @@ -529,7 +530,8 @@ public: void operator()(void_action &f) { std::for_each(start, end, f); if (!self.mDefaultValue.has_value()) { - self.mValues.resize(std::distance(start, end)); + if (!self.mAcceptsOptionalLikeValue) + self.mValues.resize(std::distance(start, end)); } } @@ -882,6 +884,7 @@ private: [](const std::string &aValue) { return aValue; }}; std::vector mValues; SizeRange mNumArgsRange {1, 1}; + bool mAcceptsOptionalLikeValue = false; bool mIsOptional : true; bool mIsRequired : true; bool mIsRepeatable : true;