diff options
author | Taylor C. Richberger <Taywee@gmx.com> | 2016-05-05 11:41:25 -0600 |
---|---|---|
committer | Taylor C. Richberger <Taywee@gmx.com> | 2016-05-05 11:41:25 -0600 |
commit | 86e1bd1bd2b22ccffa774006dd8e99de313f545f (patch) | |
tree | 3895ffbe247f6b63eca2796af2d139c507647b19 | |
parent | add simple test and allow some simple unicode support (diff) | |
download | args.hxx-86e1bd1bd2b22ccffa774006dd8e99de313f545f.tar.xz |
add terminator flag, rework interface a little
-rw-r--r-- | args.hxx | 76 | ||||
-rw-r--r-- | test.cxx | 20 |
2 files changed, 46 insertions, 50 deletions
@@ -585,6 +585,8 @@ namespace args std::string longseparator; + std::string terminator; + public: ArgumentParser(const std::string &description, const std::string &epilog = std::string()) : Group("arguments", Group::Validators::AllChildGroups), @@ -592,7 +594,8 @@ namespace args epilog(epilog), longprefix("--"), shortprefix("-"), - longseparator("=") {} + longseparator("="), + terminator("--") {} // Ugly getter/setter section const std::string &Prog() const @@ -624,8 +627,17 @@ namespace args { return longseparator; } void LongSeparator(const std::string &longseparator) { this->longseparator = longseparator; } - std::string Help(unsigned int width = 80, unsigned int progindent = 2, unsigned int descriptionindent = 4, unsigned int flagindent = 6, unsigned int helpindent = 40, unsigned int gutter = 1) const + + const std::string &Terminator() const + { return terminator; } + void Terminator(const std::string &terminator) + { this->terminator = terminator; } + + std::string Help(unsigned int width = 80, unsigned int progindent = 2, unsigned int descriptionindent = 4, unsigned int flagindent = 6, unsigned int helpindent = 25, unsigned int gutter = 1) const { + bool hasoptions = false; + bool hasarguments = false; + const std::vector<std::string> description(Wrap(this->description, width - descriptionindent)); const std::vector<std::string> epilog(Wrap(this->epilog, width - descriptionindent)); std::ostringstream help; @@ -633,10 +645,12 @@ namespace args prognameline << prog; if (HasFlag()) { + hasoptions = true; prognameline << " {OPTIONS}"; } for (const std::string &posname: GetPosNames()) { + hasarguments = true; prognameline << " [" << posname << ']'; } const std::vector<std::string> proglines(Wrap(prognameline.str(), width - (progindent + 4), width - progindent)); @@ -676,7 +690,14 @@ namespace args } for (; infoit != std::end(info); ++infoit) { - help << std::string(helpindent, ' ') << *infoit << "\n"; + help << std::string(helpindent, ' ') << *infoit << '\n'; + } + } + if (hasoptions && hasarguments) + { + for (const std::string &item: Wrap(std::string("\"") + terminator + "\" can be used to terminate flag options and force all following arguments to be treated as positional options", width - flagindent)) + { + help << std::string(flagindent, ' ') << item << '\n'; } } @@ -690,13 +711,18 @@ namespace args void ParseArgs(const std::vector<std::string> &args) { + bool terminated = false; + // Check all arg chunks for (auto it = std::begin(args); it != std::end(args); ++it) { const std::string &chunk = *it; + if (!terminated and chunk == terminator) + { + terminated = true; // If a long arg was found - if (chunk.find(longprefix) == 0 && chunk.size() > longprefix.size()) + } else if (!terminated && chunk.find(longprefix) == 0 && chunk.size() > longprefix.size()) { const std::string argchunk(chunk.substr(longprefix.size())); // Try to separate it, in case of a separator: @@ -740,7 +766,7 @@ namespace args throw ParseError(problem.str().c_str()); } // Check short args - } else if (chunk.find(shortprefix) == 0 && chunk.size() > shortprefix.size()) + } else if (!terminated && chunk.find(shortprefix) == 0 && chunk.size() > shortprefix.size()) { std::string argchunk(chunk.substr(shortprefix.size())); for (auto argit = std::begin(argchunk); argit != std::end(argchunk); ++argit) @@ -864,10 +890,9 @@ namespace args // Count matches class Counter : public FlagBase { - private: + public: unsigned int count; - public: Counter(Group &group, const std::string &name, const std::string &help, Matcher &&matcher, const unsigned int startcount = 0): FlagBase(name, help, std::move(matcher)), count(startcount) { group.Add(*this); @@ -894,11 +919,6 @@ namespace args } return me; } - - unsigned int Count() - { - return count; - } }; template <typename T> @@ -924,10 +944,9 @@ namespace args template <typename T, void (*Reader)(const std::string &, const std::string &, T&) = ArgReader<T>> class ArgFlag : public ArgFlagBase { - private: + public: 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) { group.Add(*this); @@ -939,11 +958,6 @@ namespace args { Reader(name, value, this->value); } - - const T &Value() - { - return value; - } }; template < @@ -952,10 +966,9 @@ namespace args void (*Reader)(const std::string &, const std::string &, T&) = ArgReader<T>> class ArgFlagList : public ArgFlagBase { - private: + public: 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) { group.Add(*this); @@ -968,20 +981,14 @@ namespace args values.emplace_back(); Reader(name, value, values.back()); } - - const List &Values() - { - return values; - } }; template <typename T, void (*Reader)(const std::string &, const std::string &, T&) = ArgReader<T>> class PosArg : public PosBase { - private: + public: T value; - public: PosArg(Group &group, const std::string &name, const std::string &help, const T &defaultValue = T()): PosBase(name, help), value(defaultValue) { group.Add(*this); @@ -996,11 +1003,6 @@ namespace args matched = true; } - const T &Value() - { - return value; - } - virtual std::string ArgName() const override { return GetArgName(name); @@ -1013,10 +1015,9 @@ namespace args void (*Reader)(const std::string &, const std::string &, T&) = ArgReader<T>> class PosArgList : public PosBase { - private: + public: List values; - public: PosArgList(Group &group, const std::string &name, const std::string &help, const List &defaultValues = List()): PosBase(name, help), values(defaultValues) { group.Add(*this); @@ -1031,11 +1032,6 @@ namespace args matched = true; } - const List &Values() - { - return values; - } - virtual std::string ArgName() const override { return GetArgName(name) + std::string("..."); @@ -19,10 +19,11 @@ int main(int argc, char **argv) args::HelpFlag help(parser, "help", "Display this help menu", args::Matcher({'h'}, {"help"})); args::Flag fooflag(parser, "foo", "This is a foo flag", args::Matcher({'f', 'F'}, {"Foo", "foo"})); args::ArgFlag<std::string> bararg(parser, "bar", "This is a bar flag", args::Matcher({'b', 'B'}, {"Bar", "bar"})); - args::ArgFlag<double> baz(parser, "baz", "This is a baz flag", args::Matcher({'z', 'Z'}, {"Baz", "baz"})); + args::ArgFlag<double> baz(parser, "baz", "This is a baz flag, and it is long enough that it needs to be wrapped.", args::Matcher({'z', 'Z'}, {"Baz", "baz"})); args::ArgFlagList<double> list(parser, "flaglist", "This is a list flag", args::Matcher({'l'}, {"list"})); - args::PosArg<double> pos(parser, "Position", "This is a position arg"); - args::PosArg<double> pos2(parser, "Position", "This is a position arg"); + args::PosArg<std::string> pos(parser, "Position", "This is a position arg"); + args::PosArgList<double> poslist(parser, "Position list", "This is a position list arg"); + args::PosArg<double> pos2(parser, "Position", "This is a position arg which has a long enough description to probably necessitate wrapping"); args::PosArg<double> pos3(parser, "Position", "This is a position arg"); args::PosArg<double> pos4(parser, "Pösitiön", "This is a position arg"); args::PosArg<double> pos5(parser, "Position", "This is a position arg"); @@ -34,7 +35,6 @@ int main(int argc, char **argv) args::PosArg<double> pos8(parser, "Position", "This is a position arg"); args::PosArgList<double> poslist4(parser, "Position list", "This is a position list arg"); args::PosArg<double> pos9(parser, "Position", "This is a position arg"); - args::PosArgList<double> poslist(parser, "Position list", "This is a position list arg"); args::Counter counter(parser, "counter", "This is a counter flag", args::Matcher({'c'})); try { @@ -69,32 +69,32 @@ int main(int argc, char **argv) } if (bararg) { - std::cout << "Bar arg found: " << bararg.Value() << std::endl; + std::cout << "Bar arg found: " << bararg.value << std::endl; } if (baz) { - std::cout << "Baz arg found: " << baz.Value() << std::endl; + std::cout << "Baz arg found: " << baz.value << std::endl; } if (counter) { - std::cout << "counter found: " << counter.Count() << std::endl; + std::cout << "counter found: " << counter.count << std::endl; } if (list) { std::cout << "list found: " << std::endl; - for (const auto &item: list.Values()) + for (const auto &item: list.values) { std::cout << "- " << item << std::endl; } } if (pos) { - std::cout << "pos found: " << pos.Value() << std::endl; + std::cout << "pos found: " << pos.value << std::endl; } if (poslist) { std::cout << "poslist found: " << std::endl; - for (const auto &item: poslist.Values()) + for (const auto &item: poslist.values) { std::cout << "- " << item << std::endl; } |