From 86e1bd1bd2b22ccffa774006dd8e99de313f545f Mon Sep 17 00:00:00 2001 From: "Taylor C. Richberger" Date: Thu, 5 May 2016 11:41:25 -0600 Subject: add terminator flag, rework interface a little --- args.hxx | 76 ++++++++++++++++++++++++++++++---------------------------------- 1 file changed, 36 insertions(+), 40 deletions(-) (limited to 'args.hxx') diff --git a/args.hxx b/args.hxx index a547a57..ac7854a 100644 --- a/args.hxx +++ b/args.hxx @@ -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 description(Wrap(this->description, width - descriptionindent)); const std::vector 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 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 &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 @@ -924,10 +944,9 @@ namespace args template > 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> 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 > 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> 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("..."); -- cgit v1.2.1