35#pragma push_macro("min")
36#pragma push_macro("max")
40#define ARGS_VERSION "6.4.16"
41#define ARGS_VERSION_MAJOR 6
42#define ARGS_VERSION_MINOR 4
43#define ARGS_VERSION_PATCH 16
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)
411 for (
const auto &element : array)
434 inline std::vector<std::string>
Wrap(
const std::string &in,
const std::string::size_type width, std::string::size_type firstlinewidth = 0)
437 const auto newlineloc = in.find(
'\n');
438 if (newlineloc != in.npos)
440 auto first =
Wrap(std::string(in, 0, newlineloc), width);
441 auto second =
Wrap(std::string(in, newlineloc + 1), width);
444 std::make_move_iterator(std::begin(second)),
445 std::make_move_iterator(std::end(second)));
449 std::istringstream stream(in);
450 std::string::size_type indent = 0;
454 if (!std::isspace(
static_cast<unsigned char>(c)))
461 return Wrap(std::istream_iterator<std::string>(stream), std::istream_iterator<std::string>(),
462 width, firstlinewidth, indent);
483 class Error :
public std::runtime_error
486 Error(
const std::string &problem) : std::runtime_error(problem) {}
549 Help(
const std::string &flag) :
Error(flag) {}
555 class SubparserError :
public Error
558 SubparserError() :
Error(
"") {}
559 virtual ~SubparserError() {}
577 const char shortFlag;
578 const std::string longFlag;
579 EitherFlag(
const std::string &flag) : isShort(
false), shortFlag(), longFlag(flag) {}
580 EitherFlag(
const char *flag) : isShort(
false), shortFlag(), longFlag(flag) {}
581 EitherFlag(
const char flag) : isShort(
true), shortFlag(flag), longFlag() {}
585 static std::unordered_set<std::string>
GetLong(std::initializer_list<EitherFlag> flags)
587 std::unordered_set<std::string> longFlags;
592 longFlags.insert(flag.longFlag);
600 static std::unordered_set<char>
GetShort(std::initializer_list<EitherFlag> flags)
602 std::unordered_set<char> shortFlags;
607 shortFlags.insert(flag.shortFlag);
613 std::string str()
const
615 return isShort ? std::string(1, shortFlag) : longFlag;
618 std::string str(
const std::string &shortPrefix,
const std::string &longPrefix)
const
620 return isShort ? shortPrefix + std::string(1, shortFlag) : longPrefix + longFlag;
635 const std::unordered_set<char> shortFlags;
636 const std::unordered_set<std::string> longFlags;
643 template <
typename ShortIt,
typename LongIt>
644 Matcher(ShortIt shortFlagsStart, ShortIt shortFlagsEnd, LongIt longFlagsStart, LongIt longFlagsEnd) :
645 shortFlags(shortFlagsStart, shortFlagsEnd),
646 longFlags(longFlagsStart, longFlagsEnd)
648 if (shortFlags.empty() && longFlags.empty())
658 Error GetError() const noexcept
660 return shortFlags.empty() && longFlags.empty() ? Error::Usage : Error::None;
668 template <
typename Short,
typename Long>
670 Matcher(std::begin(shortIn), std::end(shortIn), std::begin(longIn), std::end(longIn))
685 Matcher(std::initializer_list<EitherFlag> in) :
688 Matcher(
Matcher &&other) noexcept : shortFlags(std::move(other.shortFlags)), longFlags(std::move(other.longFlags))
697 return shortFlags.find(flag) != shortFlags.end();
702 bool Match(
const std::string &flag)
const
704 return longFlags.find(flag) != longFlags.end();
711 return flag.isShort ?
Match(flag.shortFlag) :
Match(flag.longFlag);
718 std::vector<EitherFlag> flagStrings;
719 flagStrings.reserve(shortFlags.size() + longFlags.size());
720 for (
const char flag: shortFlags)
722 flagStrings.emplace_back(flag);
724 for (
const std::string &flag: longFlags)
726 flagStrings.emplace_back(flag);
735 if (!longFlags.empty())
737 return *longFlags.begin();
740 if (!shortFlags.empty())
742 return *shortFlags.begin();
753 if (!shortFlags.empty())
755 return *shortFlags.begin();
758 if (!longFlags.empty())
760 return *longFlags.begin();
811 return static_cast<Options>(
static_cast<int>(lhs) |
static_cast<int>(rhs));
816 return static_cast<Options>(
static_cast<int>(lhs) &
static_cast<int>(rhs));
820 class PositionalBase;
822 class ArgumentParser;
988 Nargs(
size_t min_,
size_t max_) : min{min_}, max{max_}
998 Nargs(
size_t num_) : min{num_}, max{num_}
1002 friend bool operator == (
const Nargs &lhs,
const Nargs &rhs)
1004 return lhs.min == rhs.min && lhs.max == rhs.max;
1007 friend bool operator != (
const Nargs &lhs,
const Nargs &rhs)
1009 return !(lhs == rhs);
1021 bool matched =
false;
1022 const std::string help;
1025 mutable Error error = Error::None;
1026 mutable std::string errorMsg;
1030 Base(
const std::string &help_,
Options options_ = {}) : options(options_), help(help_) {}
1033 Options GetOptions()
const noexcept
1038 bool IsRequired()
const noexcept
1043 virtual bool Matched()
const noexcept
1048 virtual void Validate(
const std::string &,
const std::string &)
const
1052 operator bool()
const noexcept
1057 virtual std::vector<std::tuple<std::string, std::string, unsigned>> GetDescription(
const HelpParams &,
const unsigned indentLevel)
const
1059 std::tuple<std::string, std::string, unsigned> description;
1060 std::get<1>(description) = help;
1061 std::get<2>(description) = indentLevel;
1062 return { std::move(description) };
1065 virtual std::vector<Command*> GetCommands()
1070 virtual bool IsGroup()
const
1085 virtual std::vector<FlagBase*> GetAllFlags()
1090 virtual bool HasFlag()
const
1095 virtual bool HasPositional()
const
1100 virtual bool HasCommand()
const
1105 virtual std::vector<std::string> GetProgramLine(
const HelpParams &)
const
1129 virtual void Reset() noexcept
1133 error = Error::None;
1140 virtual Error GetError()
const
1146 virtual std::string GetErrorMsg()
const
1158 const std::string name;
1159 bool kickout =
false;
1160 std::string defaultString;
1161 bool defaultStringManual =
false;
1162 std::vector<std::string> choicesStrings;
1163 bool choicesStringManual =
false;
1165 virtual std::string GetDefaultString(
const HelpParams&)
const {
return {}; }
1167 virtual std::vector<std::string> GetChoicesStrings(
const HelpParams&)
const {
return {}; }
1169 virtual std::string GetNameString(
const HelpParams&)
const {
return Name(); }
1171 void AddDescriptionPostfix(std::string &dest,
const bool isManual,
const std::string &manual,
bool isGenerated,
const std::string &generated,
const std::string &str)
const
1173 if (isManual && !manual.empty())
1178 else if (!isManual && isGenerated && !generated.empty())
1186 NamedBase(
const std::string &name_,
const std::string &help_,
Options options_ = {}) :
Base(help_, options_), name(name_) {}
1194 defaultStringManual =
true;
1195 defaultString = str;
1202 return defaultStringManual ? defaultString : GetDefaultString(params);
1210 choicesStringManual =
true;
1211 choicesStrings = array;
1218 return choicesStringManual ? choicesStrings : GetChoicesStrings(params);
1221 virtual std::vector<std::tuple<std::string, std::string, unsigned>> GetDescription(
const HelpParams ¶ms,
const unsigned indentLevel)
const override
1223 std::tuple<std::string, std::string, unsigned> description;
1224 std::get<0>(description) = GetNameString(params);
1225 std::get<1>(description) = help;
1226 std::get<2>(description) = indentLevel;
1228 AddDescriptionPostfix(std::get<1>(description), choicesStringManual, detail::Join(choicesStrings,
", "), params.
addChoices, detail::Join(GetChoicesStrings(params),
", "), params.
choiceString);
1229 AddDescriptionPostfix(std::get<1>(description), defaultStringManual, defaultString, params.
addDefault, GetDefaultString(params), params.
defaultString);
1231 return { std::move(description) };
1234 virtual std::string Name()
const
1242 template<
typename T>
1243 using vector = std::vector<T, std::allocator<T>>;
1245 template<
typename K,
typename T>
1246 using unordered_map = std::unordered_map<K, T, std::hash<K>,
1247 std::equal_to<K>, std::allocator<std::pair<const K, T> > >;
1249 template<
typename S,
typename T>
1252 template<
typename SS,
typename TT>
1253 static auto test(
int)
1254 ->
decltype( std::declval<SS&>() << std::declval<TT>(), std::true_type() );
1256 template<
typename,
typename>
1257 static auto test(...) -> std::false_type;
1260 using type =
decltype(test<S,T>(0));
1263 template <
typename T>
1264 using IsConvertableToString =
typename is_streamable<std::ostringstream, T>::type;
1266 template <
typename T>
1267 typename std::enable_if<IsConvertableToString<T>::value, std::string>::type
1268 ToString(
const T &value)
1270 std::ostringstream s;
1275 template <
typename T>
1276 typename std::enable_if<!IsConvertableToString<T>::value, std::string>::type
1282 template <
typename T>
1283 std::vector<std::string> MapKeysToStrings(
const T &map)
1285 std::vector<std::string> res;
1286 using K =
typename std::decay<
decltype(std::begin(map)->first)>::type;
1287 if (IsConvertableToString<K>::value)
1289 for (
const auto &p : map)
1291 res.push_back(detail::ToString(p.first));
1294 std::sort(res.begin(), res.end());
1307 virtual std::string GetNameString(
const HelpParams ¶ms)
const override
1312 const bool useValueNameOnce = flagStrings.size() == 1 ? false : params.
useValueNameOnce;
1313 for (
auto it = flagStrings.begin(); it != flagStrings.end(); ++it)
1316 if (it != flagStrings.begin())
1322 flags += flag.str();
1324 if (!postfix.empty() && (!useValueNameOnce || it + 1 == flagStrings.end()))
1337 FlagBase(
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
Options options_) :
NamedBase(name_, help_, options_), matcher(std::move(matcher_)) {}
1343 if (matcher.
Match(flag))
1347 std::ostringstream problem;
1348 problem <<
"Flag '" << flag.str() <<
"' was passed multiple times, but is only allowed to be passed once";
1350 error = Error::Extra;
1351 errorMsg = problem.str();
1362 virtual std::vector<FlagBase*> GetAllFlags()
override
1367 const Matcher &GetMatcher()
const
1372 virtual void Validate(
const std::string &shortPrefix,
const std::string &longPrefix)
const override
1374 if (!Matched() && IsRequired())
1376 std::ostringstream problem;
1377 problem <<
"Flag '" << matcher.
GetLongOrAny().str(shortPrefix, longPrefix) <<
"' is required";
1379 error = Error::Required;
1380 errorMsg = problem.str();
1387 virtual std::vector<std::string> GetProgramLine(
const HelpParams ¶ms)
const override
1397 if (!postfix.empty())
1406 virtual bool HasFlag()
const override
1413 virtual Error GetError()
const override
1416 if (nargs.min > nargs.max)
1418 return Error::Usage;
1421 const auto matcherError = matcher.GetError();
1422 if (matcherError != Error::None)
1424 return matcherError;
1441 virtual
void ParseValue(const std::vector<std::
string> &value) = 0;
1449 ValueFlagBase(
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const bool extraError_ =
false) :
FlagBase(name_, help_, std::move(matcher_), extraError_) {}
1462 std::vector<std::string> reply;
1466 template <
typename GroupClass>
1469 group_.AddCompletion(*
this);
1479 virtual void ParseValue(
const std::vector<std::string> &value_)
override
1481 syntax = value_.at(0);
1482 const std::string &raw = value_.at(1);
1483 bool failed =
false;
1485 const auto firstNonSpace = std::find_if_not(raw.begin(), raw.end(), [](
char c)
1487 return std::isspace(static_cast<unsigned char>(c)) != 0;
1493 if (firstNonSpace != raw.end() && (*firstNonSpace ==
'-' || *firstNonSpace ==
'+'))
1501 std::istringstream ss(raw);
1507 ss.imbue(std::locale::classic());
1530 error = Error::Parse;
1531 errorMsg =
"Argument 'completion' received invalid value type '" + raw +
"'";
1533 std::ostringstream problem;
1534 problem <<
"Argument 'completion' received invalid value type '" << raw <<
"'";
1547 return detail::Join(reply,
"\n");
1550 virtual void Reset() noexcept
override
1552 ValueFlagBase::Reset();
1576 virtual void ParseValue(
const std::string &value_) = 0;
1578 virtual void Reset()
noexcept override
1583 error = Error::None;
1590 return Ready() ? this :
nullptr;
1593 virtual bool HasPositional()
const override
1598 virtual std::vector<std::string> GetProgramLine(
const HelpParams ¶ms)
const override
1604 virtual void Validate(
const std::string &,
const std::string &)
const override
1606 if (IsRequired() && !Matched())
1608 std::ostringstream problem;
1609 problem <<
"Option '" << Name() <<
"' is required";
1611 error = Error::Required;
1612 errorMsg = problem.str();
1625 std::vector<Base*> children;
1626 std::function<bool(
const Group &)> validator;
1633 static bool Xor(
const Group &group)
1638 static bool AtLeastOne(
const Group &group)
1643 static bool AtMostOne(
const Group &group)
1648 static bool All(
const Group &group)
1653 static bool AllOrNone(
const Group &group)
1655 return (All(group) ||
None(group));
1658 static bool AllChildGroups(
const Group &group)
1660 return std::none_of(std::begin(group.
Children()), std::end(group.
Children()), [](
const Base* child) ->
bool {
1661 return child->IsGroup() && !child->Matched();
1665 static bool DontCare(
const Group &)
1670 static bool CareTooMuch(
const Group &)
1681 Group(
const std::string &help_ = std::string(),
const std::function<
bool(
const Group &)> &validator_ = Validators::DontCare,
Options options_ = {}) :
Base(help_, options_), validator(validator_) {}
1683 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_)
1693 children.emplace_back(&child);
1710 for (
Base *child: Children())
1712 if (
FlagBase *match = child->Match(flag))
1720 virtual std::vector<FlagBase*> GetAllFlags()
override
1722 std::vector<FlagBase*> res;
1723 for (
Base *child: Children())
1725 auto childRes = child->GetAllFlags();
1726 res.insert(res.end(), childRes.begin(), childRes.end());
1731 virtual void Validate(
const std::string &shortPrefix,
const std::string &longPrefix)
const override
1733 for (Base *child: Children())
1735 child->Validate(shortPrefix, longPrefix);
1745 for (
Base *child: Children())
1747 if (
auto next = child->GetNextPositional())
1761 return std::any_of(Children().begin(), Children().end(), [](
Base *child) {
return child->HasFlag(); });
1770 return std::any_of(Children().begin(), Children().end(), [](
Base *child) {
return child->HasPositional(); });
1779 return std::any_of(Children().begin(), Children().end(), [](
Base *child) {
return child->HasCommand(); });
1787 return static_cast<std::vector<Base *>::size_type
>(
1788 std::count_if(std::begin(Children()), std::end(Children()), [](
const Base *child){
return child->Matched();}));
1795 return validator(*
this);
1807 virtual std::vector<std::tuple<std::string, std::string, unsigned>>
GetDescription(
const HelpParams ¶ms,
const unsigned int indent)
const override
1809 std::vector<std::tuple<std::string, std::string, unsigned int>> descriptions;
1812 unsigned addindent = 0;
1815 descriptions.emplace_back(help,
"", indent);
1819 for (
Base *child: Children())
1821 if ((child->GetOptions() & Options::HiddenFromDescription) != Options::None)
1826 auto groupDescriptions = child->GetDescription(params, indent + addindent);
1827 descriptions.insert(
1828 std::end(descriptions),
1829 std::make_move_iterator(std::begin(groupDescriptions)),
1830 std::make_move_iterator(std::end(groupDescriptions)));
1832 return descriptions;
1839 std::vector <std::string> names;
1840 for (
Base *child: Children())
1842 if ((child->GetOptions() & Options::HiddenFromUsage) != Options::None)
1847 auto groupNames = child->GetProgramLine(params);
1850 std::make_move_iterator(std::begin(groupNames)),
1851 std::make_move_iterator(std::end(groupNames)));
1856 virtual std::vector<Command*> GetCommands()
override
1858 std::vector<Command*> res;
1859 for (
const auto &child : Children())
1861 auto subparsers = child->GetCommands();
1862 res.insert(std::end(res), std::begin(subparsers), std::end(subparsers));
1867 virtual bool IsGroup()
const override
1872 virtual void Reset() noexcept
override
1876 for (
auto &child: Children())
1881 error = Error::None;
1888 virtual Error GetError()
const override
1890 if (error != Error::None)
1895 auto it = std::find_if(Children().begin(), Children().end(), [](
const Base *child){
return child->GetError() != Error::None;});
1896 if (it == Children().end())
1901 return (*it)->GetError();
1906 virtual std::string GetErrorMsg()
const override
1908 if (error != Error::None)
1913 auto it = std::find_if(Children().begin(), Children().end(), [](
const Base *child){
return child->GetError() != Error::None;});
1914 if (it == Children().end())
1919 return (*it)->GetErrorMsg();
1957 std::vector<std::string>
args;
1958 std::vector<std::string> kicked;
1962 bool isParsed =
false;
1966 :
Group({}, Validators::AllChildGroups),
args(std::move(args_)), parser(&parser_), helpParams(helpParams_), command(command_)
2016 std::string description;
2018 std::string proglinePostfix;
2020 std::function<void(
Subparser&)> parserCoroutine;
2021 bool commandIsRequired =
true;
2022 Command *selectedCommand =
nullptr;
2024 mutable std::vector<std::tuple<std::string, std::string, unsigned>> subparserDescription;
2025 mutable std::vector<std::string> subparserProgramLine;
2026 mutable bool subparserHasFlag =
false;
2027 mutable bool subparserHasPositional =
false;
2028 mutable bool subparserHasCommand =
false;
2030 mutable Error subparserError = Error::None;
2039 RaiiSubparser(
ArgumentParser &parser_, std::vector<std::string> args_);
2044 command.subparser = oldSubparser;
2060 std::function<void(
Subparser&)> &GetCoroutine()
2062 return selectedCommand !=
nullptr ? selectedCommand->GetCoroutine() : parserCoroutine;
2068 while (res->selectedCommand !=
nullptr)
2070 res = res->selectedCommand;
2076 const Command &SelectedCommand()
const
2079 while (res->selectedCommand !=
nullptr)
2081 res = res->selectedCommand;
2087 void UpdateSubparserHelp(
const HelpParams ¶ms)
const
2089 if (parserCoroutine)
2091 RaiiSubparser coro(*
this, params);
2092#ifndef ARGS_NOEXCEPT
2095 parserCoroutine(coro.Parser());
2097 catch (args::SubparserError&)
2101 parserCoroutine(coro.Parser());
2107 Command(
Group &base_, std::string name_, std::string help_, std::function<
void(
Subparser&)> coroutine_ = {})
2108 : name(std::move(name_)), help(std::move(help_)), parserCoroutine(std::move(coroutine_))
2116 {
return proglinePostfix; }
2121 { this->proglinePostfix = proglinePostfix_; }
2126 {
return description; }
2131 { this->description = description_; }
2141 { this->epilog = epilog_; }
2158 { commandIsRequired = value; }
2160 virtual bool IsGroup()
const override
2164 {
return Base::Matched(); }
2166 operator bool() const noexcept
2167 {
return Matched(); }
2169 void Match() noexcept
2172 void SelectCommand(Command *c)
noexcept
2174 selectedCommand = c;
2184 if (selectedCommand !=
nullptr)
2186 if (
auto *res = selectedCommand->Match(flag))
2191 for (
auto *child: Children())
2193 if ((child->GetOptions() & Options::Global) != Options::None)
2195 if (
auto *res = child->Match(flag))
2205 if (subparser !=
nullptr)
2207 return subparser->
Match(flag);
2210 return Matched() ? Group::Match(flag) :
nullptr;
2213 virtual std::vector<FlagBase*> GetAllFlags()
override
2215 std::vector<FlagBase*> res;
2222 for (
auto *child: Children())
2224 if (selectedCommand ==
nullptr || (child->GetOptions() & Options::Global) != Options::None)
2226 auto childFlags = child->GetAllFlags();
2227 res.insert(res.end(), childFlags.begin(), childFlags.end());
2231 if (selectedCommand !=
nullptr)
2233 auto childFlags = selectedCommand->GetAllFlags();
2234 res.insert(res.end(), childFlags.begin(), childFlags.end());
2237 if (subparser !=
nullptr)
2239 auto childFlags = subparser->GetAllFlags();
2240 res.insert(res.end(), childFlags.begin(), childFlags.end());
2248 if (selectedCommand !=
nullptr)
2255 for (
auto *child: Children())
2257 if ((child->GetOptions() & Options::Global) != Options::None)
2259 if (
auto *res = child->GetNextPositional())
2269 if (subparser !=
nullptr)
2274 return Matched() ? Group::GetNextPositional() :
nullptr;
2279 return subparserHasFlag || Group::HasFlag();
2284 return subparserHasPositional || Group::HasPositional();
2292 std::vector<std::string> GetCommandProgramLine(
const HelpParams ¶ms)
const
2294 UpdateSubparserHelp(params);
2296 std::vector<std::string> res;
2303 auto group_res = Group::GetProgramLine(params);
2304 std::move(std::move(group_res).begin(), std::move(group_res).end(), std::back_inserter(res));
2306 res.insert(res.end(), subparserProgramLine.begin(), subparserProgramLine.end());
2308 if (!params.
proglineCommand.empty() && (Group::HasCommand() || subparserHasCommand))
2310 res.insert(res.begin(), commandIsRequired ? params.
proglineCommand :
"[" + params.proglineCommand +
"]");
2313 if (!Name().empty())
2315 res.insert(res.begin(), Name());
2318 if (!ProglinePostfix().empty())
2321 for (
auto c : ProglinePostfix())
2323 if (std::isspace(
static_cast<unsigned char>(c)))
2327 res.push_back(line);
2333 res.push_back(
"\n");
2344 res.push_back(line);
2358 return GetCommandProgramLine(params);
2361 virtual std::vector<Command*> GetCommands()
override
2363 if (selectedCommand !=
nullptr)
2365 return selectedCommand->GetCommands();
2370 return Group::GetCommands();
2376 virtual std::vector<std::tuple<std::string, std::string, unsigned>>
GetDescription(
const HelpParams ¶ms,
const unsigned int indent)
const override
2378 std::vector<std::tuple<std::string, std::string, unsigned>> descriptions;
2379 unsigned addindent = 0;
2381 UpdateSubparserHelp(params);
2387 std::ostringstream s;
2389 for (
const auto &progline: GetCommandProgramLine(params))
2403 descriptions.emplace_back(s.str(),
"", indent);
2407 descriptions.emplace_back(Name(), help, indent);
2412 return descriptions;
2420 descriptions.emplace_back(
"",
"", indent + addindent);
2421 descriptions.emplace_back(Description().empty() ?
Help() : Description(),
"", indent + addindent);
2422 descriptions.emplace_back(
"",
"", indent + addindent);
2425 for (
Base *child: Children())
2427 if ((child->GetOptions() & Options::HiddenFromDescription) != Options::None)
2432 auto groupDescriptions = child->GetDescription(params, indent + addindent);
2433 descriptions.insert(
2434 std::end(descriptions),
2435 std::make_move_iterator(std::begin(groupDescriptions)),
2436 std::make_move_iterator(std::end(groupDescriptions)));
2439 for (
auto childDescription: subparserDescription)
2441 std::get<2>(childDescription) += indent + addindent;
2442 descriptions.push_back(std::move(childDescription));
2447 descriptions.emplace_back(
"",
"", indent + addindent);
2448 if (!Epilog().empty())
2450 descriptions.emplace_back(Epilog(),
"", indent + addindent);
2451 descriptions.emplace_back(
"",
"", indent + addindent);
2455 return descriptions;
2458 virtual void Validate(
const std::string &shortprefix,
const std::string &longprefix)
const override
2465 auto onValidationError = [&]
2467 std::ostringstream problem;
2468 problem <<
"Group validation failed somewhere!";
2470 error = Error::Validation;
2471 errorMsg = problem.str();
2473 throw ValidationError(problem.str());
2477 for (Base *child: Children())
2479 if (child->IsGroup() && !child->Matched())
2481 onValidationError();
2484 child->Validate(shortprefix, longprefix);
2487 if (subparser !=
nullptr)
2489 subparser->Validate(shortprefix, longprefix);
2492 onValidationError();
2496 if (selectedCommand ==
nullptr && commandIsRequired && (Group::HasCommand() || subparserHasCommand))
2498 std::ostringstream problem;
2499 problem <<
"Command is required";
2501 error = Error::Validation;
2502 errorMsg = problem.str();
2504 throw ValidationError(problem.str());
2509 virtual void Reset() noexcept
override
2512 selectedCommand =
nullptr;
2513 subparserProgramLine.clear();
2514 subparserDescription.clear();
2515 subparserHasFlag =
false;
2516 subparserHasPositional =
false;
2517 subparserHasCommand =
false;
2519 subparserError = Error::None;
2525 virtual Error GetError()
const override
2532 if (error != Error::None)
2537 if (subparserError != Error::None)
2539 return subparserError;
2542 return Group::GetError();
2554 std::string longprefix;
2555 std::string shortprefix;
2557 std::string longseparator;
2559 std::string terminator;
2561 bool allowJoinedShortValue =
true;
2562 bool allowJoinedLongValue =
true;
2563 bool allowSeparateShortValue =
true;
2564 bool allowSeparateLongValue =
true;
2566 bool readCompletion =
false;
2570 enum class OptionType
2577 OptionType ParseOption(
const std::string &s,
bool allowEmpty =
false)
2579 if (s.find(longprefix) == 0 && (allowEmpty || s.length() > longprefix.length()))
2581 return OptionType::LongFlag;
2584 if (s.find(shortprefix) == 0 && (allowEmpty || s.length() > shortprefix.length()))
2586 return OptionType::ShortFlag;
2589 return OptionType::Positional;
2592 template <
typename It>
2593 bool Complete(
FlagBase &flag, It it, It end)
2596 if (!readCompletion || (++nextIt != end))
2601 const auto &chunk = *it;
2604 AddCompletionReply(chunk, choice);
2607#ifndef ARGS_NOEXCEPT
2623 template <
typename It>
2625 const bool allowSeparate,
const bool allowJoined,
2626 const bool hasJoined,
const std::string &joinedArg,
2627 const bool canDiscardJoined, std::vector<std::string> &values)
2633 if (hasJoined && !allowJoined && nargs.min != 0)
2635 return "Flag '" + arg +
"' was passed a joined argument, but these are disallowed";
2640 if (!canDiscardJoined || nargs.max != 0)
2642 values.push_back(joinedArg);
2644 }
else if (!allowSeparate)
2648 return "Flag '" + arg +
"' was passed a separate argument, but these are disallowed";
2655 while (valueIt != end &&
2656 values.size() < nargs.max &&
2657 (values.size() < nargs.min || ParseOption(*valueIt) == OptionType::Positional))
2659 if (Complete(flag, valueIt, end))
2674 values.push_back(*valueIt);
2680 if (values.size() > nargs.max)
2682 return "Passed an argument into a non-argument flag: " + arg;
2683 }
else if (values.size() < nargs.min)
2685 if (nargs.min == 1 && nargs.max == 1)
2687 return "Flag '" + arg +
"' requires an argument but received none";
2688 }
else if (nargs.min == 1)
2690 return "Flag '" + arg +
"' requires at least one argument but received none";
2691 }
else if (nargs.min != nargs.max)
2693 return "Flag '" + arg +
"' requires at least " + std::to_string(nargs.min) +
2694 " arguments but received " + std::to_string(values.size());
2697 return "Flag '" + arg +
"' requires " + std::to_string(nargs.min) +
2698 " arguments but received " + std::to_string(values.size());
2705 template <
typename It>
2706 bool ParseLong(It &it, It end)
2708 const auto &chunk = *it;
2709 const auto argchunk = chunk.substr(longprefix.size());
2711 const auto separator = longseparator.empty() ? argchunk.npos : argchunk.find(longseparator);
2713 const auto arg = (separator != argchunk.npos ?
2714 std::string(argchunk, 0, separator)
2716 const auto joined = (separator != argchunk.npos ?
2717 argchunk.substr(separator + longseparator.size())
2720 if (
auto flag = Match(arg))
2728 if (flag->GetError() != Error::None)
2733 std::vector<std::string> values;
2734 const std::string errorMessage = ParseArgsValues(*flag, arg, it, end, allowSeparateLongValue, allowJoinedLongValue,
2735 separator != argchunk.npos, joined,
false, values);
2736 if (!errorMessage.empty())
2738#ifndef ARGS_NOEXCEPT
2739 throw ParseError(errorMessage);
2741 error = Error::Parse;
2742 errorMsg = errorMessage;
2747 if (!readCompletion)
2756 if (flag->GetError() != Error::None)
2770 const std::string errorMessage(
"Flag could not be matched: " + arg);
2771#ifndef ARGS_NOEXCEPT
2772 throw ParseError(errorMessage);
2774 error = Error::Parse;
2775 errorMsg = errorMessage;
2783 template <
typename It>
2784 bool ParseShort(It &it, It end)
2786 const auto &chunk = *it;
2787 const auto argchunk = chunk.substr(shortprefix.size());
2788 for (
auto argit = std::begin(argchunk); argit != std::end(argchunk); ++argit)
2790 const auto arg = *argit;
2792 if (
auto flag = Match(arg))
2798 if (flag->GetError() != Error::None)
2803 const std::string value(argit + 1, std::end(argchunk));
2804 std::vector<std::string> values;
2805 const std::string errorMessage = ParseArgsValues(*flag, std::string(1, arg), it, end,
2806 allowSeparateShortValue, allowJoinedShortValue,
2807 !value.empty(), value, !value.empty(), values);
2809 if (!errorMessage.empty())
2811#ifndef ARGS_NOEXCEPT
2812 throw ParseError(errorMessage);
2814 error = Error::Parse;
2815 errorMsg = errorMessage;
2820 if (!readCompletion)
2827 if (flag->GetError() != Error::None)
2840 if (!values.empty())
2846 const std::string errorMessage(
"Flag could not be matched: '" + std::string(1, arg) +
"'");
2847#ifndef ARGS_NOEXCEPT
2848 throw ParseError(errorMessage);
2850 error = Error::Parse;
2851 errorMsg = errorMessage;
2860 bool AddCompletionReply(
const std::string &cur,
const std::string &choice)
2862 if (cur.empty() || choice.find(cur) == 0)
2864 if (completion->syntax ==
"bash" && ParseOption(choice) == OptionType::LongFlag && choice.find(longseparator) != std::string::npos)
2866 completion->reply.push_back(choice.substr(choice.find(longseparator) + longseparator.size()));
2869 completion->reply.push_back(choice);
2877 template <
typename It>
2878 bool Complete(It it, It end)
2881 if (!readCompletion || (++nextIt != end))
2886 const auto &chunk = *it;
2887 auto pos = GetNextPositional();
2888 std::vector<Command *> commands = GetCommands();
2889 const auto optionType = ParseOption(chunk,
true);
2891 if (!commands.empty() && (chunk.empty() || optionType == OptionType::Positional))
2893 for (
auto &cmd : commands)
2895 if ((cmd->GetOptions() & Options::HiddenFromCompletion) == Options::None)
2897 AddCompletionReply(chunk, cmd->Name());
2902 bool hasPositionalCompletion =
true;
2904 if (!commands.empty())
2906 for (
auto &cmd : commands)
2908 if ((cmd->GetOptions() & Options::HiddenFromCompletion) == Options::None)
2910 AddCompletionReply(chunk, cmd->Name());
2915 if ((pos->GetOptions() & Options::HiddenFromCompletion) == Options::None)
2917 auto choices = pos->HelpChoices(helpParams);
2918 hasPositionalCompletion = !choices.empty() || optionType != OptionType::Positional;
2919 for (
auto &choice : choices)
2921 AddCompletionReply(chunk, choice);
2926 if (hasPositionalCompletion)
2928 auto flags = GetAllFlags();
2929 for (
auto flag : flags)
2931 if ((flag->GetOptions() & Options::HiddenFromCompletion) != Options::None)
2936 auto &matcher = flag->GetMatcher();
2937 if (!AddCompletionReply(chunk, matcher.
GetShortOrAny().str(shortprefix, longprefix)))
2939 for (
auto &flagName : matcher.GetFlagStrings())
2941 if (AddCompletionReply(chunk, flagName.str(shortprefix, longprefix)))
2949 if (optionType == OptionType::LongFlag && allowJoinedLongValue)
2951 const auto separator = longseparator.empty() ? chunk.npos : chunk.find(longseparator);
2965 if (separator != chunk.npos && separator >= longprefix.size())
2967 std::string arg(chunk, 0, separator);
2968 if (
auto flag = this->Match(arg.substr(longprefix.size())))
2970 for (
auto &choice : flag->HelpChoices(helpParams))
2972 AddCompletionReply(chunk, arg + longseparator + choice);
2976 }
else if (optionType == OptionType::ShortFlag && allowJoinedShortValue)
2978 if (chunk.size() > shortprefix.size() + 1)
2980 auto arg = chunk.at(shortprefix.size());
2982 if (
auto flag = this->Match(arg))
2984 for (
auto &choice : flag->HelpChoices(helpParams))
2986 AddCompletionReply(chunk, shortprefix + arg + choice);
2994#ifndef ARGS_NOEXCEPT
2995 throw Completion(completion->
Get());
3001 template <
typename It>
3002 It Parse(It begin, It end)
3004 bool terminated =
false;
3005 std::vector<Command *> commands = GetCommands();
3008 for (
auto it = begin; it != end; ++it)
3010 if (Complete(it, end))
3015 const auto &chunk = *it;
3017 if (!terminated && chunk == terminator)
3020 }
else if (!terminated && ParseOption(chunk) == OptionType::LongFlag)
3022 if (!ParseLong(it, end))
3026 }
else if (!terminated && ParseOption(chunk) == OptionType::ShortFlag)
3028 if (!ParseShort(it, end))
3032 }
else if (!terminated && !commands.empty())
3034 auto itCommand = std::find_if(commands.begin(), commands.end(), [&chunk](Command *c) { return c->Name() == chunk; });
3035 if (itCommand == commands.end())
3037 const std::string errorMessage(
"Unknown command: " + chunk);
3038#ifndef ARGS_NOEXCEPT
3039 throw ParseError(errorMessage);
3041 error = Error::Parse;
3042 errorMsg = errorMessage;
3047 SelectCommand(*itCommand);
3049 if (
const auto &coroutine = GetCoroutine())
3052 RaiiSubparser coro(*
this, std::vector<std::string>(it, end));
3053 coroutine(coro.Parser());
3056 if (error != Error::None)
3061 if (!coro.Parser().IsParsed())
3063 error = Error::Usage;
3067 if (!coro.Parser().IsParsed())
3069 throw UsageError(
"Subparser::Parse was not called");
3076 commands = GetCommands();
3079 auto pos = GetNextPositional();
3082 pos->ParseValue(chunk);
3084 if (pos->GetError() != Error::None)
3096 const std::string errorMessage(
"Passed in argument, but no positional arguments were ready to receive it: " + chunk);
3097#ifndef ARGS_NOEXCEPT
3098 throw ParseError(errorMessage);
3100 error = Error::Parse;
3101 errorMsg = errorMessage;
3107 if (!readCompletion && completion !=
nullptr && completion->Matched())
3110 if (completion->GetError() != Error::None)
3112 error = completion->GetError();
3113 if (errorMsg.empty())
3115 errorMsg = completion->GetErrorMsg();
3120 error = Error::Completion;
3122 readCompletion =
true;
3124 const auto argsLeft =
static_cast<size_t>(std::distance(it, end));
3125 if (completion->cword == 0 || argsLeft <= 1 || completion->cword >= argsLeft)
3127#ifndef ARGS_NOEXCEPT
3128 throw Completion(
"");
3135 std::vector<std::string> curArgs;
3136 curArgs.reserve(completion->cword);
3138 for (
size_t idx = 0; idx < completion->cword && curIt != end; ++idx, ++curIt)
3140 curArgs.push_back(*curIt);
3143 if (completion->syntax ==
"bash")
3147 for (
size_t idx = 0; idx < curArgs.size(); )
3149 if (idx > 0 && curArgs[idx] ==
"=")
3151 size_t prev_idx = idx - 1;
3152 curArgs[prev_idx] +=
"=";
3153 size_t next_idx = 0;
3154 if (SafeAdd<size_t>(idx,
static_cast<size_t>(1), next_idx) && next_idx < curArgs.size())
3156 curArgs[prev_idx] += curArgs[next_idx];
3158 size_t erase_end = 0;
3159 if (SafeAdd<size_t>(next_idx,
static_cast<size_t>(1), erase_end))
3161 typedef std::vector<std::string>::difference_type diff_t;
3162 curArgs.erase(curArgs.begin() +
static_cast<diff_t
>(idx),
3163 curArgs.begin() +
static_cast<diff_t
>(erase_end));
3168 typedef std::vector<std::string>::difference_type diff_t;
3169 curArgs.erase(curArgs.begin() +
static_cast<diff_t
>(idx));
3179#ifndef ARGS_NOEXCEPT
3182 Parse(curArgs.begin(), curArgs.end());
3183 throw Completion(
"");
3185 catch (Completion &)
3191 throw Completion(
"");
3201 Parse(curArgs.begin(), curArgs.end());
3202 error = Error::Completion;
3209 Validate(shortprefix, longprefix);
3214 HelpParams helpParams;
3216 ArgumentParser(
const std::string &description_,
const std::string &epilog_ = std::string())
3218 Description(description_);
3224 SetArgumentSeparations(
true,
true,
true,
true);
3228 void AddCompletion(CompletionFlag &completionFlag)
3230 completion = &completionFlag;
3231 Add(completionFlag);
3237 {
return helpParams.programName; }
3240 void Prog(
const std::string &prog_)
3241 { this->helpParams.programName = prog_; }
3246 {
return longprefix; }
3251 this->longprefix = longprefix_;
3252 this->helpParams.longPrefix = longprefix_;
3258 {
return shortprefix; }
3263 this->shortprefix = shortprefix_;
3264 this->helpParams.shortPrefix = shortprefix_;
3270 {
return longseparator; }
3275 if (longseparator_.empty())
3277 const std::string errorMessage(
"longseparator can not be set to empty");
3279 error = Error::Usage;
3280 errorMsg = errorMessage;
3286 this->longseparator = longseparator_;
3287 this->helpParams.longSeparator = allowJoinedLongValue ? longseparator :
" ";
3294 {
return terminator; }
3298 { this->terminator = terminator_; }
3305 bool &allowJoinedShortValue_,
3306 bool &allowJoinedLongValue_,
3307 bool &allowSeparateShortValue_,
3308 bool &allowSeparateLongValue_)
const
3310 allowJoinedShortValue_ = this->allowJoinedShortValue;
3311 allowJoinedLongValue_ = this->allowJoinedLongValue;
3312 allowSeparateShortValue_ = this->allowSeparateShortValue;
3313 allowSeparateLongValue_ = this->allowSeparateLongValue;
3324 const bool allowJoinedShortValue_,
3325 const bool allowJoinedLongValue_,
3326 const bool allowSeparateShortValue_,
3327 const bool allowSeparateLongValue_)
3329 this->allowJoinedShortValue = allowJoinedShortValue_;
3330 this->allowJoinedLongValue = allowJoinedLongValue_;
3331 this->allowSeparateShortValue = allowSeparateShortValue_;
3332 this->allowSeparateLongValue = allowSeparateLongValue_;
3334 this->helpParams.longSeparator = allowJoinedLongValue ? longseparator :
" ";
3335 this->helpParams.shortSeparator = allowJoinedShortValue ?
"" :
" ";
3340 void Help(std::ostream &help_)
const
3342 auto &command = SelectedCommand();
3343 const auto &commandDescription = command.Description().empty() ? command.Help() : command.Description();
3344 const auto desc_indent = helpParams.descriptionindent;
3345 const auto effective_desc_width = (helpParams.width > desc_indent) ? helpParams.width - desc_indent : 0;
3346 const auto description_text =
Wrap(commandDescription, effective_desc_width);
3347 const auto epilog_text =
Wrap(command.Epilog(), effective_desc_width);
3349 const bool hasoptions = command.HasFlag();
3350 const bool hasarguments = command.HasPositional();
3352 std::vector<std::string> prognameline;
3353 prognameline.push_back(helpParams.usageString);
3354 prognameline.push_back(Prog());
3355 auto commandProgLine = command.GetProgramLine(helpParams);
3356 prognameline.insert(prognameline.end(), commandProgLine.begin(), commandProgLine.end());
3358 const auto prog_sum = helpParams.progindent + helpParams.progtailindent;
3359 const auto effective_prog_width = (helpParams.width > prog_sum) ? helpParams.width - prog_sum : 0;
3360 const auto effective_prog_first = (helpParams.width > helpParams.progindent) ? helpParams.width - helpParams.progindent : 0;
3361 const auto proglines =
Wrap(prognameline.begin(), prognameline.end(),
3362 effective_prog_width,
3363 effective_prog_first);
3364 auto progit = std::begin(proglines);
3365 if (progit != std::end(proglines))
3367 help_ << std::string(helpParams.progindent,
' ') << *progit <<
'\n';
3370 for (; progit != std::end(proglines); ++progit)
3372 help_ << std::string(helpParams.progtailindent,
' ') << *progit <<
'\n';
3377 if (!description_text.empty())
3379 for (
const auto &line: description_text)
3381 help_ << std::string(helpParams.descriptionindent,
' ') << line <<
"\n";
3386 bool lastDescriptionIsNewline =
false;
3388 if (!helpParams.optionsString.empty())
3390 help_ << std::string(helpParams.progindent,
' ') << helpParams.optionsString <<
"\n\n";
3393 for (
const auto &desc: command.GetDescription(helpParams, 0))
3395 lastDescriptionIsNewline = std::get<0>(desc).empty() && std::get<1>(desc).empty();
3396 const auto groupindent = std::get<2>(desc) * helpParams.eachgroupindent;
3397 const auto flag_sum = helpParams.flagindent + helpParams.helpindent + helpParams.gutter;
3398 const auto effective_flag_width = (helpParams.width > flag_sum) ? helpParams.width - flag_sum : 0;
3399 const auto flags =
Wrap(std::get<0>(desc), effective_flag_width);
3400 const auto info_sum = helpParams.helpindent + groupindent;
3401 const auto effective_info_width = (helpParams.width > info_sum) ? helpParams.width - info_sum : 0;
3402 const auto info =
Wrap(std::get<1>(desc), effective_info_width);
3404 std::string::size_type flagssize = 0;
3405 for (
auto flagsit = std::begin(flags); flagsit != std::end(flags); ++flagsit)
3407 if (flagsit != std::begin(flags))
3411 help_ << std::string(groupindent + helpParams.flagindent,
' ') << *flagsit;
3412 flagssize =
Glyphs(*flagsit);
3415 auto infoit = std::begin(info);
3417 if ((helpParams.flagindent + flagssize + helpParams.gutter) > helpParams.helpindent || infoit == std::end(info) || helpParams.addNewlineBeforeDescription)
3423 const auto indent_sum = helpParams.flagindent + flagssize;
3424 const auto effective_space = (helpParams.helpindent > indent_sum) ? helpParams.helpindent - indent_sum : 0;
3425 help_ << std::string(effective_space,
' ') << *infoit <<
'\n';
3428 for (; infoit != std::end(info); ++infoit)
3430 help_ << std::string(groupindent + helpParams.helpindent,
' ') << *infoit <<
'\n';
3433 if (hasoptions && hasarguments && helpParams.showTerminator)
3435 lastDescriptionIsNewline =
false;
3436 const auto effective_term_width = (helpParams.width > helpParams.flagindent) ? helpParams.width - helpParams.flagindent : 0;
3437 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))
3439 help_ << std::string(helpParams.flagindent,
' ') << item <<
'\n';
3443 if (!lastDescriptionIsNewline)
3448 for (
const auto &line: epilog_text)
3450 help_ << std::string(helpParams.descriptionindent,
' ') << line <<
"\n";
3460 std::ostringstream help_;
3465 virtual void Reset() noexcept
override
3469 readCompletion =
false;
3478 template <
typename It>
3485 if (error != Error::None)
3490 return Parse(begin, end);
3498 template <
typename T>
3501 return ParseArgs(std::begin(
args), std::end(
args));
3510 bool ParseCLI(
const int argc,
const char *
const * argv)
3512 if (argc > 0 && argv !=
nullptr && argv[0] !=
nullptr && Prog().empty())
3517 std::vector<std::string>
args;
3518 if (argc > 1 && argv !=
nullptr)
3520 args.assign(argv + 1, argv + argc);
3523 return ParseArgs(
args) == std::end(
args);
3526 template <
typename T>
3527 bool ParseCLI(
const T &
args)
3529 return ParseArgs(
args) == std::end(
args);
3533 inline Command::RaiiSubparser::RaiiSubparser(ArgumentParser &parser_, std::vector<std::string> args_)
3534 : command(parser_.SelectedCommand()), parser(std::move(args_), parser_, command, parser_.helpParams), oldSubparser(command.subparser)
3536 command.subparser = &parser;
3539 inline Command::RaiiSubparser::RaiiSubparser(
const Command &command_,
const HelpParams ¶ms_): command(command_), parser(command, params_), oldSubparser(command.subparser)
3541 command.subparser = &parser;
3549 command.subparserHasFlag =
HasFlag();
3553 if (parser ==
nullptr)
3555#ifndef ARGS_NOEXCEPT
3556 throw args::SubparserError();
3558 error = Error::Subparser;
3563 auto it = parser->Parse(
args.begin(),
args.end());
3565 kicked.assign(it,
args.end());
3568 command.subparserError = GetError();
3572 inline std::ostream &operator<<(std::ostream &os,
const ArgumentParser &parser)
3583 Flag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
Options options_):
FlagBase(name_, help_, std::move(matcher_), options_)
3606 virtual void ParseValue(
const std::vector<std::string>&)
override
3618 HelpFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
Options options_ = {}):
Flag(group_, name_, help_, std::move(matcher_), options_) {}
3625 error = Error::Help;
3645 const int startcount;
3649 CounterFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const int startcount_ = 0,
Options options_ = {}):
3650 Flag(group_, name_, help_, std::move(matcher_), options_), startcount(startcount_), count(startcount_) {}
3656 auto me = FlagBase::Match(arg);
3664 if (GetError() != Error::None)
3681 int &operator *() noexcept {
3685 const int &operator *() const noexcept {
3689 virtual void Reset() noexcept
override
3701 std::function<void(
const std::vector<std::string> &)> action;
3705 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_ = {}):
3706 FlagBase(name_, help_, std::move(matcher_), options_), action(std::move(action_)), nargs(nargs_)
3711 ActionFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_, std::function<
void(
const std::string &)> action_,
Options options_ = {}):
3712 FlagBase(name_, help_, std::move(matcher_), options_), nargs(1)
3715 action = [action_](
const std::vector<std::string> &a) {
return action_(a.at(0)); };
3718 ActionFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_, std::function<
void()> action_,
Options options_ = {}):
3719 FlagBase(name_, help_, std::move(matcher_), options_), nargs(0)
3722 action = [action_](
const std::vector<std::string> &) {
return action_(); };
3728 virtual void ParseValue(
const std::vector<std::string> &value)
override
3741 template <
typename T>
3742 static typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value,
bool>::type
3743 HasUnsignedNegativeSign(
const std::string &value)
3745 const auto firstNonSpace = std::find_if_not(value.begin(), value.end(), [](
char c)
3747 return std::isspace(static_cast<unsigned char>(c)) != 0;
3750 return firstNonSpace != value.end() && *firstNonSpace ==
'-';
3753 template <
typename T>
3754 static typename std::enable_if<!std::is_integral<T>::value || !std::is_unsigned<T>::value,
bool>::type
3755 HasUnsignedNegativeSign(
const std::string &)
3761 template <
typename T>
3762 typename std::enable_if<
3763 std::is_integral<T>::value &&
3764 !std::is_same<T, bool>::value &&
3765 !std::is_same<T, char>::value &&
3766 !std::is_same<T, signed char>::value &&
3767 !std::is_same<T, unsigned char>::value,
3769 ParseNumericValue(
const std::string &value, T &destination)
3771 if (HasUnsignedNegativeSign<T>(value))
3776 const char *begin = value.c_str();
3784 const char *
const stop = begin + value.size();
3790 const int saved_errno = errno;
3793 char *end =
nullptr;
3795 if (std::is_unsigned<T>::value)
3797 const unsigned long long parsed = std::strtoull(begin, &end, 0);
3800 errno = saved_errno;
3803 while (end != stop && std::isspace(
static_cast<unsigned char>(*end)))
3807 if (end != stop || errno == ERANGE ||
3808 parsed >
static_cast<unsigned long long>(std::numeric_limits<T>::max()))
3810 errno = saved_errno;
3814 destination =
static_cast<T
>(parsed);
3818 const long long parsed = std::strtoll(begin, &end, 0);
3821 errno = saved_errno;
3824 while (end != stop && std::isspace(
static_cast<unsigned char>(*end)))
3828 if (end != stop || errno == ERANGE ||
3829 parsed <
static_cast<long long>(std::numeric_limits<T>::min()) ||
3830 parsed >
static_cast<long long>(std::numeric_limits<T>::max()))
3832 errno = saved_errno;
3836 destination =
static_cast<T
>(parsed);
3839 errno = saved_errno;
3843 template <
typename T>
3844 typename std::enable_if<
3845 !std::is_integral<T>::value ||
3846 std::is_same<T, bool>::value ||
3847 std::is_same<T, char>::value ||
3848 std::is_same<T, signed char>::value ||
3849 std::is_same<T, unsigned char>::value,
3851 ParseNumericValue(
const std::string &value, T &destination)
3853 std::istringstream ss(value);
3859 ss.imbue(std::locale::classic());
3870 ss >> std::ws >> extra;
3877 ss.clear(ss.rdstate() & ~std::ios::failbit);
3884 template <
typename T>
3885 typename std::enable_if<!std::is_assignable<T, std::string>::value,
bool>::type
3886 operator ()(
const std::string &name,
const std::string &value, T &destination)
3888 const bool success = ParseNumericValue(value, destination);
3895 std::ostringstream problem;
3896 problem <<
"Argument '" << name <<
"' received invalid value type '" << value <<
"'";
3903 template <
typename T>
3904 typename std::enable_if<std::is_assignable<T, std::string>::value,
bool>::type
3905 operator()(
const std::string &,
const std::string &value, T &destination)
3907 destination = value;
3926 virtual std::string GetDefaultString(
const HelpParams&)
const override
3928 return detail::ToString(defaultValue);
3936 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_)
3941 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)
3945 ValueFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
Options options_):
ValueFlag(group_, name_, help_, std::move(matcher_), T(), options_)
3951 virtual void ParseValue(
const std::vector<std::string> &values_)
override
3953 const std::string &value_ = values_.at(0);
3956 if (!reader(name, value_, this->value))
3958 error = Error::Parse;
3961 reader(name, value_, this->value);
3965 virtual void Reset() noexcept
override
3967 ValueFlagBase::Reset();
3968 value = defaultValue;
4010 return defaultValue;
4021 typename Reader = ValueReader>
4029 ImplicitValueFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const T &implicitValue_,
const T &defaultValue_ = T(),
Options options_ = {})
4030 :
ValueFlag<T, Reader>(group_, name_, help_, std::move(matcher_), defaultValue_, options_), implicitValue(implicitValue_)
4035 :
ValueFlag<T, Reader>(group_, name_, help_, std::move(matcher_), defaultValue_, options_), implicitValue(defaultValue_)
4040 :
ValueFlag<T, Reader>(group_, name_, help_, std::move(matcher_), {}, options_), implicitValue()
4051 virtual void ParseValue(
const std::vector<std::string> &value_)
override
4055 this->value = implicitValue;
4071 template <
typename...>
class List = detail::vector,
4072 typename Reader = ValueReader>
4078 const List<T> defaultValues;
4084 typedef List<T> Container;
4085 typedef T value_type;
4086 typedef typename Container::allocator_type allocator_type;
4087 typedef typename Container::pointer pointer;
4088 typedef typename Container::const_pointer const_pointer;
4089 typedef T& reference;
4090 typedef const T& const_reference;
4091 typedef typename Container::size_type size_type;
4092 typedef typename Container::difference_type difference_type;
4093 typedef typename Container::iterator iterator;
4094 typedef typename Container::const_iterator const_iterator;
4095 typedef std::reverse_iterator<iterator> reverse_iterator;
4096 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
4099 :
FlagBase(name_, help_, std::move(matcher_), options_), values(defaultValues_), defaultValues(defaultValues_),nargs(nargs_)
4111 virtual void ParseValue(
const std::vector<std::string> &values_)
override
4115 for (
const std::string &value : values_)
4119 if (!reader(name, value, v))
4121 error = Error::Parse;
4125 reader(name, value, v);
4127 values.insert(std::end(values), v);
4131 List<T> &Get() noexcept
4164 iterator begin() noexcept
4166 return values.begin();
4169 const_iterator begin() const noexcept
4171 return values.begin();
4174 const_iterator cbegin() const noexcept
4176 return values.cbegin();
4179 iterator end() noexcept
4181 return values.end();
4184 const_iterator end() const noexcept
4186 return values.end();
4189 const_iterator cend() const noexcept
4191 return values.cend();
4194 virtual void Reset() noexcept
override
4197 values = defaultValues;
4200 virtual FlagBase *Match(
const EitherFlag &arg)
override
4202 const bool wasMatched = Matched();
4203 auto me = FlagBase::Match(arg);
4204 if (me && !wasMatched)
4220 template <
typename...>
class List = detail::vector,
4221 typename Reader = ValueReader>
4225 using Container = List<T>;
4227 const Container defaultValues;
4232 typedef T value_type;
4233 typedef typename Container::allocator_type allocator_type;
4234 typedef typename Container::pointer pointer;
4235 typedef typename Container::const_pointer const_pointer;
4236 typedef T& reference;
4237 typedef const T& const_reference;
4238 typedef typename Container::size_type size_type;
4239 typedef typename Container::difference_type difference_type;
4240 typedef typename Container::iterator iterator;
4241 typedef typename Container::const_iterator const_iterator;
4242 typedef std::reverse_iterator<iterator> reverse_iterator;
4243 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
4245 ValueFlagList(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const Container &defaultValues_ = Container(),
Options options_ = {}):
4246 ValueFlagBase(name_, help_, std::move(matcher_), options_), values(defaultValues_), defaultValues(defaultValues_)
4253 virtual void ParseValue(
const std::vector<std::string> &values_)
override
4255 const std::string &value_ = values_.at(0);
4259 if (!reader(name, value_, v))
4261 error = Error::Parse;
4265 reader(name, value_, v);
4267 values.insert(std::end(values), v);
4305 virtual std::string Name()
const override
4307 return name + std::string(
"...");
4310 virtual void Reset() noexcept
override
4312 ValueFlagBase::Reset();
4313 values = defaultValues;
4316 virtual FlagBase *Match(
const EitherFlag &arg)
override
4318 const bool wasMatched = Matched();
4319 auto me = FlagBase::Match(arg);
4320 if (me && !wasMatched)
4327 iterator begin() noexcept
4329 return values.begin();
4332 const_iterator begin() const noexcept
4334 return values.begin();
4337 const_iterator cbegin() const noexcept
4339 return values.cbegin();
4342 iterator end() noexcept
4344 return values.end();
4347 const_iterator end() const noexcept
4349 return values.end();
4352 const_iterator cend() const noexcept
4354 return values.cend();
4368 typename Reader = ValueReader,
4369 template <
typename...>
class Map = detail::unordered_map>
4373 const Map<K, T> map;
4375 const T defaultValue;
4379 virtual std::vector<std::string> GetChoicesStrings(
const HelpParams &)
const override
4381 return detail::MapKeysToStrings(map);
4386 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_)
4391 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)
4395 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_)
4401 virtual void ParseValue(
const std::vector<std::string> &values_)
override
4403 const std::string &value_ = values_.at(0);
4407 if (!reader(name, value_, key))
4409 error = Error::Parse;
4413 reader(name, value_, key);
4415 auto it = map.find(key);
4416 if (it == std::end(map))
4418 std::ostringstream problem;
4419 problem <<
"Could not find key '" << key <<
"' in map for arg '" << name <<
"'";
4422 errorMsg = problem.str();
4428 this->value = it->second;
4467 virtual void Reset() noexcept
override
4469 ValueFlagBase::Reset();
4470 value = defaultValue;
4485 template <
typename...>
class List = detail::vector,
4486 typename Reader = ValueReader,
4487 template <
typename...>
class Map = detail::unordered_map>
4491 using Container = List<T>;
4492 const Map<K, T> map;
4494 const Container defaultValues;
4498 virtual std::vector<std::string> GetChoicesStrings(
const HelpParams &)
const override
4500 return detail::MapKeysToStrings(map);
4504 typedef T value_type;
4505 typedef typename Container::allocator_type allocator_type;
4506 typedef typename Container::pointer pointer;
4507 typedef typename Container::const_pointer const_pointer;
4508 typedef T& reference;
4509 typedef const T& const_reference;
4510 typedef typename Container::size_type size_type;
4511 typedef typename Container::difference_type difference_type;
4512 typedef typename Container::iterator iterator;
4513 typedef typename Container::const_iterator const_iterator;
4514 typedef std::reverse_iterator<iterator> reverse_iterator;
4515 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
4517 MapFlagList(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const Map<K, T> &map_,
const Container &defaultValues_ = Container(),
Options options_ = {}):
4518 ValueFlagBase(name_, help_, std::move(matcher_), options_), map(map_), values(defaultValues_), defaultValues(defaultValues_)
4525 virtual void ParseValue(
const std::vector<std::string> &values_)
override
4527 const std::string &value_ = values_.at(0);
4531 if (!reader(name, value_, key))
4533 error = Error::Parse;
4537 reader(name, value_, key);
4539 auto it = map.find(key);
4540 if (it == std::end(map))
4542 std::ostringstream problem;
4543 problem <<
"Could not find key '" << key <<
"' in map for arg '" << name <<
"'";
4546 errorMsg = problem.str();
4552 this->values.emplace_back(it->second);
4591 virtual std::string Name()
const override
4593 return name + std::string(
"...");
4596 virtual void Reset() noexcept
override
4598 ValueFlagBase::Reset();
4599 values = defaultValues;
4602 virtual FlagBase *Match(
const EitherFlag &arg)
override
4604 const bool wasMatched = Matched();
4605 auto me = FlagBase::Match(arg);
4606 if (me && !wasMatched)
4613 iterator begin() noexcept
4615 return values.begin();
4618 const_iterator begin() const noexcept
4620 return values.begin();
4623 const_iterator cbegin() const noexcept
4625 return values.cbegin();
4628 iterator end() noexcept
4630 return values.end();
4633 const_iterator end() const noexcept
4635 return values.end();
4638 const_iterator cend() const noexcept
4640 return values.cend();
4651 typename Reader = ValueReader>
4656 const T defaultValue;
4659 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_)
4670 virtual void ParseValue(
const std::string &value_)
override
4673 if (!reader(name, value_, this->value))
4675 error = Error::Parse;
4679 reader(name, value_, this->value);
4720 virtual void Reset() noexcept
override
4722 PositionalBase::Reset();
4723 value = defaultValue;
4735 template <
typename...>
class List = detail::vector,
4736 typename Reader = ValueReader>
4740 using Container = List<T>;
4742 const Container defaultValues;
4746 typedef T value_type;
4747 typedef typename Container::allocator_type allocator_type;
4748 typedef typename Container::pointer pointer;
4749 typedef typename Container::const_pointer const_pointer;
4750 typedef T& reference;
4751 typedef const T& const_reference;
4752 typedef typename Container::size_type size_type;
4753 typedef typename Container::difference_type difference_type;
4754 typedef typename Container::iterator iterator;
4755 typedef typename Container::const_iterator const_iterator;
4756 typedef std::reverse_iterator<iterator> reverse_iterator;
4757 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
4759 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_)
4770 virtual void ParseValue(
const std::string &value_)
override
4774 if (!reader(name, value_, v))
4776 error = Error::Parse;
4780 reader(name, value_, v);
4782 values.insert(std::end(values), v);
4786 virtual std::string Name()
const override
4788 return name + std::string(
"...");
4826 virtual void Reset() noexcept
override
4828 PositionalBase::Reset();
4829 values = defaultValues;
4832 virtual PositionalBase *GetNextPositional()
override
4834 const bool wasMatched = Matched();
4835 auto me = PositionalBase::GetNextPositional();
4836 if (me && !wasMatched)
4843 iterator begin() noexcept
4845 return values.begin();
4848 const_iterator begin() const noexcept
4850 return values.begin();
4853 const_iterator cbegin() const noexcept
4855 return values.cbegin();
4858 iterator end() noexcept
4860 return values.end();
4863 const_iterator end() const noexcept
4865 return values.end();
4868 const_iterator cend() const noexcept
4870 return values.cend();
4884 typename Reader = ValueReader,
4885 template <
typename...>
class Map = detail::unordered_map>
4889 const Map<K, T> map;
4891 const T defaultValue;
4895 virtual std::vector<std::string> GetChoicesStrings(
const HelpParams &)
const override
4897 return detail::MapKeysToStrings(map);
4902 MapPositional(
Group &group_,
const std::string &name_,
const std::string &help_,
const Map<K, T> &map_,
const T &defaultValue_ = T(),
Options options_ = {}):
4903 PositionalBase(name_, help_, options_), map(map_), value(defaultValue_), defaultValue(defaultValue_)
4910 virtual void ParseValue(
const std::string &value_)
override
4914 if (!reader(name, value_, key))
4916 error = Error::Parse;
4920 reader(name, value_, key);
4922 auto it = map.find(key);
4923 if (it == std::end(map))
4925 std::ostringstream problem;
4926 problem <<
"Could not find key '" << key <<
"' in map for arg '" << name <<
"'";
4929 errorMsg = problem.str();
4935 this->value = it->second;
4976 virtual void Reset() noexcept
override
4978 PositionalBase::Reset();
4979 value = defaultValue;
4994 template <
typename...>
class List = detail::vector,
4995 typename Reader = ValueReader,
4996 template <
typename...>
class Map = detail::unordered_map>
5000 using Container = List<T>;
5002 const Map<K, T> map;
5004 const Container defaultValues;
5008 virtual std::vector<std::string> GetChoicesStrings(
const HelpParams &)
const override
5010 return detail::MapKeysToStrings(map);
5014 typedef T value_type;
5015 typedef typename Container::allocator_type allocator_type;
5016 typedef typename Container::pointer pointer;
5017 typedef typename Container::const_pointer const_pointer;
5018 typedef T& reference;
5019 typedef const T& const_reference;
5020 typedef typename Container::size_type size_type;
5021 typedef typename Container::difference_type difference_type;
5022 typedef typename Container::iterator iterator;
5023 typedef typename Container::const_iterator const_iterator;
5024 typedef std::reverse_iterator<iterator> reverse_iterator;
5025 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
5027 MapPositionalList(
Group &group_,
const std::string &name_,
const std::string &help_,
const Map<K, T> &map_,
const Container &defaultValues_ = Container(),
Options options_ = {}):
5028 PositionalBase(name_, help_, options_), map(map_), values(defaultValues_), defaultValues(defaultValues_)
5035 virtual void ParseValue(
const std::string &value_)
override
5039 if (!reader(name, value_, key))
5041 error = Error::Parse;
5045 reader(name, value_, key);
5047 auto it = map.find(key);
5048 if (it == std::end(map))
5050 std::ostringstream problem;
5051 problem <<
"Could not find key '" << key <<
"' in map for arg '" << name <<
"'";
5054 errorMsg = problem.str();
5060 this->values.emplace_back(it->second);
5100 virtual std::string Name()
const override
5102 return name + std::string(
"...");
5105 virtual void Reset() noexcept
override
5107 PositionalBase::Reset();
5108 values = defaultValues;
5111 virtual PositionalBase *GetNextPositional()
override
5113 const bool wasMatched = Matched();
5114 auto me = PositionalBase::GetNextPositional();
5115 if (me && !wasMatched)
5122 iterator begin() noexcept
5124 return values.begin();
5127 const_iterator begin() const noexcept
5129 return values.begin();
5132 const_iterator cbegin() const noexcept
5134 return values.cbegin();
5137 iterator end() noexcept
5139 return values.end();
5142 const_iterator end() const noexcept
5144 return values.end();
5147 const_iterator cend() const noexcept
5149 return values.cend();
5154#pragma pop_macro("min")
5155#pragma pop_macro("max")
A flag class that calls a function when it's matched.
Definition args.hxx:3699
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:3725
virtual void ParseValue(const std::vector< std::string > &value) override
Parse values of this option.
Definition args.hxx:3728
The main user facing command line argument parser class.
Definition args.hxx:2550
const std::string & ShortPrefix() const
The prefix for short flags.
Definition args.hxx:3257
void SetArgumentSeparations(const bool allowJoinedShortValue_, const bool allowJoinedLongValue_, const bool allowSeparateShortValue_, const bool allowSeparateLongValue_)
Change allowed option separation.
Definition args.hxx:3323
void Prog(const std::string &prog_)
The program name for help generation.
Definition args.hxx:3240
It ParseArgs(It begin, It end)
Parse all arguments.
Definition args.hxx:3479
const std::string & Prog() const
The program name for help generation.
Definition args.hxx:3236
void LongPrefix(const std::string &longprefix_)
The prefix for long flags.
Definition args.hxx:3249
void LongSeparator(const std::string &longseparator_)
The separator for long flags.
Definition args.hxx:3273
void Help(std::ostream &help_) const
Pass the help menu into an ostream.
Definition args.hxx:3340
const std::string & LongPrefix() const
The prefix for long flags.
Definition args.hxx:3245
const std::string & LongSeparator() const
The separator for long flags.
Definition args.hxx:3269
bool ParseCLI(const int argc, const char *const *argv)
Convenience function to parse the CLI from argc and argv.
Definition args.hxx:3510
const std::string & Terminator() const
The terminator that forcibly separates flags from positionals.
Definition args.hxx:3293
auto ParseArgs(const T &args) -> decltype(std::begin(args))
Parse all arguments.
Definition args.hxx:3499
void Terminator(const std::string &terminator_)
The terminator that forcibly separates flags from positionals.
Definition args.hxx:3297
void GetArgumentSeparations(bool &allowJoinedShortValue_, bool &allowJoinedLongValue_, bool &allowSeparateShortValue_, bool &allowSeparateLongValue_) const
Get the current argument separation parameters.
Definition args.hxx:3304
std::string Help() const
Generate a help menu as a string.
Definition args.hxx:3458
void ShortPrefix(const std::string &shortprefix_)
The prefix for short flags.
Definition args.hxx:3261
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:2624
Base class for all match types.
Definition args.hxx:1016
void KickOut(bool kickout_) noexcept
Sets a kick-out value for building subparsers.
Definition args.hxx:1111
bool KickOut() const noexcept
Gets the kick-out value for building subparsers.
Definition args.hxx:1124
Main class for building subparsers.
Definition args.hxx:2010
const std::string & Name() const
The name of command.
Definition args.hxx:2145
virtual PositionalBase * GetNextPositional() override
Get the next ready positional, or nullptr if there is none.
Definition args.hxx:2246
const std::string & ProglinePostfix() const
The description that appears on the prog line after options.
Definition args.hxx:2115
void Description(const std::string &description_)
The description that appears above options.
Definition args.hxx:2130
virtual bool HasPositional() const override
Get whether this has any PositionalBase children.
Definition args.hxx:2282
const std::string & Description() const
The description that appears above options.
Definition args.hxx:2125
const std::string & Help() const
The description of command.
Definition args.hxx:2150
void Epilog(const std::string &epilog_)
The description that appears below options.
Definition args.hxx:2140
void ProglinePostfix(const std::string &proglinePostfix_)
The description that appears on the prog line after options.
Definition args.hxx:2120
virtual FlagBase * Match(const EitherFlag &flag) override
Return the first FlagBase that matches flag, or nullptr.
Definition args.hxx:2182
virtual bool HasCommand() const override
Get whether this has any Command children.
Definition args.hxx:2287
virtual std::vector< std::string > GetProgramLine(const HelpParams ¶ms) const override
Get the names of positional parameters.
Definition args.hxx:2351
virtual bool HasFlag() const override
Get whether this has any FlagBase children.
Definition args.hxx:2277
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:2376
const std::string & Epilog() const
The description that appears below options.
Definition args.hxx:2135
virtual bool Matched() const noexcept override
Whether or not this group matches validation.
Definition args.hxx:2163
void RequireCommand(bool value)
If value is true, parser will fail if no command was parsed.
Definition args.hxx:2157
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:1474
std::string Get() noexcept
Get the completion reply.
Definition args.hxx:1545
virtual void ParseValue(const std::vector< std::string > &value_) override
Parse values of this option.
Definition args.hxx:1479
An exception that contains autocompletion reply.
Definition args.hxx:565
A flag class that simply counts the number of times it's matched.
Definition args.hxx:3643
int & Get() noexcept
Get the count.
Definition args.hxx:3676
Base error class.
Definition args.hxx:484
Base class for all flag options.
Definition args.hxx:1303
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:3581
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:3601
virtual void ParseValue(const std::vector< std::string > &) override
Parse values of this option.
Definition args.hxx:3606
bool Get() const
Get whether this was matched.
Definition args.hxx:3596
Class for using global options in ArgumentParser.
Definition args.hxx:1929
Class for all kinds of validating groups, including ArgumentParser.
Definition args.hxx:1623
virtual bool HasCommand() const override
Get whether this has any Command children.
Definition args.hxx:1777
std::vector< Base * >::size_type MatchedChildren() const
Count the number of matched children this group has.
Definition args.hxx:1784
virtual bool HasPositional() const override
Get whether this has any PositionalBase children.
Definition args.hxx:1768
virtual std::vector< std::string > GetProgramLine(const HelpParams ¶ms) const override
Get the names of positional parameters.
Definition args.hxx:1837
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:1683
virtual bool HasFlag() const override
Get whether this has any FlagBase children.
Definition args.hxx:1759
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:1681
virtual bool Matched() const noexcept override
Whether or not this group matches validation.
Definition args.hxx:1793
virtual FlagBase * Match(const EitherFlag &flag) override
Return the first FlagBase that matches flag, or nullptr.
Definition args.hxx:1708
bool Get() const
Get validation.
Definition args.hxx:1800
const std::vector< Base * > & Children() const
Get all this group's children.
Definition args.hxx:1698
void Add(Base &child)
Append a child to this Group.
Definition args.hxx:1691
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:1807
virtual PositionalBase * GetNextPositional() override
Get the next ready positional, or nullptr if there is none.
Definition args.hxx:1743
Help flag class.
Definition args.hxx:3616
bool Get() const noexcept
Get whether this was matched.
Definition args.hxx:3634
virtual void ParseValue(const std::vector< std::string > &)
Parse values of this option.
Definition args.hxx:3622
An exception that indicates that the user has requested help.
Definition args.hxx:547
An optional argument-accepting flag class.
Definition args.hxx:4023
virtual void ParseValue(const std::vector< std::string > &value_) override
Parse values of this option.
Definition args.hxx:4051
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:4046
Errors in map lookups.
Definition args.hxx:529
A mapping value flag list class.
Definition args.hxx:4489
Container * operator->() noexcept
Get the values.
Definition args.hxx:4579
Container & Get() noexcept
Get the value.
Definition args.hxx:4558
virtual void ParseValue(const std::vector< std::string > &values_) override
Parse values of this option.
Definition args.hxx:4525
Container & operator*() noexcept
Get the value.
Definition args.hxx:4565
A mapping value flag class.
Definition args.hxx:4371
virtual void ParseValue(const std::vector< std::string > &values_) override
Parse values of this option.
Definition args.hxx:4401
T & Get() noexcept
Get the value.
Definition args.hxx:4434
T * operator->() noexcept
Get the value.
Definition args.hxx:4455
T & operator*() noexcept
Get the value.
Definition args.hxx:4441
A positional argument mapping list class.
Definition args.hxx:4998
Container & operator*() noexcept
Get the value.
Definition args.hxx:5074
Container * operator->() noexcept
Get the values.
Definition args.hxx:5088
Container & Get() noexcept
Get the value.
Definition args.hxx:5067
A positional argument mapping class.
Definition args.hxx:4887
T * operator->() noexcept
Get the value.
Definition args.hxx:4964
T & Get() noexcept
Get the value.
Definition args.hxx:4943
T & operator*() noexcept
Get the value.
Definition args.hxx:4950
A class of "matchers", specifying short and flags that can possibly be matched.
Definition args.hxx:633
EitherFlag GetShortOrAny() const
(INTERNAL) Get short flag if it exists or any long flag
Definition args.hxx:751
std::vector< EitherFlag > GetFlagStrings() const
(INTERNAL) Get all flag strings as a vector, with the prefixes embedded
Definition args.hxx:716
Matcher(Short &&shortIn, Long &&longIn)
Specify short and long flags separately as iterables.
Definition args.hxx:669
Matcher(ShortIt shortFlagsStart, ShortIt shortFlagsEnd, LongIt longFlagsStart, LongIt longFlagsEnd)
Specify short and long flags separately as iterators.
Definition args.hxx:644
bool Match(const std::string &flag) const
(INTERNAL) Check if there is a match of a long flag
Definition args.hxx:702
EitherFlag GetLongOrAny() const
(INTERNAL) Get long flag if it exists or any short flag
Definition args.hxx:733
bool Match(const char flag) const
(INTERNAL) Check if there is a match of a short flag
Definition args.hxx:695
bool Match(const EitherFlag &flag) const
(INTERNAL) Check if there is a match of a flag
Definition args.hxx:709
Matcher(std::initializer_list< EitherFlag > in)
Specify a mixed single initializer-list of both short and long flags.
Definition args.hxx:685
Base class for all match types that have a name.
Definition args.hxx:1156
void HelpDefault(const std::string &str)
Sets default value string that will be added to argument description.
Definition args.hxx:1192
void HelpChoices(const std::vector< std::string > &array)
Sets choices strings that will be added to argument description.
Definition args.hxx:1208
std::string HelpDefault(const HelpParams ¶ms) const
Gets default value string that will be added to argument description.
Definition args.hxx:1200
std::vector< std::string > HelpChoices(const HelpParams ¶ms) const
Gets choices strings that will be added to argument description.
Definition args.hxx:1216
A variadic arguments accepting flag class.
Definition args.hxx:4074
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:4106
virtual void ParseValue(const std::vector< std::string > &values_) override
Parse values of this option.
Definition args.hxx:4111
List< T > * operator->() noexcept
Get the values.
Definition args.hxx:4152
List< T > & operator*() noexcept
Get the value.
Definition args.hxx:4138
Errors that occur during regular parsing.
Definition args.hxx:502
Base class for positional options.
Definition args.hxx:1563
A positional argument class that pushes the found values into a list.
Definition args.hxx:4738
Container & operator*() noexcept
Get the value.
Definition args.hxx:4800
Container & Get() noexcept
Get the values.
Definition args.hxx:4793
Container * operator->() noexcept
Get the values.
Definition args.hxx:4814
A positional argument class.
Definition args.hxx:4653
T & operator*() noexcept
Get the value.
Definition args.hxx:4694
T & Get() noexcept
Get the value.
Definition args.hxx:4687
T * operator->() noexcept
Get the value.
Definition args.hxx:4708
Errors that when a required flag is omitted.
Definition args.hxx:520
Utility class for building subparsers with coroutines/callbacks.
Definition args.hxx:1955
void Parse()
Continue parsing arguments for new command.
Definition args.hxx:3544
const std::vector< std::string > & KickedOut() const noexcept
Returns a vector of kicked out arguments.
Definition args.hxx:1999
bool IsParsed() const
(INTERNAL) Determines whether Parse was called or not.
Definition args.hxx:1986
Errors that occur during usage.
Definition args.hxx:493
Errors that are detected from group validation after parsing finishes.
Definition args.hxx:511
Base class for value-accepting flag options.
Definition args.hxx:1447
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:1453
An argument-accepting flag class that pushes the found values into a list.
Definition args.hxx:4223
Container * operator->() noexcept
Get the values.
Definition args.hxx:4293
Container & Get() noexcept
Get the values.
Definition args.hxx:4272
Container & operator*() noexcept
Get the value.
Definition args.hxx:4279
virtual void ParseValue(const std::vector< std::string > &values_) override
Parse values of this option.
Definition args.hxx:4253
An argument-accepting flag class.
Definition args.hxx:3921
T & operator*() noexcept
Get the value.
Definition args.hxx:3980
T * operator->() noexcept
Get the value.
Definition args.hxx:3994
T & Get() noexcept
Get the value.
Definition args.hxx:3973
const T & GetDefault() noexcept
Get the default value.
Definition args.hxx:4008
virtual void ParseValue(const std::vector< std::string > &values_) override
Parse values of this option.
Definition args.hxx:3951
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:771
@ 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:575
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:600
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:585
Default validators.
Definition args.hxx:1632
A simple structure of parameters for easy user-modifyable help menus.
Definition args.hxx:827
std::string programName
The program name for help generation.
Definition args.hxx:884
bool showCommandFullHelp
Show command's descriptions and epilog.
Definition args.hxx:892
bool proglineShowFlags
Show flags in program line.
Definition args.hxx:928
std::string usageString
Program line prefix.
Definition args.hxx:936
unsigned int width
The width of the help menu.
Definition args.hxx:830
std::string proglineNonrequiredClose
The postfix for progline non-required argument.
Definition args.hxx:924
unsigned int helpindent
The indent of the flag descriptions.
Definition args.hxx:845
bool proglinePreferShortFlags
Use short flags in program lines when possible.
Definition args.hxx:932
std::string proglineCommand
The prefix for progline when command has any subcommands.
Definition args.hxx:900
std::string proglineOptions
The postfix for progline when showProglineOptions is true and command has any flags.
Definition args.hxx:896
std::string longSeparator
The separator for long flags.
Definition args.hxx:880
bool showValueName
Show value name.
Definition args.hxx:948
bool showTerminator
Show the terminator when both options and positional parameters are present.
Definition args.hxx:856
std::string proglineValueOpen
The prefix for progline value.
Definition args.hxx:904
std::string valueOpen
The prefix for option value.
Definition args.hxx:956
unsigned int progtailindent
The indent of the program trailing lines for long parameters.
Definition args.hxx:836
std::string proglineNonrequiredOpen
The prefix for progline non-required argument.
Definition args.hxx:920
unsigned int descriptionindent
The indent of the description and epilogs.
Definition args.hxx:839
bool showCommandChildren
Show command's flags.
Definition args.hxx:888
bool showProglineOptions
Show the {OPTIONS} on the prog line when this is true.
Definition args.hxx:860
std::string valueClose
The postfix for option value.
Definition args.hxx:960
std::string longPrefix
The prefix for long flags.
Definition args.hxx:872
std::string proglineRequiredClose
The postfix for progline required argument.
Definition args.hxx:916
unsigned int flagindent
The indent of the flags.
Definition args.hxx:842
std::string optionsString
String shown in help before flags descriptions.
Definition args.hxx:940
bool addNewlineBeforeDescription
Add newline before flag description.
Definition args.hxx:952
std::string shortPrefix
The prefix for short flags.
Definition args.hxx:868
bool addDefault
Add default values to argument description.
Definition args.hxx:972
unsigned int gutter
The minimum gutter between each flag and its help.
Definition args.hxx:852
bool showProglinePositionals
Show the positionals on the prog line when this is true.
Definition args.hxx:864
std::string shortSeparator
The separator for short flags.
Definition args.hxx:876
std::string proglineValueClose
The postfix for progline value.
Definition args.hxx:908
bool useValueNameOnce
Display value name after all the long and short flags.
Definition args.hxx:944
std::string defaultString
The prefix for default values.
Definition args.hxx:976
std::string proglineRequiredOpen
The prefix for progline required argument.
Definition args.hxx:912
unsigned int eachgroupindent
The additional indent each group adds.
Definition args.hxx:848
unsigned int progindent
The indent of the program line.
Definition args.hxx:833
bool addChoices
Add choices to argument description.
Definition args.hxx:964
std::string choiceString
The prefix for choices.
Definition args.hxx:968
A number of arguments which can be consumed by an option.
Definition args.hxx:984
A default Reader class for argument classes.
Definition args.hxx:3739