aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Belikov <pavel.fuchs.belikov@gmail.com>2017-12-23 16:30:37 +0300
committerPavel Belikov <pavel.fuchs.belikov@gmail.com>2017-12-23 16:30:37 +0300
commitf0ae519bdf43a67cfb6b238e28bdcc75917d94de (patch)
treee4d9cfe02c771f2edfd9f5cd63082a8ac250dfe0
parentadd auto completion for flags (diff)
downloadargs.hxx-f0ae519bdf43a67cfb6b238e28bdcc75917d94de.tar.xz
add completion for flag values
-rw-r--r--args.hxx65
-rw-r--r--test.cxx5
2 files changed, 69 insertions, 1 deletions
diff --git a/args.hxx b/args.hxx
index 2165f10..91cd368 100644
--- a/args.hxx
+++ b/args.hxx
@@ -2224,6 +2224,28 @@ namespace args
return OptionType::Positional;
}
+ template <typename It>
+ bool Complete(FlagBase &flag, It it, It end)
+ {
+ auto nextIt = it;
+ if (!readCompletion || (++nextIt != end))
+ {
+ return false;
+ }
+
+ const auto &chunk = *it;
+ for (auto &choice : flag.HelpChoices(helpParams))
+ {
+ AddCompletionReply(chunk, choice);
+ }
+
+#ifndef ARGS_NOEXCEPT
+ throw Completion(completion->Get());
+#else
+ return true;
+#endif
+ }
+
/** (INTERNAL) Parse flag's values
*
* \param arg The string to display in error message as a flag name
@@ -2269,6 +2291,11 @@ namespace args
values.size() < nargs.max &&
(nargs.min == nargs.max || ParseOption(*valueIt) == OptionType::Positional))
{
+ if (Complete(flag, valueIt, end))
+ {
+ it = end;
+ return "";
+ }
values.push_back(*valueIt);
++it;
@@ -2476,7 +2503,43 @@ namespace args
auto &matcher = flag->GetMatcher();
if (!AddCompletionReply(chunk, matcher.GetShortOrAny().str(shortprefix, longprefix)))
{
- AddCompletionReply(chunk, matcher.GetLongOrAny().str(shortprefix, longprefix));
+ for (auto &name : matcher.GetFlagStrings())
+ {
+ if (AddCompletionReply(chunk, name.str(shortprefix, longprefix)))
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ if (ParseOption(chunk) == OptionType::LongFlag && allowJoinedLongValue)
+ {
+ const auto separator = longseparator.empty() ? chunk.npos : chunk.find(longseparator);
+ if (separator != chunk.npos)
+ {
+ std::string arg(chunk, 0, separator);
+ if (auto flag = this->Match(arg.substr(longprefix.size())))
+ {
+ for (auto &choice : flag->HelpChoices(helpParams))
+ {
+ AddCompletionReply(chunk, arg + longseparator + choice);
+ }
+ }
+ }
+ } else if (ParseOption(chunk) == OptionType::ShortFlag && allowJoinedShortValue)
+ {
+ if (chunk.size() > shortprefix.size() + 1)
+ {
+ auto name = chunk.at(shortprefix.size());
+ //TODO: support -abcVALUE where a and b take no value
+ if (auto flag = this->Match(name))
+ {
+ for (auto &choice : flag->HelpChoices(helpParams))
+ {
+ AddCompletionReply(chunk, shortprefix + name + choice);
+ }
+ }
}
}
}
diff --git a/test.cxx b/test.cxx
index 2d3b625..4768cde 100644
--- a/test.cxx
+++ b/test.cxx
@@ -1257,6 +1257,11 @@ TEST_CASE("Completion works as expected", "[args]")
REQUIRE_THROWS_WITH(p.ParseArgs(std::vector<std::string>{"--completion", "bash", "1", "test", "-"}), Equals("-f\n-b"));
REQUIRE_THROWS_WITH(p.ParseArgs(std::vector<std::string>{"--completion", "bash", "1", "test", "-f"}), Equals("-f"));
REQUIRE_THROWS_WITH(p.ParseArgs(std::vector<std::string>{"--completion", "bash", "1", "test", "--"}), Equals("--foo\n--bar"));
+
+ args::MapFlag<std::string, int> m(p, "mappos", "mappos", {'m', "map"}, {{"1",1}, {"2", 2}});
+ REQUIRE_THROWS_WITH(p.ParseArgs(std::vector<std::string>{"--completion", "bash", "2", "test", "-m", ""}), Equals("1\n2"));
+ REQUIRE_THROWS_WITH(p.ParseArgs(std::vector<std::string>{"--completion", "bash", "1", "test", "--map="}), Equals("--map=1\n--map=2"));
+ REQUIRE_THROWS_WITH(p.ParseArgs(std::vector<std::string>{"--completion", "bash", "1", "test", "-m1"}), Equals("-m1"));
}
#undef ARGS_HXX