diff options
author | ridiculousfish <corydoras@ridiculousfish.com> | 2015-08-03 22:09:25 -0700 |
---|---|---|
committer | ridiculousfish <corydoras@ridiculousfish.com> | 2015-08-08 13:55:50 -0700 |
commit | bcbe91461ec70d2be75a1e1fc3d1baa5a89bd44f (patch) | |
tree | a3374875a79b25c765d8e2c7a4b9e000990840e8 /src/wildcard.cpp | |
parent | b68410d6193ae2b1f863f0bca125ac14eae5e95b (diff) |
Move the "wildcard_complete" test into wildcard_test_flags_then_complete
Simplifies code yet further
Diffstat (limited to 'src/wildcard.cpp')
-rw-r--r-- | src/wildcard.cpp | 69 |
1 files changed, 41 insertions, 28 deletions
diff --git a/src/wildcard.cpp b/src/wildcard.cpp index 76046161..3d731574 100644 --- a/src/wildcard.cpp +++ b/src/wildcard.cpp @@ -238,6 +238,23 @@ struct wc_complete_pack_t wc_complete_pack_t(const wcstring &str) : orig(str) {} }; +/* Weirdly specific and non-reusable helper function that makes its one call site much clearer */ +static bool has_prefix_match(const std::vector<completion_t> *comps, size_t first) +{ + if (comps != NULL) + { + const size_t after_count = comps->size(); + for (size_t j = first; j < after_count; j++) + { + if (comps->at(j).match.type <= fuzzy_match_prefix) + { + return true; + } + } + } + return false; +} + /** Matches the string against the wildcard, and if the wildcard is a possible completion of the string, the remainder of the string is @@ -281,7 +298,7 @@ static bool wildcard_complete_internal(const wchar_t *str, match_acceptable = match_type_shares_prefix(match.type); } - if (match_acceptable) + if (match_acceptable && out != NULL) { /* Wildcard complete */ bool full_replacement = match_type_requires_full_replacement(match.type) || (flags & COMPLETE_REPLACES_TOKEN); @@ -299,24 +316,23 @@ static bool wildcard_complete_internal(const wchar_t *str, } else if (next_wc_char_pos > 0) { - bool result; /* Here we have a non-wildcard prefix. Note that we don't do fuzzy matching for stuff before a wildcard, so just do case comparison and then recurse. */ if (wcsncmp(str, wc, next_wc_char_pos) == 0) { // Normal match - result = wildcard_complete_internal(str + next_wc_char_pos, wc + next_wc_char_pos, params, flags, out); + return wildcard_complete_internal(str + next_wc_char_pos, wc + next_wc_char_pos, params, flags, out); } else if (wcsncasecmp(str, wc, next_wc_char_pos) == 0) { // Case insensitive match - result = wildcard_complete_internal(str + next_wc_char_pos, wc + next_wc_char_pos, params, flags | COMPLETE_REPLACES_TOKEN, out); + return wildcard_complete_internal(str + next_wc_char_pos, wc + next_wc_char_pos, params, flags | COMPLETE_REPLACES_TOKEN, out); } else { // No match - result = false; + return false; } - return result; + assert(0 && "Unreachable code reached"); } else { @@ -339,25 +355,20 @@ static bool wildcard_complete_internal(const wchar_t *str, case ANY_STRING: { + /* Try all submatches. #929: if the recursive call gives us a prefix match, just stop. This is sloppy - what we really want to do is say, once we've seen a match of a particular type, ignore all matches of that type further down the string, such that the wildcard produces the "minimal match.". */ bool has_match = false; - /* Try all submatches. #929: if the recursive call gives us a prefix match, just stop. This is sloppy - what we really want to do is say, once we've seen a match of a particular type, ignore all matches of that type further down the string, such that the wildcard produces the "minimal match." */ - bool has_prefix_match = false; - for (size_t i=0; str[i] != L'\0' && ! has_prefix_match; i++) + for (size_t i=0; str[i] != L'\0'; i++) { - const size_t before_count = out->size(); + const size_t before_count = out ? out->size() : 0; if (wildcard_complete_internal(str + i, wc + 1, params, flags, out)) { + /* We found a match */ has_match = true; - /* Determine if we have a prefix match */ - const size_t after_count = out->size(); - for (size_t j = before_count; j < after_count; j++) + /* If out is NULL, we don't care about the actual matches. If out is not NULL but we have a prefix match, stop there. */ + if (out == NULL || has_prefix_match(out, before_count)) { - if (out->at(j).match.type <= fuzzy_match_prefix) - { - has_prefix_match = true; - break; - } + break; } } } @@ -384,7 +395,8 @@ bool wildcard_complete(const wcstring &str, expand_flags_t expand_flags, complete_flags_t flags) { - assert(out != NULL); + // Note out may be NULL + assert(wc != NULL); wc_complete_pack_t params(str); params.desc = desc; params.desc_func = desc_func; @@ -527,7 +539,13 @@ static bool wildcard_test_flags_then_complete(const wcstring &filepath, const wchar_t *wc, expand_flags_t expand_flags, std::vector<completion_t> *out) -{ +{ + /* Check if it will match before stat() */ + if (! wildcard_complete(filename, wc, NULL, NULL, NULL, expand_flags, 0)) + { + return false; + } + struct stat lstat_buf = {}, stat_buf = {}; int stat_res = -1; int stat_errno = 0; @@ -776,15 +794,10 @@ void wildcard_expander_t::expand_last_segment(const wcstring &base_dir, DIR *bas { if (flags & EXPAND_FOR_COMPLETIONS) { - /* Test for matches before stating file, so as to minimize the number of calls to the much slower stat function. The only expand flag we care about is EXPAND_FUZZY_MATCH; we have no complete flags. */ - std::vector<completion_t> local_matches; - if (wildcard_complete(name_str, wc.c_str(), L"", NULL, &local_matches, flags & EXPAND_FUZZY_MATCH, 0)) + const wcstring filepath = base_dir + name_str; + if (wildcard_test_flags_then_complete(filepath, name_str, wc.c_str(), flags, this->resolved)) { - const wcstring filepath = base_dir + name_str; - if (wildcard_test_flags_then_complete(filepath, name_str, wc.c_str(), flags, this->resolved)) - { - this->did_add = true; - } + this->did_add = true; } } else |