@@ -200,19 +200,21 @@ namespace cs::semantic {
200200 if (auto result = check_equal (key, *candidate); result) {
201201 return result;
202202 }
203- // check if the argument is allowed to stick to the flag
204- if (auto result = check_partial (key, *candidate); result) {
205- return result;
206- }
207203 }
208- // partial match is less likely to be a few steps away from the lower bound,
209- // therefore search the whole flag list again.
210- for (const auto &candidate : flags_) {
211- if (auto result = check_partial (key, candidate); result) {
212- return result;
204+
205+ std::optional<std::string> candidate_longest = std::nullopt ;
206+ for (const auto &[candidate, info] : flags_) {
207+ if (const auto & extra = split_extra (candidate, key); extra) {
208+ const size_t prefix_length = key.size () - extra.value ().size ();
209+ if (!candidate_longest || (prefix_length > candidate_longest.value ().size ())) {
210+ candidate_longest = std::make_optional (std::string (candidate));
211+ }
213212 }
214213 }
215- return std::nullopt ;
214+
215+ return (candidate_longest.has_value ())
216+ ? check_partial (key, *(flags_.find (candidate_longest.value ())))
217+ : std::nullopt ;
216218 }
217219
218220 std::optional<FlagParser::Match>
@@ -228,26 +230,24 @@ namespace cs::semantic {
228230 std::optional<FlagParser::Match>
229231 FlagParser::check_partial (const std::string_view &key, const FlagsByName::value_type &candidate) {
230232 const auto &flag_definition = candidate.second ;
231- if (const auto &extra = split_extra (candidate.first , key); extra) {
232- const auto flag_matching = classify_flag_matching (extra.value ());
233- switch (flag_matching) {
234- case FlagMatch::GLUED:
235- if (is_glue_allowed (flag_definition.match )) {
236- const size_t decrease = is_prefix_match (flag_definition.match ) ? 0 : 1 ;
237- const size_t count = count_of_arguments (flag_definition.match ) - decrease;
238- return std::make_optional (std::make_tuple (count, flag_definition.type ));
239- }
240- break ;
241- case FlagMatch::GLUED_WITH_EQ:
242- if (is_glue_with_equal_allowed (flag_definition.match )) {
243- const size_t count = count_of_arguments (flag_definition.match ) - 1 ;
244- return std::make_optional (std::make_tuple (count, flag_definition.type ));
245- }
246- break ;
247- default :
248- // This should not happen here. Exact match is already filtered out.
249- return std::nullopt ;
250- }
233+ const auto flag_matching = classify_flag_matching (key.substr (candidate.first .size ()));
234+ switch (flag_matching) {
235+ case FlagMatch::GLUED:
236+ if (is_glue_allowed (flag_definition.match )) {
237+ const size_t decrease = is_prefix_match (flag_definition.match ) ? 0 : 1 ;
238+ const size_t count = count_of_arguments (flag_definition.match ) - decrease;
239+ return std::make_optional (std::make_tuple (count, flag_definition.type ));
240+ }
241+ break ;
242+ case FlagMatch::GLUED_WITH_EQ:
243+ if (is_glue_with_equal_allowed (flag_definition.match )) {
244+ const size_t count = count_of_arguments (flag_definition.match ) - 1 ;
245+ return std::make_optional (std::make_tuple (count, flag_definition.type ));
246+ }
247+ break ;
248+ default :
249+ // This should not happen here. Exact match is already filtered out.
250+ __builtin_unreachable ();
251251 }
252252 return std::nullopt ;
253253 }
0 commit comments