diff options
| -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;          } | 
