35#pragma push_macro("min")
36#pragma push_macro("max")
40#define ARGS_VERSION "6.6.1"
41#define ARGS_VERSION_MAJOR 6
42#define ARGS_VERSION_MINOR 6
43#define ARGS_VERSION_PATCH 1
53#include <unordered_map>
54#include <unordered_set>
63#if defined(_MSC_VER) && _MSC_VER <= 1800
77 template <
typename Option>
78 auto get(Option &option_) ->
decltype(option_.Get())
91 inline std::string::size_type
Glyphs(
const std::string &string_)
93 std::string::size_type length = 0;
94 for (
const char c: string_)
96 if ((c & 0xc0) != 0x80)
110 static_assert(std::is_integral<T>::value,
"SafeAdd requires integral types.");
111 if (std::is_unsigned<T>::value)
113 using U =
typename std::make_unsigned<T>::type;
114 const U ua =
static_cast<U
>(a);
115 const U ub =
static_cast<U
>(b);
116 const U maxv = std::numeric_limits<U>::max();
121 out =
static_cast<T
>(ua + ub);
126#if defined(__clang__) || defined(__GNUC__)
127 return !__builtin_add_overflow(a, b, &out);
130 if (b > 0 && a > std::numeric_limits<T>::max() - b)
134 if (b < 0 && a < std::numeric_limits<T>::min() - b)
150 static_assert(std::is_integral<T>::value,
"SafeMultiply requires integral types.");
152 if (a == 0 || b == 0)
158 if (std::is_unsigned<T>::value)
160 using U =
typename std::make_unsigned<T>::type;
161 const U ua =
static_cast<U
>(a);
162 const U ub =
static_cast<U
>(b);
163 const U maxv = std::numeric_limits<U>::max();
168 out =
static_cast<T
>(ua * ub);
173#if defined(__clang__) || defined(__GNUC__)
174 return !__builtin_mul_overflow(a, b, &out);
177 if (a == -1 && b == std::numeric_limits<T>::min())
181 if (b == -1 && a == std::numeric_limits<T>::min())
185 if ((a > 0 && b > 0 && a > std::numeric_limits<T>::max() / b) ||
186 (a > 0 && b < 0 && b < std::numeric_limits<T>::min() / a) ||
187 (a < 0 && b > 0 && a < std::numeric_limits<T>::min() / b) ||
188 (a < 0 && b < 0 && a < std::numeric_limits<T>::max() / b))
204 static_assert(std::is_integral<T>::value,
"SafeSub requires integral types.");
205 if (std::is_unsigned<T>::value)
216#if defined(__clang__) || defined(__GNUC__)
217 return !__builtin_sub_overflow(a, b, &out);
220 if (b > 0 && a < std::numeric_limits<T>::min() + b)
224 if (b < 0 && a > std::numeric_limits<T>::max() + b)
239 typename std::enable_if<std::is_unsigned<T>::value,
bool>::type
242 static_assert(std::is_integral<T>::value,
"SafeNeg requires integral types.");
253 typename std::enable_if<std::is_signed<T>::value,
bool>::type
256 static_assert(std::is_integral<T>::value,
"SafeNeg requires integral types.");
257 if (a == std::numeric_limits<T>::min())
276 template <
typename It>
277 inline std::vector<std::string>
Wrap(It begin,
279 const std::string::size_type width,
280 std::string::size_type firstlinewidth = 0,
281 std::string::size_type firstlineindent = 0)
283 std::vector<std::string> output;
284 std::string line(firstlineindent,
' ');
287 if (firstlinewidth == 0)
289 firstlinewidth = width;
292 auto currentwidth = firstlinewidth;
294 for (
auto it = begin; it != end; ++it)
305 output.push_back(line);
308 currentwidth = width;
314 auto itemsize =
Glyphs(*it);
317 bool needsWrap =
false;
318 if (itemsize >= currentwidth)
324 size_t remainingWidth = (currentwidth > itemsize) ? (currentwidth - itemsize) : 0;
325 size_t nextLength = 0;
326 if (!SafeAdd<std::string::size_type>(line.length(),
static_cast<std::string::size_type
>(1), nextLength) || nextLength > remainingWidth)
336 output.push_back(line);
339 currentwidth = width;
357 output.push_back(line);
365 template <
typename T>
366 std::string Join(
const T& array,
const std::string &delimiter)
371 using size_type = std::string::size_type;
374 const size_type delim_size =
static_cast<size_type
>(delimiter.size());
375 bool can_reserve =
true;
377 for (
const auto &element : array)
379 const size_type elem_size =
static_cast<size_type
>(element.size());
380 if (!SafeAdd<size_type>(total, elem_size, total))
388 if (can_reserve && count > 1)
390 size_type delim_count = count - 1;
391 size_type delim_total = 0;
392 if (!SafeMultiply<size_type>(delim_count, delim_size, delim_total) ||
393 !SafeAdd<size_type>(total, delim_total, total))
399 if (can_reserve && total > 0)
405 for (
const auto &element : array)
428 inline std::vector<std::string>
Wrap(
const std::string &in,
const std::string::size_type width, std::string::size_type firstlinewidth = 0)
431 const auto newlineloc = in.find(
'\n');
432 if (newlineloc != in.npos)
434 auto first =
Wrap(std::string(in, 0, newlineloc), width);
435 auto second =
Wrap(std::string(in, newlineloc + 1), width);
438 std::make_move_iterator(std::begin(second)),
439 std::make_move_iterator(std::end(second)));
443 std::istringstream stream(in);
444 std::string::size_type indent = 0;
448 if (!std::isspace(
static_cast<unsigned char>(c)))
455 return Wrap(std::istream_iterator<std::string>(stream), std::istream_iterator<std::string>(),
456 width, firstlinewidth, indent);
477 class Error :
public std::runtime_error
480 Error(
const std::string &problem) : std::runtime_error(problem) {}
543 Help(
const std::string &flag) :
Error(flag) {}
549 class SubparserError :
public Error
552 SubparserError() :
Error(
"") {}
553 virtual ~SubparserError() {}
571 const char shortFlag;
572 const std::string longFlag;
573 EitherFlag(
const std::string &flag) : isShort(
false), shortFlag(), longFlag(flag) {}
574 EitherFlag(
const char *flag) : isShort(
false), shortFlag(), longFlag(flag) {}
575 EitherFlag(
const char flag) : isShort(
true), shortFlag(flag), longFlag() {}
579 static std::unordered_set<std::string>
GetLong(std::initializer_list<EitherFlag> flags)
581 std::unordered_set<std::string> longFlags;
586 longFlags.insert(flag.longFlag);
594 static std::unordered_set<char>
GetShort(std::initializer_list<EitherFlag> flags)
596 std::unordered_set<char> shortFlags;
601 shortFlags.insert(flag.shortFlag);
607 std::string str()
const
609 return isShort ? std::string(1, shortFlag) : longFlag;
612 std::string str(
const std::string &shortPrefix,
const std::string &longPrefix)
const
614 return isShort ? shortPrefix + std::string(1, shortFlag) : longPrefix + longFlag;
629 const std::unordered_set<char> shortFlags;
630 const std::unordered_set<std::string> longFlags;
637 template <
typename ShortIt,
typename LongIt>
638 Matcher(ShortIt shortFlagsStart, ShortIt shortFlagsEnd, LongIt longFlagsStart, LongIt longFlagsEnd) :
639 shortFlags(shortFlagsStart, shortFlagsEnd),
640 longFlags(longFlagsStart, longFlagsEnd)
642 if (shortFlags.empty() && longFlags.empty())
652 Error GetError() const noexcept
654 return shortFlags.empty() && longFlags.empty() ? Error::Usage : Error::None;
662 template <
typename Short,
typename Long>
664 Matcher(std::begin(shortIn), std::end(shortIn), std::begin(longIn), std::end(longIn))
679 Matcher(std::initializer_list<EitherFlag> in) :
682 Matcher(
Matcher &&other) noexcept : shortFlags(std::move(other.shortFlags)), longFlags(std::move(other.longFlags))
691 return shortFlags.find(flag) != shortFlags.end();
696 bool Match(
const std::string &flag)
const
698 return longFlags.find(flag) != longFlags.end();
705 return flag.isShort ?
Match(flag.shortFlag) :
Match(flag.longFlag);
712 std::vector<EitherFlag> flagStrings;
713 flagStrings.reserve(shortFlags.size() + longFlags.size());
714 for (
const char flag: shortFlags)
716 flagStrings.emplace_back(flag);
718 for (
const std::string &flag: longFlags)
720 flagStrings.emplace_back(flag);
729 if (!longFlags.empty())
731 return *longFlags.begin();
734 if (!shortFlags.empty())
736 return *shortFlags.begin();
747 if (!shortFlags.empty())
749 return *shortFlags.begin();
752 if (!longFlags.empty())
754 return *longFlags.begin();
805 return static_cast<Options>(
static_cast<int>(lhs) |
static_cast<int>(rhs));
810 return static_cast<Options>(
static_cast<int>(lhs) &
static_cast<int>(rhs));
814 class PositionalBase;
816 class ArgumentParser;
982 Nargs(
size_t min_,
size_t max_) : min{min_}, max{max_}
992 Nargs(
size_t num_) : min{num_}, max{num_}
996 friend bool operator == (
const Nargs &lhs,
const Nargs &rhs)
998 return lhs.min == rhs.min && lhs.max == rhs.max;
1001 friend bool operator != (
const Nargs &lhs,
const Nargs &rhs)
1003 return !(lhs == rhs);
1015 bool matched =
false;
1016 const std::string help;
1019 mutable Error error = Error::None;
1020 mutable std::string errorMsg;
1024 Base(
const std::string &help_,
Options options_ = {}) : options(options_), help(help_) {}
1027 Options GetOptions()
const noexcept
1032 bool IsRequired()
const noexcept
1037 virtual bool Matched()
const noexcept
1042 virtual void Validate(
const std::string &,
const std::string &)
const
1046 operator bool()
const noexcept
1051 virtual std::vector<std::tuple<std::string, std::string, unsigned>> GetDescription(
const HelpParams &,
const unsigned indentLevel)
const
1053 std::tuple<std::string, std::string, unsigned> description;
1054 std::get<1>(description) = help;
1055 std::get<2>(description) = indentLevel;
1056 return { std::move(description) };
1059 virtual std::vector<Command*> GetCommands()
1064 virtual bool IsGroup()
const
1069 virtual bool IsFlag()
const
1084 virtual std::vector<FlagBase*> GetAllFlags()
1089 virtual bool HasFlag()
const
1094 virtual bool HasPositional()
const
1099 virtual bool HasCommand()
const
1104 virtual std::vector<std::string> GetProgramLine(
const HelpParams &)
const
1128 virtual void Reset() noexcept
1132 error = Error::None;
1139 virtual Error GetError()
const
1145 virtual std::string GetErrorMsg()
const
1157 const std::string name;
1158 bool kickout =
false;
1159 std::string defaultString;
1160 bool defaultStringManual =
false;
1161 std::vector<std::string> choicesStrings;
1162 bool choicesStringManual =
false;
1164 virtual std::string GetDefaultString(
const HelpParams&)
const {
return {}; }
1166 virtual std::vector<std::string> GetChoicesStrings(
const HelpParams&)
const {
return {}; }
1168 virtual std::string GetNameString(
const HelpParams&)
const {
return Name(); }
1170 void AddDescriptionPostfix(std::string &dest,
const bool isManual,
const std::string &manual,
bool isGenerated,
const std::string &generated,
const std::string &str)
const
1172 if (isManual && !manual.empty())
1177 else if (!isManual && isGenerated && !generated.empty())
1185 NamedBase(
const std::string &name_,
const std::string &help_,
Options options_ = {}) :
Base(help_, options_), name(name_) {}
1193 defaultStringManual =
true;
1194 defaultString = str;
1201 return defaultStringManual ? defaultString : GetDefaultString(params);
1209 choicesStringManual =
true;
1210 choicesStrings = array;
1217 return choicesStringManual ? choicesStrings : GetChoicesStrings(params);
1220 virtual std::vector<std::tuple<std::string, std::string, unsigned>> GetDescription(
const HelpParams ¶ms,
const unsigned indentLevel)
const override
1222 std::tuple<std::string, std::string, unsigned> description;
1223 std::get<0>(description) = GetNameString(params);
1224 std::get<1>(description) = help;
1225 std::get<2>(description) = indentLevel;
1227 AddDescriptionPostfix(std::get<1>(description), choicesStringManual, detail::Join(choicesStrings,
", "), params.
addChoices, detail::Join(GetChoicesStrings(params),
", "), params.
choiceString);
1228 AddDescriptionPostfix(std::get<1>(description), defaultStringManual, defaultString, params.
addDefault, GetDefaultString(params), params.
defaultString);
1230 return { std::move(description) };
1233 virtual std::string Name()
const
1241 template<
typename T>
1242 using vector = std::vector<T, std::allocator<T>>;
1244 template<
typename K,
typename T>
1245 using unordered_map = std::unordered_map<K, T, std::hash<K>,
1246 std::equal_to<K>, std::allocator<std::pair<const K, T> > >;
1248 template<
typename S,
typename T>
1251 template<
typename SS,
typename TT>
1252 static auto test(
int)
1253 ->
decltype( std::declval<SS&>() << std::declval<TT>(), std::true_type() );
1255 template<
typename,
typename>
1256 static auto test(...) -> std::false_type;
1259 using type =
decltype(test<S,T>(0));
1262 template <
typename T>
1263 using IsConvertableToString =
typename is_streamable<std::ostringstream, T>::type;
1265 template <
typename T>
1266 typename std::enable_if<IsConvertableToString<T>::value, std::string>::type
1267 ToString(
const T &value)
1269 std::ostringstream s;
1274 template <
typename T>
1275 typename std::enable_if<!IsConvertableToString<T>::value, std::string>::type
1283 template <
typename Container,
typename T>
1284 auto AppendMappedValue(Container &container,
const T &value,
int)
1285 ->
decltype(container.emplace_back(value), void())
1287 container.emplace_back(value);
1290 template <
typename Container,
typename T>
1291 auto AppendMappedValue(Container &container,
const T &value,
long)
1292 ->
decltype(container.insert(std::end(container), value), void())
1294 container.insert(std::end(container), value);
1297 template <
typename T>
1298 std::vector<std::string> MapKeysToStrings(
const T &map)
1300 std::vector<std::string> res;
1301 using K =
typename std::decay<
decltype(std::begin(map)->first)>::type;
1302 if (IsConvertableToString<K>::value)
1304 for (
const auto &p : map)
1306 res.push_back(detail::ToString(p.first));
1309 std::sort(res.begin(), res.end());
1322 virtual std::string GetNameString(
const HelpParams ¶ms)
const override
1327 const bool useValueNameOnce = flagStrings.size() == 1 ? false : params.
useValueNameOnce;
1328 for (
auto it = flagStrings.begin(); it != flagStrings.end(); ++it)
1331 if (it != flagStrings.begin())
1337 flags += flag.str();
1339 if (!postfix.empty() && (!useValueNameOnce || it + 1 == flagStrings.end()))
1352 FlagBase(
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
Options options_) :
NamedBase(name_, help_, options_), matcher(std::move(matcher_)) {}
1356 virtual bool IsFlag()
const override
1363 if (matcher.
Match(flag))
1367 std::ostringstream problem;
1368 problem <<
"Flag '" << flag.str() <<
"' was passed multiple times, but is only allowed to be passed once";
1370 error = Error::Extra;
1371 errorMsg = problem.str();
1382 virtual std::vector<FlagBase*> GetAllFlags()
override
1387 const Matcher &GetMatcher()
const
1392 virtual void Validate(
const std::string &shortPrefix,
const std::string &longPrefix)
const override
1394 if (!Matched() && IsRequired())
1396 std::ostringstream problem;
1397 problem <<
"Flag '" << matcher.
GetLongOrAny().str(shortPrefix, longPrefix) <<
"' is required";
1399 error = Error::Required;
1400 errorMsg = problem.str();
1407 virtual std::vector<std::string> GetProgramLine(
const HelpParams ¶ms)
const override
1417 if (!postfix.empty())
1426 virtual bool HasFlag()
const override
1433 bool usageError =
false;
1434 void SetUsageError()
1438 void ClearUsageError()
1442 virtual Error GetError()
const override
1446 return Error::Usage;
1449 if (nargs.min > nargs.max)
1451 return Error::Usage;
1454 const auto matcherError = matcher.GetError();
1455 if (matcherError != Error::None)
1457 return matcherError;
1474 virtual
void ParseValue(const std::vector<std::
string> &value) = 0;
1482 ValueFlagBase(
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const bool extraError_ =
false) :
FlagBase(name_, help_, std::move(matcher_), extraError_) {}
1495 std::vector<std::string> reply;
1499 template <
typename GroupClass>
1502 group_.AddCompletion(*
this);
1512 virtual void ParseValue(
const std::vector<std::string> &value_)
override
1514 syntax = value_.at(0);
1515 const std::string &raw = value_.at(1);
1516 bool failed =
false;
1518 const auto firstNonSpace = std::find_if_not(raw.begin(), raw.end(), [](
char c)
1520 return std::isspace(static_cast<unsigned char>(c)) != 0;
1526 if (firstNonSpace != raw.end() && (*firstNonSpace ==
'-' || *firstNonSpace ==
'+'))
1534 std::istringstream ss(raw);
1540 ss.imbue(std::locale::classic());
1563 error = Error::Parse;
1564 errorMsg =
"Argument 'completion' received invalid value type '" + raw +
"'";
1566 std::ostringstream problem;
1567 problem <<
"Argument 'completion' received invalid value type '" << raw <<
"'";
1580 return detail::Join(reply,
"\n");
1583 virtual void Reset() noexcept
override
1585 ValueFlagBase::Reset();
1609 virtual void ParseValue(
const std::string &value_) = 0;
1611 virtual void Reset()
noexcept override
1616 error = Error::None;
1623 return Ready() ? this :
nullptr;
1626 virtual bool HasPositional()
const override
1631 virtual std::vector<std::string> GetProgramLine(
const HelpParams ¶ms)
const override
1637 virtual void Validate(
const std::string &,
const std::string &)
const override
1639 if (IsRequired() && !Matched())
1641 std::ostringstream problem;
1642 problem <<
"Option '" << Name() <<
"' is required";
1644 error = Error::Required;
1645 errorMsg = problem.str();
1659 std::vector<Base*> children;
1660 std::function<bool(
const Group &)> validator;
1667 static bool Xor(
const Group &group)
1672 static bool AtLeastOne(
const Group &group)
1677 static bool AtMostOne(
const Group &group)
1682 static bool All(
const Group &group)
1687 static bool AllOrNone(
const Group &group)
1689 return (All(group) ||
None(group));
1692 static bool AllChildGroups(
const Group &group)
1694 return std::none_of(std::begin(group.
Children()), std::end(group.
Children()), [](
const Base* child) ->
bool {
1695 return child->IsGroup() && !child->Matched();
1699 static bool DontCare(
const Group &)
1704 static bool CareTooMuch(
const Group &)
1715 Group(
const std::string &help_ = std::string(),
const std::function<
bool(
const Group &)> &validator_ = Validators::DontCare,
Options options_ = {}) :
Base(help_, options_), validator(validator_)
1720 Group(
Group &group_,
const std::string &help_ = std::string(),
const std::function<
bool(
const Group &)> &validator_ = Validators::DontCare,
Options options_ = {}) :
Base(help_, options_), validator(validator_)
1731 children.emplace_back(&child);
1733 if(child.IsFlag()) {
1734#ifndef ARGS_NOEXCEPT
1742 SignalDetectDuplicates();
1746 children.pop_back();
1750 SignalDetectDuplicates();
1769 for (
Base *child: Children())
1771 if (
FlagBase *match = child->Match(flag))
1779 virtual std::vector<FlagBase*> GetAllFlags()
override
1781 std::vector<FlagBase*> res;
1782 for (
Base *child: Children())
1784 auto childRes = child->GetAllFlags();
1785 res.insert(res.end(), childRes.begin(), childRes.end());
1790 virtual void Validate(
const std::string &shortPrefix,
const std::string &longPrefix)
const override
1792 for (Base *child: Children())
1794 child->Validate(shortPrefix, longPrefix);
1804 for (
Base *child: Children())
1806 if (
auto next = child->GetNextPositional())
1820 return std::any_of(Children().begin(), Children().end(), [](
Base *child) {
return child->HasFlag(); });
1829 return std::any_of(Children().begin(), Children().end(), [](
Base *child) {
return child->HasPositional(); });
1838 return std::any_of(Children().begin(), Children().end(), [](
Base *child) {
return child->HasCommand(); });
1846 return static_cast<std::vector<Base *>::size_type
>(
1847 std::count_if(std::begin(Children()), std::end(Children()), [](
const Base *child){
return child->Matched();}));
1855 std::vector<Base*> matched_children;
1856 std::copy_if(children.begin(), children.end(), std::back_inserter(matched_children), [](
Base* b){
1857 return b->Matched();
1859 return matched_children;
1867 template <
typename ChildType>
1870 std::vector<ChildType *> filtered_children;
1871 for(
Base *child : children) {
1872 if(!matching || child->Matched())
1874 ChildType* cast_result =
dynamic_cast<ChildType*
>(child);
1875 if(cast_result !=
nullptr)
1877 filtered_children.push_back(cast_result);
1882 return filtered_children;
1889 return validator(*
this);
1901 virtual std::vector<std::tuple<std::string, std::string, unsigned>>
GetDescription(
const HelpParams ¶ms,
const unsigned int indent)
const override
1903 std::vector<std::tuple<std::string, std::string, unsigned int>> descriptions;
1906 unsigned addindent = 0;
1909 descriptions.emplace_back(help,
"", indent);
1913 for (
Base *child: Children())
1915 if ((child->GetOptions() & Options::HiddenFromDescription) != Options::None)
1920 auto groupDescriptions = child->GetDescription(params, indent + addindent);
1921 descriptions.insert(
1922 std::end(descriptions),
1923 std::make_move_iterator(std::begin(groupDescriptions)),
1924 std::make_move_iterator(std::end(groupDescriptions)));
1926 return descriptions;
1933 std::vector <std::string> names;
1934 for (
Base *child: Children())
1936 if ((child->GetOptions() & Options::HiddenFromUsage) != Options::None)
1941 auto groupNames = child->GetProgramLine(params);
1944 std::make_move_iterator(std::begin(groupNames)),
1945 std::make_move_iterator(std::end(groupNames)));
1950 virtual std::vector<Command*> GetCommands()
override
1952 std::vector<Command*> res;
1953 for (
const auto &child : Children())
1955 auto subparsers = child->GetCommands();
1956 res.insert(std::end(res), std::begin(subparsers), std::end(subparsers));
1961 virtual bool IsGroup()
const override
1966 virtual void Reset() noexcept
override
1970 for (
auto &child: Children())
1975 error = Error::None;
1986 else DetectDuplicateFlags();
1995 std::unordered_set<char> usedShortFlags;
1996 std::unordered_set<std::string> usedLongFlags;
1997 DetectDuplicateFlags(usedShortFlags, usedLongFlags);
2002 void DetectDuplicateFlags(std::unordered_set<char> &usedShortFlags, std::unordered_set<std::string> &usedLongFlags)
2004 for (
Base *child: Children())
2006 if(
auto flag =
dynamic_cast<FlagBase*
>(child))
2010 for(
EitherFlag flagString: flag->GetMatcher().GetFlagStrings())
2012 if(flagString.isShort)
2014 if(usedShortFlags.count(flagString.shortFlag))
2017 flag->SetUsageError();
2019 throw ParseError(
"duplicate short flag detected");
2024 usedShortFlags.insert(flagString.shortFlag);
2029 if(usedLongFlags.count(flagString.longFlag))
2032 flag->SetUsageError();
2034 throw ParseError(
"duplicate long flag detected");
2039 usedLongFlags.insert(flagString.longFlag);
2044 else if(
auto group =
dynamic_cast<Group*
>(child))
2051 if(group->IsGroup())
2053 group->DetectDuplicateFlags(usedShortFlags, usedLongFlags);
2061 virtual Error GetError()
const override
2063 if (error != Error::None)
2068 auto it = std::find_if(Children().begin(), Children().end(), [](
const Base *child){
return child->GetError() != Error::None;});
2069 if (it == Children().end())
2074 return (*it)->GetError();
2079 virtual std::string GetErrorMsg()
const override
2081 if (error != Error::None)
2086 auto it = std::find_if(Children().begin(), Children().end(), [](
const Base *child){
return child->GetError() != Error::None;});
2087 if (it == Children().end())
2092 return (*it)->GetErrorMsg();
2130 std::vector<std::string>
args;
2131 std::vector<std::string> kicked;
2135 bool isParsed =
false;
2139 :
Group({}, Validators::AllChildGroups),
args(std::move(args_)), parser(&parser_), helpParams(helpParams_), command(command_)
2189 std::string description;
2191 std::string proglinePostfix;
2193 std::function<void(
Subparser&)> parserCoroutine;
2194 bool commandIsRequired =
true;
2195 Command *selectedCommand =
nullptr;
2197 mutable std::vector<std::tuple<std::string, std::string, unsigned>> subparserDescription;
2198 mutable std::vector<std::string> subparserProgramLine;
2199 mutable bool subparserHasFlag =
false;
2200 mutable bool subparserHasPositional =
false;
2201 mutable bool subparserHasCommand =
false;
2203 mutable Error subparserError = Error::None;
2212 RaiiSubparser(
ArgumentParser &parser_, std::vector<std::string> args_);
2217 command.subparser = oldSubparser;
2233 std::function<void(
Subparser&)> &GetCoroutine()
2235 return selectedCommand !=
nullptr ? selectedCommand->GetCoroutine() : parserCoroutine;
2241 while (res->selectedCommand !=
nullptr)
2243 res = res->selectedCommand;
2249 const Command &SelectedCommand()
const
2252 while (res->selectedCommand !=
nullptr)
2254 res = res->selectedCommand;
2260 void UpdateSubparserHelp(
const HelpParams ¶ms)
const
2262 if (parserCoroutine)
2264 RaiiSubparser coro(*
this, params);
2265#ifndef ARGS_NOEXCEPT
2268 parserCoroutine(coro.Parser());
2270 catch (args::SubparserError&)
2274 parserCoroutine(coro.Parser());
2280 Command(
Group &base_, std::string name_, std::string help_, std::function<
void(
Subparser&)> coroutine_ = {})
2281 : name(std::move(name_)), help(std::move(help_)), parserCoroutine(std::move(coroutine_))
2289 {
return proglinePostfix; }
2294 { this->proglinePostfix = proglinePostfix_; }
2299 {
return description; }
2304 { this->description = description_; }
2314 { this->epilog = epilog_; }
2331 { commandIsRequired = value; }
2333 virtual bool IsGroup()
const override
2337 {
return Base::Matched(); }
2339 operator bool() const noexcept
2340 {
return Matched(); }
2342 void Match() noexcept
2345 void SelectCommand(Command *c)
noexcept
2347 selectedCommand = c;
2357 if (selectedCommand !=
nullptr)
2359 if (
auto *res = selectedCommand->Match(flag))
2364 for (
auto *child: Children())
2366 if ((child->GetOptions() & Options::Global) != Options::None)
2368 if (
auto *res = child->Match(flag))
2378 if (subparser !=
nullptr)
2380 return subparser->
Match(flag);
2383 return Matched() ? Group::Match(flag) :
nullptr;
2386 virtual std::vector<FlagBase*> GetAllFlags()
override
2388 std::vector<FlagBase*> res;
2395 for (
auto *child: Children())
2397 if (selectedCommand ==
nullptr || (child->GetOptions() & Options::Global) != Options::None)
2399 auto childFlags = child->GetAllFlags();
2400 res.insert(res.end(), childFlags.begin(), childFlags.end());
2404 if (selectedCommand !=
nullptr)
2406 auto childFlags = selectedCommand->GetAllFlags();
2407 res.insert(res.end(), childFlags.begin(), childFlags.end());
2410 if (subparser !=
nullptr)
2412 auto childFlags = subparser->GetAllFlags();
2413 res.insert(res.end(), childFlags.begin(), childFlags.end());
2421 if (selectedCommand !=
nullptr)
2428 for (
auto *child: Children())
2430 if ((child->GetOptions() & Options::Global) != Options::None)
2432 if (
auto *res = child->GetNextPositional())
2442 if (subparser !=
nullptr)
2447 return Matched() ? Group::GetNextPositional() :
nullptr;
2452 return subparserHasFlag || Group::HasFlag();
2457 return subparserHasPositional || Group::HasPositional();
2465 std::vector<std::string> GetCommandProgramLine(
const HelpParams ¶ms)
const
2467 UpdateSubparserHelp(params);
2469 std::vector<std::string> res;
2476 auto group_res = Group::GetProgramLine(params);
2477 std::move(std::move(group_res).begin(), std::move(group_res).end(), std::back_inserter(res));
2479 res.insert(res.end(), subparserProgramLine.begin(), subparserProgramLine.end());
2481 if (!params.
proglineCommand.empty() && (Group::HasCommand() || subparserHasCommand))
2483 res.insert(res.begin(), commandIsRequired ? params.
proglineCommand :
"[" + params.proglineCommand +
"]");
2486 if (!Name().empty())
2488 res.insert(res.begin(), Name());
2491 if (!ProglinePostfix().empty())
2494 for (
auto c : ProglinePostfix())
2496 if (std::isspace(
static_cast<unsigned char>(c)))
2500 res.push_back(line);
2506 res.push_back(
"\n");
2517 res.push_back(line);
2531 return GetCommandProgramLine(params);
2534 virtual std::vector<Command*> GetCommands()
override
2536 if (selectedCommand !=
nullptr)
2538 return selectedCommand->GetCommands();
2543 return Group::GetCommands();
2549 virtual std::vector<std::tuple<std::string, std::string, unsigned>>
GetDescription(
const HelpParams ¶ms,
const unsigned int indent)
const override
2551 std::vector<std::tuple<std::string, std::string, unsigned>> descriptions;
2552 unsigned addindent = 0;
2554 UpdateSubparserHelp(params);
2560 std::ostringstream s;
2562 for (
const auto &progline: GetCommandProgramLine(params))
2576 descriptions.emplace_back(s.str(),
"", indent);
2580 descriptions.emplace_back(Name(), help, indent);
2585 return descriptions;
2593 descriptions.emplace_back(
"",
"", indent + addindent);
2594 descriptions.emplace_back(Description().empty() ?
Help() : Description(),
"", indent + addindent);
2595 descriptions.emplace_back(
"",
"", indent + addindent);
2598 for (
Base *child: Children())
2600 if ((child->GetOptions() & Options::HiddenFromDescription) != Options::None)
2605 auto groupDescriptions = child->GetDescription(params, indent + addindent);
2606 descriptions.insert(
2607 std::end(descriptions),
2608 std::make_move_iterator(std::begin(groupDescriptions)),
2609 std::make_move_iterator(std::end(groupDescriptions)));
2612 for (
auto childDescription: subparserDescription)
2614 std::get<2>(childDescription) += indent + addindent;
2615 descriptions.push_back(std::move(childDescription));
2620 descriptions.emplace_back(
"",
"", indent + addindent);
2621 if (!Epilog().empty())
2623 descriptions.emplace_back(Epilog(),
"", indent + addindent);
2624 descriptions.emplace_back(
"",
"", indent + addindent);
2628 return descriptions;
2631 virtual void Validate(
const std::string &shortprefix,
const std::string &longprefix)
const override
2638 auto onValidationError = [&]
2640 std::ostringstream problem;
2641 problem <<
"Group validation failed somewhere!";
2643 error = Error::Validation;
2644 errorMsg = problem.str();
2646 throw ValidationError(problem.str());
2650 for (Base *child: Children())
2652 if (child->IsGroup() && !child->Matched())
2654 onValidationError();
2657 child->Validate(shortprefix, longprefix);
2660 if (subparser !=
nullptr)
2662 subparser->Validate(shortprefix, longprefix);
2665 onValidationError();
2669 if (selectedCommand ==
nullptr && commandIsRequired && (Group::HasCommand() || subparserHasCommand))
2671 std::ostringstream problem;
2672 problem <<
"Command is required";
2674 error = Error::Validation;
2675 errorMsg = problem.str();
2677 throw ValidationError(problem.str());
2682 virtual void Reset() noexcept
override
2685 selectedCommand =
nullptr;
2686 subparserProgramLine.clear();
2687 subparserDescription.clear();
2688 subparserHasFlag =
false;
2689 subparserHasPositional =
false;
2690 subparserHasCommand =
false;
2692 subparserError = Error::None;
2698 virtual Error GetError()
const override
2705 if (error != Error::None)
2710 if (subparserError != Error::None)
2712 return subparserError;
2715 return Group::GetError();
2727 std::string longprefix;
2728 std::string shortprefix;
2730 std::string longseparator;
2732 std::string terminator;
2734 bool allowJoinedShortValue =
true;
2735 bool allowJoinedLongValue =
true;
2736 bool allowSeparateShortValue =
true;
2737 bool allowSeparateLongValue =
true;
2739 bool readCompletion =
false;
2743 enum class OptionType
2750 OptionType ParseOption(
const std::string &s,
bool allowEmpty =
false)
2752 const bool matchesLong = s.find(longprefix) == 0 && (allowEmpty || s.length() > longprefix.length());
2753 const bool matchesShort = s.find(shortprefix) == 0 && (allowEmpty || s.length() > shortprefix.length());
2761 if (matchesLong && matchesShort)
2763 return longprefix.length() >= shortprefix.length() ? OptionType::LongFlag : OptionType::ShortFlag;
2768 return OptionType::LongFlag;
2773 return OptionType::ShortFlag;
2776 return OptionType::Positional;
2779 template <
typename It>
2780 bool Complete(
FlagBase &flag, It it, It end)
2783 if (!readCompletion || (++nextIt != end))
2788 const auto &chunk = *it;
2791 AddCompletionReply(chunk, choice);
2794#ifndef ARGS_NOEXCEPT
2810 template <
typename It>
2812 const bool allowSeparate,
const bool allowJoined,
2813 const bool hasJoined,
const std::string &joinedArg,
2814 const bool canDiscardJoined, std::vector<std::string> &values)
2820 if (hasJoined && !allowJoined && (nargs.min != 0 || !canDiscardJoined))
2822 return "Flag '" + arg +
"' was passed a joined argument, but these are disallowed";
2827 if (!canDiscardJoined || (allowJoined && nargs.max != 0))
2829 values.push_back(joinedArg);
2831 }
else if (!allowSeparate)
2835 return "Flag '" + arg +
"' was passed a separate argument, but these are disallowed";
2837 }
else if (allowSeparate && (!hasJoined || !values.empty())) {
2845 while (valueIt != end &&
2846 *valueIt != terminator &&
2847 values.size() < nargs.max &&
2848 (values.size() < nargs.min || ParseOption(*valueIt) == OptionType::Positional))
2850 if (Complete(flag, valueIt, end))
2865 values.push_back(*valueIt);
2871 if (values.size() > nargs.max)
2873 return "Passed an argument into a non-argument flag: " + arg;
2874 }
else if (values.size() < nargs.min)
2876 if (nargs.min == 1 && nargs.max == 1)
2878 return "Flag '" + arg +
"' requires an argument but received none";
2879 }
else if (nargs.min == 1)
2881 return "Flag '" + arg +
"' requires at least one argument but received none";
2882 }
else if (nargs.min != nargs.max)
2884 return "Flag '" + arg +
"' requires at least " + std::to_string(nargs.min) +
2885 " arguments but received " + std::to_string(values.size());
2888 return "Flag '" + arg +
"' requires " + std::to_string(nargs.min) +
2889 " arguments but received " + std::to_string(values.size());
2896 template <
typename It>
2897 bool ParseLong(It &it, It end)
2899 const auto &chunk = *it;
2900 const auto argchunk = chunk.substr(longprefix.size());
2902 const auto separator = longseparator.empty() ? argchunk.npos : argchunk.find(longseparator);
2904 const auto arg = (separator != argchunk.npos ?
2905 std::string(argchunk, 0, separator)
2907 const auto joined = (separator != argchunk.npos ?
2908 argchunk.substr(separator + longseparator.size())
2911 if (
auto flag = Match(arg))
2919 if (flag->GetError() != Error::None)
2924 std::vector<std::string> values;
2925 const std::string errorMessage = ParseArgsValues(*flag, arg, it, end, allowSeparateLongValue, allowJoinedLongValue,
2926 separator != argchunk.npos, joined,
false, values);
2927 if (!errorMessage.empty())
2929#ifndef ARGS_NOEXCEPT
2930 throw ParseError(errorMessage);
2932 error = Error::Parse;
2933 errorMsg = errorMessage;
2938 if (!readCompletion)
2947 if (flag->GetError() != Error::None)
2961 const std::string errorMessage(
"Flag could not be matched: " + arg);
2962#ifndef ARGS_NOEXCEPT
2963 throw ParseError(errorMessage);
2965 error = Error::Parse;
2966 errorMsg = errorMessage;
2974 template <
typename It>
2975 bool ParseShort(It &it, It end)
2977 const auto &chunk = *it;
2978 const auto argchunk = chunk.substr(shortprefix.size());
2979 for (
auto argit = std::begin(argchunk); argit != std::end(argchunk); ++argit)
2981 const auto arg = *argit;
2983 if (
auto flag = Match(arg))
2989 if (flag->GetError() != Error::None)
2994 const std::string value(argit + 1, std::end(argchunk));
2995 std::vector<std::string> values;
2996 const std::string errorMessage = ParseArgsValues(*flag, std::string(1, arg), it, end,
2997 allowSeparateShortValue, allowJoinedShortValue,
2998 !value.empty(), value, !value.empty(), values);
3000 if (!errorMessage.empty())
3002#ifndef ARGS_NOEXCEPT
3003 throw ParseError(errorMessage);
3005 error = Error::Parse;
3006 errorMsg = errorMessage;
3011 if (!readCompletion)
3018 if (flag->GetError() != Error::None)
3031 if (!values.empty())
3037 const std::string errorMessage(
"Flag could not be matched: '" + std::string(1, arg) +
"'");
3038#ifndef ARGS_NOEXCEPT
3039 throw ParseError(errorMessage);
3041 error = Error::Parse;
3042 errorMsg = errorMessage;
3051 bool AddCompletionReply(
const std::string &cur,
const std::string &choice)
3053 if (cur.empty() || choice.find(cur) == 0)
3055 if (completion->syntax ==
"bash" && ParseOption(choice) == OptionType::LongFlag && choice.find(longseparator) != std::string::npos)
3057 completion->reply.push_back(choice.substr(choice.find(longseparator) + longseparator.size()));
3060 completion->reply.push_back(choice);
3068 template <
typename It>
3069 bool Complete(It it, It end,
bool terminated)
3072 if (!readCompletion || (++nextIt != end))
3077 const auto &chunk = *it;
3078 auto pos = GetNextPositional();
3079 std::vector<Command *> commands = GetCommands();
3080 const auto optionType = ParseOption(chunk,
true);
3086 if (!terminated && !commands.empty() && (chunk.empty() || optionType == OptionType::Positional))
3088 for (
auto &cmd : commands)
3090 if ((cmd->GetOptions() & Options::HiddenFromCompletion) == Options::None)
3092 AddCompletionReply(chunk, cmd->Name());
3097 bool hasPositionalCompletion =
true;
3099 if (!terminated && !commands.empty())
3101 for (
auto &cmd : commands)
3103 if ((cmd->GetOptions() & Options::HiddenFromCompletion) == Options::None)
3105 AddCompletionReply(chunk, cmd->Name());
3110 if ((pos->GetOptions() & Options::HiddenFromCompletion) == Options::None)
3112 auto choices = pos->HelpChoices(helpParams);
3113 hasPositionalCompletion = !choices.empty() || optionType != OptionType::Positional;
3114 for (
auto &choice : choices)
3116 AddCompletionReply(chunk, choice);
3121 if (!terminated && hasPositionalCompletion)
3123 auto flags = GetAllFlags();
3124 for (
auto flag : flags)
3126 if ((flag->GetOptions() & Options::HiddenFromCompletion) != Options::None)
3131 auto &matcher = flag->GetMatcher();
3132 if (!AddCompletionReply(chunk, matcher.
GetShortOrAny().str(shortprefix, longprefix)))
3134 for (
auto &flagName : matcher.GetFlagStrings())
3136 if (AddCompletionReply(chunk, flagName.str(shortprefix, longprefix)))
3144 if (optionType == OptionType::LongFlag && allowJoinedLongValue)
3146 const auto separator = longseparator.empty() ? chunk.npos : chunk.find(longseparator);
3160 if (separator != chunk.npos && separator >= longprefix.size())
3162 std::string arg(chunk, 0, separator);
3163 if (
auto flag = this->Match(arg.substr(longprefix.size())))
3165 for (
auto &choice : flag->HelpChoices(helpParams))
3167 AddCompletionReply(chunk, arg + longseparator + choice);
3171 }
else if (optionType == OptionType::ShortFlag && allowJoinedShortValue)
3173 if (chunk.size() > shortprefix.size() + 1)
3175 auto arg = chunk.at(shortprefix.size());
3177 if (
auto flag = this->Match(arg))
3179 for (
auto &choice : flag->HelpChoices(helpParams))
3181 AddCompletionReply(chunk, shortprefix + arg + choice);
3189#ifndef ARGS_NOEXCEPT
3190 throw Completion(completion->
Get());
3196 template <
typename It>
3197 It Parse(It begin, It end)
3199 bool terminated =
false;
3200 std::vector<Command *> commands = GetCommands();
3203 for (
auto it = begin; it != end; ++it)
3205 if (Complete(it, end, terminated))
3210 const auto &chunk = *it;
3212 if (!terminated && chunk == terminator)
3215 }
else if (!terminated && ParseOption(chunk) == OptionType::LongFlag)
3217 if (!ParseLong(it, end))
3221 }
else if (!terminated && ParseOption(chunk) == OptionType::ShortFlag)
3223 if (!ParseShort(it, end))
3227 }
else if (!terminated && !commands.empty())
3229 auto itCommand = std::find_if(commands.begin(), commands.end(), [&chunk](Command *c) { return c->Name() == chunk; });
3230 if (itCommand == commands.end())
3232 const std::string errorMessage(
"Unknown command: " + chunk);
3233#ifndef ARGS_NOEXCEPT
3234 throw ParseError(errorMessage);
3236 error = Error::Parse;
3237 errorMsg = errorMessage;
3242 SelectCommand(*itCommand);
3244 if (
const auto &coroutine = GetCoroutine())
3247 RaiiSubparser coro(*
this, std::vector<std::string>(it, end));
3248 coroutine(coro.Parser());
3251 if (error != Error::None)
3256 if (!coro.Parser().IsParsed())
3258 error = Error::Usage;
3262 if (!coro.Parser().IsParsed())
3264 throw UsageError(
"Subparser::Parse was not called");
3271 commands = GetCommands();
3274 auto pos = GetNextPositional();
3277 pos->ParseValue(chunk);
3279 if (pos->GetError() != Error::None)
3291 const std::string errorMessage(
"Passed in argument, but no positional arguments were ready to receive it: " + chunk);
3292#ifndef ARGS_NOEXCEPT
3293 throw ParseError(errorMessage);
3295 error = Error::Parse;
3296 errorMsg = errorMessage;
3302 if (!readCompletion && completion !=
nullptr && completion->Matched())
3305 if (completion->GetError() != Error::None)
3307 error = completion->GetError();
3308 if (errorMsg.empty())
3310 errorMsg = completion->GetErrorMsg();
3315 error = Error::Completion;
3317 readCompletion =
true;
3319 const auto argsLeft =
static_cast<size_t>(std::distance(it, end));
3320 if (completion->cword == 0 || argsLeft <= 1 || completion->cword >= argsLeft)
3322#ifndef ARGS_NOEXCEPT
3323 throw Completion(
"");
3330 std::vector<std::string> curArgs;
3331 curArgs.reserve(completion->cword);
3333 for (
size_t idx = 0; idx < completion->cword && curIt != end; ++idx, ++curIt)
3335 curArgs.push_back(*curIt);
3338 if (completion->syntax ==
"bash")
3342 for (
size_t idx = 0; idx < curArgs.size(); )
3344 if (idx > 0 && curArgs[idx] ==
"=")
3346 size_t prev_idx = idx - 1;
3347 curArgs[prev_idx] +=
"=";
3348 size_t next_idx = 0;
3349 if (SafeAdd<size_t>(idx,
static_cast<size_t>(1), next_idx) && next_idx < curArgs.size())
3351 curArgs[prev_idx] += curArgs[next_idx];
3353 size_t erase_end = 0;
3354 if (SafeAdd<size_t>(next_idx,
static_cast<size_t>(1), erase_end))
3356 typedef std::vector<std::string>::difference_type diff_t;
3357 curArgs.erase(curArgs.begin() +
static_cast<diff_t
>(idx),
3358 curArgs.begin() +
static_cast<diff_t
>(erase_end));
3363 typedef std::vector<std::string>::difference_type diff_t;
3364 curArgs.erase(curArgs.begin() +
static_cast<diff_t
>(idx));
3374#ifndef ARGS_NOEXCEPT
3377 Parse(curArgs.begin(), curArgs.end());
3378 throw Completion(
"");
3380 catch (Completion &)
3386 throw Completion(
"");
3396 Parse(curArgs.begin(), curArgs.end());
3397 error = Error::Completion;
3404 Validate(shortprefix, longprefix);
3409 HelpParams helpParams;
3411 ArgumentParser(
const std::string &description_,
const std::string &epilog_ = std::string())
3413 Description(description_);
3419 SetArgumentSeparations(
true,
true,
true,
true);
3423 void AddCompletion(CompletionFlag &completionFlag)
3428 Add(completionFlag);
3429 completion = &completionFlag;
3435 {
return helpParams.programName; }
3438 void Prog(
const std::string &prog_)
3439 { this->helpParams.programName = prog_; }
3444 {
return longprefix; }
3449 this->longprefix = longprefix_;
3450 this->helpParams.longPrefix = longprefix_;
3456 {
return shortprefix; }
3461 this->shortprefix = shortprefix_;
3462 this->helpParams.shortPrefix = shortprefix_;
3468 {
return longseparator; }
3473 if (longseparator_.empty())
3475 const std::string errorMessage(
"longseparator can not be set to empty");
3477 error = Error::Usage;
3478 errorMsg = errorMessage;
3484 this->longseparator = longseparator_;
3485 this->helpParams.longSeparator = allowJoinedLongValue ? longseparator :
" ";
3492 {
return terminator; }
3496 { this->terminator = terminator_; }
3503 bool &allowJoinedShortValue_,
3504 bool &allowJoinedLongValue_,
3505 bool &allowSeparateShortValue_,
3506 bool &allowSeparateLongValue_)
const
3508 allowJoinedShortValue_ = this->allowJoinedShortValue;
3509 allowJoinedLongValue_ = this->allowJoinedLongValue;
3510 allowSeparateShortValue_ = this->allowSeparateShortValue;
3511 allowSeparateLongValue_ = this->allowSeparateLongValue;
3522 const bool allowJoinedShortValue_,
3523 const bool allowJoinedLongValue_,
3524 const bool allowSeparateShortValue_,
3525 const bool allowSeparateLongValue_)
3527 this->allowJoinedShortValue = allowJoinedShortValue_;
3528 this->allowJoinedLongValue = allowJoinedLongValue_;
3529 this->allowSeparateShortValue = allowSeparateShortValue_;
3530 this->allowSeparateLongValue = allowSeparateLongValue_;
3532 this->helpParams.longSeparator = allowJoinedLongValue ? longseparator :
" ";
3533 this->helpParams.shortSeparator = allowJoinedShortValue ?
"" :
" ";
3538 void Help(std::ostream &help_)
const
3540 auto &command = SelectedCommand();
3541 const auto &commandDescription = command.Description().empty() ? command.Help() : command.Description();
3542 const auto desc_indent = helpParams.descriptionindent;
3543 const auto effective_desc_width = (helpParams.width > desc_indent) ? helpParams.width - desc_indent : 0;
3544 const auto description_text =
Wrap(commandDescription, effective_desc_width);
3545 const auto epilog_text =
Wrap(command.Epilog(), effective_desc_width);
3547 const bool hasoptions = command.HasFlag();
3548 const bool hasarguments = command.HasPositional();
3550 std::vector<std::string> prognameline;
3551 prognameline.push_back(helpParams.usageString);
3552 prognameline.push_back(Prog());
3553 auto commandProgLine = command.GetProgramLine(helpParams);
3554 prognameline.insert(prognameline.end(), commandProgLine.begin(), commandProgLine.end());
3556 const auto prog_sum = helpParams.progindent + helpParams.progtailindent;
3557 const auto effective_prog_width = (helpParams.width > prog_sum) ? helpParams.width - prog_sum : 0;
3558 const auto effective_prog_first = (helpParams.width > helpParams.progindent) ? helpParams.width - helpParams.progindent : 0;
3559 const auto proglines =
Wrap(prognameline.begin(), prognameline.end(),
3560 effective_prog_width,
3561 effective_prog_first);
3562 auto progit = std::begin(proglines);
3563 if (progit != std::end(proglines))
3565 help_ << std::string(helpParams.progindent,
' ') << *progit <<
'\n';
3568 for (; progit != std::end(proglines); ++progit)
3570 help_ << std::string(helpParams.progtailindent,
' ') << *progit <<
'\n';
3575 if (!description_text.empty())
3577 for (
const auto &line: description_text)
3579 help_ << std::string(helpParams.descriptionindent,
' ') << line <<
"\n";
3584 bool lastDescriptionIsNewline =
false;
3586 if (!helpParams.optionsString.empty())
3588 help_ << std::string(helpParams.progindent,
' ') << helpParams.optionsString <<
"\n\n";
3591 for (
const auto &desc: command.GetDescription(helpParams, 0))
3593 lastDescriptionIsNewline = std::get<0>(desc).empty() && std::get<1>(desc).empty();
3594 const auto groupindent = std::get<2>(desc) * helpParams.eachgroupindent;
3595 const auto flag_sum = helpParams.flagindent + helpParams.helpindent + helpParams.gutter;
3596 const auto effective_flag_width = (helpParams.width > flag_sum) ? helpParams.width - flag_sum : 0;
3597 const auto flags =
Wrap(std::get<0>(desc), effective_flag_width);
3598 const auto info_sum = helpParams.helpindent + groupindent;
3599 const auto effective_info_width = (helpParams.width > info_sum) ? helpParams.width - info_sum : 0;
3600 const auto info =
Wrap(std::get<1>(desc), effective_info_width);
3602 std::string::size_type flagssize = 0;
3603 for (
auto flagsit = std::begin(flags); flagsit != std::end(flags); ++flagsit)
3605 if (flagsit != std::begin(flags))
3609 help_ << std::string(groupindent + helpParams.flagindent,
' ') << *flagsit;
3610 flagssize =
Glyphs(*flagsit);
3613 auto infoit = std::begin(info);
3615 if ((helpParams.flagindent + flagssize + helpParams.gutter) > helpParams.helpindent || infoit == std::end(info) || helpParams.addNewlineBeforeDescription)
3621 const auto indent_sum = helpParams.flagindent + flagssize;
3622 const auto effective_space = (helpParams.helpindent > indent_sum) ? helpParams.helpindent - indent_sum : 0;
3623 help_ << std::string(effective_space,
' ') << *infoit <<
'\n';
3626 for (; infoit != std::end(info); ++infoit)
3628 help_ << std::string(groupindent + helpParams.helpindent,
' ') << *infoit <<
'\n';
3631 if (hasoptions && hasarguments && helpParams.showTerminator)
3633 lastDescriptionIsNewline =
false;
3634 const auto effective_term_width = (helpParams.width > helpParams.flagindent) ? helpParams.width - helpParams.flagindent : 0;
3635 for (
const auto &item:
Wrap(std::string(
"\"") + terminator +
"\" can be used to terminate flag options and force all following arguments to be treated as positional options", effective_term_width))
3637 help_ << std::string(helpParams.flagindent,
' ') << item <<
'\n';
3641 if (!lastDescriptionIsNewline)
3646 for (
const auto &line: epilog_text)
3648 help_ << std::string(helpParams.descriptionindent,
' ') << line <<
"\n";
3658 std::ostringstream help_;
3663 virtual void Reset() noexcept
override
3667 readCompletion =
false;
3676 template <
typename It>
3683 if (error != Error::None)
3688 return Parse(begin, end);
3696 template <
typename T>
3699 return ParseArgs(std::begin(
args), std::end(
args));
3708 bool ParseCLI(
const int argc,
const char *
const * argv)
3710 if (argc > 0 && argv !=
nullptr && argv[0] !=
nullptr && Prog().empty())
3715 std::vector<std::string>
args;
3716 if (argc > 1 && argv !=
nullptr)
3718 args.assign(argv + 1, argv + argc);
3721 return ParseArgs(
args) == std::end(
args);
3724 template <
typename T>
3725 bool ParseCLI(
const T &
args)
3727 return ParseArgs(
args) == std::end(
args);
3731 inline Command::RaiiSubparser::RaiiSubparser(ArgumentParser &parser_, std::vector<std::string> args_)
3732 : command(parser_.SelectedCommand()), parser(std::move(args_), parser_, command, parser_.helpParams), oldSubparser(command.subparser)
3734 command.subparser = &parser;
3737 inline Command::RaiiSubparser::RaiiSubparser(
const Command &command_,
const HelpParams ¶ms_): command(command_), parser(command, params_), oldSubparser(command.subparser)
3739 command.subparser = &parser;
3747 command.subparserHasFlag =
HasFlag();
3751 if (parser ==
nullptr)
3753#ifndef ARGS_NOEXCEPT
3754 throw args::SubparserError();
3756 error = Error::Subparser;
3761 auto it = parser->Parse(
args.begin(),
args.end());
3763 kicked.assign(it,
args.end());
3766 command.subparserError = GetError();
3770 inline std::ostream &operator<<(std::ostream &os,
const ArgumentParser &parser)
3781 Flag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
Options options_):
FlagBase(name_, help_, std::move(matcher_), options_)
3804 virtual void ParseValue(
const std::vector<std::string>&)
override
3816 HelpFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
Options options_ = {}):
Flag(group_, name_, help_, std::move(matcher_), options_) {}
3823 error = Error::Help;
3843 const int startcount;
3847 CounterFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const int startcount_ = 0,
Options options_ = {}):
3848 Flag(group_, name_, help_, std::move(matcher_), options_), startcount(startcount_), count(startcount_) {}
3854 auto me = FlagBase::Match(arg);
3862 if (GetError() != Error::None)
3879 int &operator *() noexcept {
3883 const int &operator *() const noexcept {
3887 virtual void Reset() noexcept
override
3899 std::function<void(
const std::vector<std::string> &)> action;
3903 ActionFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
Nargs nargs_, std::function<
void(
const std::vector<std::string> &)> action_,
Options options_ = {}):
3904 FlagBase(name_, help_, std::move(matcher_), options_), action(std::move(action_)), nargs(nargs_)
3909 ActionFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_, std::function<
void(
const std::string &)> action_,
Options options_ = {}):
3910 FlagBase(name_, help_, std::move(matcher_), options_), nargs(1)
3913 action = [action_](
const std::vector<std::string> &a) {
return action_(a.at(0)); };
3916 ActionFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_, std::function<
void()> action_,
Options options_ = {}):
3917 FlagBase(name_, help_, std::move(matcher_), options_), nargs(0)
3920 action = [action_](
const std::vector<std::string> &) {
return action_(); };
3926 virtual void ParseValue(
const std::vector<std::string> &value)
override
3939 template <
typename T>
3940 static typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value,
bool>::type
3941 HasUnsignedNegativeSign(
const std::string &value)
3943 const auto firstNonSpace = std::find_if_not(value.begin(), value.end(), [](
char c)
3945 return std::isspace(static_cast<unsigned char>(c)) != 0;
3948 return firstNonSpace != value.end() && *firstNonSpace ==
'-';
3951 template <
typename T>
3952 static typename std::enable_if<!std::is_integral<T>::value || !std::is_unsigned<T>::value,
bool>::type
3953 HasUnsignedNegativeSign(
const std::string &)
3959 template <
typename T>
3960 typename std::enable_if<
3961 std::is_integral<T>::value &&
3962 !std::is_same<T, bool>::value &&
3963 !std::is_same<T, char>::value &&
3964 !std::is_same<T, signed char>::value &&
3965 !std::is_same<T, unsigned char>::value,
3967 ParseNumericValue(
const std::string &value, T &destination)
3969 if (HasUnsignedNegativeSign<T>(value))
3974 const char *begin = value.c_str();
3982 const char *
const stop = begin + value.size();
3988 const int saved_errno = errno;
3991 char *end =
nullptr;
3993 if (std::is_unsigned<T>::value)
3995 const unsigned long long parsed = std::strtoull(begin, &end, 0);
3998 errno = saved_errno;
4001 while (end != stop && std::isspace(
static_cast<unsigned char>(*end)))
4005 if (end != stop || errno == ERANGE ||
4006 parsed >
static_cast<unsigned long long>(std::numeric_limits<T>::max()))
4008 errno = saved_errno;
4012 destination =
static_cast<T
>(parsed);
4016 const long long parsed = std::strtoll(begin, &end, 0);
4019 errno = saved_errno;
4022 while (end != stop && std::isspace(
static_cast<unsigned char>(*end)))
4026 if (end != stop || errno == ERANGE ||
4027 parsed <
static_cast<long long>(std::numeric_limits<T>::min()) ||
4028 parsed >
static_cast<long long>(std::numeric_limits<T>::max()))
4030 errno = saved_errno;
4034 destination =
static_cast<T
>(parsed);
4037 errno = saved_errno;
4041 template <
typename T>
4042 typename std::enable_if<
4043 !std::is_integral<T>::value ||
4044 std::is_same<T, bool>::value ||
4045 std::is_same<T, char>::value ||
4046 std::is_same<T, signed char>::value ||
4047 std::is_same<T, unsigned char>::value,
4049 ParseNumericValue(
const std::string &value, T &destination)
4051 std::istringstream ss(value);
4057 ss.imbue(std::locale::classic());
4068 ss >> std::ws >> extra;
4075 ss.clear(ss.rdstate() & ~std::ios::failbit);
4082 template <
typename T>
4083 typename std::enable_if<!std::is_assignable<T, std::string>::value,
bool>::type
4084 operator ()(
const std::string &name,
const std::string &value, T &destination)
4086 const bool success = ParseNumericValue(value, destination);
4093 std::ostringstream problem;
4094 problem <<
"Argument '" << name <<
"' received invalid value type '" << value <<
"'";
4101 template <
typename T>
4102 typename std::enable_if<std::is_assignable<T, std::string>::value,
bool>::type
4103 operator()(
const std::string &,
const std::string &value, T &destination)
4105 destination = value;
4124 virtual std::string GetDefaultString(
const HelpParams&)
const override
4126 return detail::ToString(defaultValue);
4134 ValueFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const T &defaultValue_,
Options options_):
ValueFlagBase(name_, help_, std::move(matcher_), options_), value(defaultValue_), defaultValue(defaultValue_)
4139 ValueFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const T &defaultValue_ = T(),
const bool extraError_ =
false):
ValueFlag(group_, name_, help_, std::move(matcher_), defaultValue_, extraError_ ?
Options::Single :
Options::None)
4143 ValueFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
Options options_):
ValueFlag(group_, name_, help_, std::move(matcher_), T(), options_)
4149 virtual void ParseValue(
const std::vector<std::string> &values_)
override
4151 const std::string &value_ = values_.at(0);
4154 if (!reader(name, value_, this->value))
4156 error = Error::Parse;
4159 reader(name, value_, this->value);
4163 virtual void Reset() noexcept
override
4165 ValueFlagBase::Reset();
4166 value = defaultValue;
4208 return defaultValue;
4219 typename Reader = ValueReader>
4227 ImplicitValueFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const T &implicitValue_,
const T &defaultValue_ = T(),
Options options_ = {})
4228 :
ValueFlag<T, Reader>(group_, name_, help_, std::move(matcher_), defaultValue_, options_), implicitValue(implicitValue_)
4233 :
ValueFlag<T, Reader>(group_, name_, help_, std::move(matcher_), defaultValue_, options_), implicitValue(defaultValue_)
4238 :
ValueFlag<T, Reader>(group_, name_, help_, std::move(matcher_), {}, options_), implicitValue()
4249 virtual void ParseValue(
const std::vector<std::string> &value_)
override
4253 this->value = implicitValue;
4265 template <
typename T>
4273 Flag(group_, name_, help_, std::move(matcher_), options_),
4277 ConstantFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const T& value_,
bool extraError_ =
false):
4278 Flag(group_, name_, help_, std::move(matcher_), extraError_),
4282 T operator * ()
const noexcept
4287 T Get()
const noexcept
4292 const T *operator -> ()
const noexcept
4306 template <
typename...>
class List = detail::vector,
4313 const List<T> defaultValues;
4319 typedef List<T> Container;
4320 typedef T value_type;
4321 typedef typename Container::allocator_type allocator_type;
4322 typedef typename Container::pointer pointer;
4323 typedef typename Container::const_pointer const_pointer;
4324 typedef T& reference;
4325 typedef const T& const_reference;
4326 typedef typename Container::size_type size_type;
4327 typedef typename Container::difference_type difference_type;
4328 typedef typename Container::iterator iterator;
4329 typedef typename Container::const_iterator const_iterator;
4330 typedef std::reverse_iterator<iterator> reverse_iterator;
4331 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
4334 :
FlagBase(name_, help_, std::move(matcher_), options_), values(defaultValues_), defaultValues(defaultValues_),nargs(nargs_)
4346 virtual void ParseValue(
const std::vector<std::string> &values_)
override
4350 for (
const std::string &value : values_)
4354 if (!reader(name, value, v))
4356 error = Error::Parse;
4360 reader(name, value, v);
4362 values.insert(std::end(values), v);
4366 List<T> &Get() noexcept
4399 iterator begin() noexcept
4401 return values.begin();
4404 const_iterator begin() const noexcept
4406 return values.begin();
4409 const_iterator cbegin() const noexcept
4411 return values.cbegin();
4414 iterator end() noexcept
4416 return values.end();
4419 const_iterator end() const noexcept
4421 return values.end();
4424 const_iterator cend() const noexcept
4426 return values.cend();
4429 virtual void Reset() noexcept
override
4432 values = defaultValues;
4435 virtual FlagBase *Match(
const EitherFlag &arg)
override
4437 const bool wasMatched = Matched();
4438 auto me = FlagBase::Match(arg);
4439 if (me && !wasMatched)
4455 template <
typename...>
class List = detail::vector,
4456 typename Reader = ValueReader>
4460 using Container = List<T>;
4462 const Container defaultValues;
4467 typedef T value_type;
4468 typedef typename Container::allocator_type allocator_type;
4469 typedef typename Container::pointer pointer;
4470 typedef typename Container::const_pointer const_pointer;
4471 typedef T& reference;
4472 typedef const T& const_reference;
4473 typedef typename Container::size_type size_type;
4474 typedef typename Container::difference_type difference_type;
4475 typedef typename Container::iterator iterator;
4476 typedef typename Container::const_iterator const_iterator;
4477 typedef std::reverse_iterator<iterator> reverse_iterator;
4478 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
4480 ValueFlagList(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const Container &defaultValues_ = Container(),
Options options_ = {}):
4481 ValueFlagBase(name_, help_, std::move(matcher_), options_), values(defaultValues_), defaultValues(defaultValues_)
4488 virtual void ParseValue(
const std::vector<std::string> &values_)
override
4490 const std::string &value_ = values_.at(0);
4494 if (!reader(name, value_, v))
4496 error = Error::Parse;
4500 reader(name, value_, v);
4502 values.insert(std::end(values), v);
4540 virtual std::string Name()
const override
4542 return name + std::string(
"...");
4545 virtual void Reset() noexcept
override
4547 ValueFlagBase::Reset();
4548 values = defaultValues;
4551 virtual FlagBase *Match(
const EitherFlag &arg)
override
4553 const bool wasMatched = Matched();
4554 auto me = FlagBase::Match(arg);
4555 if (me && !wasMatched)
4562 iterator begin() noexcept
4564 return values.begin();
4567 const_iterator begin() const noexcept
4569 return values.begin();
4572 const_iterator cbegin() const noexcept
4574 return values.cbegin();
4577 iterator end() noexcept
4579 return values.end();
4582 const_iterator end() const noexcept
4584 return values.end();
4587 const_iterator cend() const noexcept
4589 return values.cend();
4603 typename Reader = ValueReader,
4604 template <
typename...>
class Map = detail::unordered_map>
4608 const Map<K, T> map;
4610 const T defaultValue;
4614 virtual std::vector<std::string> GetChoicesStrings(
const HelpParams &)
const override
4616 return detail::MapKeysToStrings(map);
4621 MapFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const Map<K, T> &map_,
const T &defaultValue_,
Options options_):
ValueFlagBase(name_, help_, std::move(matcher_), options_), map(map_), value(defaultValue_), defaultValue(defaultValue_)
4626 MapFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const Map<K, T> &map_,
const T &defaultValue_ = T(),
const bool extraError_ =
false):
MapFlag(group_, name_, help_, std::move(matcher_), map_, defaultValue_, extraError_ ?
Options::Single :
Options::None)
4630 MapFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const Map<K, T> &map_,
Options options_):
MapFlag(group_, name_, help_, std::move(matcher_), map_, T(), options_)
4636 virtual void ParseValue(
const std::vector<std::string> &values_)
override
4638 const std::string &value_ = values_.at(0);
4642 if (!reader(name, value_, key))
4644 error = Error::Parse;
4648 reader(name, value_, key);
4650 auto it = map.find(key);
4651 if (it == std::end(map))
4653 std::ostringstream problem;
4654 problem <<
"Could not find key '" << key <<
"' in map for arg '" << name <<
"'";
4657 errorMsg = problem.str();
4663 this->value = it->second;
4702 virtual void Reset() noexcept
override
4704 ValueFlagBase::Reset();
4705 value = defaultValue;
4720 template <
typename...>
class List = detail::vector,
4721 typename Reader = ValueReader,
4722 template <
typename...>
class Map = detail::unordered_map>
4726 using Container = List<T>;
4727 const Map<K, T> map;
4729 const Container defaultValues;
4733 virtual std::vector<std::string> GetChoicesStrings(
const HelpParams &)
const override
4735 return detail::MapKeysToStrings(map);
4739 typedef T value_type;
4740 typedef typename Container::allocator_type allocator_type;
4741 typedef typename Container::pointer pointer;
4742 typedef typename Container::const_pointer const_pointer;
4743 typedef T& reference;
4744 typedef const T& const_reference;
4745 typedef typename Container::size_type size_type;
4746 typedef typename Container::difference_type difference_type;
4747 typedef typename Container::iterator iterator;
4748 typedef typename Container::const_iterator const_iterator;
4749 typedef std::reverse_iterator<iterator> reverse_iterator;
4750 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
4752 MapFlagList(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const Map<K, T> &map_,
const Container &defaultValues_ = Container(),
Options options_ = {}):
4753 ValueFlagBase(name_, help_, std::move(matcher_), options_), map(map_), values(defaultValues_), defaultValues(defaultValues_)
4760 virtual void ParseValue(
const std::vector<std::string> &values_)
override
4762 const std::string &value_ = values_.at(0);
4766 if (!reader(name, value_, key))
4768 error = Error::Parse;
4772 reader(name, value_, key);
4774 auto it = map.find(key);
4775 if (it == std::end(map))
4777 std::ostringstream problem;
4778 problem <<
"Could not find key '" << key <<
"' in map for arg '" << name <<
"'";
4781 errorMsg = problem.str();
4787 detail::AppendMappedValue(values, it->second, 0);
4826 virtual std::string Name()
const override
4828 return name + std::string(
"...");
4831 virtual void Reset() noexcept
override
4833 ValueFlagBase::Reset();
4834 values = defaultValues;
4837 virtual FlagBase *Match(
const EitherFlag &arg)
override
4839 const bool wasMatched = Matched();
4840 auto me = FlagBase::Match(arg);
4841 if (me && !wasMatched)
4848 iterator begin() noexcept
4850 return values.begin();
4853 const_iterator begin() const noexcept
4855 return values.begin();
4858 const_iterator cbegin() const noexcept
4860 return values.cbegin();
4863 iterator end() noexcept
4865 return values.end();
4868 const_iterator end() const noexcept
4870 return values.end();
4873 const_iterator cend() const noexcept
4875 return values.cend();
4886 typename Reader = ValueReader>
4891 const T defaultValue;
4894 Positional(
Group &group_,
const std::string &name_,
const std::string &help_,
const T &defaultValue_ = T(),
Options options_ = {}):
PositionalBase(name_, help_, options_), value(defaultValue_), defaultValue(defaultValue_)
4905 virtual void ParseValue(
const std::string &value_)
override
4908 if (!reader(name, value_, this->value))
4910 error = Error::Parse;
4914 reader(name, value_, this->value);
4955 virtual void Reset() noexcept
override
4957 PositionalBase::Reset();
4958 value = defaultValue;
4970 template <
typename...>
class List = detail::vector,
4971 typename Reader = ValueReader>
4975 using Container = List<T>;
4977 const Container defaultValues;
4981 typedef T value_type;
4982 typedef typename Container::allocator_type allocator_type;
4983 typedef typename Container::pointer pointer;
4984 typedef typename Container::const_pointer const_pointer;
4985 typedef T& reference;
4986 typedef const T& const_reference;
4987 typedef typename Container::size_type size_type;
4988 typedef typename Container::difference_type difference_type;
4989 typedef typename Container::iterator iterator;
4990 typedef typename Container::const_iterator const_iterator;
4991 typedef std::reverse_iterator<iterator> reverse_iterator;
4992 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
4994 PositionalList(
Group &group_,
const std::string &name_,
const std::string &help_,
const Container &defaultValues_ = Container(),
Options options_ = {}):
PositionalBase(name_, help_, options_), values(defaultValues_), defaultValues(defaultValues_)
5005 virtual void ParseValue(
const std::string &value_)
override
5009 if (!reader(name, value_, v))
5011 error = Error::Parse;
5015 reader(name, value_, v);
5017 values.insert(std::end(values), v);
5021 virtual std::string Name()
const override
5023 return name + std::string(
"...");
5061 virtual void Reset() noexcept
override
5063 PositionalBase::Reset();
5064 values = defaultValues;
5067 virtual PositionalBase *GetNextPositional()
override
5069 const bool wasMatched = Matched();
5070 auto me = PositionalBase::GetNextPositional();
5071 if (me && !wasMatched)
5078 iterator begin() noexcept
5080 return values.begin();
5083 const_iterator begin() const noexcept
5085 return values.begin();
5088 const_iterator cbegin() const noexcept
5090 return values.cbegin();
5093 iterator end() noexcept
5095 return values.end();
5098 const_iterator end() const noexcept
5100 return values.end();
5103 const_iterator cend() const noexcept
5105 return values.cend();
5119 typename Reader = ValueReader,
5120 template <
typename...>
class Map = detail::unordered_map>
5124 const Map<K, T> map;
5126 const T defaultValue;
5130 virtual std::vector<std::string> GetChoicesStrings(
const HelpParams &)
const override
5132 return detail::MapKeysToStrings(map);
5137 MapPositional(
Group &group_,
const std::string &name_,
const std::string &help_,
const Map<K, T> &map_,
const T &defaultValue_ = T(),
Options options_ = {}):
5138 PositionalBase(name_, help_, options_), map(map_), value(defaultValue_), defaultValue(defaultValue_)
5145 virtual void ParseValue(
const std::string &value_)
override
5149 if (!reader(name, value_, key))
5151 error = Error::Parse;
5155 reader(name, value_, key);
5157 auto it = map.find(key);
5158 if (it == std::end(map))
5160 std::ostringstream problem;
5161 problem <<
"Could not find key '" << key <<
"' in map for arg '" << name <<
"'";
5164 errorMsg = problem.str();
5170 this->value = it->second;
5211 virtual void Reset() noexcept
override
5213 PositionalBase::Reset();
5214 value = defaultValue;
5229 template <
typename...>
class List = detail::vector,
5230 typename Reader = ValueReader,
5231 template <
typename...>
class Map = detail::unordered_map>
5235 using Container = List<T>;
5237 const Map<K, T> map;
5239 const Container defaultValues;
5243 virtual std::vector<std::string> GetChoicesStrings(
const HelpParams &)
const override
5245 return detail::MapKeysToStrings(map);
5249 typedef T value_type;
5250 typedef typename Container::allocator_type allocator_type;
5251 typedef typename Container::pointer pointer;
5252 typedef typename Container::const_pointer const_pointer;
5253 typedef T& reference;
5254 typedef const T& const_reference;
5255 typedef typename Container::size_type size_type;
5256 typedef typename Container::difference_type difference_type;
5257 typedef typename Container::iterator iterator;
5258 typedef typename Container::const_iterator const_iterator;
5259 typedef std::reverse_iterator<iterator> reverse_iterator;
5260 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
5262 MapPositionalList(
Group &group_,
const std::string &name_,
const std::string &help_,
const Map<K, T> &map_,
const Container &defaultValues_ = Container(),
Options options_ = {}):
5263 PositionalBase(name_, help_, options_), map(map_), values(defaultValues_), defaultValues(defaultValues_)
5270 virtual void ParseValue(
const std::string &value_)
override
5274 if (!reader(name, value_, key))
5276 error = Error::Parse;
5280 reader(name, value_, key);
5282 auto it = map.find(key);
5283 if (it == std::end(map))
5285 std::ostringstream problem;
5286 problem <<
"Could not find key '" << key <<
"' in map for arg '" << name <<
"'";
5289 errorMsg = problem.str();
5295 detail::AppendMappedValue(values, it->second, 0);
5335 virtual std::string Name()
const override
5337 return name + std::string(
"...");
5340 virtual void Reset() noexcept
override
5342 PositionalBase::Reset();
5343 values = defaultValues;
5346 virtual PositionalBase *GetNextPositional()
override
5348 const bool wasMatched = Matched();
5349 auto me = PositionalBase::GetNextPositional();
5350 if (me && !wasMatched)
5357 iterator begin() noexcept
5359 return values.begin();
5362 const_iterator begin() const noexcept
5364 return values.begin();
5367 const_iterator cbegin() const noexcept
5369 return values.cbegin();
5372 iterator end() noexcept
5374 return values.end();
5377 const_iterator end() const noexcept
5379 return values.end();
5382 const_iterator cend() const noexcept
5384 return values.cend();
5389#pragma pop_macro("min")
5390#pragma pop_macro("max")
A flag class that calls a function when it's matched.
Definition args.hxx:3897
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:3923
virtual void ParseValue(const std::vector< std::string > &value) override
Parse values of this option.
Definition args.hxx:3926
The main user facing command line argument parser class.
Definition args.hxx:2723
const std::string & ShortPrefix() const
The prefix for short flags.
Definition args.hxx:3455
void SetArgumentSeparations(const bool allowJoinedShortValue_, const bool allowJoinedLongValue_, const bool allowSeparateShortValue_, const bool allowSeparateLongValue_)
Change allowed option separation.
Definition args.hxx:3521
void Prog(const std::string &prog_)
The program name for help generation.
Definition args.hxx:3438
It ParseArgs(It begin, It end)
Parse all arguments.
Definition args.hxx:3677
const std::string & Prog() const
The program name for help generation.
Definition args.hxx:3434
void LongPrefix(const std::string &longprefix_)
The prefix for long flags.
Definition args.hxx:3447
void LongSeparator(const std::string &longseparator_)
The separator for long flags.
Definition args.hxx:3471
void Help(std::ostream &help_) const
Pass the help menu into an ostream.
Definition args.hxx:3538
const std::string & LongPrefix() const
The prefix for long flags.
Definition args.hxx:3443
const std::string & LongSeparator() const
The separator for long flags.
Definition args.hxx:3467
bool ParseCLI(const int argc, const char *const *argv)
Convenience function to parse the CLI from argc and argv.
Definition args.hxx:3708
const std::string & Terminator() const
The terminator that forcibly separates flags from positionals.
Definition args.hxx:3491
auto ParseArgs(const T &args) -> decltype(std::begin(args))
Parse all arguments.
Definition args.hxx:3697
void Terminator(const std::string &terminator_)
The terminator that forcibly separates flags from positionals.
Definition args.hxx:3495
void GetArgumentSeparations(bool &allowJoinedShortValue_, bool &allowJoinedLongValue_, bool &allowSeparateShortValue_, bool &allowSeparateLongValue_) const
Get the current argument separation parameters.
Definition args.hxx:3502
std::string Help() const
Generate a help menu as a string.
Definition args.hxx:3656
void ShortPrefix(const std::string &shortprefix_)
The prefix for short flags.
Definition args.hxx:3459
std::string ParseArgsValues(FlagBase &flag, const std::string &arg, It &it, It end, const bool allowSeparate, const bool allowJoined, const bool hasJoined, const std::string &joinedArg, const bool canDiscardJoined, std::vector< std::string > &values)
(INTERNAL) Parse flag's values
Definition args.hxx:2811
Base class for all match types.
Definition args.hxx:1010
void KickOut(bool kickout_) noexcept
Sets a kick-out value for building subparsers.
Definition args.hxx:1110
bool KickOut() const noexcept
Gets the kick-out value for building subparsers.
Definition args.hxx:1123
Main class for building subparsers.
Definition args.hxx:2183
const std::string & Name() const
The name of command.
Definition args.hxx:2318
virtual PositionalBase * GetNextPositional() override
Get the next ready positional, or nullptr if there is none.
Definition args.hxx:2419
const std::string & ProglinePostfix() const
The description that appears on the prog line after options.
Definition args.hxx:2288
void Description(const std::string &description_)
The description that appears above options.
Definition args.hxx:2303
virtual bool HasPositional() const override
Get whether this has any PositionalBase children.
Definition args.hxx:2455
const std::string & Description() const
The description that appears above options.
Definition args.hxx:2298
const std::string & Help() const
The description of command.
Definition args.hxx:2323
void Epilog(const std::string &epilog_)
The description that appears below options.
Definition args.hxx:2313
void ProglinePostfix(const std::string &proglinePostfix_)
The description that appears on the prog line after options.
Definition args.hxx:2293
virtual FlagBase * Match(const EitherFlag &flag) override
Return the first FlagBase that matches flag, or nullptr.
Definition args.hxx:2355
virtual bool HasCommand() const override
Get whether this has any Command children.
Definition args.hxx:2460
virtual std::vector< std::string > GetProgramLine(const HelpParams ¶ms) const override
Get the names of positional parameters.
Definition args.hxx:2524
virtual bool HasFlag() const override
Get whether this has any FlagBase children.
Definition args.hxx:2450
virtual std::vector< std::tuple< std::string, std::string, unsigned > > GetDescription(const HelpParams ¶ms, const unsigned int indent) const override
Get all the child descriptions for help generation.
Definition args.hxx:2549
const std::string & Epilog() const
The description that appears below options.
Definition args.hxx:2308
virtual bool Matched() const noexcept override
Whether or not this group matches validation.
Definition args.hxx:2336
void RequireCommand(bool value)
If value is true, parser will fail if no command was parsed.
Definition args.hxx:2330
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:1507
std::string Get() noexcept
Get the completion reply.
Definition args.hxx:1578
virtual void ParseValue(const std::vector< std::string > &value_) override
Parse values of this option.
Definition args.hxx:1512
An exception that contains autocompletion reply.
Definition args.hxx:559
A boolean flag containing a retrievable constant.
Definition args.hxx:4267
A flag class that simply counts the number of times it's matched.
Definition args.hxx:3841
int & Get() noexcept
Get the count.
Definition args.hxx:3874
Base error class.
Definition args.hxx:478
Base class for all flag options.
Definition args.hxx:1318
virtual void ParseValue(const std::vector< std::string > &value)=0
Parse values of this option.
virtual Nargs NumberOfArguments() const noexcept=0
Defines how many values can be consumed by this option.
Boolean argument matcher.
Definition args.hxx:3779
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:3799
virtual void ParseValue(const std::vector< std::string > &) override
Parse values of this option.
Definition args.hxx:3804
bool Get() const
Get whether this was matched.
Definition args.hxx:3794
Class for using global options in ArgumentParser.
Definition args.hxx:2102
Class for all kinds of validating groups, including ArgumentParser.
Definition args.hxx:1656
virtual bool HasCommand() const override
Get whether this has any Command children.
Definition args.hxx:1836
std::vector< Base * >::size_type MatchedChildren() const
Count the number of matched children this group has.
Definition args.hxx:1843
virtual bool HasPositional() const override
Get whether this has any PositionalBase children.
Definition args.hxx:1827
virtual std::vector< std::string > GetProgramLine(const HelpParams ¶ms) const override
Get the names of positional parameters.
Definition args.hxx:1931
Group(Group &group_, const std::string &help_=std::string(), const std::function< bool(const Group &)> &validator_=Validators::DontCare, Options options_={})
If help is empty, this group will not be printed in help output.
Definition args.hxx:1720
void SignalDetectDuplicates()
Sends a signal to the root of the tree to begin checking for duplicates.
Definition args.hxx:1983
virtual bool HasFlag() const override
Get whether this has any FlagBase children.
Definition args.hxx:1818
Group(const std::string &help_=std::string(), const std::function< bool(const Group &)> &validator_=Validators::DontCare, Options options_={})
If help is empty, this group will not be printed in help output.
Definition args.hxx:1715
virtual bool Matched() const noexcept override
Whether or not this group matches validation.
Definition args.hxx:1887
void DetectDuplicateFlags(std::unordered_set< char > &usedShortFlags, std::unordered_set< std::string > &usedLongFlags)
Used by parameterless DetectDuplicateFlags.
Definition args.hxx:2002
virtual FlagBase * Match(const EitherFlag &flag) override
Return the first FlagBase that matches flag, or nullptr.
Definition args.hxx:1767
bool Get() const
Get validation.
Definition args.hxx:1894
const std::vector< Base * > & Children() const
Get all this group's children.
Definition args.hxx:1757
std::vector< Base * > GetMatchedChildren() const
Get the list of children which were matched.
Definition args.hxx:1852
void DetectDuplicateFlags()
Detect duplicate flags.
Definition args.hxx:1993
void Add(Base &child)
Append a child to this Group.
Definition args.hxx:1729
std::vector< ChildType * > GetFilteredChildren(bool matching=false) const
Gets the children which are a certain type.
Definition args.hxx:1868
virtual std::vector< std::tuple< std::string, std::string, unsigned > > GetDescription(const HelpParams ¶ms, const unsigned int indent) const override
Get all the child descriptions for help generation.
Definition args.hxx:1901
virtual PositionalBase * GetNextPositional() override
Get the next ready positional, or nullptr if there is none.
Definition args.hxx:1802
Help flag class.
Definition args.hxx:3814
bool Get() const noexcept
Get whether this was matched.
Definition args.hxx:3832
virtual void ParseValue(const std::vector< std::string > &)
Parse values of this option.
Definition args.hxx:3820
An exception that indicates that the user has requested help.
Definition args.hxx:541
An optional argument-accepting flag class.
Definition args.hxx:4221
virtual void ParseValue(const std::vector< std::string > &value_) override
Parse values of this option.
Definition args.hxx:4249
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:4244
Errors in map lookups.
Definition args.hxx:523
A mapping value flag list class.
Definition args.hxx:4724
Container * operator->() noexcept
Get the values.
Definition args.hxx:4814
Container & Get() noexcept
Get the value.
Definition args.hxx:4793
virtual void ParseValue(const std::vector< std::string > &values_) override
Parse values of this option.
Definition args.hxx:4760
Container & operator*() noexcept
Get the value.
Definition args.hxx:4800
A mapping value flag class.
Definition args.hxx:4606
virtual void ParseValue(const std::vector< std::string > &values_) override
Parse values of this option.
Definition args.hxx:4636
T & Get() noexcept
Get the value.
Definition args.hxx:4669
T * operator->() noexcept
Get the value.
Definition args.hxx:4690
T & operator*() noexcept
Get the value.
Definition args.hxx:4676
A positional argument mapping list class.
Definition args.hxx:5233
Container & operator*() noexcept
Get the value.
Definition args.hxx:5309
Container * operator->() noexcept
Get the values.
Definition args.hxx:5323
Container & Get() noexcept
Get the value.
Definition args.hxx:5302
A positional argument mapping class.
Definition args.hxx:5122
T * operator->() noexcept
Get the value.
Definition args.hxx:5199
T & Get() noexcept
Get the value.
Definition args.hxx:5178
T & operator*() noexcept
Get the value.
Definition args.hxx:5185
A class of "matchers", specifying short and flags that can possibly be matched.
Definition args.hxx:627
EitherFlag GetShortOrAny() const
(INTERNAL) Get short flag if it exists or any long flag
Definition args.hxx:745
std::vector< EitherFlag > GetFlagStrings() const
(INTERNAL) Get all flag strings as a vector, with the prefixes embedded
Definition args.hxx:710
Matcher(Short &&shortIn, Long &&longIn)
Specify short and long flags separately as iterables.
Definition args.hxx:663
Matcher(ShortIt shortFlagsStart, ShortIt shortFlagsEnd, LongIt longFlagsStart, LongIt longFlagsEnd)
Specify short and long flags separately as iterators.
Definition args.hxx:638
bool Match(const std::string &flag) const
(INTERNAL) Check if there is a match of a long flag
Definition args.hxx:696
EitherFlag GetLongOrAny() const
(INTERNAL) Get long flag if it exists or any short flag
Definition args.hxx:727
bool Match(const char flag) const
(INTERNAL) Check if there is a match of a short flag
Definition args.hxx:689
bool Match(const EitherFlag &flag) const
(INTERNAL) Check if there is a match of a flag
Definition args.hxx:703
Matcher(std::initializer_list< EitherFlag > in)
Specify a mixed single initializer-list of both short and long flags.
Definition args.hxx:679
Base class for all match types that have a name.
Definition args.hxx:1155
void HelpDefault(const std::string &str)
Sets default value string that will be added to argument description.
Definition args.hxx:1191
void HelpChoices(const std::vector< std::string > &array)
Sets choices strings that will be added to argument description.
Definition args.hxx:1207
std::string HelpDefault(const HelpParams ¶ms) const
Gets default value string that will be added to argument description.
Definition args.hxx:1199
std::vector< std::string > HelpChoices(const HelpParams ¶ms) const
Gets choices strings that will be added to argument description.
Definition args.hxx:1215
A variadic arguments accepting flag class.
Definition args.hxx:4309
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:4341
virtual void ParseValue(const std::vector< std::string > &values_) override
Parse values of this option.
Definition args.hxx:4346
List< T > * operator->() noexcept
Get the values.
Definition args.hxx:4387
List< T > & operator*() noexcept
Get the value.
Definition args.hxx:4373
Errors that occur during regular parsing.
Definition args.hxx:496
Base class for positional options.
Definition args.hxx:1596
A positional argument class that pushes the found values into a list.
Definition args.hxx:4973
Container & operator*() noexcept
Get the value.
Definition args.hxx:5035
Container & Get() noexcept
Get the values.
Definition args.hxx:5028
Container * operator->() noexcept
Get the values.
Definition args.hxx:5049
A positional argument class.
Definition args.hxx:4888
T & operator*() noexcept
Get the value.
Definition args.hxx:4929
T & Get() noexcept
Get the value.
Definition args.hxx:4922
T * operator->() noexcept
Get the value.
Definition args.hxx:4943
Errors that when a required flag is omitted.
Definition args.hxx:514
Utility class for building subparsers with coroutines/callbacks.
Definition args.hxx:2128
void Parse()
Continue parsing arguments for new command.
Definition args.hxx:3742
const std::vector< std::string > & KickedOut() const noexcept
Returns a vector of kicked out arguments.
Definition args.hxx:2172
bool IsParsed() const
(INTERNAL) Determines whether Parse was called or not.
Definition args.hxx:2159
Errors that occur during usage.
Definition args.hxx:487
Errors that are detected from group validation after parsing finishes.
Definition args.hxx:505
Base class for value-accepting flag options.
Definition args.hxx:1480
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:1486
An argument-accepting flag class that pushes the found values into a list.
Definition args.hxx:4458
Container * operator->() noexcept
Get the values.
Definition args.hxx:4528
Container & Get() noexcept
Get the values.
Definition args.hxx:4507
Container & operator*() noexcept
Get the value.
Definition args.hxx:4514
virtual void ParseValue(const std::vector< std::string > &values_) override
Parse values of this option.
Definition args.hxx:4488
An argument-accepting flag class.
Definition args.hxx:4119
T & operator*() noexcept
Get the value.
Definition args.hxx:4178
T * operator->() noexcept
Get the value.
Definition args.hxx:4192
T & Get() noexcept
Get the value.
Definition args.hxx:4171
const T & GetDefault() noexcept
Get the default value.
Definition args.hxx:4206
virtual void ParseValue(const std::vector< std::string > &values_) override
Parse values of this option.
Definition args.hxx:4149
contains all the functionality of the args library
std::vector< std::string > Wrap(It begin, It end, const std::string::size_type width, std::string::size_type firstlinewidth=0, std::string::size_type firstlineindent=0)
(INTERNAL) Wrap a vector of words into a vector of lines
Definition args.hxx:277
bool SafeAdd(T a, T b, T &out) noexcept
Safe addition to prevent integer overflow.
Definition args.hxx:108
bool SafeMultiply(T a, T b, T &out) noexcept
Safe multiplication to prevent integer overflow.
Definition args.hxx:148
bool SafeSub(T a, T b, T &out) noexcept
Safe subtraction to prevent integer underflow.
Definition args.hxx:202
Options
Attributes for flags.
Definition args.hxx:765
@ HiddenFromCompletion
Flag is excluded from auto completion.
@ Global
Flag is global and can be used in any subcommand.
@ Single
Flag can't be passed multiple times.
@ HiddenFromUsage
Flag is excluded from usage line.
@ Hidden
Flag is excluded from options help and usage line.
@ Required
Flag can't be omitted.
@ KickOut
Flag stops a parser.
@ HiddenFromDescription
Flag is excluded from options help.
std::enable_if< std::is_unsigned< T >::value, bool >::type SafeNeg(T a, T &out) noexcept
Safe negation to prevent integer overflow.
Definition args.hxx:240
auto get(Option &option_) -> decltype(option_.Get())
Getter to grab the value from the argument type.
Definition args.hxx:78
std::string::size_type Glyphs(const std::string &string_)
(INTERNAL) Count UTF-8 glyphs
Definition args.hxx:91
A simple unified option type for unified initializer lists for the Matcher class.
Definition args.hxx:569
static std::unordered_set< char > GetShort(std::initializer_list< EitherFlag > flags)
Get just the short flags from an initializer list of EitherFlags.
Definition args.hxx:594
static std::unordered_set< std::string > GetLong(std::initializer_list< EitherFlag > flags)
Get just the long flags from an initializer list of EitherFlags.
Definition args.hxx:579
Default validators.
Definition args.hxx:1666
A simple structure of parameters for easy user-modifyable help menus.
Definition args.hxx:821
std::string programName
The program name for help generation.
Definition args.hxx:878
bool showCommandFullHelp
Show command's descriptions and epilog.
Definition args.hxx:886
bool proglineShowFlags
Show flags in program line.
Definition args.hxx:922
std::string usageString
Program line prefix.
Definition args.hxx:930
unsigned int width
The width of the help menu.
Definition args.hxx:824
std::string proglineNonrequiredClose
The postfix for progline non-required argument.
Definition args.hxx:918
unsigned int helpindent
The indent of the flag descriptions.
Definition args.hxx:839
bool proglinePreferShortFlags
Use short flags in program lines when possible.
Definition args.hxx:926
std::string proglineCommand
The prefix for progline when command has any subcommands.
Definition args.hxx:894
std::string proglineOptions
The postfix for progline when showProglineOptions is true and command has any flags.
Definition args.hxx:890
std::string longSeparator
The separator for long flags.
Definition args.hxx:874
bool showValueName
Show value name.
Definition args.hxx:942
bool showTerminator
Show the terminator when both options and positional parameters are present.
Definition args.hxx:850
std::string proglineValueOpen
The prefix for progline value.
Definition args.hxx:898
std::string valueOpen
The prefix for option value.
Definition args.hxx:950
unsigned int progtailindent
The indent of the program trailing lines for long parameters.
Definition args.hxx:830
std::string proglineNonrequiredOpen
The prefix for progline non-required argument.
Definition args.hxx:914
unsigned int descriptionindent
The indent of the description and epilogs.
Definition args.hxx:833
bool showCommandChildren
Show command's flags.
Definition args.hxx:882
bool showProglineOptions
Show the {OPTIONS} on the prog line when this is true.
Definition args.hxx:854
std::string valueClose
The postfix for option value.
Definition args.hxx:954
std::string longPrefix
The prefix for long flags.
Definition args.hxx:866
std::string proglineRequiredClose
The postfix for progline required argument.
Definition args.hxx:910
unsigned int flagindent
The indent of the flags.
Definition args.hxx:836
std::string optionsString
String shown in help before flags descriptions.
Definition args.hxx:934
bool addNewlineBeforeDescription
Add newline before flag description.
Definition args.hxx:946
std::string shortPrefix
The prefix for short flags.
Definition args.hxx:862
bool addDefault
Add default values to argument description.
Definition args.hxx:966
unsigned int gutter
The minimum gutter between each flag and its help.
Definition args.hxx:846
bool showProglinePositionals
Show the positionals on the prog line when this is true.
Definition args.hxx:858
std::string shortSeparator
The separator for short flags.
Definition args.hxx:870
std::string proglineValueClose
The postfix for progline value.
Definition args.hxx:902
bool useValueNameOnce
Display value name after all the long and short flags.
Definition args.hxx:938
std::string defaultString
The prefix for default values.
Definition args.hxx:970
std::string proglineRequiredOpen
The prefix for progline required argument.
Definition args.hxx:906
unsigned int eachgroupindent
The additional indent each group adds.
Definition args.hxx:842
unsigned int progindent
The indent of the program line.
Definition args.hxx:827
bool addChoices
Add choices to argument description.
Definition args.hxx:958
std::string choiceString
The prefix for choices.
Definition args.hxx:962
A number of arguments which can be consumed by an option.
Definition args.hxx:978
A default Reader class for argument classes.
Definition args.hxx:3937