summaryrefslogtreecommitdiff
path: root/src/parameters_parser.cc
diff options
context:
space:
mode:
authorJohannes Altmanninger <aclopte@gmail.com>2023-02-12 20:12:52 +0100
committerJohannes Altmanninger <aclopte@gmail.com>2023-02-17 20:50:58 +0100
commit64d4d29d43c78a403cff81d52ad0dabe06518f51 (patch)
treee2fd2c840166e4f319df69a588b899cf86182cc7 /src/parameters_parser.cc
parentafaa47e93fb937fbedb60bcdbc768bb937108f86 (diff)
Use parameter parser to skip switch args in completion
The command line "hook -group xyz " should get scope completions but it actually gets hook completions because "xyz" is wrongly interpreted as positional argument. Fix this by using the parameters parser to compute positional arguments. Fixes #4840
Diffstat (limited to 'src/parameters_parser.cc')
-rw-r--r--src/parameters_parser.cc28
1 files changed, 24 insertions, 4 deletions
diff --git a/src/parameters_parser.cc b/src/parameters_parser.cc
index 8de8241b..633cb092 100644
--- a/src/parameters_parser.cc
+++ b/src/parameters_parser.cc
@@ -25,7 +25,7 @@ String generate_switches_doc(const SwitchMap& switches)
return res;
}
-ParametersParser::ParametersParser(ParameterList params, const ParameterDesc& desc)
+ParametersParser::ParametersParser(ParameterList params, const ParameterDesc& desc, bool ignore_errors)
: m_params(params)
{
const bool switches_only_at_start = desc.flags & ParameterDesc::Flags::SwitchesOnlyAtStart;
@@ -36,11 +36,16 @@ ParametersParser::ParametersParser(ParameterList params, const ParameterDesc& de
for (size_t i = 0; i < params.size(); ++i)
{
if (not only_pos and not ignore_unknown_switches and params[i] == "--")
+ {
+ m_state = State::Switch;
only_pos = true;
+ }
else if (not only_pos and not params[i].empty() and params[i][0_byte] == '-')
{
StringView switch_name = params[i].substr(1_byte);
auto it = desc.switches.find(switch_name);
+ m_state = it == desc.switches.end() and ignore_unknown_switches ?
+ State::Positional : State::Switch;
if (it == desc.switches.end())
{
if (ignore_unknown_switches)
@@ -50,28 +55,43 @@ ParametersParser::ParametersParser(ParameterList params, const ParameterDesc& de
only_pos = true;
continue;
}
+ if (ignore_errors)
+ continue;
throw unknown_option(params[i]);
}
auto switch_index = it - desc.switches.begin();
if (switch_seen[switch_index])
+ {
+ if (ignore_errors)
+ continue;
throw runtime_error{format("switch '-{}' specified more than once", it->key)};
+ }
switch_seen[switch_index] = true;
- if (it->value.takes_arg and ++i == params.size())
- throw missing_option_value(it->key);
+ if (it->value.takes_arg)
+ {
+ if (++i == params.size())
+ {
+ if (ignore_errors)
+ continue;
+ throw missing_option_value(it->key);
+ }
+ m_state = State::SwitchArgument;
+ }
m_switches[switch_name.str()] = it->value.takes_arg ? params[i] : StringView{};
}
else // positional
{
+ m_state = State::Positional;
if (switches_only_at_start)
only_pos = true;
m_positional_indices.push_back(i);
}
}
size_t count = m_positional_indices.size();
- if (count > desc.max_positionals or count < desc.min_positionals)
+ if (not ignore_errors and (count > desc.max_positionals or count < desc.min_positionals))
throw wrong_argument_count();
}