aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/args.cc
diff options
context:
space:
mode:
authorNaïm Favier <n@monade.li>2022-02-18 13:24:39 +0100
committerNaïm Favier <n@monade.li>2022-03-07 12:01:54 +0100
commita6d7cd418385e20feab8d7260a7251f218a0d5bb (patch)
treea4752d1c1864d72901b5b1f6e35797b92548e2b0 /src/libutil/args.cc
parent5f06a91bf77e45c580202324ba2a5f0338a78b7e (diff)
Ensure the completion marker is not processed beyond completion
I was surprised to see an error mentioning ___COMPLETE___ when trying to complete a flag argument that had no completer implemented
Diffstat (limited to 'src/libutil/args.cc')
-rw-r--r--src/libutil/args.cc27
1 files changed, 15 insertions, 12 deletions
diff --git a/src/libutil/args.cc b/src/libutil/args.cc
index f970c0e9e..38c748be0 100644
--- a/src/libutil/args.cc
+++ b/src/libutil/args.cc
@@ -127,11 +127,11 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end)
if (flag.handler.arity == ArityAny) break;
throw UsageError("flag '%s' requires %d argument(s)", name, flag.handler.arity);
}
- if (flag.completer)
- if (auto prefix = needsCompletion(*pos)) {
- anyCompleted = true;
+ if (auto prefix = needsCompletion(*pos)) {
+ anyCompleted = true;
+ if (flag.completer)
flag.completer(n, *prefix);
- }
+ }
args.push_back(*pos++);
}
if (!anyCompleted)
@@ -146,6 +146,7 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end)
&& hasPrefix(name, std::string(*prefix, 2)))
completions->add("--" + name, flag->description);
}
+ return false;
}
auto i = longFlags.find(std::string(*pos, 2));
if (i == longFlags.end()) return false;
@@ -187,10 +188,12 @@ bool Args::processArgs(const Strings & args, bool finish)
{
std::vector<std::string> ss;
for (const auto &[n, s] : enumerate(args)) {
- ss.push_back(s);
- if (exp.completer)
- if (auto prefix = needsCompletion(s))
+ if (auto prefix = needsCompletion(s)) {
+ ss.push_back(*prefix);
+ if (exp.completer)
exp.completer(n, *prefix);
+ } else
+ ss.push_back(s);
}
exp.handler.fun(ss);
expectedArgs.pop_front();
@@ -322,16 +325,16 @@ MultiCommand::MultiCommand(const Commands & commands_)
.optional = true,
.handler = {[=](std::string s) {
assert(!command);
- if (auto prefix = needsCompletion(s)) {
- for (auto & [name, command] : commands)
- if (hasPrefix(name, *prefix))
- completions->add(name);
- }
auto i = commands.find(s);
if (i == commands.end())
throw UsageError("'%s' is not a recognised command", s);
command = {s, i->second()};
command->second->parent = this;
+ }},
+ .completer = {[&](size_t, std::string_view prefix) {
+ for (auto & [name, command] : commands)
+ if (hasPrefix(name, prefix))
+ completions->add(name);
}}
});