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 if (b > std::numeric_limits<T>::max() - a)
119 if ((b > 0 && a > std::numeric_limits<T>::max() - b) ||
120 (b < 0 && a < std::numeric_limits<T>::min() - b))
135 static_assert(std::is_integral<T>::value,
"SafeMultiply requires integral types.");
137 if (a == 0 || b == 0)
143 if (std::is_unsigned<T>::value)
145 if (b > std::numeric_limits<T>::max() / a)
152 if (a == -1 && b == std::numeric_limits<T>::min())
156 if (b == -1 && a == std::numeric_limits<T>::min())
161 if ((a > 0 && b > 0 && a > std::numeric_limits<T>::max() / b) ||
162 (a > 0 && b < 0 && b < std::numeric_limits<T>::min() / a) ||
163 (a < 0 && b > 0 && a < std::numeric_limits<T>::min() / b) ||
164 (a < 0 && b < 0 && a < std::numeric_limits<T>::max() / b))
185 template <
typename It>
186 inline std::vector<std::string>
Wrap(It begin,
188 const std::string::size_type width,
189 std::string::size_type firstlinewidth = 0,
190 std::string::size_type firstlineindent = 0)
192 std::vector<std::string> output;
193 std::string line(firstlineindent,
' ');
196 if (firstlinewidth == 0)
198 firstlinewidth = width;
201 auto currentwidth = firstlinewidth;
203 for (
auto it = begin; it != end; ++it)
214 output.push_back(line);
217 currentwidth = width;
223 auto itemsize =
Glyphs(*it);
226 bool needsWrap =
false;
227 if (itemsize >= currentwidth)
233 size_t remainingWidth = (currentwidth > itemsize) ? (currentwidth - itemsize) : 0;
234 size_t nextLength = 0;
235 if (!SafeAdd<std::string::size_type>(line.length(),
static_cast<std::string::size_type
>(1), nextLength) || nextLength > remainingWidth)
245 output.push_back(line);
248 currentwidth = width;
266 output.push_back(line);
274 template <
typename T>
275 std::string Join(
const T& array,
const std::string &delimiter)
278 for (
auto &element : array)
301 inline std::vector<std::string>
Wrap(
const std::string &in,
const std::string::size_type width, std::string::size_type firstlinewidth = 0)
304 const auto newlineloc = in.find(
'\n');
305 if (newlineloc != in.npos)
307 auto first =
Wrap(std::string(in, 0, newlineloc), width);
308 auto second =
Wrap(std::string(in, newlineloc + 1), width);
311 std::make_move_iterator(std::begin(second)),
312 std::make_move_iterator(std::end(second)));
316 std::istringstream stream(in);
317 std::string::size_type indent = 0;
321 if (!std::isspace(
static_cast<unsigned char>(c)))
328 return Wrap(std::istream_iterator<std::string>(stream), std::istream_iterator<std::string>(),
329 width, firstlinewidth, indent);
350 class Error :
public std::runtime_error
353 Error(
const std::string &problem) : std::runtime_error(problem) {}
416 Help(
const std::string &flag) :
Error(flag) {}
422 class SubparserError :
public Error
425 SubparserError() :
Error(
"") {}
426 virtual ~SubparserError() {}
444 const char shortFlag;
445 const std::string longFlag;
446 EitherFlag(
const std::string &flag) : isShort(
false), shortFlag(), longFlag(flag) {}
447 EitherFlag(
const char *flag) : isShort(
false), shortFlag(), longFlag(flag) {}
448 EitherFlag(
const char flag) : isShort(
true), shortFlag(flag), longFlag() {}
452 static std::unordered_set<std::string>
GetLong(std::initializer_list<EitherFlag> flags)
454 std::unordered_set<std::string> longFlags;
459 longFlags.insert(flag.longFlag);
467 static std::unordered_set<char>
GetShort(std::initializer_list<EitherFlag> flags)
469 std::unordered_set<char> shortFlags;
474 shortFlags.insert(flag.shortFlag);
480 std::string str()
const
482 return isShort ? std::string(1, shortFlag) : longFlag;
485 std::string str(
const std::string &shortPrefix,
const std::string &longPrefix)
const
487 return isShort ? shortPrefix + std::string(1, shortFlag) : longPrefix + longFlag;
502 const std::unordered_set<char> shortFlags;
503 const std::unordered_set<std::string> longFlags;
510 template <
typename ShortIt,
typename LongIt>
511 Matcher(ShortIt shortFlagsStart, ShortIt shortFlagsEnd, LongIt longFlagsStart, LongIt longFlagsEnd) :
512 shortFlags(shortFlagsStart, shortFlagsEnd),
513 longFlags(longFlagsStart, longFlagsEnd)
515 if (shortFlags.empty() && longFlags.empty())
525 Error GetError() const noexcept
527 return shortFlags.empty() && longFlags.empty() ? Error::Usage : Error::None;
535 template <
typename Short,
typename Long>
537 Matcher(std::begin(shortIn), std::end(shortIn), std::begin(longIn), std::end(longIn))
552 Matcher(std::initializer_list<EitherFlag> in) :
555 Matcher(
Matcher &&other) noexcept : shortFlags(std::move(other.shortFlags)), longFlags(std::move(other.longFlags))
564 return shortFlags.find(flag) != shortFlags.end();
569 bool Match(
const std::string &flag)
const
571 return longFlags.find(flag) != longFlags.end();
578 return flag.isShort ?
Match(flag.shortFlag) :
Match(flag.longFlag);
585 std::vector<EitherFlag> flagStrings;
586 flagStrings.reserve(shortFlags.size() + longFlags.size());
587 for (
const char flag: shortFlags)
589 flagStrings.emplace_back(flag);
591 for (
const std::string &flag: longFlags)
593 flagStrings.emplace_back(flag);
602 if (!longFlags.empty())
604 return *longFlags.begin();
607 if (!shortFlags.empty())
609 return *shortFlags.begin();
620 if (!shortFlags.empty())
622 return *shortFlags.begin();
625 if (!longFlags.empty())
627 return *longFlags.begin();
678 return static_cast<Options>(
static_cast<int>(lhs) |
static_cast<int>(rhs));
683 return static_cast<Options>(
static_cast<int>(lhs) &
static_cast<int>(rhs));
687 class PositionalBase;
689 class ArgumentParser;
855 Nargs(
size_t min_,
size_t max_) : min{min_}, max{max_}
865 Nargs(
size_t num_) : min{num_}, max{num_}
869 friend bool operator == (
const Nargs &lhs,
const Nargs &rhs)
871 return lhs.min == rhs.min && lhs.max == rhs.max;
874 friend bool operator != (
const Nargs &lhs,
const Nargs &rhs)
876 return !(lhs == rhs);
888 bool matched =
false;
889 const std::string help;
892 mutable Error error = Error::None;
893 mutable std::string errorMsg;
897 Base(
const std::string &help_,
Options options_ = {}) : options(options_), help(help_) {}
900 Options GetOptions()
const noexcept
905 bool IsRequired()
const noexcept
910 virtual bool Matched()
const noexcept
915 virtual void Validate(
const std::string &,
const std::string &)
const
919 operator bool()
const noexcept
924 virtual std::vector<std::tuple<std::string, std::string, unsigned>> GetDescription(
const HelpParams &,
const unsigned indentLevel)
const
926 std::tuple<std::string, std::string, unsigned> description;
927 std::get<1>(description) = help;
928 std::get<2>(description) = indentLevel;
929 return { std::move(description) };
932 virtual std::vector<Command*> GetCommands()
937 virtual bool IsGroup()
const
952 virtual std::vector<FlagBase*> GetAllFlags()
957 virtual bool HasFlag()
const
962 virtual bool HasPositional()
const
967 virtual bool HasCommand()
const
972 virtual std::vector<std::string> GetProgramLine(
const HelpParams &)
const
996 virtual void Reset() noexcept
1000 error = Error::None;
1007 virtual Error GetError()
const
1013 virtual std::string GetErrorMsg()
const
1025 const std::string name;
1026 bool kickout =
false;
1027 std::string defaultString;
1028 bool defaultStringManual =
false;
1029 std::vector<std::string> choicesStrings;
1030 bool choicesStringManual =
false;
1032 virtual std::string GetDefaultString(
const HelpParams&)
const {
return {}; }
1034 virtual std::vector<std::string> GetChoicesStrings(
const HelpParams&)
const {
return {}; }
1036 virtual std::string GetNameString(
const HelpParams&)
const {
return Name(); }
1038 void AddDescriptionPostfix(std::string &dest,
const bool isManual,
const std::string &manual,
bool isGenerated,
const std::string &generated,
const std::string &str)
const
1040 if (isManual && !manual.empty())
1045 else if (!isManual && isGenerated && !generated.empty())
1053 NamedBase(
const std::string &name_,
const std::string &help_,
Options options_ = {}) :
Base(help_, options_), name(name_) {}
1061 defaultStringManual =
true;
1062 defaultString = str;
1069 return defaultStringManual ? defaultString : GetDefaultString(params);
1077 choicesStringManual =
true;
1078 choicesStrings = array;
1085 return choicesStringManual ? choicesStrings : GetChoicesStrings(params);
1088 virtual std::vector<std::tuple<std::string, std::string, unsigned>> GetDescription(
const HelpParams ¶ms,
const unsigned indentLevel)
const override
1090 std::tuple<std::string, std::string, unsigned> description;
1091 std::get<0>(description) = GetNameString(params);
1092 std::get<1>(description) = help;
1093 std::get<2>(description) = indentLevel;
1095 AddDescriptionPostfix(std::get<1>(description), choicesStringManual, detail::Join(choicesStrings,
", "), params.
addChoices, detail::Join(GetChoicesStrings(params),
", "), params.
choiceString);
1096 AddDescriptionPostfix(std::get<1>(description), defaultStringManual, defaultString, params.
addDefault, GetDefaultString(params), params.
defaultString);
1098 return { std::move(description) };
1101 virtual std::string Name()
const
1109 template<
typename T>
1110 using vector = std::vector<T, std::allocator<T>>;
1112 template<
typename K,
typename T>
1113 using unordered_map = std::unordered_map<K, T, std::hash<K>,
1114 std::equal_to<K>, std::allocator<std::pair<const K, T> > >;
1116 template<
typename S,
typename T>
1119 template<
typename SS,
typename TT>
1120 static auto test(
int)
1121 ->
decltype( std::declval<SS&>() << std::declval<TT>(), std::true_type() );
1123 template<
typename,
typename>
1124 static auto test(...) -> std::false_type;
1127 using type =
decltype(test<S,T>(0));
1130 template <
typename T>
1131 using IsConvertableToString =
typename is_streamable<std::ostringstream, T>::type;
1133 template <
typename T>
1134 typename std::enable_if<IsConvertableToString<T>::value, std::string>::type
1135 ToString(
const T &value)
1137 std::ostringstream s;
1142 template <
typename T>
1143 typename std::enable_if<!IsConvertableToString<T>::value, std::string>::type
1149 template <
typename T>
1150 std::vector<std::string> MapKeysToStrings(
const T &map)
1152 std::vector<std::string> res;
1153 using K =
typename std::decay<
decltype(std::begin(map)->first)>::type;
1154 if (IsConvertableToString<K>::value)
1156 for (
const auto &p : map)
1158 res.push_back(detail::ToString(p.first));
1161 std::sort(res.begin(), res.end());
1174 virtual std::string GetNameString(
const HelpParams ¶ms)
const override
1179 const bool useValueNameOnce = flagStrings.size() == 1 ? false : params.
useValueNameOnce;
1180 for (
auto it = flagStrings.begin(); it != flagStrings.end(); ++it)
1183 if (it != flagStrings.begin())
1189 flags += flag.str();
1191 if (!postfix.empty() && (!useValueNameOnce || it + 1 == flagStrings.end()))
1204 FlagBase(
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
Options options_) :
NamedBase(name_, help_, options_), matcher(std::move(matcher_)) {}
1210 if (matcher.
Match(flag))
1214 std::ostringstream problem;
1215 problem <<
"Flag '" << flag.str() <<
"' was passed multiple times, but is only allowed to be passed once";
1217 error = Error::Extra;
1218 errorMsg = problem.str();
1229 virtual std::vector<FlagBase*> GetAllFlags()
override
1234 const Matcher &GetMatcher()
const
1239 virtual void Validate(
const std::string &shortPrefix,
const std::string &longPrefix)
const override
1241 if (!Matched() && IsRequired())
1243 std::ostringstream problem;
1244 problem <<
"Flag '" << matcher.
GetLongOrAny().str(shortPrefix, longPrefix) <<
"' is required";
1246 error = Error::Required;
1247 errorMsg = problem.str();
1254 virtual std::vector<std::string> GetProgramLine(
const HelpParams ¶ms)
const override
1264 if (!postfix.empty())
1273 virtual bool HasFlag()
const override
1280 virtual Error GetError()
const override
1283 if (nargs.min > nargs.max)
1285 return Error::Usage;
1288 const auto matcherError = matcher.GetError();
1289 if (matcherError != Error::None)
1291 return matcherError;
1308 virtual
void ParseValue(const std::vector<std::
string> &value) = 0;
1316 ValueFlagBase(
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const bool extraError_ =
false) :
FlagBase(name_, help_, std::move(matcher_), extraError_) {}
1329 std::vector<std::string> reply;
1333 template <
typename GroupClass>
1336 group_.AddCompletion(*
this);
1346 virtual void ParseValue(
const std::vector<std::string> &value_)
override
1348 syntax = value_.at(0);
1349 const std::string &raw = value_.at(1);
1350 bool failed =
false;
1352 const auto firstNonSpace = std::find_if_not(raw.begin(), raw.end(), [](
char c)
1354 return std::isspace(static_cast<unsigned char>(c)) != 0;
1357 if (firstNonSpace != raw.end() && *firstNonSpace ==
'-')
1365 std::istringstream ss(raw);
1388 error = Error::Parse;
1389 errorMsg =
"Argument 'completion' received invalid value type '" + raw +
"'";
1391 std::ostringstream problem;
1392 problem <<
"Argument 'completion' received invalid value type '" << raw <<
"'";
1405 return detail::Join(reply,
"\n");
1408 virtual void Reset() noexcept
override
1410 ValueFlagBase::Reset();
1434 virtual void ParseValue(
const std::string &value_) = 0;
1436 virtual void Reset()
noexcept override
1441 error = Error::None;
1448 return Ready() ? this :
nullptr;
1451 virtual bool HasPositional()
const override
1456 virtual std::vector<std::string> GetProgramLine(
const HelpParams ¶ms)
const override
1462 virtual void Validate(
const std::string &,
const std::string &)
const override
1464 if (IsRequired() && !Matched())
1466 std::ostringstream problem;
1467 problem <<
"Option '" << Name() <<
"' is required";
1469 error = Error::Required;
1470 errorMsg = problem.str();
1483 std::vector<Base*> children;
1484 std::function<bool(
const Group &)> validator;
1491 static bool Xor(
const Group &group)
1496 static bool AtLeastOne(
const Group &group)
1501 static bool AtMostOne(
const Group &group)
1506 static bool All(
const Group &group)
1511 static bool AllOrNone(
const Group &group)
1513 return (All(group) ||
None(group));
1516 static bool AllChildGroups(
const Group &group)
1518 return std::none_of(std::begin(group.
Children()), std::end(group.
Children()), [](
const Base* child) ->
bool {
1519 return child->IsGroup() && !child->Matched();
1523 static bool DontCare(
const Group &)
1528 static bool CareTooMuch(
const Group &)
1539 Group(
const std::string &help_ = std::string(),
const std::function<
bool(
const Group &)> &validator_ = Validators::DontCare,
Options options_ = {}) :
Base(help_, options_), validator(validator_) {}
1541 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_)
1551 children.emplace_back(&child);
1568 for (
Base *child: Children())
1570 if (
FlagBase *match = child->Match(flag))
1578 virtual std::vector<FlagBase*> GetAllFlags()
override
1580 std::vector<FlagBase*> res;
1581 for (
Base *child: Children())
1583 auto childRes = child->GetAllFlags();
1584 res.insert(res.end(), childRes.begin(), childRes.end());
1589 virtual void Validate(
const std::string &shortPrefix,
const std::string &longPrefix)
const override
1591 for (Base *child: Children())
1593 child->Validate(shortPrefix, longPrefix);
1603 for (
Base *child: Children())
1605 if (
auto next = child->GetNextPositional())
1619 return std::any_of(Children().begin(), Children().end(), [](
Base *child) {
return child->HasFlag(); });
1628 return std::any_of(Children().begin(), Children().end(), [](
Base *child) {
return child->HasPositional(); });
1637 return std::any_of(Children().begin(), Children().end(), [](
Base *child) {
return child->HasCommand(); });
1645 return static_cast<std::vector<Base *>::size_type
>(
1646 std::count_if(std::begin(Children()), std::end(Children()), [](
const Base *child){
return child->Matched();}));
1653 return validator(*
this);
1665 virtual std::vector<std::tuple<std::string, std::string, unsigned>>
GetDescription(
const HelpParams ¶ms,
const unsigned int indent)
const override
1667 std::vector<std::tuple<std::string, std::string, unsigned int>> descriptions;
1670 unsigned addindent = 0;
1673 descriptions.emplace_back(help,
"", indent);
1677 for (
Base *child: Children())
1679 if ((child->GetOptions() & Options::HiddenFromDescription) != Options::None)
1684 auto groupDescriptions = child->GetDescription(params, indent + addindent);
1685 descriptions.insert(
1686 std::end(descriptions),
1687 std::make_move_iterator(std::begin(groupDescriptions)),
1688 std::make_move_iterator(std::end(groupDescriptions)));
1690 return descriptions;
1697 std::vector <std::string> names;
1698 for (
Base *child: Children())
1700 if ((child->GetOptions() & Options::HiddenFromUsage) != Options::None)
1705 auto groupNames = child->GetProgramLine(params);
1708 std::make_move_iterator(std::begin(groupNames)),
1709 std::make_move_iterator(std::end(groupNames)));
1714 virtual std::vector<Command*> GetCommands()
override
1716 std::vector<Command*> res;
1717 for (
const auto &child : Children())
1719 auto subparsers = child->GetCommands();
1720 res.insert(std::end(res), std::begin(subparsers), std::end(subparsers));
1725 virtual bool IsGroup()
const override
1730 virtual void Reset() noexcept
override
1734 for (
auto &child: Children())
1739 error = Error::None;
1746 virtual Error GetError()
const override
1748 if (error != Error::None)
1753 auto it = std::find_if(Children().begin(), Children().end(), [](
const Base *child){
return child->GetError() != Error::None;});
1754 if (it == Children().end())
1759 return (*it)->GetError();
1764 virtual std::string GetErrorMsg()
const override
1766 if (error != Error::None)
1771 auto it = std::find_if(Children().begin(), Children().end(), [](
const Base *child){
return child->GetError() != Error::None;});
1772 if (it == Children().end())
1777 return (*it)->GetErrorMsg();
1815 std::vector<std::string>
args;
1816 std::vector<std::string> kicked;
1820 bool isParsed =
false;
1824 :
Group({}, Validators::AllChildGroups),
args(std::move(args_)), parser(&parser_), helpParams(helpParams_), command(command_)
1874 std::string description;
1876 std::string proglinePostfix;
1878 std::function<void(
Subparser&)> parserCoroutine;
1879 bool commandIsRequired =
true;
1880 Command *selectedCommand =
nullptr;
1882 mutable std::vector<std::tuple<std::string, std::string, unsigned>> subparserDescription;
1883 mutable std::vector<std::string> subparserProgramLine;
1884 mutable bool subparserHasFlag =
false;
1885 mutable bool subparserHasPositional =
false;
1886 mutable bool subparserHasCommand =
false;
1888 mutable Error subparserError = Error::None;
1897 RaiiSubparser(
ArgumentParser &parser_, std::vector<std::string> args_);
1902 command.subparser = oldSubparser;
1918 std::function<void(
Subparser&)> &GetCoroutine()
1920 return selectedCommand !=
nullptr ? selectedCommand->GetCoroutine() : parserCoroutine;
1926 while (res->selectedCommand !=
nullptr)
1928 res = res->selectedCommand;
1934 const Command &SelectedCommand()
const
1937 while (res->selectedCommand !=
nullptr)
1939 res = res->selectedCommand;
1945 void UpdateSubparserHelp(
const HelpParams ¶ms)
const
1947 if (parserCoroutine)
1949 RaiiSubparser coro(*
this, params);
1950#ifndef ARGS_NOEXCEPT
1953 parserCoroutine(coro.Parser());
1955 catch (args::SubparserError&)
1959 parserCoroutine(coro.Parser());
1965 Command(
Group &base_, std::string name_, std::string help_, std::function<
void(
Subparser&)> coroutine_ = {})
1966 : name(std::move(name_)), help(std::move(help_)), parserCoroutine(std::move(coroutine_))
1974 {
return proglinePostfix; }
1979 { this->proglinePostfix = proglinePostfix_; }
1984 {
return description; }
1989 { this->description = description_; }
1999 { this->epilog = epilog_; }
2016 { commandIsRequired = value; }
2018 virtual bool IsGroup()
const override
2022 {
return Base::Matched(); }
2024 operator bool() const noexcept
2025 {
return Matched(); }
2027 void Match() noexcept
2030 void SelectCommand(Command *c)
noexcept
2032 selectedCommand = c;
2042 if (selectedCommand !=
nullptr)
2044 if (
auto *res = selectedCommand->Match(flag))
2049 for (
auto *child: Children())
2051 if ((child->GetOptions() & Options::Global) != Options::None)
2053 if (
auto *res = child->Match(flag))
2063 if (subparser !=
nullptr)
2065 return subparser->
Match(flag);
2068 return Matched() ? Group::Match(flag) :
nullptr;
2071 virtual std::vector<FlagBase*> GetAllFlags()
override
2073 std::vector<FlagBase*> res;
2080 for (
auto *child: Children())
2082 if (selectedCommand ==
nullptr || (child->GetOptions() & Options::Global) != Options::None)
2084 auto childFlags = child->GetAllFlags();
2085 res.insert(res.end(), childFlags.begin(), childFlags.end());
2089 if (selectedCommand !=
nullptr)
2091 auto childFlags = selectedCommand->GetAllFlags();
2092 res.insert(res.end(), childFlags.begin(), childFlags.end());
2095 if (subparser !=
nullptr)
2097 auto childFlags = subparser->GetAllFlags();
2098 res.insert(res.end(), childFlags.begin(), childFlags.end());
2106 if (selectedCommand !=
nullptr)
2113 for (
auto *child: Children())
2115 if ((child->GetOptions() & Options::Global) != Options::None)
2117 if (
auto *res = child->GetNextPositional())
2127 if (subparser !=
nullptr)
2132 return Matched() ? Group::GetNextPositional() :
nullptr;
2137 return subparserHasFlag || Group::HasFlag();
2142 return subparserHasPositional || Group::HasPositional();
2150 std::vector<std::string> GetCommandProgramLine(
const HelpParams ¶ms)
const
2152 UpdateSubparserHelp(params);
2154 std::vector<std::string> res;
2161 auto group_res = Group::GetProgramLine(params);
2162 std::move(std::move(group_res).begin(), std::move(group_res).end(), std::back_inserter(res));
2164 res.insert(res.end(), subparserProgramLine.begin(), subparserProgramLine.end());
2166 if (!params.
proglineCommand.empty() && (Group::HasCommand() || subparserHasCommand))
2168 res.insert(res.begin(), commandIsRequired ? params.
proglineCommand :
"[" + params.proglineCommand +
"]");
2171 if (!Name().empty())
2173 res.insert(res.begin(), Name());
2176 if (!ProglinePostfix().empty())
2179 for (
auto c : ProglinePostfix())
2181 if (std::isspace(
static_cast<unsigned char>(c)))
2185 res.push_back(line);
2191 res.push_back(
"\n");
2202 res.push_back(line);
2216 return GetCommandProgramLine(params);
2219 virtual std::vector<Command*> GetCommands()
override
2221 if (selectedCommand !=
nullptr)
2223 return selectedCommand->GetCommands();
2228 return Group::GetCommands();
2234 virtual std::vector<std::tuple<std::string, std::string, unsigned>>
GetDescription(
const HelpParams ¶ms,
const unsigned int indent)
const override
2236 std::vector<std::tuple<std::string, std::string, unsigned>> descriptions;
2237 unsigned addindent = 0;
2239 UpdateSubparserHelp(params);
2245 std::ostringstream s;
2247 for (
const auto &progline: GetCommandProgramLine(params))
2261 descriptions.emplace_back(s.str(),
"", indent);
2265 descriptions.emplace_back(Name(), help, indent);
2270 return descriptions;
2278 descriptions.emplace_back(
"",
"", indent + addindent);
2279 descriptions.emplace_back(Description().empty() ?
Help() : Description(),
"", indent + addindent);
2280 descriptions.emplace_back(
"",
"", indent + addindent);
2283 for (
Base *child: Children())
2285 if ((child->GetOptions() & Options::HiddenFromDescription) != Options::None)
2290 auto groupDescriptions = child->GetDescription(params, indent + addindent);
2291 descriptions.insert(
2292 std::end(descriptions),
2293 std::make_move_iterator(std::begin(groupDescriptions)),
2294 std::make_move_iterator(std::end(groupDescriptions)));
2297 for (
auto childDescription: subparserDescription)
2299 std::get<2>(childDescription) += indent + addindent;
2300 descriptions.push_back(std::move(childDescription));
2305 descriptions.emplace_back(
"",
"", indent + addindent);
2306 if (!Epilog().empty())
2308 descriptions.emplace_back(Epilog(),
"", indent + addindent);
2309 descriptions.emplace_back(
"",
"", indent + addindent);
2313 return descriptions;
2316 virtual void Validate(
const std::string &shortprefix,
const std::string &longprefix)
const override
2323 auto onValidationError = [&]
2325 std::ostringstream problem;
2326 problem <<
"Group validation failed somewhere!";
2328 error = Error::Validation;
2329 errorMsg = problem.str();
2331 throw ValidationError(problem.str());
2335 for (Base *child: Children())
2337 if (child->IsGroup() && !child->Matched())
2339 onValidationError();
2342 child->Validate(shortprefix, longprefix);
2345 if (subparser !=
nullptr)
2347 subparser->Validate(shortprefix, longprefix);
2350 onValidationError();
2354 if (selectedCommand ==
nullptr && commandIsRequired && (Group::HasCommand() || subparserHasCommand))
2356 std::ostringstream problem;
2357 problem <<
"Command is required";
2359 error = Error::Validation;
2360 errorMsg = problem.str();
2362 throw ValidationError(problem.str());
2367 virtual void Reset() noexcept
override
2370 selectedCommand =
nullptr;
2371 subparserProgramLine.clear();
2372 subparserDescription.clear();
2373 subparserHasFlag =
false;
2374 subparserHasPositional =
false;
2375 subparserHasCommand =
false;
2377 subparserError = Error::None;
2383 virtual Error GetError()
const override
2390 if (error != Error::None)
2395 if (subparserError != Error::None)
2397 return subparserError;
2400 return Group::GetError();
2412 std::string longprefix;
2413 std::string shortprefix;
2415 std::string longseparator;
2417 std::string terminator;
2419 bool allowJoinedShortValue =
true;
2420 bool allowJoinedLongValue =
true;
2421 bool allowSeparateShortValue =
true;
2422 bool allowSeparateLongValue =
true;
2424 bool readCompletion =
false;
2428 enum class OptionType
2435 OptionType ParseOption(
const std::string &s,
bool allowEmpty =
false)
2437 if (s.find(longprefix) == 0 && (allowEmpty || s.length() > longprefix.length()))
2439 return OptionType::LongFlag;
2442 if (s.find(shortprefix) == 0 && (allowEmpty || s.length() > shortprefix.length()))
2444 return OptionType::ShortFlag;
2447 return OptionType::Positional;
2450 template <
typename It>
2451 bool Complete(
FlagBase &flag, It it, It end)
2454 if (!readCompletion || (++nextIt != end))
2459 const auto &chunk = *it;
2462 AddCompletionReply(chunk, choice);
2465#ifndef ARGS_NOEXCEPT
2481 template <
typename It>
2483 const bool allowSeparate,
const bool allowJoined,
2484 const bool hasJoined,
const std::string &joinedArg,
2485 const bool canDiscardJoined, std::vector<std::string> &values)
2491 if (hasJoined && !allowJoined && nargs.min != 0)
2493 return "Flag '" + arg +
"' was passed a joined argument, but these are disallowed";
2498 if (!canDiscardJoined || nargs.max != 0)
2500 values.push_back(joinedArg);
2502 }
else if (!allowSeparate)
2506 return "Flag '" + arg +
"' was passed a separate argument, but these are disallowed";
2513 while (valueIt != end &&
2514 values.size() < nargs.max &&
2515 (values.size() < nargs.min || ParseOption(*valueIt) == OptionType::Positional))
2517 if (Complete(flag, valueIt, end))
2523 values.push_back(*valueIt);
2529 if (values.size() > nargs.max)
2531 return "Passed an argument into a non-argument flag: " + arg;
2532 }
else if (values.size() < nargs.min)
2534 if (nargs.min == 1 && nargs.max == 1)
2536 return "Flag '" + arg +
"' requires an argument but received none";
2537 }
else if (nargs.min == 1)
2539 return "Flag '" + arg +
"' requires at least one argument but received none";
2540 }
else if (nargs.min != nargs.max)
2542 return "Flag '" + arg +
"' requires at least " + std::to_string(nargs.min) +
2543 " arguments but received " + std::to_string(values.size());
2546 return "Flag '" + arg +
"' requires " + std::to_string(nargs.min) +
2547 " arguments but received " + std::to_string(values.size());
2554 template <
typename It>
2555 bool ParseLong(It &it, It end)
2557 const auto &chunk = *it;
2558 const auto argchunk = chunk.substr(longprefix.size());
2560 const auto separator = longseparator.empty() ? argchunk.npos : argchunk.find(longseparator);
2562 const auto arg = (separator != argchunk.npos ?
2563 std::string(argchunk, 0, separator)
2565 const auto joined = (separator != argchunk.npos ?
2566 argchunk.substr(separator + longseparator.size())
2569 if (
auto flag = Match(arg))
2577 if (flag->GetError() != Error::None)
2582 std::vector<std::string> values;
2583 const std::string errorMessage = ParseArgsValues(*flag, arg, it, end, allowSeparateLongValue, allowJoinedLongValue,
2584 separator != argchunk.npos, joined,
false, values);
2585 if (!errorMessage.empty())
2587#ifndef ARGS_NOEXCEPT
2588 throw ParseError(errorMessage);
2590 error = Error::Parse;
2591 errorMsg = errorMessage;
2596 if (!readCompletion)
2605 if (flag->GetError() != Error::None)
2619 const std::string errorMessage(
"Flag could not be matched: " + arg);
2620#ifndef ARGS_NOEXCEPT
2621 throw ParseError(errorMessage);
2623 error = Error::Parse;
2624 errorMsg = errorMessage;
2632 template <
typename It>
2633 bool ParseShort(It &it, It end)
2635 const auto &chunk = *it;
2636 const auto argchunk = chunk.substr(shortprefix.size());
2637 for (
auto argit = std::begin(argchunk); argit != std::end(argchunk); ++argit)
2639 const auto arg = *argit;
2641 if (
auto flag = Match(arg))
2647 if (flag->GetError() != Error::None)
2652 const std::string value(argit + 1, std::end(argchunk));
2653 std::vector<std::string> values;
2654 const std::string errorMessage = ParseArgsValues(*flag, std::string(1, arg), it, end,
2655 allowSeparateShortValue, allowJoinedShortValue,
2656 !value.empty(), value, !value.empty(), values);
2658 if (!errorMessage.empty())
2660#ifndef ARGS_NOEXCEPT
2661 throw ParseError(errorMessage);
2663 error = Error::Parse;
2664 errorMsg = errorMessage;
2669 if (!readCompletion)
2676 if (flag->GetError() != Error::None)
2689 if (!values.empty())
2695 const std::string errorMessage(
"Flag could not be matched: '" + std::string(1, arg) +
"'");
2696#ifndef ARGS_NOEXCEPT
2697 throw ParseError(errorMessage);
2699 error = Error::Parse;
2700 errorMsg = errorMessage;
2709 bool AddCompletionReply(
const std::string &cur,
const std::string &choice)
2711 if (cur.empty() || choice.find(cur) == 0)
2713 if (completion->syntax ==
"bash" && ParseOption(choice) == OptionType::LongFlag && choice.find(longseparator) != std::string::npos)
2715 completion->reply.push_back(choice.substr(choice.find(longseparator) + longseparator.size()));
2718 completion->reply.push_back(choice);
2726 template <
typename It>
2727 bool Complete(It it, It end)
2730 if (!readCompletion || (++nextIt != end))
2735 const auto &chunk = *it;
2736 auto pos = GetNextPositional();
2737 std::vector<Command *> commands = GetCommands();
2738 const auto optionType = ParseOption(chunk,
true);
2740 if (!commands.empty() && (chunk.empty() || optionType == OptionType::Positional))
2742 for (
auto &cmd : commands)
2744 if ((cmd->GetOptions() & Options::HiddenFromCompletion) == Options::None)
2746 AddCompletionReply(chunk, cmd->Name());
2751 bool hasPositionalCompletion =
true;
2753 if (!commands.empty())
2755 for (
auto &cmd : commands)
2757 if ((cmd->GetOptions() & Options::HiddenFromCompletion) == Options::None)
2759 AddCompletionReply(chunk, cmd->Name());
2764 if ((pos->GetOptions() & Options::HiddenFromCompletion) == Options::None)
2766 auto choices = pos->HelpChoices(helpParams);
2767 hasPositionalCompletion = !choices.empty() || optionType != OptionType::Positional;
2768 for (
auto &choice : choices)
2770 AddCompletionReply(chunk, choice);
2775 if (hasPositionalCompletion)
2777 auto flags = GetAllFlags();
2778 for (
auto flag : flags)
2780 if ((flag->GetOptions() & Options::HiddenFromCompletion) != Options::None)
2785 auto &matcher = flag->GetMatcher();
2786 if (!AddCompletionReply(chunk, matcher.
GetShortOrAny().str(shortprefix, longprefix)))
2788 for (
auto &flagName : matcher.GetFlagStrings())
2790 if (AddCompletionReply(chunk, flagName.str(shortprefix, longprefix)))
2798 if (optionType == OptionType::LongFlag && allowJoinedLongValue)
2800 const auto separator = longseparator.empty() ? chunk.npos : chunk.find(longseparator);
2801 if (separator != chunk.npos)
2803 std::string arg(chunk, 0, separator);
2804 if (
auto flag = this->Match(arg.substr(longprefix.size())))
2806 for (
auto &choice : flag->HelpChoices(helpParams))
2808 AddCompletionReply(chunk, arg + longseparator + choice);
2812 }
else if (optionType == OptionType::ShortFlag && allowJoinedShortValue)
2814 if (chunk.size() > shortprefix.size() + 1)
2816 auto arg = chunk.at(shortprefix.size());
2818 if (
auto flag = this->Match(arg))
2820 for (
auto &choice : flag->HelpChoices(helpParams))
2822 AddCompletionReply(chunk, shortprefix + arg + choice);
2830#ifndef ARGS_NOEXCEPT
2831 throw Completion(completion->
Get());
2837 template <
typename It>
2838 It Parse(It begin, It end)
2840 bool terminated =
false;
2841 std::vector<Command *> commands = GetCommands();
2844 for (
auto it = begin; it != end; ++it)
2846 if (Complete(it, end))
2851 const auto &chunk = *it;
2853 if (!terminated && chunk == terminator)
2856 }
else if (!terminated && ParseOption(chunk) == OptionType::LongFlag)
2858 if (!ParseLong(it, end))
2862 }
else if (!terminated && ParseOption(chunk) == OptionType::ShortFlag)
2864 if (!ParseShort(it, end))
2868 }
else if (!terminated && !commands.empty())
2870 auto itCommand = std::find_if(commands.begin(), commands.end(), [&chunk](Command *c) { return c->Name() == chunk; });
2871 if (itCommand == commands.end())
2873 const std::string errorMessage(
"Unknown command: " + chunk);
2874#ifndef ARGS_NOEXCEPT
2875 throw ParseError(errorMessage);
2877 error = Error::Parse;
2878 errorMsg = errorMessage;
2883 SelectCommand(*itCommand);
2885 if (
const auto &coroutine = GetCoroutine())
2888 RaiiSubparser coro(*
this, std::vector<std::string>(it, end));
2889 coroutine(coro.Parser());
2892 if (error != Error::None)
2897 if (!coro.Parser().IsParsed())
2899 error = Error::Usage;
2903 if (!coro.Parser().IsParsed())
2905 throw UsageError(
"Subparser::Parse was not called");
2912 commands = GetCommands();
2915 auto pos = GetNextPositional();
2918 pos->ParseValue(chunk);
2926 const std::string errorMessage(
"Passed in argument, but no positional arguments were ready to receive it: " + chunk);
2927#ifndef ARGS_NOEXCEPT
2928 throw ParseError(errorMessage);
2930 error = Error::Parse;
2931 errorMsg = errorMessage;
2937 if (!readCompletion && completion !=
nullptr && completion->Matched())
2940 if (completion->GetError() != Error::None)
2942 error = completion->GetError();
2943 if (errorMsg.empty())
2945 errorMsg = completion->GetErrorMsg();
2950 error = Error::Completion;
2952 readCompletion =
true;
2954 const auto argsLeft =
static_cast<size_t>(std::distance(it, end));
2955 if (completion->cword == 0 || argsLeft <= 1 || completion->cword >= argsLeft)
2957#ifndef ARGS_NOEXCEPT
2958 throw Completion(
"");
2965 std::vector<std::string> curArgs;
2966 curArgs.reserve(completion->cword);
2968 for (
size_t idx = 0; idx < completion->cword && curIt != end; ++idx, ++curIt)
2970 curArgs.push_back(*curIt);
2973 if (completion->syntax ==
"bash")
2977 for (
size_t idx = 0; idx < curArgs.size(); )
2979 if (idx > 0 && curArgs[idx] ==
"=")
2981 size_t prev_idx = idx - 1;
2982 curArgs[prev_idx] +=
"=";
2983 size_t next_idx = 0;
2984 if (SafeAdd<size_t>(idx,
static_cast<size_t>(1), next_idx) && next_idx < curArgs.size())
2986 curArgs[prev_idx] += curArgs[next_idx];
2988 size_t erase_end = 0;
2989 if (SafeAdd<size_t>(next_idx,
static_cast<size_t>(1), erase_end))
2991 curArgs.erase(curArgs.begin() + idx,
2992 curArgs.begin() + erase_end);
2997 curArgs.erase(curArgs.begin() + idx);
3007#ifndef ARGS_NOEXCEPT
3010 Parse(curArgs.begin(), curArgs.end());
3011 throw Completion(
"");
3013 catch (Completion &)
3019 throw Completion(
"");
3022 return Parse(curArgs.begin(), curArgs.end());
3027 Validate(shortprefix, longprefix);
3032 HelpParams helpParams;
3034 ArgumentParser(
const std::string &description_,
const std::string &epilog_ = std::string())
3036 Description(description_);
3042 SetArgumentSeparations(
true,
true,
true,
true);
3046 void AddCompletion(CompletionFlag &completionFlag)
3048 completion = &completionFlag;
3049 Add(completionFlag);
3055 {
return helpParams.programName; }
3058 void Prog(
const std::string &prog_)
3059 { this->helpParams.programName = prog_; }
3064 {
return longprefix; }
3069 this->longprefix = longprefix_;
3070 this->helpParams.longPrefix = longprefix_;
3076 {
return shortprefix; }
3081 this->shortprefix = shortprefix_;
3082 this->helpParams.shortPrefix = shortprefix_;
3088 {
return longseparator; }
3093 if (longseparator_.empty())
3095 const std::string errorMessage(
"longseparator can not be set to empty");
3097 error = Error::Usage;
3098 errorMsg = errorMessage;
3104 this->longseparator = longseparator_;
3105 this->helpParams.longSeparator = allowJoinedLongValue ? longseparator :
" ";
3112 {
return terminator; }
3116 { this->terminator = terminator_; }
3123 bool &allowJoinedShortValue_,
3124 bool &allowJoinedLongValue_,
3125 bool &allowSeparateShortValue_,
3126 bool &allowSeparateLongValue_)
const
3128 allowJoinedShortValue_ = this->allowJoinedShortValue;
3129 allowJoinedLongValue_ = this->allowJoinedLongValue;
3130 allowSeparateShortValue_ = this->allowSeparateShortValue;
3131 allowSeparateLongValue_ = this->allowSeparateLongValue;
3142 const bool allowJoinedShortValue_,
3143 const bool allowJoinedLongValue_,
3144 const bool allowSeparateShortValue_,
3145 const bool allowSeparateLongValue_)
3147 this->allowJoinedShortValue = allowJoinedShortValue_;
3148 this->allowJoinedLongValue = allowJoinedLongValue_;
3149 this->allowSeparateShortValue = allowSeparateShortValue_;
3150 this->allowSeparateLongValue = allowSeparateLongValue_;
3152 this->helpParams.longSeparator = allowJoinedLongValue ? longseparator :
" ";
3153 this->helpParams.shortSeparator = allowJoinedShortValue ?
"" :
" ";
3158 void Help(std::ostream &help_)
const
3160 auto &command = SelectedCommand();
3161 const auto &commandDescription = command.Description().empty() ? command.Help() : command.Description();
3162 const auto desc_indent = helpParams.descriptionindent;
3163 const auto effective_desc_width = (helpParams.width > desc_indent) ? helpParams.width - desc_indent : 0;
3164 const auto description_text =
Wrap(commandDescription, effective_desc_width);
3165 const auto epilog_text =
Wrap(command.Epilog(), effective_desc_width);
3167 const bool hasoptions = command.HasFlag();
3168 const bool hasarguments = command.HasPositional();
3170 std::vector<std::string> prognameline;
3171 prognameline.push_back(helpParams.usageString);
3172 prognameline.push_back(Prog());
3173 auto commandProgLine = command.GetProgramLine(helpParams);
3174 prognameline.insert(prognameline.end(), commandProgLine.begin(), commandProgLine.end());
3176 const auto prog_sum = helpParams.progindent + helpParams.progtailindent;
3177 const auto effective_prog_width = (helpParams.width > prog_sum) ? helpParams.width - prog_sum : 0;
3178 const auto effective_prog_first = (helpParams.width > helpParams.progindent) ? helpParams.width - helpParams.progindent : 0;
3179 const auto proglines =
Wrap(prognameline.begin(), prognameline.end(),
3180 effective_prog_width,
3181 effective_prog_first);
3182 auto progit = std::begin(proglines);
3183 if (progit != std::end(proglines))
3185 help_ << std::string(helpParams.progindent,
' ') << *progit <<
'\n';
3188 for (; progit != std::end(proglines); ++progit)
3190 help_ << std::string(helpParams.progtailindent,
' ') << *progit <<
'\n';
3195 if (!description_text.empty())
3197 for (
const auto &line: description_text)
3199 help_ << std::string(helpParams.descriptionindent,
' ') << line <<
"\n";
3204 bool lastDescriptionIsNewline =
false;
3206 if (!helpParams.optionsString.empty())
3208 help_ << std::string(helpParams.progindent,
' ') << helpParams.optionsString <<
"\n\n";
3211 for (
const auto &desc: command.GetDescription(helpParams, 0))
3213 lastDescriptionIsNewline = std::get<0>(desc).empty() && std::get<1>(desc).empty();
3214 const auto groupindent = std::get<2>(desc) * helpParams.eachgroupindent;
3215 const auto flag_sum = helpParams.flagindent + helpParams.helpindent + helpParams.gutter;
3216 const auto effective_flag_width = (helpParams.width > flag_sum) ? helpParams.width - flag_sum : 0;
3217 const auto flags =
Wrap(std::get<0>(desc), effective_flag_width);
3218 const auto info_sum = helpParams.helpindent + groupindent;
3219 const auto effective_info_width = (helpParams.width > info_sum) ? helpParams.width - info_sum : 0;
3220 const auto info =
Wrap(std::get<1>(desc), effective_info_width);
3222 std::string::size_type flagssize = 0;
3223 for (
auto flagsit = std::begin(flags); flagsit != std::end(flags); ++flagsit)
3225 if (flagsit != std::begin(flags))
3229 help_ << std::string(groupindent + helpParams.flagindent,
' ') << *flagsit;
3230 flagssize =
Glyphs(*flagsit);
3233 auto infoit = std::begin(info);
3235 if ((helpParams.flagindent + flagssize + helpParams.gutter) > helpParams.helpindent || infoit == std::end(info) || helpParams.addNewlineBeforeDescription)
3241 const auto indent_sum = helpParams.flagindent + flagssize;
3242 const auto effective_space = (helpParams.helpindent > indent_sum) ? helpParams.helpindent - indent_sum : 0;
3243 help_ << std::string(effective_space,
' ') << *infoit <<
'\n';
3246 for (; infoit != std::end(info); ++infoit)
3248 help_ << std::string(groupindent + helpParams.helpindent,
' ') << *infoit <<
'\n';
3251 if (hasoptions && hasarguments && helpParams.showTerminator)
3253 lastDescriptionIsNewline =
false;
3254 const auto effective_term_width = (helpParams.width > helpParams.flagindent) ? helpParams.width - helpParams.flagindent : 0;
3255 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))
3257 help_ << std::string(helpParams.flagindent,
' ') << item <<
'\n';
3261 if (!lastDescriptionIsNewline)
3266 for (
const auto &line: epilog_text)
3268 help_ << std::string(helpParams.descriptionindent,
' ') << line <<
"\n";
3278 std::ostringstream help_;
3283 virtual void Reset() noexcept
override
3287 readCompletion =
false;
3296 template <
typename It>
3303 if (error != Error::None)
3308 return Parse(begin, end);
3316 template <
typename T>
3319 return ParseArgs(std::begin(
args), std::end(
args));
3328 bool ParseCLI(
const int argc,
const char *
const * argv)
3330 if (argc > 0 && argv !=
nullptr && argv[0] !=
nullptr && Prog().empty())
3335 std::vector<std::string>
args;
3336 if (argc > 1 && argv !=
nullptr)
3338 args.assign(argv + 1, argv + argc);
3341 return ParseArgs(
args) == std::end(
args);
3344 template <
typename T>
3345 bool ParseCLI(
const T &
args)
3347 return ParseArgs(
args) == std::end(
args);
3351 inline Command::RaiiSubparser::RaiiSubparser(ArgumentParser &parser_, std::vector<std::string> args_)
3352 : command(parser_.SelectedCommand()), parser(std::move(args_), parser_, command, parser_.helpParams), oldSubparser(command.subparser)
3354 command.subparser = &parser;
3357 inline Command::RaiiSubparser::RaiiSubparser(
const Command &command_,
const HelpParams ¶ms_): command(command_), parser(command, params_), oldSubparser(command.subparser)
3359 command.subparser = &parser;
3367 command.subparserHasFlag =
HasFlag();
3371 if (parser ==
nullptr)
3373#ifndef ARGS_NOEXCEPT
3374 throw args::SubparserError();
3376 error = Error::Subparser;
3381 auto it = parser->Parse(
args.begin(),
args.end());
3383 kicked.assign(it,
args.end());
3386 command.subparserError = GetError();
3390 inline std::ostream &operator<<(std::ostream &os,
const ArgumentParser &parser)
3401 Flag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
Options options_):
FlagBase(name_, help_, std::move(matcher_), options_)
3424 virtual void ParseValue(
const std::vector<std::string>&)
override
3436 HelpFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
Options options_ = {}):
Flag(group_, name_, help_, std::move(matcher_), options_) {}
3443 error = Error::Help;
3463 const int startcount;
3467 CounterFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const int startcount_ = 0,
Options options_ = {}):
3468 Flag(group_, name_, help_, std::move(matcher_), options_), startcount(startcount_), count(startcount_) {}
3474 auto me = FlagBase::Match(arg);
3482 if (GetError() != Error::None)
3499 int &operator *() noexcept {
3503 const int &operator *() const noexcept {
3507 virtual void Reset() noexcept
override
3519 std::function<void(
const std::vector<std::string> &)> action;
3523 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_ = {}):
3524 FlagBase(name_, help_, std::move(matcher_), options_), action(std::move(action_)), nargs(nargs_)
3529 ActionFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_, std::function<
void(
const std::string &)> action_,
Options options_ = {}):
3530 FlagBase(name_, help_, std::move(matcher_), options_), nargs(1)
3533 action = [action_](
const std::vector<std::string> &a) {
return action_(a.at(0)); };
3536 ActionFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_, std::function<
void()> action_,
Options options_ = {}):
3537 FlagBase(name_, help_, std::move(matcher_), options_), nargs(0)
3540 action = [action_](
const std::vector<std::string> &) {
return action_(); };
3546 virtual void ParseValue(
const std::vector<std::string> &value)
override
3559 template <
typename T>
3560 static typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value,
bool>::type
3561 HasUnsignedNegativeSign(
const std::string &value)
3563 const auto firstNonSpace = std::find_if_not(value.begin(), value.end(), [](
char c)
3565 return std::isspace(static_cast<unsigned char>(c)) != 0;
3568 return firstNonSpace != value.end() && *firstNonSpace ==
'-';
3571 template <
typename T>
3572 static typename std::enable_if<!std::is_integral<T>::value || !std::is_unsigned<T>::value,
bool>::type
3573 HasUnsignedNegativeSign(
const std::string &)
3579 template <
typename T>
3580 typename std::enable_if<
3581 std::is_integral<T>::value &&
3582 !std::is_same<T, bool>::value &&
3583 !std::is_same<T, char>::value &&
3584 !std::is_same<T, signed char>::value &&
3585 !std::is_same<T, unsigned char>::value,
3587 ParseNumericValue(
const std::string &value, T &destination)
3589 if (HasUnsignedNegativeSign<T>(value))
3594 const char *begin = value.c_str();
3598#if __cplusplus >= 201703L
3599 const char *end_pos = value.c_str() + value.length();
3601 auto result = std::from_chars(begin, end_pos, parsed);
3604 end_pos = result.ptr;
3607 while (end_pos != value.c_str() + value.length() &&
3608 std::isspace(
static_cast<unsigned char>(*end_pos)))
3613 if (end_pos != value.c_str() + value.length() ||
3614 result.ec == std::errc::invalid_argument ||
3615 result.ec == std::errc::result_out_of_range)
3620 destination = parsed;
3629 const int saved_errno = errno;
3632 char *end =
nullptr;
3634 if (std::is_unsigned<T>::value)
3636 const unsigned long long parsed = std::strtoull(begin, &end, 0);
3637 while (end !=
nullptr && *end !=
'\0' && std::isspace(
static_cast<unsigned char>(*end)))
3641 if (end == begin || *end !=
'\0' || errno == ERANGE || parsed >
static_cast<unsigned long long>(std::numeric_limits<T>::max()))
3643 errno = saved_errno;
3647 destination =
static_cast<T
>(parsed);
3651 const long long parsed = std::strtoll(begin, &end, 0);
3652 while (end !=
nullptr && *end !=
'\0' && std::isspace(
static_cast<unsigned char>(*end)))
3656 if (end == begin || *end !=
'\0' || errno == ERANGE ||
3657 parsed <
static_cast<long long>(std::numeric_limits<T>::min()) ||
3658 parsed >
static_cast<long long>(std::numeric_limits<T>::max()))
3660 errno = saved_errno;
3664 destination =
static_cast<T
>(parsed);
3667 errno = saved_errno;
3672 template <
typename T>
3673 typename std::enable_if<
3674 !std::is_integral<T>::value ||
3675 std::is_same<T, bool>::value ||
3676 std::is_same<T, char>::value ||
3677 std::is_same<T, signed char>::value ||
3678 std::is_same<T, unsigned char>::value,
3680 ParseNumericValue(
const std::string &value, T &destination)
3682 std::istringstream ss(value);
3690 return ss.peek() == std::char_traits<char>::eof();
3693 template <
typename T>
3694 typename std::enable_if<!std::is_assignable<T, std::string>::value,
bool>::type
3695 operator ()(
const std::string &name,
const std::string &value, T &destination)
3697 const bool success = ParseNumericValue(value, destination);
3704 std::ostringstream problem;
3705 problem <<
"Argument '" << name <<
"' received invalid value type '" << value <<
"'";
3712 template <
typename T>
3713 typename std::enable_if<std::is_assignable<T, std::string>::value,
bool>::type
3714 operator()(
const std::string &,
const std::string &value, T &destination)
3716 destination = value;
3735 virtual std::string GetDefaultString(
const HelpParams&)
const override
3737 return detail::ToString(defaultValue);
3745 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_)
3750 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)
3754 ValueFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
Options options_):
ValueFlag(group_, name_, help_, std::move(matcher_), T(), options_)
3760 virtual void ParseValue(
const std::vector<std::string> &values_)
override
3762 const std::string &value_ = values_.at(0);
3765 if (!reader(name, value_, this->value))
3767 error = Error::Parse;
3770 reader(name, value_, this->value);
3774 virtual void Reset() noexcept
override
3776 ValueFlagBase::Reset();
3777 value = defaultValue;
3819 return defaultValue;
3830 typename Reader = ValueReader>
3838 ImplicitValueFlag(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const T &implicitValue_,
const T &defaultValue_ = T(),
Options options_ = {})
3839 :
ValueFlag<T, Reader>(group_, name_, help_, std::move(matcher_), defaultValue_, options_), implicitValue(implicitValue_)
3844 :
ValueFlag<T, Reader>(group_, name_, help_, std::move(matcher_), defaultValue_, options_), implicitValue(defaultValue_)
3849 :
ValueFlag<T, Reader>(group_, name_, help_, std::move(matcher_), {}, options_), implicitValue()
3860 virtual void ParseValue(
const std::vector<std::string> &value_)
override
3864 this->value = implicitValue;
3880 template <
typename...>
class List = detail::vector,
3881 typename Reader = ValueReader>
3887 const List<T> defaultValues;
3893 typedef List<T> Container;
3894 typedef T value_type;
3895 typedef typename Container::allocator_type allocator_type;
3896 typedef typename Container::pointer pointer;
3897 typedef typename Container::const_pointer const_pointer;
3898 typedef T& reference;
3899 typedef const T& const_reference;
3900 typedef typename Container::size_type size_type;
3901 typedef typename Container::difference_type difference_type;
3902 typedef typename Container::iterator iterator;
3903 typedef typename Container::const_iterator const_iterator;
3904 typedef std::reverse_iterator<iterator> reverse_iterator;
3905 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
3908 :
FlagBase(name_, help_, std::move(matcher_), options_), values(defaultValues_), defaultValues(defaultValues_),nargs(nargs_)
3920 virtual void ParseValue(
const std::vector<std::string> &values_)
override
3924 for (
const std::string &value : values_)
3928 if (!reader(name, value, v))
3930 error = Error::Parse;
3934 reader(name, value, v);
3936 values.insert(std::end(values), v);
3940 List<T> &Get() noexcept
3973 iterator begin() noexcept
3975 return values.begin();
3978 const_iterator begin() const noexcept
3980 return values.begin();
3983 const_iterator cbegin() const noexcept
3985 return values.cbegin();
3988 iterator end() noexcept
3990 return values.end();
3993 const_iterator end() const noexcept
3995 return values.end();
3998 const_iterator cend() const noexcept
4000 return values.cend();
4003 virtual void Reset() noexcept
override
4006 values = defaultValues;
4009 virtual FlagBase *Match(
const EitherFlag &arg)
override
4011 const bool wasMatched = Matched();
4012 auto me = FlagBase::Match(arg);
4013 if (me && !wasMatched)
4029 template <
typename...>
class List = detail::vector,
4030 typename Reader = ValueReader>
4034 using Container = List<T>;
4036 const Container defaultValues;
4041 typedef T value_type;
4042 typedef typename Container::allocator_type allocator_type;
4043 typedef typename Container::pointer pointer;
4044 typedef typename Container::const_pointer const_pointer;
4045 typedef T& reference;
4046 typedef const T& const_reference;
4047 typedef typename Container::size_type size_type;
4048 typedef typename Container::difference_type difference_type;
4049 typedef typename Container::iterator iterator;
4050 typedef typename Container::const_iterator const_iterator;
4051 typedef std::reverse_iterator<iterator> reverse_iterator;
4052 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
4054 ValueFlagList(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const Container &defaultValues_ = Container(),
Options options_ = {}):
4055 ValueFlagBase(name_, help_, std::move(matcher_), options_), values(defaultValues_), defaultValues(defaultValues_)
4062 virtual void ParseValue(
const std::vector<std::string> &values_)
override
4064 const std::string &value_ = values_.at(0);
4068 if (!reader(name, value_, v))
4070 error = Error::Parse;
4074 reader(name, value_, v);
4076 values.insert(std::end(values), v);
4114 virtual std::string Name()
const override
4116 return name + std::string(
"...");
4119 virtual void Reset() noexcept
override
4121 ValueFlagBase::Reset();
4122 values = defaultValues;
4125 virtual FlagBase *Match(
const EitherFlag &arg)
override
4127 const bool wasMatched = Matched();
4128 auto me = FlagBase::Match(arg);
4129 if (me && !wasMatched)
4136 iterator begin() noexcept
4138 return values.begin();
4141 const_iterator begin() const noexcept
4143 return values.begin();
4146 const_iterator cbegin() const noexcept
4148 return values.cbegin();
4151 iterator end() noexcept
4153 return values.end();
4156 const_iterator end() const noexcept
4158 return values.end();
4161 const_iterator cend() const noexcept
4163 return values.cend();
4177 typename Reader = ValueReader,
4178 template <
typename...>
class Map = detail::unordered_map>
4182 const Map<K, T> map;
4184 const T defaultValue;
4188 virtual std::vector<std::string> GetChoicesStrings(
const HelpParams &)
const override
4190 return detail::MapKeysToStrings(map);
4195 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_)
4200 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)
4204 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_)
4210 virtual void ParseValue(
const std::vector<std::string> &values_)
override
4212 const std::string &value_ = values_.at(0);
4216 if (!reader(name, value_, key))
4218 error = Error::Parse;
4222 reader(name, value_, key);
4224 auto it = map.find(key);
4225 if (it == std::end(map))
4227 std::ostringstream problem;
4228 problem <<
"Could not find key '" << key <<
"' in map for arg '" << name <<
"'";
4231 errorMsg = problem.str();
4237 this->value = it->second;
4276 virtual void Reset() noexcept
override
4278 ValueFlagBase::Reset();
4279 value = defaultValue;
4294 template <
typename...>
class List = detail::vector,
4295 typename Reader = ValueReader,
4296 template <
typename...>
class Map = detail::unordered_map>
4300 using Container = List<T>;
4301 const Map<K, T> map;
4303 const Container defaultValues;
4307 virtual std::vector<std::string> GetChoicesStrings(
const HelpParams &)
const override
4309 return detail::MapKeysToStrings(map);
4313 typedef T value_type;
4314 typedef typename Container::allocator_type allocator_type;
4315 typedef typename Container::pointer pointer;
4316 typedef typename Container::const_pointer const_pointer;
4317 typedef T& reference;
4318 typedef const T& const_reference;
4319 typedef typename Container::size_type size_type;
4320 typedef typename Container::difference_type difference_type;
4321 typedef typename Container::iterator iterator;
4322 typedef typename Container::const_iterator const_iterator;
4323 typedef std::reverse_iterator<iterator> reverse_iterator;
4324 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
4326 MapFlagList(
Group &group_,
const std::string &name_,
const std::string &help_,
Matcher &&matcher_,
const Map<K, T> &map_,
const Container &defaultValues_ = Container(),
Options options_ = {}):
4327 ValueFlagBase(name_, help_, std::move(matcher_), options_), map(map_), values(defaultValues_), defaultValues(defaultValues_)
4334 virtual void ParseValue(
const std::vector<std::string> &values_)
override
4336 const std::string &value_ = values_.at(0);
4340 if (!reader(name, value_, key))
4342 error = Error::Parse;
4346 reader(name, value_, key);
4348 auto it = map.find(key);
4349 if (it == std::end(map))
4351 std::ostringstream problem;
4352 problem <<
"Could not find key '" << key <<
"' in map for arg '" << name <<
"'";
4355 errorMsg = problem.str();
4361 this->values.emplace_back(it->second);
4400 virtual std::string Name()
const override
4402 return name + std::string(
"...");
4405 virtual void Reset() noexcept
override
4407 ValueFlagBase::Reset();
4408 values = defaultValues;
4411 virtual FlagBase *Match(
const EitherFlag &arg)
override
4413 const bool wasMatched = Matched();
4414 auto me = FlagBase::Match(arg);
4415 if (me && !wasMatched)
4422 iterator begin() noexcept
4424 return values.begin();
4427 const_iterator begin() const noexcept
4429 return values.begin();
4432 const_iterator cbegin() const noexcept
4434 return values.cbegin();
4437 iterator end() noexcept
4439 return values.end();
4442 const_iterator end() const noexcept
4444 return values.end();
4447 const_iterator cend() const noexcept
4449 return values.cend();
4460 typename Reader = ValueReader>
4465 const T defaultValue;
4468 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_)
4479 virtual void ParseValue(
const std::string &value_)
override
4482 if (!reader(name, value_, this->value))
4484 error = Error::Parse;
4488 reader(name, value_, this->value);
4529 virtual void Reset() noexcept
override
4531 PositionalBase::Reset();
4532 value = defaultValue;
4544 template <
typename...>
class List = detail::vector,
4545 typename Reader = ValueReader>
4549 using Container = List<T>;
4551 const Container defaultValues;
4555 typedef T value_type;
4556 typedef typename Container::allocator_type allocator_type;
4557 typedef typename Container::pointer pointer;
4558 typedef typename Container::const_pointer const_pointer;
4559 typedef T& reference;
4560 typedef const T& const_reference;
4561 typedef typename Container::size_type size_type;
4562 typedef typename Container::difference_type difference_type;
4563 typedef typename Container::iterator iterator;
4564 typedef typename Container::const_iterator const_iterator;
4565 typedef std::reverse_iterator<iterator> reverse_iterator;
4566 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
4568 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_)
4579 virtual void ParseValue(
const std::string &value_)
override
4583 if (!reader(name, value_, v))
4585 error = Error::Parse;
4589 reader(name, value_, v);
4591 values.insert(std::end(values), v);
4595 virtual std::string Name()
const override
4597 return name + std::string(
"...");
4635 virtual void Reset() noexcept
override
4637 PositionalBase::Reset();
4638 values = defaultValues;
4641 virtual PositionalBase *GetNextPositional()
override
4643 const bool wasMatched = Matched();
4644 auto me = PositionalBase::GetNextPositional();
4645 if (me && !wasMatched)
4652 iterator begin() noexcept
4654 return values.begin();
4657 const_iterator begin() const noexcept
4659 return values.begin();
4662 const_iterator cbegin() const noexcept
4664 return values.cbegin();
4667 iterator end() noexcept
4669 return values.end();
4672 const_iterator end() const noexcept
4674 return values.end();
4677 const_iterator cend() const noexcept
4679 return values.cend();
4693 typename Reader = ValueReader,
4694 template <
typename...>
class Map = detail::unordered_map>
4698 const Map<K, T> map;
4700 const T defaultValue;
4704 virtual std::vector<std::string> GetChoicesStrings(
const HelpParams &)
const override
4706 return detail::MapKeysToStrings(map);
4711 MapPositional(
Group &group_,
const std::string &name_,
const std::string &help_,
const Map<K, T> &map_,
const T &defaultValue_ = T(),
Options options_ = {}):
4712 PositionalBase(name_, help_, options_), map(map_), value(defaultValue_), defaultValue(defaultValue_)
4719 virtual void ParseValue(
const std::string &value_)
override
4723 if (!reader(name, value_, key))
4725 error = Error::Parse;
4729 reader(name, value_, key);
4731 auto it = map.find(key);
4732 if (it == std::end(map))
4734 std::ostringstream problem;
4735 problem <<
"Could not find key '" << key <<
"' in map for arg '" << name <<
"'";
4738 errorMsg = problem.str();
4744 this->value = it->second;
4785 virtual void Reset() noexcept
override
4787 PositionalBase::Reset();
4788 value = defaultValue;
4803 template <
typename...>
class List = detail::vector,
4804 typename Reader = ValueReader,
4805 template <
typename...>
class Map = detail::unordered_map>
4809 using Container = List<T>;
4811 const Map<K, T> map;
4813 const Container defaultValues;
4817 virtual std::vector<std::string> GetChoicesStrings(
const HelpParams &)
const override
4819 return detail::MapKeysToStrings(map);
4823 typedef T value_type;
4824 typedef typename Container::allocator_type allocator_type;
4825 typedef typename Container::pointer pointer;
4826 typedef typename Container::const_pointer const_pointer;
4827 typedef T& reference;
4828 typedef const T& const_reference;
4829 typedef typename Container::size_type size_type;
4830 typedef typename Container::difference_type difference_type;
4831 typedef typename Container::iterator iterator;
4832 typedef typename Container::const_iterator const_iterator;
4833 typedef std::reverse_iterator<iterator> reverse_iterator;
4834 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
4836 MapPositionalList(
Group &group_,
const std::string &name_,
const std::string &help_,
const Map<K, T> &map_,
const Container &defaultValues_ = Container(),
Options options_ = {}):
4837 PositionalBase(name_, help_, options_), map(map_), values(defaultValues_), defaultValues(defaultValues_)
4844 virtual void ParseValue(
const std::string &value_)
override
4848 if (!reader(name, value_, key))
4850 error = Error::Parse;
4854 reader(name, value_, key);
4856 auto it = map.find(key);
4857 if (it == std::end(map))
4859 std::ostringstream problem;
4860 problem <<
"Could not find key '" << key <<
"' in map for arg '" << name <<
"'";
4863 errorMsg = problem.str();
4869 this->values.emplace_back(it->second);
4909 virtual std::string Name()
const override
4911 return name + std::string(
"...");
4914 virtual void Reset() noexcept
override
4916 PositionalBase::Reset();
4917 values = defaultValues;
4920 virtual PositionalBase *GetNextPositional()
override
4922 const bool wasMatched = Matched();
4923 auto me = PositionalBase::GetNextPositional();
4924 if (me && !wasMatched)
4931 iterator begin() noexcept
4933 return values.begin();
4936 const_iterator begin() const noexcept
4938 return values.begin();
4941 const_iterator cbegin() const noexcept
4943 return values.cbegin();
4946 iterator end() noexcept
4948 return values.end();
4951 const_iterator end() const noexcept
4953 return values.end();
4956 const_iterator cend() const noexcept
4958 return values.cend();
4963#pragma pop_macro("min")
4964#pragma pop_macro("max")
A flag class that calls a function when it's matched.
Definition args.hxx:3517
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:3543
virtual void ParseValue(const std::vector< std::string > &value) override
Parse values of this option.
Definition args.hxx:3546
The main user facing command line argument parser class.
Definition args.hxx:2408
const std::string & ShortPrefix() const
The prefix for short flags.
Definition args.hxx:3075
void SetArgumentSeparations(const bool allowJoinedShortValue_, const bool allowJoinedLongValue_, const bool allowSeparateShortValue_, const bool allowSeparateLongValue_)
Change allowed option separation.
Definition args.hxx:3141
void Prog(const std::string &prog_)
The program name for help generation.
Definition args.hxx:3058
It ParseArgs(It begin, It end)
Parse all arguments.
Definition args.hxx:3297
const std::string & Prog() const
The program name for help generation.
Definition args.hxx:3054
void LongPrefix(const std::string &longprefix_)
The prefix for long flags.
Definition args.hxx:3067
void LongSeparator(const std::string &longseparator_)
The separator for long flags.
Definition args.hxx:3091
void Help(std::ostream &help_) const
Pass the help menu into an ostream.
Definition args.hxx:3158
const std::string & LongPrefix() const
The prefix for long flags.
Definition args.hxx:3063
const std::string & LongSeparator() const
The separator for long flags.
Definition args.hxx:3087
bool ParseCLI(const int argc, const char *const *argv)
Convenience function to parse the CLI from argc and argv.
Definition args.hxx:3328
const std::string & Terminator() const
The terminator that forcibly separates flags from positionals.
Definition args.hxx:3111
auto ParseArgs(const T &args) -> decltype(std::begin(args))
Parse all arguments.
Definition args.hxx:3317
void Terminator(const std::string &terminator_)
The terminator that forcibly separates flags from positionals.
Definition args.hxx:3115
void GetArgumentSeparations(bool &allowJoinedShortValue_, bool &allowJoinedLongValue_, bool &allowSeparateShortValue_, bool &allowSeparateLongValue_) const
Get the current argument separation parameters.
Definition args.hxx:3122
std::string Help() const
Generate a help menu as a string.
Definition args.hxx:3276
void ShortPrefix(const std::string &shortprefix_)
The prefix for short flags.
Definition args.hxx:3079
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:2482
Base class for all match types.
Definition args.hxx:883
void KickOut(bool kickout_) noexcept
Sets a kick-out value for building subparsers.
Definition args.hxx:978
bool KickOut() const noexcept
Gets the kick-out value for building subparsers.
Definition args.hxx:991
Main class for building subparsers.
Definition args.hxx:1868
const std::string & Name() const
The name of command.
Definition args.hxx:2003
virtual PositionalBase * GetNextPositional() override
Get the next ready positional, or nullptr if there is none.
Definition args.hxx:2104
const std::string & ProglinePostfix() const
The description that appears on the prog line after options.
Definition args.hxx:1973
void Description(const std::string &description_)
The description that appears above options.
Definition args.hxx:1988
virtual bool HasPositional() const override
Get whether this has any PositionalBase children.
Definition args.hxx:2140
const std::string & Description() const
The description that appears above options.
Definition args.hxx:1983
const std::string & Help() const
The description of command.
Definition args.hxx:2008
void Epilog(const std::string &epilog_)
The description that appears below options.
Definition args.hxx:1998
void ProglinePostfix(const std::string &proglinePostfix_)
The description that appears on the prog line after options.
Definition args.hxx:1978
virtual FlagBase * Match(const EitherFlag &flag) override
Return the first FlagBase that matches flag, or nullptr.
Definition args.hxx:2040
virtual bool HasCommand() const override
Get whether this has any Command children.
Definition args.hxx:2145
virtual std::vector< std::string > GetProgramLine(const HelpParams ¶ms) const override
Get the names of positional parameters.
Definition args.hxx:2209
virtual bool HasFlag() const override
Get whether this has any FlagBase children.
Definition args.hxx:2135
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:2234
const std::string & Epilog() const
The description that appears below options.
Definition args.hxx:1993
virtual bool Matched() const noexcept override
Whether or not this group matches validation.
Definition args.hxx:2021
void RequireCommand(bool value)
If value is true, parser will fail if no command was parsed.
Definition args.hxx:2015
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:1341
std::string Get() noexcept
Get the completion reply.
Definition args.hxx:1403
virtual void ParseValue(const std::vector< std::string > &value_) override
Parse values of this option.
Definition args.hxx:1346
An exception that contains autocompletion reply.
Definition args.hxx:432
A flag class that simply counts the number of times it's matched.
Definition args.hxx:3461
int & Get() noexcept
Get the count.
Definition args.hxx:3494
Base error class.
Definition args.hxx:351
Base class for all flag options.
Definition args.hxx:1170
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:3399
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:3419
virtual void ParseValue(const std::vector< std::string > &) override
Parse values of this option.
Definition args.hxx:3424
bool Get() const
Get whether this was matched.
Definition args.hxx:3414
Class for using global options in ArgumentParser.
Definition args.hxx:1787
Class for all kinds of validating groups, including ArgumentParser.
Definition args.hxx:1481
virtual bool HasCommand() const override
Get whether this has any Command children.
Definition args.hxx:1635
std::vector< Base * >::size_type MatchedChildren() const
Count the number of matched children this group has.
Definition args.hxx:1642
virtual bool HasPositional() const override
Get whether this has any PositionalBase children.
Definition args.hxx:1626
virtual std::vector< std::string > GetProgramLine(const HelpParams ¶ms) const override
Get the names of positional parameters.
Definition args.hxx:1695
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:1541
virtual bool HasFlag() const override
Get whether this has any FlagBase children.
Definition args.hxx:1617
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:1539
virtual bool Matched() const noexcept override
Whether or not this group matches validation.
Definition args.hxx:1651
virtual FlagBase * Match(const EitherFlag &flag) override
Return the first FlagBase that matches flag, or nullptr.
Definition args.hxx:1566
bool Get() const
Get validation.
Definition args.hxx:1658
const std::vector< Base * > & Children() const
Get all this group's children.
Definition args.hxx:1556
void Add(Base &child)
Append a child to this Group.
Definition args.hxx:1549
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:1665
virtual PositionalBase * GetNextPositional() override
Get the next ready positional, or nullptr if there is none.
Definition args.hxx:1601
Help flag class.
Definition args.hxx:3434
bool Get() const noexcept
Get whether this was matched.
Definition args.hxx:3452
virtual void ParseValue(const std::vector< std::string > &)
Parse values of this option.
Definition args.hxx:3440
An exception that indicates that the user has requested help.
Definition args.hxx:414
An optional argument-accepting flag class.
Definition args.hxx:3832
virtual void ParseValue(const std::vector< std::string > &value_) override
Parse values of this option.
Definition args.hxx:3860
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:3855
Errors in map lookups.
Definition args.hxx:396
A mapping value flag list class.
Definition args.hxx:4298
Container * operator->() noexcept
Get the values.
Definition args.hxx:4388
Container & Get() noexcept
Get the value.
Definition args.hxx:4367
virtual void ParseValue(const std::vector< std::string > &values_) override
Parse values of this option.
Definition args.hxx:4334
Container & operator*() noexcept
Get the value.
Definition args.hxx:4374
A mapping value flag class.
Definition args.hxx:4180
virtual void ParseValue(const std::vector< std::string > &values_) override
Parse values of this option.
Definition args.hxx:4210
T & Get() noexcept
Get the value.
Definition args.hxx:4243
T * operator->() noexcept
Get the value.
Definition args.hxx:4264
T & operator*() noexcept
Get the value.
Definition args.hxx:4250
A positional argument mapping list class.
Definition args.hxx:4807
Container & operator*() noexcept
Get the value.
Definition args.hxx:4883
Container * operator->() noexcept
Get the values.
Definition args.hxx:4897
Container & Get() noexcept
Get the value.
Definition args.hxx:4876
A positional argument mapping class.
Definition args.hxx:4696
T * operator->() noexcept
Get the value.
Definition args.hxx:4773
T & Get() noexcept
Get the value.
Definition args.hxx:4752
T & operator*() noexcept
Get the value.
Definition args.hxx:4759
A class of "matchers", specifying short and flags that can possibly be matched.
Definition args.hxx:500
EitherFlag GetShortOrAny() const
(INTERNAL) Get short flag if it exists or any long flag
Definition args.hxx:618
std::vector< EitherFlag > GetFlagStrings() const
(INTERNAL) Get all flag strings as a vector, with the prefixes embedded
Definition args.hxx:583
Matcher(Short &&shortIn, Long &&longIn)
Specify short and long flags separately as iterables.
Definition args.hxx:536
Matcher(ShortIt shortFlagsStart, ShortIt shortFlagsEnd, LongIt longFlagsStart, LongIt longFlagsEnd)
Specify short and long flags separately as iterators.
Definition args.hxx:511
bool Match(const std::string &flag) const
(INTERNAL) Check if there is a match of a long flag
Definition args.hxx:569
EitherFlag GetLongOrAny() const
(INTERNAL) Get long flag if it exists or any short flag
Definition args.hxx:600
bool Match(const char flag) const
(INTERNAL) Check if there is a match of a short flag
Definition args.hxx:562
bool Match(const EitherFlag &flag) const
(INTERNAL) Check if there is a match of a flag
Definition args.hxx:576
Matcher(std::initializer_list< EitherFlag > in)
Specify a mixed single initializer-list of both short and long flags.
Definition args.hxx:552
Base class for all match types that have a name.
Definition args.hxx:1023
void HelpDefault(const std::string &str)
Sets default value string that will be added to argument description.
Definition args.hxx:1059
void HelpChoices(const std::vector< std::string > &array)
Sets choices strings that will be added to argument description.
Definition args.hxx:1075
std::string HelpDefault(const HelpParams ¶ms) const
Gets default value string that will be added to argument description.
Definition args.hxx:1067
std::vector< std::string > HelpChoices(const HelpParams ¶ms) const
Gets choices strings that will be added to argument description.
Definition args.hxx:1083
A variadic arguments accepting flag class.
Definition args.hxx:3883
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:3915
virtual void ParseValue(const std::vector< std::string > &values_) override
Parse values of this option.
Definition args.hxx:3920
List< T > * operator->() noexcept
Get the values.
Definition args.hxx:3961
List< T > & operator*() noexcept
Get the value.
Definition args.hxx:3947
Errors that occur during regular parsing.
Definition args.hxx:369
Base class for positional options.
Definition args.hxx:1421
A positional argument class that pushes the found values into a list.
Definition args.hxx:4547
Container & operator*() noexcept
Get the value.
Definition args.hxx:4609
Container & Get() noexcept
Get the values.
Definition args.hxx:4602
Container * operator->() noexcept
Get the values.
Definition args.hxx:4623
A positional argument class.
Definition args.hxx:4462
T & operator*() noexcept
Get the value.
Definition args.hxx:4503
T & Get() noexcept
Get the value.
Definition args.hxx:4496
T * operator->() noexcept
Get the value.
Definition args.hxx:4517
Errors that when a required flag is omitted.
Definition args.hxx:387
Utility class for building subparsers with coroutines/callbacks.
Definition args.hxx:1813
void Parse()
Continue parsing arguments for new command.
Definition args.hxx:3362
const std::vector< std::string > & KickedOut() const noexcept
Returns a vector of kicked out arguments.
Definition args.hxx:1857
bool IsParsed() const
(INTERNAL) Determines whether Parse was called or not.
Definition args.hxx:1844
Errors that occur during usage.
Definition args.hxx:360
Errors that are detected from group validation after parsing finishes.
Definition args.hxx:378
Base class for value-accepting flag options.
Definition args.hxx:1314
virtual Nargs NumberOfArguments() const noexcept override
Defines how many values can be consumed by this option.
Definition args.hxx:1320
An argument-accepting flag class that pushes the found values into a list.
Definition args.hxx:4032
Container * operator->() noexcept
Get the values.
Definition args.hxx:4102
Container & Get() noexcept
Get the values.
Definition args.hxx:4081
Container & operator*() noexcept
Get the value.
Definition args.hxx:4088
virtual void ParseValue(const std::vector< std::string > &values_) override
Parse values of this option.
Definition args.hxx:4062
An argument-accepting flag class.
Definition args.hxx:3730
T & operator*() noexcept
Get the value.
Definition args.hxx:3789
T * operator->() noexcept
Get the value.
Definition args.hxx:3803
T & Get() noexcept
Get the value.
Definition args.hxx:3782
const T & GetDefault() noexcept
Get the default value.
Definition args.hxx:3817
virtual void ParseValue(const std::vector< std::string > &values_) override
Parse values of this option.
Definition args.hxx:3760
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:186
bool SafeMultiply(T a, T b, T &out)
Safe multiplication to prevent integer overflow.
Definition args.hxx:133
Options
Attributes for flags.
Definition args.hxx:638
@ 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.
bool SafeAdd(T a, T b, T &out)
Safe addition to prevent integer overflow.
Definition args.hxx:108
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:442
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:467
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:452
Default validators.
Definition args.hxx:1490
A simple structure of parameters for easy user-modifyable help menus.
Definition args.hxx:694
std::string programName
The program name for help generation.
Definition args.hxx:751
bool showCommandFullHelp
Show command's descriptions and epilog.
Definition args.hxx:759
bool proglineShowFlags
Show flags in program line.
Definition args.hxx:795
std::string usageString
Program line prefix.
Definition args.hxx:803
unsigned int width
The width of the help menu.
Definition args.hxx:697
std::string proglineNonrequiredClose
The postfix for progline non-required argument.
Definition args.hxx:791
unsigned int helpindent
The indent of the flag descriptions.
Definition args.hxx:712
bool proglinePreferShortFlags
Use short flags in program lines when possible.
Definition args.hxx:799
std::string proglineCommand
The prefix for progline when command has any subcommands.
Definition args.hxx:767
std::string proglineOptions
The postfix for progline when showProglineOptions is true and command has any flags.
Definition args.hxx:763
std::string longSeparator
The separator for long flags.
Definition args.hxx:747
bool showValueName
Show value name.
Definition args.hxx:815
bool showTerminator
Show the terminator when both options and positional parameters are present.
Definition args.hxx:723
std::string proglineValueOpen
The prefix for progline value.
Definition args.hxx:771
std::string valueOpen
The prefix for option value.
Definition args.hxx:823
unsigned int progtailindent
The indent of the program trailing lines for long parameters.
Definition args.hxx:703
std::string proglineNonrequiredOpen
The prefix for progline non-required argument.
Definition args.hxx:787
unsigned int descriptionindent
The indent of the description and epilogs.
Definition args.hxx:706
bool showCommandChildren
Show command's flags.
Definition args.hxx:755
bool showProglineOptions
Show the {OPTIONS} on the prog line when this is true.
Definition args.hxx:727
std::string valueClose
The postfix for option value.
Definition args.hxx:827
std::string longPrefix
The prefix for long flags.
Definition args.hxx:739
std::string proglineRequiredClose
The postfix for progline required argument.
Definition args.hxx:783
unsigned int flagindent
The indent of the flags.
Definition args.hxx:709
std::string optionsString
String shown in help before flags descriptions.
Definition args.hxx:807
bool addNewlineBeforeDescription
Add newline before flag description.
Definition args.hxx:819
std::string shortPrefix
The prefix for short flags.
Definition args.hxx:735
bool addDefault
Add default values to argument description.
Definition args.hxx:839
unsigned int gutter
The minimum gutter between each flag and its help.
Definition args.hxx:719
bool showProglinePositionals
Show the positionals on the prog line when this is true.
Definition args.hxx:731
std::string shortSeparator
The separator for short flags.
Definition args.hxx:743
std::string proglineValueClose
The postfix for progline value.
Definition args.hxx:775
bool useValueNameOnce
Display value name after all the long and short flags.
Definition args.hxx:811
std::string defaultString
The prefix for default values.
Definition args.hxx:843
std::string proglineRequiredOpen
The prefix for progline required argument.
Definition args.hxx:779
unsigned int eachgroupindent
The additional indent each group adds.
Definition args.hxx:715
unsigned int progindent
The indent of the program line.
Definition args.hxx:700
bool addChoices
Add choices to argument description.
Definition args.hxx:831
std::string choiceString
The prefix for choices.
Definition args.hxx:835
A number of arguments which can be consumed by an option.
Definition args.hxx:851
A default Reader class for argument classes.
Definition args.hxx:3557