aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTaylor C. Richberger <taywee@gmx.com>2017-11-14 15:11:07 -0700
committerGitHub <noreply@github.com>2017-11-14 15:11:07 -0700
commit09b0d8c0fe1e6abbc27e13434355fea36a032213 (patch)
tree4d77fce4d5c42caa4ca8cd376ad67f0fe2d2c70d
parentMerge pull request #42 from pavel-belikov/better-progline (diff)
parentfix HelpParams::showValueNameOnce (diff)
downloadargs.hxx-09b0d8c0fe1e6abbc27e13434355fea36a032213.tar.xz
Merge pull request #43 from pavel-belikov/better-help
Add more help parameters
-rw-r--r--args.hxx82
-rw-r--r--test.cxx102
2 files changed, 163 insertions, 21 deletions
diff --git a/args.hxx b/args.hxx
index c595ab7..7af24c4 100644
--- a/args.hxx
+++ b/args.hxx
@@ -114,37 +114,48 @@ namespace args
std::istringstream stream(in);
std::vector<std::string> output;
- std::ostringstream line;
- std::string::size_type linesize = 0;
+ std::string line;
+ bool empty = true;
+
+ for (char c : in)
+ {
+ if (!isspace(c))
+ {
+ break;
+ }
+ line += c;
+ }
+
while (stream)
{
std::string item;
stream >> item;
auto itemsize = Glyphs(item);
- if ((linesize + 1 + itemsize) > currentwidth)
+ if ((line.length() + 1 + itemsize) > currentwidth)
{
- if (linesize > 0)
+ if (!empty)
{
- output.push_back(line.str());
- line.str(std::string());
- linesize = 0;
+ output.push_back(line);
+ line.clear();
+ empty = true;
currentwidth = width;
}
}
if (itemsize > 0)
{
- if (linesize)
+ if (!empty)
{
- ++linesize;
- line << " ";
+ line += ' ';
}
- line << item;
- linesize += itemsize;
+
+ line += item;
+ empty = false;
}
}
- if (linesize > 0)
+
+ if (!empty)
{
- output.push_back(line.str());
+ output.push_back(line);
}
return output;
}
@@ -571,6 +582,26 @@ namespace args
/** Use short flags in program lines when possible
*/
bool proglinePreferShortFlags = false;
+
+ /** Program line prefix
+ */
+ std::string usageString;
+
+ /** String shown in help before flags descriptions
+ */
+ std::string optionsString = "OPTIONS:";
+
+ /** Display value name after all the long and short flags
+ */
+ bool useValueNameOnce = false;
+
+ /** Show value name
+ */
+ bool showValueName = true;
+
+ /** Add newline before flag description
+ */
+ bool addNewlineBeforeDescription = false;
};
/** Base class for all match types
@@ -832,23 +863,28 @@ namespace args
virtual std::vector<std::tuple<std::string, std::string, unsigned>> GetDescription(const HelpParams &params, const unsigned indentLevel) const override
{
std::tuple<std::string, std::string, unsigned> description;
- const std::string postfix = NumberOfArguments() == 0 ? std::string() : Name();
+ const std::string postfix = !params.showValueName || NumberOfArguments() == 0 ? std::string() : Name();
std::string flags;
- for (const auto &flag : matcher.GetFlagStrings())
+ const auto flagStrings = matcher.GetFlagStrings();
+ const bool useValueNameOnce = flagStrings.size() == 1 ? false : params.useValueNameOnce;
+ for (auto it = flagStrings.begin(); it != flagStrings.end(); ++it)
{
- if (!flags.empty())
+ auto &flag = *it;
+ if (it != flagStrings.begin())
{
flags += ", ";
}
flags += flag.isShort ? params.shortPrefix : params.longPrefix;
flags += flag.str();
- if (!postfix.empty())
+
+ if (!postfix.empty() && (!useValueNameOnce || it + 1 == flagStrings.end()))
{
flags += flag.isShort ? params.shortSeparator : params.longSeparator;
flags += "[" + postfix + "]";
}
}
+
std::get<0>(description) = std::move(flags);
std::get<1>(description) = help;
std::get<2>(description) = indentLevel;
@@ -2236,7 +2272,7 @@ namespace args
const bool hasarguments = command.HasPositional();
std::ostringstream prognameline;
- prognameline << Prog();
+ prognameline << helpParams.usageString << Prog();
for (const std::string &posname: command.GetProgramLine(helpParams))
{
@@ -2268,7 +2304,11 @@ namespace args
bool lastDescriptionIsNewline = false;
- help_ << std::string(helpParams.progindent, ' ') << "OPTIONS:\n\n";
+ if (!helpParams.optionsString.empty())
+ {
+ help_ << std::string(helpParams.progindent, ' ') << helpParams.optionsString << "\n\n";
+ }
+
for (const auto &desc: command.GetDescription(helpParams, 0))
{
lastDescriptionIsNewline = std::get<0>(desc).empty() && std::get<1>(desc).empty();
@@ -2289,7 +2329,7 @@ namespace args
auto infoit = std::begin(info);
// groupindent is on both sides of this inequality, and therefore can be removed
- if ((helpParams.flagindent + flagssize + helpParams.gutter) > helpParams.helpindent || infoit == std::end(info))
+ if ((helpParams.flagindent + flagssize + helpParams.gutter) > helpParams.helpindent || infoit == std::end(info) || helpParams.addNewlineBeforeDescription)
{
help_ << '\n';
} else
diff --git a/test.cxx b/test.cxx
index 71f1fb7..1189f97 100644
--- a/test.cxx
+++ b/test.cxx
@@ -964,6 +964,108 @@ TEST_CASE("Matcher validation works as expected", "[args]")
REQUIRE_THROWS_AS(args::ValueFlag<int>(parser, "", "", {}), args::UsageError);
}
+TEST_CASE("HelpParams work as expected", "[args]")
+{
+ args::ArgumentParser p("parser");
+ args::ValueFlag<std::string> f(p, "name", "description", {'f', "foo"});
+ args::ValueFlag<std::string> g(p, "name", "description\n d1\n d2", {'g'});
+ p.Prog("prog");
+
+ REQUIRE(p.Help() == R"( prog {OPTIONS}
+
+ parser
+
+ OPTIONS:
+
+ -f[name], --foo=[name] description
+ -g[name] description
+ d1
+ d2
+
+)");
+
+ p.helpParams.usageString = "usage: ";
+ p.helpParams.optionsString = "Options";
+ p.helpParams.useValueNameOnce = true;
+ REQUIRE(p.Help() == R"( usage: prog {OPTIONS}
+
+ parser
+
+ Options
+
+ -f, --foo=[name] description
+ -g[name] description
+ d1
+ d2
+
+)");
+
+ p.helpParams.showValueName = false;
+ p.helpParams.optionsString = {};
+ REQUIRE(p.Help() == R"( usage: prog {OPTIONS}
+
+ parser
+
+ -f, --foo description
+ -g description
+ d1
+ d2
+
+)");
+
+ p.helpParams.helpindent = 12;
+ p.helpParams.optionsString = "Options";
+ REQUIRE(p.Help() == R"( usage: prog {OPTIONS}
+
+ parser
+
+ Options
+
+ -f, --foo
+ description
+ -g description
+ d1
+ d2
+
+)");
+
+ p.helpParams.addNewlineBeforeDescription = true;
+ REQUIRE(p.Help() == R"( usage: prog {OPTIONS}
+
+ parser
+
+ Options
+
+ -f, --foo
+ description
+ -g
+ description
+ d1
+ d2
+
+)");
+
+ args::ValueFlag<std::string> e(p, "name", "some reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally loooooooooooooooooooooooooooong description", {'e'});
+ REQUIRE(p.Help() == R"( usage: prog {OPTIONS}
+
+ parser
+
+ Options
+
+ -f, --foo
+ description
+ -g
+ description
+ d1
+ d2
+ -e
+ some reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally
+ loooooooooooooooooooooooooooong description
+
+)");
+
+}
+
#undef ARGS_HXX
#define ARGS_TESTNAMESPACE
#define ARGS_NOEXCEPT