From eef2da1547ba10b61c232a0df19374c5efbb7597 Mon Sep 17 00:00:00 2001 From: "Taylor C. Richberger" Date: Tue, 10 May 2016 16:40:57 -0600 Subject: rename everything --- CHANGELOG | 11 ++ CONTRIBUTING.md | 3 +- Doxyfile | 2 +- README.md | 108 ++++++++--------- args.hxx | 356 ++++++++++++++++++++++++++++---------------------------- test.cxx | 74 ++++++------ 6 files changed, 283 insertions(+), 271 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e69de29..0dd68bc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -0,0 +1,11 @@ +* 4.0.0 +Changed all wording: + +ArgFlag -> ValueFlag +Counter -> CounterFlag +PosArg -> Positional + +Argument now solely refers to command line arguments. +Value refers to the argument that flags or positionals can take and store. +Positional is a positional option, which contains a value. +Option refers to flags and positionals, which can contain values. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0231691..59f6696 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,4 @@ * Use Allman style * Don't use any non-standard-library libraries -* Keep everything in the args namespace \ No newline at end of file +* Keep everything in the args namespace +* Keep it simple and fast diff --git a/Doxyfile b/Doxyfile index 4182cbc..fad6b1f 100644 --- a/Doxyfile +++ b/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "args" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 3.0.4 +PROJECT_NUMBER = 4.0.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/README.md b/README.md index f7c6d26..a1abbcf 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,9 @@ A simple, small, flexible, single-header C++11 argument parsing library, in about 1K lines of code. -This is designed to somewhat replicate the behavior of Python's argparse, but -in C++, with static type checking, and hopefully a lot faster. +This is designed to appear somewhat similar to Python's argparse, but in C++, +with static type checking, and hopefully a lot faster (also allowing fully +nestable group logic, where Python's argparse does not). UTF-8 support is limited at best. No normalization is performed, so non-ascii characters are very best kept out of flags, and combined glyphs are probably @@ -31,16 +32,16 @@ There are also somewhat extensive examples below. It: -* lets you handle flags, flag+arguments, and positional arguments simply and - elegently, with the full help of static typechecking. +* lets you handle flags, flag+value, and positional arguments simply and + elegently, with the full help of static typechecking. * allows you to use your own types in a pretty simple way. * lets you use count flags, and lists of all argument-accepting types. * Allows full validation of groups of required arguments, though output isn't - pretty when something fails group validation. User validation functions are - accepted. Groups are fully nestable. + pretty when something fails group validation. User validation functions are + accepted. Groups are fully nestable. * Generates pretty help for you, with some good tweakable parameters. * Lets you customize all prefixes and most separators, allowing you to create - an infinite number of different argument syntaxes + an infinite number of different argument syntaxes * Lets you parse, by default, any type that has a stream extractor operator for it. If this doesn't work for your uses, you can supply a function and parse the string yourself if you like. @@ -56,14 +57,13 @@ There are tons of things this library does not do! ## It will not ever: * Allow you to create subparsers like argparse in a master parser (you can do - this yourself with iterators and multiple parsers) -* Allow one argument flag to take a specific number of arguments - (like `--foo first second`). You can instead split that with a flag list - (`--foo first --foo second`) or a custom type extraction - (`--foo first,second`) + this yourself with iterators and multiple parsers) +* Allow one argument flag to take a specific number of arguments (like `--foo + first second`). You can instead split that with a flag list (`--foo first + --foo second`) or a custom type extraction (`--foo first,second`) * Allow you to intermix multiple different prefix types (eg. `++foo` and - `--foo` in the same parser), though shortopt and longopt prefixes can be - different. + `--foo` in the same parser), though shortopt and longopt prefixes can be + different. * Allow you to have argument flags only optionally accept arguments * Allow you to make flag arguments sensitive to order (like gnu find), or make them sensitive to relative ordering with positional flags. The only @@ -72,12 +72,12 @@ There are tons of things this library does not do! * List positional options or flag arguments to each of their own respective items * Allow you to use a positional argument list before any other positional - arguments (the last argument list will slurp all subsequent positional - arguments). The logic for allowing this would be a lot more code than I'd - like, and would make static checking much more difficult, requiring us to - sort std::string arguments and pair them to positional arguments before - assigning them, rather than what we currently do, which is assiging them as - we go for better simplicity and speed. + arguments (the last argument list will slurp all subsequent positional + arguments). The logic for allowing this would be a lot more code than I'd + like, and would make static checking much more difficult, requiring us to + sort std::string arguments and pair them to positional arguments before + assigning them, rather than what we currently do, which is assiging them as + we go for better simplicity and speed. # How do I install it? @@ -174,9 +174,9 @@ int main() { std::vector arguments(carguments); args::ArgumentParser parser("This is a test program.", "This goes after the options."); - args::ArgFlag integer(parser, "integer", "The integer flag", args::Matcher{'i', "int"}); - args::ArgFlagList characters(parser, "characters", "The character flag", args::Matcher{'c', "char"}); - args::PosArgList numbers(parser, "numbers", "The numbers position list"); + args::ValueFlag integer(parser, "integer", "The integer flag", args::Matcher{'i', "int"}); + args::ValueFlagList characters(parser, "characters", "The character flag", args::Matcher{'c', "char"}); + args::PositionalList numbers(parser, "numbers", "The numbers position list"); parser.ParseArgs(arguments); const int i = args::get(integer); const std::vector c(args::get(characters)); @@ -409,10 +409,10 @@ int main(int argc, char **argv) { args::ArgumentParser parser("This is a test program.", "This goes after the options."); args::HelpFlag help(parser, "help", "Display this help menu", args::Matcher{'h', "help"}); - args::ArgFlag integer(parser, "integer", "The integer flag", args::Matcher({'i'})); - args::ArgFlagList characters(parser, "characters", "The character flag", args::Matcher({'c'})); - args::PosArg foo(parser, "foo", "The foo position"); - args::PosArgList numbers(parser, "numbers", "The numbers position list"); + args::ValueFlag integer(parser, "integer", "The integer flag", args::Matcher({'i'})); + args::ValueFlagList characters(parser, "characters", "The character flag", args::Matcher({'c'})); + args::Positional foo(parser, "foo", "The foo position"); + args::PositionalList numbers(parser, "numbers", "The numbers position list"); try { parser.ParseCLI(argc, argv); @@ -511,8 +511,8 @@ void DoublesReader(const std::string &name, const std::string &value, std::tuple int main(int argc, char **argv) { args::ArgumentParser parser("This is a test program."); - args::PosArg> ints(parser, "INTS", "This takes a pair of integers."); - args::PosArg, DoublesReader> doubles(parser, "DOUBLES", "This takes a pair of doubles."); + args::Positional> ints(parser, "INTS", "This takes a pair of integers."); + args::Positional, DoublesReader> doubles(parser, "DOUBLES", "This takes a pair of doubles."); try { parser.ParseCLI(argc, argv); @@ -589,27 +589,27 @@ int main(int argc, char **argv) { args::ArgumentParser parser("This is a test program with a really long description that is probably going to have to be wrapped across multiple different lines. This is a test to see how the line wrapping works", "This goes after the options. This epilog is also long enough that it will have to be properly wrapped to display correctly on the screen"); args::HelpFlag help(parser, "HELP", "Show this help menu.", args::Matcher{'h', "help"}); - args::ArgFlag foo(parser, "FOO", "The foo flag.", args::Matcher{'a', 'b', 'c', "a", "b", "c", "the-foo-flag"}); - args::ArgFlag bar(parser, "BAR", "The bar flag. This one has a lot of options, and will need wrapping in the description, along with its long flag list.", args::Matcher{'d', 'e', 'f', "d", "e", "f"}); - args::ArgFlag baz(parser, "FOO", "The baz flag. This one has a lot of options, and will need wrapping in the description, even with its short flag list.", args::Matcher({"baz"})); - args::PosArg pos1(parser, "POS1", "The pos1 argument."); - args::PosArgList poslist1(parser, "POSLIST1", "The poslist1 argument."); - args::PosArg pos2(parser, "POS2", "The pos2 argument."); - args::PosArgList poslist2(parser, "POSLIST2", "The poslist2 argument."); - args::PosArg pos3(parser, "POS3", "The pos3 argument."); - args::PosArgList poslist3(parser, "POSLIST3", "The poslist3 argument."); - args::PosArg pos4(parser, "POS4", "The pos4 argument."); - args::PosArgList poslist4(parser, "POSLIST4", "The poslist4 argument."); - args::PosArg pos5(parser, "POS5", "The pos5 argument."); - args::PosArgList poslist5(parser, "POSLIST5", "The poslist5 argument."); - args::PosArg pos6(parser, "POS6", "The pos6 argument."); - args::PosArgList poslist6(parser, "POSLIST6", "The poslist6 argument."); - args::PosArg pos7(parser, "POS7", "The pos7 argument."); - args::PosArgList poslist7(parser, "POSLIST7", "The poslist7 argument."); - args::PosArg pos8(parser, "POS8", "The pos8 argument."); - args::PosArgList poslist8(parser, "POSLIST8", "The poslist8 argument."); - args::PosArg pos9(parser, "POS9", "The pos9 argument."); - args::PosArgList poslist9(parser, "POSLIST9", "The poslist9 argument."); + args::ValueFlag foo(parser, "FOO", "The foo flag.", args::Matcher{'a', 'b', 'c', "a", "b", "c", "the-foo-flag"}); + args::ValueFlag bar(parser, "BAR", "The bar flag. This one has a lot of options, and will need wrapping in the description, along with its long flag list.", args::Matcher{'d', 'e', 'f', "d", "e", "f"}); + args::ValueFlag baz(parser, "FOO", "The baz flag. This one has a lot of options, and will need wrapping in the description, even with its short flag list.", args::Matcher({"baz"})); + args::Positional pos1(parser, "POS1", "The pos1 argument."); + args::PositionalList poslist1(parser, "POSLIST1", "The poslist1 argument."); + args::Positional pos2(parser, "POS2", "The pos2 argument."); + args::PositionalList poslist2(parser, "POSLIST2", "The poslist2 argument."); + args::Positional pos3(parser, "POS3", "The pos3 argument."); + args::PositionalList poslist3(parser, "POSLIST3", "The poslist3 argument."); + args::Positional pos4(parser, "POS4", "The pos4 argument."); + args::PositionalList poslist4(parser, "POSLIST4", "The poslist4 argument."); + args::Positional pos5(parser, "POS5", "The pos5 argument."); + args::PositionalList poslist5(parser, "POSLIST5", "The poslist5 argument."); + args::Positional pos6(parser, "POS6", "The pos6 argument."); + args::PositionalList poslist6(parser, "POSLIST6", "The poslist6 argument."); + args::Positional pos7(parser, "POS7", "The pos7 argument."); + args::PositionalList poslist7(parser, "POSLIST7", "The poslist7 argument."); + args::Positional pos8(parser, "POS8", "The pos8 argument."); + args::PositionalList poslist8(parser, "POSLIST8", "The poslist8 argument."); + args::Positional pos9(parser, "POS9", "The pos9 argument."); + args::PositionalList poslist9(parser, "POSLIST9", "The poslist9 argument."); try { parser.ParseCLI(argc, argv); @@ -697,10 +697,10 @@ int main(int argc, char **argv) parser.LongPrefix(""); parser.LongSeparator("="); args::HelpFlag help(parser, "HELP", "Show this help menu.", args::Matcher({"help"})); - args::ArgFlag bs(parser, "BYTES", "Block size", args::Matcher({"bs"}), 512); - args::ArgFlag skip(parser, "BYTES", "Bytes to skip", args::Matcher({"skip"}), 0); - args::ArgFlag input(parser, "BLOCK SIZE", "Block size", args::Matcher({"if"})); - args::ArgFlag output(parser, "BLOCK SIZE", "Block size", args::Matcher({"of"})); + args::ValueFlag bs(parser, "BYTES", "Block size", args::Matcher({"bs"}), 512); + args::ValueFlag skip(parser, "BYTES", "Bytes to skip", args::Matcher({"skip"}), 0); + args::ValueFlag input(parser, "BLOCK SIZE", "Block size", args::Matcher({"if"})); + args::ValueFlag output(parser, "BLOCK SIZE", "Block size", args::Matcher({"of"})); try { parser.ParseCLI(argc, argv); diff --git a/args.hxx b/args.hxx index 3a60d77..4ef5b62 100644 --- a/args.hxx +++ b/args.hxx @@ -45,10 +45,10 @@ namespace args * If the Get() function of the type returns a reference, so does this, and * the value will be modifiable. */ - template - auto get(Arg &arg) -> decltype(arg.Get()) + template + auto get(Option &option) -> decltype(option.Get()) { - return arg.Get(); + return option.Get(); } /** (INTERNAL) Count UTF-8 glyphs @@ -174,50 +174,50 @@ namespace args /** A simple unified option type for unified initializer lists for the Matcher class. */ - struct EitherOpt + struct EitherFlag { const bool isShort; - const char shortOpt; - const std::string longOpt; - EitherOpt(const std::string &opt) : isShort(false), shortOpt(), longOpt(opt) {} - EitherOpt(const char *opt) : isShort(false), shortOpt(), longOpt(opt) {} - EitherOpt(const char opt) : isShort(true), shortOpt(opt), longOpt() {} + const char shortFlag; + const std::string longFlag; + EitherFlag(const std::string &flag) : isShort(false), shortFlag(), longFlag(flag) {} + EitherFlag(const char *flag) : isShort(false), shortFlag(), longFlag(flag) {} + EitherFlag(const char flag) : isShort(true), shortFlag(flag), longFlag() {} - /** Get just the long options from an initializer list of EitherOpts + /** Get just the long flags from an initializer list of EitherFlags */ - static std::unordered_set GetLong(std::initializer_list opts) + static std::unordered_set GetLong(std::initializer_list flags) { - std::unordered_set longOpts; - for (const EitherOpt &opt: opts) + std::unordered_set longFlags; + for (const EitherFlag &flag: flags) { - if (!opt.isShort) + if (!flag.isShort) { - longOpts.insert(opt.longOpt); + longFlags.insert(flag.longFlag); } } - return longOpts; + return longFlags; } - /** Get just the short options from an initializer list of EitherOpts + /** Get just the short flags from an initializer list of EitherFlags */ - static std::unordered_set GetShort(std::initializer_list opts) + static std::unordered_set GetShort(std::initializer_list flags) { - std::unordered_set shortOpts; - for (const EitherOpt &opt: opts) + std::unordered_set shortFlags; + for (const EitherFlag &flag: flags) { - if (opt.isShort) + if (flag.isShort) { - shortOpts.insert(opt.shortOpt); + shortFlags.insert(flag.shortFlag); } } - return shortOpts; + return shortFlags; } }; - /** A class of "matchers", specifying short and long options that can - * possibly be matched. + /** A class of "matchers", specifying short and flags that can possibly be + * matched. * * This is supposed to be constructed and then passed in, not used directly * from user code. @@ -225,96 +225,96 @@ namespace args class Matcher { private: - const std::unordered_set shortOpts; - const std::unordered_set longOpts; + const std::unordered_set shortFlags; + const std::unordered_set longFlags; public: - /** Specify short and long opts separately as iterators + /** Specify short and long flags separately as iterators * - * ex: `args::Matcher(shortOpts.begin(), shortOpts.end(), longOpts.begin(), longOpts.end())` + * ex: `args::Matcher(shortFlags.begin(), shortFlags.end(), longFlags.begin(), longFlags.end())` */ template - Matcher(ShortIt shortOptsStart, ShortIt shortOptsEnd, LongIt longOptsStart, LongIt longOptsEnd) : - shortOpts(shortOptsStart, shortOptsEnd), - longOpts(longOptsStart, longOptsEnd) + Matcher(ShortIt shortFlagsStart, ShortIt shortFlagsEnd, LongIt longFlagsStart, LongIt longFlagsEnd) : + shortFlags(shortFlagsStart, shortFlagsEnd), + longFlags(longFlagsStart, longFlagsEnd) {} - /** Specify short and long opts separately as iterables + /** Specify short and long flags separately as iterables * - * ex: `args::Matcher(shortOpts, longOpts)` + * ex: `args::Matcher(shortFlags, longFlags)` */ template Matcher(Short &&shortIn, Long &&longIn) : - shortOpts(std::begin(shortIn), std::end(shortIn)), longOpts(std::begin(longIn), std::end(longIn)) + shortFlags(std::begin(shortIn), std::end(shortIn)), longFlags(std::begin(longIn), std::end(longIn)) {} - /** Specify a mixed single initializer-list of both short and long opts + /** Specify a mixed single initializer-list of both short and long flags * * This is the fancy one. It takes a single initializer list of - * any number of any mixed kinds of options. Chars are - * automatically interpreted as short options, and strings are - * automatically interpreted as long options: + * any number of any mixed kinds of flags. Chars are + * automatically interpreted as short flags, and strings are + * automatically interpreted as long flags: * * args::Matcher{'a'} * args::Matcher{"foo"} * args::Matcher{'h', "help"} * args::Matcher{"foo", 'f', 'F', "FoO"} */ - Matcher(std::initializer_list in) : - shortOpts(EitherOpt::GetShort(in)), longOpts(EitherOpt::GetLong(in)) {} + Matcher(std::initializer_list in) : + shortFlags(EitherFlag::GetShort(in)), longFlags(EitherFlag::GetLong(in)) {} - Matcher(Matcher &&other) : shortOpts(std::move(other.shortOpts)), longOpts(std::move(other.longOpts)) + Matcher(Matcher &&other) : shortFlags(std::move(other.shortFlags)), longFlags(std::move(other.longFlags)) {} ~Matcher() {} - /** (INTERNAL) Check if there is a match of a short opt + /** (INTERNAL) Check if there is a match of a short flag */ - bool Match(const char opt) const + bool Match(const char flag) const { - return shortOpts.find(opt) != shortOpts.end(); + return shortFlags.find(flag) != shortFlags.end(); } - /** (INTERNAL) Check if there is a match of a long opt + /** (INTERNAL) Check if there is a match of a long flag */ - bool Match(const std::string &opt) const + bool Match(const std::string &flag) const { - return longOpts.find(opt) != longOpts.end(); + return longFlags.find(flag) != longFlags.end(); } - /** (INTERNAL) Get all option strings as a vector, with the prefixes embedded + /** (INTERNAL) Get all flag strings as a vector, with the prefixes embedded */ - std::vector GetOptionStrings(const std::string &shortPrefix, const std::string &longPrefix) const + std::vector GetFlagStrings(const std::string &shortPrefix, const std::string &longPrefix) const { - std::vector optStrings; - optStrings.reserve(shortOpts.size() + longOpts.size()); - for (const char opt: shortOpts) + std::vector flagStrings; + flagStrings.reserve(shortFlags.size() + longFlags.size()); + for (const char flag: shortFlags) { - optStrings.emplace_back(shortPrefix + std::string(1, opt)); + flagStrings.emplace_back(shortPrefix + std::string(1, flag)); } - for (const std::string &opt: longOpts) + for (const std::string &flag: longFlags) { - optStrings.emplace_back(longPrefix + opt); + flagStrings.emplace_back(longPrefix + flag); } - return optStrings; + return flagStrings; } - /** (INTERNAL) Get all option strings as a vector, with the prefixes and names embedded + /** (INTERNAL) Get all flag strings as a vector, with the prefixes and names embedded */ - std::vector GetOptionStrings(const std::string &shortPrefix, const std::string &longPrefix, const std::string &name, const std::string &shortSeparator, const std::string longSeparator) const + std::vector GetFlagStrings(const std::string &shortPrefix, const std::string &longPrefix, const std::string &name, const std::string &shortSeparator, const std::string longSeparator) const { const std::string bracedname(std::string("[") + name + "]"); - std::vector optStrings; - optStrings.reserve(shortOpts.size() + longOpts.size()); - for (const char opt: shortOpts) + std::vector flagStrings; + flagStrings.reserve(shortFlags.size() + longFlags.size()); + for (const char flag: shortFlags) { - optStrings.emplace_back(shortPrefix + std::string(1, opt) + shortSeparator + bracedname); + flagStrings.emplace_back(shortPrefix + std::string(1, flag) + shortSeparator + bracedname); } - for (const std::string &opt: longOpts) + for (const std::string &flag: longFlags) { - optStrings.emplace_back(longPrefix + opt + longSeparator + bracedname); + flagStrings.emplace_back(longPrefix + flag + longSeparator + bracedname); } - return optStrings; + return flagStrings; } }; @@ -377,7 +377,7 @@ namespace args } }; - /** Base class for all flag arguments + /** Base class for all flag options */ class FlagBase : public NamedBase { @@ -389,9 +389,9 @@ namespace args virtual ~FlagBase() {} - virtual FlagBase *Match(const std::string &arg) + virtual FlagBase *Match(const std::string &flag) { - if (matcher.Match(arg)) + if (matcher.Match(flag)) { matched = true; return this; @@ -399,9 +399,9 @@ namespace args return nullptr; } - virtual FlagBase *Match(const char arg) + virtual FlagBase *Match(const char flag) { - if (matcher.Match(arg)) + if (matcher.Match(flag)) { matched = true; return this; @@ -412,11 +412,11 @@ namespace args virtual std::tuple GetDescription(const std::string &shortPrefix, const std::string &longPrefix, const std::string &shortSeparator, const std::string &longSeparator) const override { std::tuple description; - const std::vector optStrings(matcher.GetOptionStrings(shortPrefix, longPrefix)); + const std::vector flagStrings(matcher.GetFlagStrings(shortPrefix, longPrefix)); std::ostringstream flagstream; - for (auto it = std::begin(optStrings); it != std::end(optStrings); ++it) + for (auto it = std::begin(flagStrings); it != std::end(flagStrings); ++it) { - if (it != std::begin(optStrings)) + if (it != std::begin(flagStrings)) { flagstream << ", "; } @@ -428,23 +428,23 @@ namespace args } }; - /** Base class for argument-accepting flag arguments + /** Base class for value-accepting flag options */ - class ArgFlagBase : public FlagBase + class ValueFlagBase : public FlagBase { public: - ArgFlagBase(const std::string &name, const std::string &help, Matcher &&matcher) : FlagBase(name, help, std::move(matcher)) {} - virtual ~ArgFlagBase() {} - virtual void ParseArg(const std::string &value) = 0; + ValueFlagBase(const std::string &name, const std::string &help, Matcher &&matcher) : FlagBase(name, help, std::move(matcher)) {} + virtual ~ValueFlagBase() {} + virtual void ParseValue(const std::string &value) = 0; virtual std::tuple GetDescription(const std::string &shortPrefix, const std::string &longPrefix, const std::string &shortSeparator, const std::string &longSeparator) const override { std::tuple description; - const std::vector optStrings(matcher.GetOptionStrings(shortPrefix, longPrefix, name, shortSeparator, longSeparator)); + const std::vector flagStrings(matcher.GetFlagStrings(shortPrefix, longPrefix, name, shortSeparator, longSeparator)); std::ostringstream flagstream; - for (auto it = std::begin(optStrings); it != std::end(optStrings); ++it) + for (auto it = std::begin(flagStrings); it != std::end(flagStrings); ++it) { - if (it != std::begin(optStrings)) + if (it != std::begin(flagStrings)) { flagstream << ", "; } @@ -456,7 +456,7 @@ namespace args } }; - /** Base class for positional arguments + /** Base class for positional options */ class PosBase : public NamedBase { @@ -472,7 +472,7 @@ namespace args return ready; } - virtual void ParseArg(const std::string &value) = 0; + virtual void ParseValue(const std::string &value) = 0; }; /** Class for all kinds of validating groups, including ArgumentParser @@ -491,27 +491,27 @@ namespace args } virtual ~Group() {} - /** Return the first FlagBase that matches arg, or nullptr + /** Return the first FlagBase that matches flag, or nullptr * - * \param arg The argument with prefixes stripped + * \param flag The flag with prefixes stripped * \return the first matching FlagBase pointer, or nullptr if there is no match */ - FlagBase *Match(const std::string &arg) + FlagBase *Match(const std::string &flag) { for (Base *child: children) { - FlagBase *flag = dynamic_cast(child); + FlagBase *flagBase = dynamic_cast(child); Group *group = dynamic_cast(child); - if (flag) + if (flagBase) { - FlagBase *match = flag->Match(arg); + FlagBase *match = flagBase->Match(flag); if (match) { return match; } } else if (group) { - FlagBase *match = group->Match(arg); + FlagBase *match = group->Match(flag); if (match) { return match; @@ -521,27 +521,27 @@ namespace args return nullptr; } - /** Return the first FlagBase that matches arg, or nullptr + /** Return the first FlagBase that matches flag, or nullptr * - * \param arg The argument with prefixes stripped + * \param flag The flag with prefixes stripped * \return the first matching FlagBase pointer, or nullptr if there is no match */ - FlagBase *Match(const char arg) + FlagBase *Match(const char flag) { for (Base *child: children) { - FlagBase *flag = dynamic_cast(child); + FlagBase *flagBase = dynamic_cast(child); Group *group = dynamic_cast(child); - if (flag) + if (flagBase) { - FlagBase *match = flag->Match(arg); + FlagBase *match = flagBase->Match(flag); if (match) { return match; } } else if (group) { - FlagBase *match = group->Match(arg); + FlagBase *match = group->Match(flag); if (match) { return match; @@ -551,7 +551,7 @@ namespace args return nullptr; } - /** Get the next ready positional parameter, or nullptr if there is none + /** Get the next ready positional, or nullptr if there is none * * \return the first ready PosBase pointer, or nullptr if there is no match */ @@ -776,10 +776,10 @@ namespace args std::string terminator; - bool allowJoinedShortArgument; - bool allowJoinedLongArgument; - bool allowSeparateShortArgument; - bool allowSeparateLongArgument; + bool allowJoinedShortValue; + bool allowJoinedLongValue; + bool allowSeparateShortValue; + bool allowSeparateLongValue; public: /** A simple structure of parameters for easy user-modifyable help menus @@ -825,17 +825,17 @@ namespace args bool showProglinePositionals = true; } helpParams; ArgumentParser(const std::string &description, const std::string &epilog = std::string()) : - Group("arguments", Group::Validators::AllChildGroups), + Group("options", Group::Validators::AllChildGroups), description(description), epilog(epilog), longprefix("--"), shortprefix("-"), longseparator("="), terminator("--"), - allowJoinedShortArgument(true), - allowJoinedLongArgument(true), - allowSeparateShortArgument(true), - allowSeparateLongArgument(true) {} + allowJoinedShortValue(true), + allowJoinedLongValue(true), + allowSeparateShortValue(true), + allowSeparateLongValue(true) {} /** The program name for help generation */ @@ -846,11 +846,11 @@ namespace args void Prog(const std::string &prog) { this->prog = prog; } - /** The description that appears on the prog line after options and positionals + /** The description that appears on the prog line after options */ const std::string &ProglinePostfix() const { return proglinePostfix; } - /** The description that appears on the prog line after options and positionals + /** The description that appears on the prog line after options */ void ProglinePostfix(const std::string &proglinePostfix) { this->proglinePostfix = proglinePostfix; } @@ -873,29 +873,29 @@ namespace args void Epilog(const std::string &epilog) { this->epilog = epilog; } - /** The prefix for long options + /** The prefix for long flags */ const std::string &LongPrefix() const { return longprefix; } - /** The prefix for long options + /** The prefix for long flags */ void LongPrefix(const std::string &longprefix) { this->longprefix = longprefix; } - /** The prefix for short options + /** The prefix for short flags */ const std::string &ShortPrefix() const { return shortprefix; } - /** The prefix for short options + /** The prefix for short flags */ void ShortPrefix(const std::string &shortprefix) { this->shortprefix = shortprefix; } - /** The separator for long options + /** The separator for long flags */ const std::string &LongSeparator() const { return longseparator; } - /** The separator for long options + /** The separator for long flags */ void LongSeparator(const std::string &longseparator) { @@ -906,11 +906,11 @@ namespace args this->longseparator = longseparator; } - /** The terminator that separates short options from long ones + /** The terminator that forcibly separates flags from positionals */ const std::string &Terminator() const { return terminator; } - /** The terminator that separates short options from long ones + /** The terminator that forcibly separates flags from positionals */ void Terminator(const std::string &terminator) { this->terminator = terminator; } @@ -920,34 +920,34 @@ namespace args * See SetArgumentSeparations for details on what each one means. */ void GetArgumentSeparations( - bool &allowJoinedShortArgument, - bool &allowJoinedLongArgument, - bool &allowSeparateShortArgument, - bool &allowSeparateLongArgument) const - { - allowJoinedShortArgument = this->allowJoinedShortArgument; - allowJoinedLongArgument = this->allowJoinedLongArgument; - allowSeparateShortArgument = this->allowSeparateShortArgument; - allowSeparateLongArgument = this->allowSeparateLongArgument; + bool &allowJoinedShortValue, + bool &allowJoinedLongValue, + bool &allowSeparateShortValue, + bool &allowSeparateLongValue) const + { + allowJoinedShortValue = this->allowJoinedShortValue; + allowJoinedLongValue = this->allowJoinedLongValue; + allowSeparateShortValue = this->allowSeparateShortValue; + allowSeparateLongValue = this->allowSeparateLongValue; } /** Change allowed option separation. * - * \param allowJoinedShortArgument Allow a short flag that accepts an argument to be passed its argument immediately next to it (ie. in the same argv field) - * \param allowJoinedLongArgument Allow a long flag that accepts an argument to be passed its argument separated by the longseparator (ie. in the same argv field) - * \param allowSeparateShortArgument Allow a short flag that accepts an argument to be passed its argument separated by whitespace (ie. in the next argv field) - * \param allowSeparateLongArgument Allow a long flag that accepts an argument to be passed its argument separated by whitespace (ie. in the next argv field) + * \param allowJoinedShortValue Allow a short flag that accepts an argument to be passed its argument immediately next to it (ie. in the same argv field) + * \param allowJoinedLongValue Allow a long flag that accepts an argument to be passed its argument separated by the longseparator (ie. in the same argv field) + * \param allowSeparateShortValue Allow a short flag that accepts an argument to be passed its argument separated by whitespace (ie. in the next argv field) + * \param allowSeparateLongValue Allow a long flag that accepts an argument to be passed its argument separated by whitespace (ie. in the next argv field) */ void SetArgumentSeparations( - const bool allowJoinedShortArgument, - const bool allowJoinedLongArgument, - const bool allowSeparateShortArgument, - const bool allowSeparateLongArgument) - { - this->allowJoinedShortArgument = allowJoinedShortArgument; - this->allowJoinedLongArgument = allowJoinedLongArgument; - this->allowSeparateShortArgument = allowSeparateShortArgument; - this->allowSeparateLongArgument = allowSeparateLongArgument; + const bool allowJoinedShortValue, + const bool allowJoinedLongValue, + const bool allowSeparateShortValue, + const bool allowSeparateLongValue) + { + this->allowJoinedShortValue = allowJoinedShortValue; + this->allowJoinedLongValue = allowJoinedLongValue; + this->allowSeparateShortValue = allowSeparateShortValue; + this->allowSeparateLongValue = allowSeparateLongValue; } /** Pass the help menu into an ostream @@ -1001,7 +1001,7 @@ namespace args } help << "\n"; help << std::string(helpParams.progindent, ' ') << "OPTIONS:\n\n"; - for (const auto &description: GetChildDescriptions(shortprefix, longprefix, allowJoinedShortArgument ? "" : " ", allowJoinedLongArgument ? longseparator : " ")) + for (const auto &description: GetChildDescriptions(shortprefix, longprefix, allowJoinedShortValue ? "" : " ", allowJoinedLongValue ? longseparator : " ")) { const unsigned int groupindent = std::get<2>(description) * helpParams.eachgroupindent; const std::vector flags(Wrap(std::get<0>(description), helpParams.width - (helpParams.flagindent + helpParams.helpindent + helpParams.gutter))); @@ -1093,14 +1093,14 @@ namespace args FlagBase *base = Match(arg); if (base) { - ArgFlagBase *argbase = dynamic_cast(base); + ValueFlagBase *argbase = dynamic_cast(base); if (argbase) { if (separator != argchunk.npos) { - if (allowJoinedLongArgument) + if (allowJoinedLongValue) { - argbase->ParseArg(argchunk.substr(separator + longseparator.size())); + argbase->ParseValue(argchunk.substr(separator + longseparator.size())); } else { std::ostringstream problem; @@ -1117,9 +1117,9 @@ namespace args throw ParseError(problem.str().c_str()); } - if (allowSeparateLongArgument) + if (allowSeparateLongValue) { - argbase->ParseArg(*it); + argbase->ParseValue(*it); } else { std::ostringstream problem; @@ -1150,15 +1150,15 @@ namespace args Base *base = Match(arg); if (base) { - ArgFlagBase *argbase = dynamic_cast(base); + ValueFlagBase *argbase = dynamic_cast(base); if (argbase) { const std::string arg(++argit, std::end(argchunk)); if (!arg.empty()) { - if (allowJoinedShortArgument) + if (allowJoinedShortValue) { - argbase->ParseArg(arg); + argbase->ParseValue(arg); } else { std::ostringstream problem; @@ -1175,9 +1175,9 @@ namespace args throw ParseError(problem.str().c_str()); } - if (allowSeparateShortArgument) + if (allowSeparateShortValue) { - argbase->ParseArg(*it); + argbase->ParseValue(*it); } else { std::ostringstream problem; @@ -1200,7 +1200,7 @@ namespace args PosBase *pos = GetNextPos(); if (pos) { - pos->ParseArg(chunk); + pos->ParseValue(chunk); } else { std::ostringstream problem; @@ -1307,15 +1307,15 @@ namespace args /** A flag class that simply counts the number of times it's matched */ - class Counter : public Flag + class CounterFlag : public Flag { private: int count; public: - Counter(Group &group, const std::string &name, const std::string &help, Matcher &&matcher, const int startcount = 0): Flag(group, name, help, std::move(matcher)), count(startcount) {} + CounterFlag(Group &group, const std::string &name, const std::string &help, Matcher &&matcher, const int startcount = 0): Flag(group, name, help, std::move(matcher)), count(startcount) {} - virtual ~Counter() {} + virtual ~CounterFlag() {} virtual FlagBase *Match(const std::string &arg) override { @@ -1351,7 +1351,7 @@ namespace args * raises a ParseError if there are any characters left. */ template - void ArgReader(const std::string &name, const std::string &value, T &destination) + void ValueReader(const std::string &name, const std::string &value, T &destination) { std::istringstream ss(value); ss >> destination; @@ -1364,13 +1364,13 @@ namespace args } } - /** std::string specialization for ArgReader + /** std::string specialization for ValueReader * * By default, stream extraction into a string splits on white spaces, and * it is more efficient to ust copy a string into the destination. */ template <> - void ArgReader(const std::string &name, const std::string &value, std::string &destination) + void ValueReader(const std::string &name, const std::string &value, std::string &destination) { destination.assign(value); } @@ -1380,22 +1380,22 @@ namespace args * \tparam T the type to extract the argument as * \tparam Reader The function used to read the argument, taking the name, value, and destination reference */ - template > - class ArgFlag : public ArgFlagBase + template > + class ValueFlag : public ValueFlagBase { private: T value; public: - ArgFlag(Group &group, const std::string &name, const std::string &help, Matcher &&matcher, const T &defaultValue = T()): ArgFlagBase(name, help, std::move(matcher)), value(defaultValue) + ValueFlag(Group &group, const std::string &name, const std::string &help, Matcher &&matcher, const T &defaultValue = T()): ValueFlagBase(name, help, std::move(matcher)), value(defaultValue) { group.Add(*this); } - virtual ~ArgFlag() {} + virtual ~ValueFlag() {} - virtual void ParseArg(const std::string &value) override + virtual void ParseValue(const std::string &value) override { Reader(name, value, this->value); } @@ -1417,22 +1417,22 @@ namespace args template < typename T, typename List = std::vector, - void (*Reader)(const std::string &, const std::string &, T&) = ArgReader> - class ArgFlagList : public ArgFlagBase + void (*Reader)(const std::string &, const std::string &, T&) = ValueReader> + class ValueFlagList : public ValueFlagBase { private: List values; public: - ArgFlagList(Group &group, const std::string &name, const std::string &help, Matcher &&matcher, const List &defaultValues = List()): ArgFlagBase(name, help, std::move(matcher)), values(defaultValues) + ValueFlagList(Group &group, const std::string &name, const std::string &help, Matcher &&matcher, const List &defaultValues = List()): ValueFlagBase(name, help, std::move(matcher)), values(defaultValues) { group.Add(*this); } - virtual ~ArgFlagList() {} + virtual ~ValueFlagList() {} - virtual void ParseArg(const std::string &value) override + virtual void ParseValue(const std::string &value) override { values.emplace_back(); Reader(name, value, values.back()); @@ -1451,20 +1451,20 @@ namespace args * \tparam T the type to extract the argument as * \tparam Reader The function used to read the argument, taking the name, value, and destination reference */ - template > - class PosArg : public PosBase + template > + class Positional : public PosBase { private: T value; public: - PosArg(Group &group, const std::string &name, const std::string &help, const T &defaultValue = T()): PosBase(name, help), value(defaultValue) + Positional(Group &group, const std::string &name, const std::string &help, const T &defaultValue = T()): PosBase(name, help), value(defaultValue) { group.Add(*this); } - virtual ~PosArg() {} + virtual ~Positional() {} - virtual void ParseArg(const std::string &value) override + virtual void ParseValue(const std::string &value) override { Reader(name, value, this->value); ready = false; @@ -1488,21 +1488,21 @@ namespace args template < typename T, typename List = std::vector, - void (*Reader)(const std::string &, const std::string &, T&) = ArgReader> - class PosArgList : public PosBase + void (*Reader)(const std::string &, const std::string &, T&) = ValueReader> + class PositionalList : public PosBase { private: List values; public: - PosArgList(Group &group, const std::string &name, const std::string &help, const List &defaultValues = List()): PosBase(name, help), values(defaultValues) + PositionalList(Group &group, const std::string &name, const std::string &help, const List &defaultValues = List()): PosBase(name, help), values(defaultValues) { group.Add(*this); } - virtual ~PosArgList() {} + virtual ~PositionalList() {} - virtual void ParseArg(const std::string &value) override + virtual void ParseValue(const std::string &value) override { values.emplace_back(); Reader(name, value, values.back()); diff --git a/test.cxx b/test.cxx index c5ab1b3..4d4e6ef 100644 --- a/test.cxx +++ b/test.cxx @@ -52,9 +52,9 @@ TEST_CASE("Boolean flags work as expected, with clustering", "[args]") TEST_CASE("Count flag works as expected", "[args]") { args::ArgumentParser parser("This is a test program.", "This goes after the options."); - args::Counter foo(parser, "FOO", "test flag", args::Matcher{'f', "foo"}); - args::Counter bar(parser, "BAR", "test flag", args::Matcher{'b', "bar"}, 7); - args::Counter baz(parser, "BAZ", "test flag", args::Matcher{'z', "baz"}, 7); + args::CounterFlag foo(parser, "FOO", "test flag", args::Matcher{'f', "foo"}); + args::CounterFlag bar(parser, "BAR", "test flag", args::Matcher{'b', "bar"}, 7); + args::CounterFlag baz(parser, "BAZ", "test flag", args::Matcher{'z', "baz"}, 7); parser.ParseArgs(std::vector{"--foo", "-fb", "--bar", "-b", "-f", "--foo"}); REQUIRE(foo); REQUIRE(bar); @@ -67,10 +67,10 @@ TEST_CASE("Count flag works as expected", "[args]") TEST_CASE("Argument flags work as expected, with clustering", "[args]") { args::ArgumentParser parser("This is a test program.", "This goes after the options."); - args::ArgFlag foo(parser, "FOO", "test flag", args::Matcher{'f', "foo"}); + args::ValueFlag foo(parser, "FOO", "test flag", args::Matcher{'f', "foo"}); args::Flag bar(parser, "BAR", "test flag", args::Matcher{'b', "bar"}); - args::ArgFlag baz(parser, "BAZ", "test flag", args::Matcher{'a', "baz"}); - args::ArgFlag bim(parser, "BAZ", "test flag", args::Matcher{'B', "bim"}); + args::ValueFlag baz(parser, "BAZ", "test flag", args::Matcher{'a', "baz"}); + args::ValueFlag bim(parser, "BAZ", "test flag", args::Matcher{'B', "bim"}); args::Flag bix(parser, "BAZ", "test flag", args::Matcher{'x', "bix"}); parser.ParseArgs(std::vector{"-bftest", "--baz=7.555e2", "--bim", "c"}); REQUIRE(foo); @@ -93,10 +93,10 @@ TEST_CASE("Passing an argument to a non-argument flag throws an error", "[args]" TEST_CASE("Unified argument lists for match work", "[args]") { args::ArgumentParser parser("This is a test program.", "This goes after the options."); - args::ArgFlag foo(parser, "FOO", "test flag", args::Matcher{'f', "foo"}); + args::ValueFlag foo(parser, "FOO", "test flag", args::Matcher{'f', "foo"}); args::Flag bar(parser, "BAR", "test flag", args::Matcher{"bar", 'b'}); - args::ArgFlag baz(parser, "BAZ", "test flag", args::Matcher{'a', "baz"}); - args::ArgFlag bim(parser, "BAZ", "test flag", args::Matcher{'B', "bim"}); + args::ValueFlag baz(parser, "BAZ", "test flag", args::Matcher{'a', "baz"}); + args::ValueFlag bim(parser, "BAZ", "test flag", args::Matcher{'B', "bim"}); args::Flag bix(parser, "BAZ", "test flag", args::Matcher{"bix"}); parser.ParseArgs(std::vector{"-bftest", "--baz=7.555e2", "--bim", "c"}); REQUIRE(foo); @@ -112,7 +112,7 @@ TEST_CASE("Unified argument lists for match work", "[args]") TEST_CASE("Get can be assigned to for non-reference types", "[args]") { args::ArgumentParser parser("This is a test program.", "This goes after the options."); - args::ArgFlag foo(parser, "FOO", "test flag", args::Matcher{'f', "foo"}); + args::ValueFlag foo(parser, "FOO", "test flag", args::Matcher{'f', "foo"}); parser.ParseArgs(std::vector{"--foo=test"}); REQUIRE(foo); REQUIRE(args::get(foo) == "test"); @@ -123,7 +123,7 @@ TEST_CASE("Get can be assigned to for non-reference types", "[args]") TEST_CASE("Invalid argument parsing throws parsing exceptions", "[args]") { args::ArgumentParser parser("This is a test program.", "This goes after the options."); - args::ArgFlag foo(parser, "FOO", "test flag", args::Matcher{'f', "foo"}); + args::ValueFlag foo(parser, "FOO", "test flag", args::Matcher{'f', "foo"}); REQUIRE_THROWS_AS(parser.ParseArgs(std::vector{"--foo=7.5"}), args::ParseError); REQUIRE_THROWS_AS(parser.ParseArgs(std::vector{"--foo", "7a"}), args::ParseError); REQUIRE_THROWS_AS(parser.ParseArgs(std::vector{"--foo", "7e4"}), args::ParseError); @@ -132,7 +132,7 @@ TEST_CASE("Invalid argument parsing throws parsing exceptions", "[args]") TEST_CASE("Argument flag lists work as expected", "[args]") { args::ArgumentParser parser("This is a test program.", "This goes after the options."); - args::ArgFlagList foo(parser, "FOO", "test flag", args::Matcher{'f', "foo"}); + args::ValueFlagList foo(parser, "FOO", "test flag", args::Matcher{'f', "foo"}); parser.ParseArgs(std::vector{"--foo=7", "-f2", "-f", "9", "--foo", "42"}); REQUIRE((args::get(foo) == std::vector{7, 2, 9, 42})); } @@ -140,9 +140,9 @@ TEST_CASE("Argument flag lists work as expected", "[args]") TEST_CASE("Positional arguments and positional argument lists work as expected", "[args]") { args::ArgumentParser parser("This is a test program.", "This goes after the options."); - args::PosArg foo(parser, "FOO", "test flag"); - args::PosArg bar(parser, "BAR", "test flag"); - args::PosArgList baz(parser, "BAZ", "test flag"); + args::Positional foo(parser, "FOO", "test flag"); + args::Positional bar(parser, "BAR", "test flag"); + args::PositionalList baz(parser, "BAZ", "test flag"); parser.ParseArgs(std::vector{"this is a test flag", "0", "a", "b", "c", "x", "y", "z"}); REQUIRE(foo); REQUIRE((args::get(foo) == "this is a test flag")); @@ -155,9 +155,9 @@ TEST_CASE("Positional arguments and positional argument lists work as expected", TEST_CASE("Positionals that are unspecified evaluate false", "[args]") { args::ArgumentParser parser("This is a test program.", "This goes after the options."); - args::PosArg foo(parser, "FOO", "test flag"); - args::PosArg bar(parser, "BAR", "test flag"); - args::PosArgList baz(parser, "BAZ", "test flag"); + args::Positional foo(parser, "FOO", "test flag"); + args::Positional bar(parser, "BAR", "test flag"); + args::PositionalList baz(parser, "BAZ", "test flag"); parser.ParseArgs(std::vector{"this is a test flag again"}); REQUIRE(foo); REQUIRE((args::get(foo) == "this is a test flag again")); @@ -168,8 +168,8 @@ TEST_CASE("Positionals that are unspecified evaluate false", "[args]") TEST_CASE("Additional positionals throw an exception", "[args]") { args::ArgumentParser parser("This is a test program.", "This goes after the options."); - args::PosArg foo(parser, "FOO", "test flag"); - args::PosArg bar(parser, "BAR", "test flag"); + args::Positional foo(parser, "FOO", "test flag"); + args::Positional bar(parser, "BAR", "test flag"); REQUIRE_THROWS_AS(parser.ParseArgs(std::vector{"this is a test flag again", "1", "this has no positional available"}), args::ParseError); } @@ -243,13 +243,13 @@ TEST_CASE("Custom types work", "[args]") { { args::ArgumentParser parser("This is a test program."); - args::PosArg> ints(parser, "INTS", "This takes a pair of integers."); - args::PosArg, DoublesReader> doubles(parser, "DOUBLES", "This takes a pair of doubles."); + args::Positional> ints(parser, "INTS", "This takes a pair of integers."); + args::Positional, DoublesReader> doubles(parser, "DOUBLES", "This takes a pair of doubles."); REQUIRE_THROWS_AS(parser.ParseArgs(std::vector{"1.2,2", "3.8,4"}), args::ParseError); } args::ArgumentParser parser("This is a test program."); - args::PosArg> ints(parser, "INTS", "This takes a pair of integers."); - args::PosArg, DoublesReader> doubles(parser, "DOUBLES", "This takes a pair of doubles."); + args::Positional> ints(parser, "INTS", "This takes a pair of integers."); + args::Positional, DoublesReader> doubles(parser, "DOUBLES", "This takes a pair of doubles."); parser.ParseArgs(std::vector{"1,2", "3.8,4"}); REQUIRE(std::get<0>(args::get(ints)) == 1); REQUIRE(std::get<1>(args::get(ints)) == 2); @@ -263,10 +263,10 @@ TEST_CASE("Custom parser prefixes (dd-style)", "[args]") parser.LongPrefix(""); parser.LongSeparator("="); args::HelpFlag help(parser, "HELP", "Show this help menu.", args::Matcher({"help"})); - args::ArgFlag bs(parser, "BYTES", "Block size", args::Matcher({"bs"}), 512); - args::ArgFlag skip(parser, "BYTES", "Bytes to skip", args::Matcher({"skip"}), 0); - args::ArgFlag input(parser, "BLOCK SIZE", "Block size", args::Matcher({"if"})); - args::ArgFlag output(parser, "BLOCK SIZE", "Block size", args::Matcher({"of"})); + args::ValueFlag bs(parser, "BYTES", "Block size", args::Matcher({"bs"}), 512); + args::ValueFlag skip(parser, "BYTES", "Bytes to skip", args::Matcher({"skip"}), 0); + args::ValueFlag input(parser, "BLOCK SIZE", "Block size", args::Matcher({"if"})); + args::ValueFlag output(parser, "BLOCK SIZE", "Block size", args::Matcher({"of"})); parser.ParseArgs(std::vector{"skip=8", "if=/dev/null"}); REQUIRE_FALSE(bs); REQUIRE(args::get(bs) == 512); @@ -283,10 +283,10 @@ TEST_CASE("Custom parser prefixes (Some Windows styles)", "[args]") parser.LongPrefix("/"); parser.LongSeparator(":"); args::HelpFlag help(parser, "HELP", "Show this help menu.", args::Matcher({"help"})); - args::ArgFlag bs(parser, "BYTES", "Block size", args::Matcher({"bs"}), 512); - args::ArgFlag skip(parser, "BYTES", "Bytes to skip", args::Matcher({"skip"}), 0); - args::ArgFlag input(parser, "BLOCK SIZE", "Block size", args::Matcher({"if"})); - args::ArgFlag output(parser, "BLOCK SIZE", "Block size", args::Matcher({"of"})); + args::ValueFlag bs(parser, "BYTES", "Block size", args::Matcher({"bs"}), 512); + args::ValueFlag skip(parser, "BYTES", "Bytes to skip", args::Matcher({"skip"}), 0); + args::ValueFlag input(parser, "BLOCK SIZE", "Block size", args::Matcher({"if"})); + args::ValueFlag output(parser, "BLOCK SIZE", "Block size", args::Matcher({"of"})); parser.ParseArgs(std::vector{"/skip:8", "/if:/dev/null"}); REQUIRE_FALSE(bs); REQUIRE(args::get(bs) == 512); @@ -302,10 +302,10 @@ TEST_CASE("Help menu can be grabbed as a string, passed into a stream, or by usi std::ostream null(nullptr); args::ArgumentParser parser("This command likes to break your disks"); args::HelpFlag help(parser, "HELP", "Show this help menu.", args::Matcher({"help"})); - args::ArgFlag bs(parser, "BYTES", "Block size", args::Matcher({"bs"}), 512); - args::ArgFlag skip(parser, "BYTES", "Bytes to skip", args::Matcher({"skip"}), 0); - args::ArgFlag input(parser, "BLOCK SIZE", "Block size", args::Matcher({"if"})); - args::ArgFlag output(parser, "BLOCK SIZE", "Block size", args::Matcher({"of"})); + args::ValueFlag bs(parser, "BYTES", "Block size", args::Matcher({"bs"}), 512); + args::ValueFlag skip(parser, "BYTES", "Bytes to skip", args::Matcher({"skip"}), 0); + args::ValueFlag input(parser, "BLOCK SIZE", "Block size", args::Matcher({"if"})); + args::ValueFlag output(parser, "BLOCK SIZE", "Block size", args::Matcher({"of"})); parser.ParseArgs(std::vector{"--skip=8", "--if=/dev/null"}); null << parser.Help(); parser.Help(null); @@ -315,7 +315,7 @@ TEST_CASE("Help menu can be grabbed as a string, passed into a stream, or by usi TEST_CASE("Required argument separation being violated throws an error", "[args]") { args::ArgumentParser parser("This is a test program.", "This goes after the options."); - args::ArgFlag bar(parser, "BAR", "test flag", args::Matcher{'b', "bar"}); + args::ValueFlag bar(parser, "BAR", "test flag", args::Matcher{'b', "bar"}); REQUIRE_NOTHROW(parser.ParseArgs(std::vector{"-btest"})); REQUIRE_NOTHROW(parser.ParseArgs(std::vector{"--bar=test"})); REQUIRE_NOTHROW(parser.ParseArgs(std::vector{"-b", "test"})); -- cgit v1.2.1