aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTaylor C. Richberger <Taywee@gmx.com>2016-05-05 11:41:25 -0600
committerTaylor C. Richberger <Taywee@gmx.com>2016-05-05 11:41:25 -0600
commit86e1bd1bd2b22ccffa774006dd8e99de313f545f (patch)
tree3895ffbe247f6b63eca2796af2d139c507647b19
parentadd simple test and allow some simple unicode support (diff)
downloadargs.hxx-86e1bd1bd2b22ccffa774006dd8e99de313f545f.tar.xz
add terminator flag, rework interface a little
-rw-r--r--args.hxx76
-rw-r--r--test.cxx20
2 files changed, 46 insertions, 50 deletions
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<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("...");
diff --git a/test.cxx b/test.cxx
index 43b2b8f..9ce23d3 100644
--- a/test.cxx
+++ b/test.cxx
@@ -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;
}