mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-23 06:05:39 +08:00
Make fuzzy_match_type_t an enum class
Also rename it to fuzzy_type_t and shorten some of its values.
This commit is contained in:
parent
9144141ded
commit
ac1ee6f1fd
|
@ -267,18 +267,18 @@ static void unique_completions_retaining_order(completion_list_t *comps) {
|
||||||
|
|
||||||
void completions_sort_and_prioritize(completion_list_t *comps, completion_request_flags_t flags) {
|
void completions_sort_and_prioritize(completion_list_t *comps, completion_request_flags_t flags) {
|
||||||
// Find the best match type.
|
// Find the best match type.
|
||||||
fuzzy_match_type_t best_type = fuzzy_match_none;
|
fuzzy_type_t best_type = fuzzy_type_t::none;
|
||||||
for (const auto &comp : *comps) {
|
for (const auto &comp : *comps) {
|
||||||
best_type = std::min(best_type, comp.match.type);
|
best_type = std::min(best_type, comp.match.type);
|
||||||
if (best_type <= fuzzy_match_prefix) {
|
if (best_type <= fuzzy_type_t::prefix) {
|
||||||
// We can't get better than this (see below)
|
// We can't get better than this (see below)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If the best type is an exact match, reduce it to prefix match. Otherwise a tab completion
|
// If the best type is an exact match, reduce it to prefix match. Otherwise a tab completion
|
||||||
// will only show one match if it matches a file exactly. (see issue #959).
|
// will only show one match if it matches a file exactly. (see issue #959).
|
||||||
if (best_type == fuzzy_match_exact) {
|
if (best_type == fuzzy_type_t::exact) {
|
||||||
best_type = fuzzy_match_prefix;
|
best_type = fuzzy_type_t::prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Throw out completions whose match types are less suitable than the best.
|
// Throw out completions whose match types are less suitable than the best.
|
||||||
|
@ -333,10 +333,10 @@ class completer_t {
|
||||||
|
|
||||||
bool fuzzy() const { return flags & completion_request_t::fuzzy_match; }
|
bool fuzzy() const { return flags & completion_request_t::fuzzy_match; }
|
||||||
|
|
||||||
fuzzy_match_type_t max_fuzzy_match_type() const {
|
fuzzy_type_t max_fuzzy_match_type() const {
|
||||||
// If we are doing fuzzy matching, request all types; if not request only prefix matching.
|
// If we are doing fuzzy matching, request all types; if not request only prefix matching.
|
||||||
if (fuzzy()) return fuzzy_match_none;
|
if (fuzzy()) return fuzzy_type_t::none;
|
||||||
return fuzzy_match_prefix_case_insensitive;
|
return fuzzy_type_t::prefix_icase;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool try_complete_variable(const wcstring &str);
|
bool try_complete_variable(const wcstring &str);
|
||||||
|
@ -1184,7 +1184,7 @@ bool completer_t::complete_variable(const wcstring &str, size_t start_offset) {
|
||||||
for (const wcstring &env_name : ctx.vars.get_names(0)) {
|
for (const wcstring &env_name : ctx.vars.get_names(0)) {
|
||||||
string_fuzzy_match_t match =
|
string_fuzzy_match_t match =
|
||||||
string_fuzzy_match_string(var, env_name, this->max_fuzzy_match_type());
|
string_fuzzy_match_string(var, env_name, this->max_fuzzy_match_type());
|
||||||
if (match.type == fuzzy_match_none) {
|
if (match.type == fuzzy_type_t::none) {
|
||||||
continue; // no match
|
continue; // no match
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ class completion_t {
|
||||||
|
|
||||||
// Construction.
|
// Construction.
|
||||||
explicit completion_t(wcstring comp, wcstring desc = wcstring(),
|
explicit completion_t(wcstring comp, wcstring desc = wcstring(),
|
||||||
string_fuzzy_match_t match = string_fuzzy_match_t(fuzzy_match_exact),
|
string_fuzzy_match_t match = string_fuzzy_match_t(fuzzy_type_t::exact),
|
||||||
complete_flags_t flags_val = 0);
|
complete_flags_t flags_val = 0);
|
||||||
completion_t(const completion_t &);
|
completion_t(const completion_t &);
|
||||||
completion_t &operator=(const completion_t &);
|
completion_t &operator=(const completion_t &);
|
||||||
|
@ -198,7 +198,7 @@ bool complete_is_valid_argument(const wcstring &str, const wcstring &opt, const
|
||||||
/// \param flags completion flags
|
/// \param flags completion flags
|
||||||
void append_completion(completion_list_t *completions, wcstring comp, wcstring desc = wcstring(),
|
void append_completion(completion_list_t *completions, wcstring comp, wcstring desc = wcstring(),
|
||||||
int flags = 0,
|
int flags = 0,
|
||||||
string_fuzzy_match_t match = string_fuzzy_match_t(fuzzy_match_exact));
|
string_fuzzy_match_t match = string_fuzzy_match_t(fuzzy_type_t::exact));
|
||||||
|
|
||||||
/// Support for "wrap targets." A wrap target is a command that completes like another command.
|
/// Support for "wrap targets." A wrap target is a command that completes like another command.
|
||||||
bool complete_add_wrapper(const wcstring &command, const wcstring &new_target);
|
bool complete_add_wrapper(const wcstring &command, const wcstring &new_target);
|
||||||
|
|
|
@ -2121,23 +2121,23 @@ static void test_expand() {
|
||||||
static void test_fuzzy_match() {
|
static void test_fuzzy_match() {
|
||||||
say(L"Testing fuzzy string matching");
|
say(L"Testing fuzzy string matching");
|
||||||
|
|
||||||
if (string_fuzzy_match_string(L"", L"").type != fuzzy_match_exact)
|
if (string_fuzzy_match_string(L"", L"").type != fuzzy_type_t::exact)
|
||||||
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
||||||
if (string_fuzzy_match_string(L"alpha", L"alpha").type != fuzzy_match_exact)
|
if (string_fuzzy_match_string(L"alpha", L"alpha").type != fuzzy_type_t::exact)
|
||||||
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
||||||
if (string_fuzzy_match_string(L"alp", L"alpha").type != fuzzy_match_prefix)
|
if (string_fuzzy_match_string(L"alp", L"alpha").type != fuzzy_type_t::prefix)
|
||||||
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
||||||
if (string_fuzzy_match_string(L"ALPHA!", L"alPhA!").type != fuzzy_match_case_insensitive)
|
if (string_fuzzy_match_string(L"ALPHA!", L"alPhA!").type != fuzzy_type_t::exact_icase)
|
||||||
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
||||||
if (string_fuzzy_match_string(L"alPh", L"ALPHA!").type != fuzzy_match_prefix_case_insensitive)
|
if (string_fuzzy_match_string(L"alPh", L"ALPHA!").type != fuzzy_type_t::prefix_icase)
|
||||||
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
||||||
if (string_fuzzy_match_string(L"LPH", L"ALPHA!").type != fuzzy_match_substring)
|
if (string_fuzzy_match_string(L"LPH", L"ALPHA!").type != fuzzy_type_t::substr)
|
||||||
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
||||||
if (string_fuzzy_match_string(L"lPh", L"ALPHA!").type != fuzzy_match_substring_case_insensitive)
|
if (string_fuzzy_match_string(L"lPh", L"ALPHA!").type != fuzzy_type_t::substr_icase)
|
||||||
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
||||||
if (string_fuzzy_match_string(L"AA", L"ALPHA!").type != fuzzy_match_subsequence_insertions_only)
|
if (string_fuzzy_match_string(L"AA", L"ALPHA!").type != fuzzy_type_t::subseq)
|
||||||
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
||||||
if (string_fuzzy_match_string(L"BB", L"ALPHA!").type != fuzzy_match_none)
|
if (string_fuzzy_match_string(L"BB", L"ALPHA!").type != fuzzy_type_t::none)
|
||||||
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -351,16 +351,16 @@ bool pager_t::completion_info_passes_filter(const comp_t &info) const {
|
||||||
const wcstring &needle = this->search_field_line.text();
|
const wcstring &needle = this->search_field_line.text();
|
||||||
|
|
||||||
// We do full fuzzy matching just like the completion code itself.
|
// We do full fuzzy matching just like the completion code itself.
|
||||||
const fuzzy_match_type_t limit = fuzzy_match_none;
|
const fuzzy_type_t limit = fuzzy_type_t::none;
|
||||||
|
|
||||||
// Match against the description.
|
// Match against the description.
|
||||||
if (string_fuzzy_match_string(needle, info.desc, limit).type != fuzzy_match_none) {
|
if (string_fuzzy_match_string(needle, info.desc, limit).type != fuzzy_type_t::none) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match against the completion strings.
|
// Match against the completion strings.
|
||||||
for (const auto &i : info.comp) {
|
for (const auto &i : info.comp) {
|
||||||
if (string_fuzzy_match_string(needle, prefix + i, limit).type != fuzzy_match_none) {
|
if (string_fuzzy_match_string(needle, prefix + i, limit).type != fuzzy_type_t::none) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1806,15 +1806,15 @@ static bool reader_can_replace(const wcstring &in, int flags) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine the best match type for a set of completions.
|
/// Determine the best match type for a set of completions.
|
||||||
static fuzzy_match_type_t get_best_match_type(const completion_list_t &comp) {
|
static fuzzy_type_t get_best_match_type(const completion_list_t &comp) {
|
||||||
fuzzy_match_type_t best_type = fuzzy_match_none;
|
fuzzy_type_t best_type = fuzzy_type_t::none;
|
||||||
for (const auto &i : comp) {
|
for (const auto &i : comp) {
|
||||||
best_type = std::min(best_type, i.match.type);
|
best_type = std::min(best_type, i.match.type);
|
||||||
}
|
}
|
||||||
// If the best type is an exact match, reduce it to prefix match. Otherwise a tab completion
|
// If the best type is an exact match, reduce it to prefix match. Otherwise a tab completion
|
||||||
// will only show one match if it matches a file exactly. (see issue #959).
|
// will only show one match if it matches a file exactly. (see issue #959).
|
||||||
if (best_type == fuzzy_match_exact) {
|
if (best_type == fuzzy_type_t::exact) {
|
||||||
best_type = fuzzy_match_prefix;
|
best_type = fuzzy_type_t::prefix;
|
||||||
}
|
}
|
||||||
return best_type;
|
return best_type;
|
||||||
}
|
}
|
||||||
|
@ -1865,7 +1865,7 @@ bool reader_data_t::handle_completions(const completion_list_t &comp, size_t tok
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
fuzzy_match_type_t best_match_type = get_best_match_type(comp);
|
fuzzy_type_t best_match_type = get_best_match_type(comp);
|
||||||
|
|
||||||
// Determine whether we are going to replace the token or not. If any commands of the best
|
// Determine whether we are going to replace the token or not. If any commands of the best
|
||||||
// type do not require replacement, then ignore all those that want to use replacement.
|
// type do not require replacement, then ignore all those that want to use replacement.
|
||||||
|
|
|
@ -154,47 +154,47 @@ static bool subsequence_in_string(const wcstring &needle, const wcstring &haysta
|
||||||
return ni == needle.end();
|
return ni == needle.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
string_fuzzy_match_t::string_fuzzy_match_t(enum fuzzy_match_type_t t, size_t distance_first,
|
string_fuzzy_match_t::string_fuzzy_match_t(enum fuzzy_type_t t, size_t distance_first,
|
||||||
size_t distance_second)
|
size_t distance_second)
|
||||||
: type(t), match_distance_first(distance_first), match_distance_second(distance_second) {}
|
: type(t), match_distance_first(distance_first), match_distance_second(distance_second) {}
|
||||||
|
|
||||||
string_fuzzy_match_t string_fuzzy_match_string(const wcstring &string,
|
string_fuzzy_match_t string_fuzzy_match_string(const wcstring &string,
|
||||||
const wcstring &match_against,
|
const wcstring &match_against,
|
||||||
fuzzy_match_type_t limit_type) {
|
fuzzy_type_t limit_type) {
|
||||||
// Distances are generally the amount of text not matched.
|
// Distances are generally the amount of text not matched.
|
||||||
string_fuzzy_match_t result(fuzzy_match_none, 0, 0);
|
string_fuzzy_match_t result(fuzzy_type_t::none, 0, 0);
|
||||||
size_t location;
|
size_t location;
|
||||||
if (limit_type >= fuzzy_match_exact && string == match_against) {
|
if (limit_type >= fuzzy_type_t::exact && string == match_against) {
|
||||||
result.type = fuzzy_match_exact;
|
result.type = fuzzy_type_t::exact;
|
||||||
} else if (limit_type >= fuzzy_match_prefix && string_prefixes_string(string, match_against)) {
|
} else if (limit_type >= fuzzy_type_t::prefix &&
|
||||||
result.type = fuzzy_match_prefix;
|
string_prefixes_string(string, match_against)) {
|
||||||
|
result.type = fuzzy_type_t::prefix;
|
||||||
assert(match_against.size() >= string.size());
|
assert(match_against.size() >= string.size());
|
||||||
result.match_distance_first = match_against.size() - string.size();
|
result.match_distance_first = match_against.size() - string.size();
|
||||||
} else if (limit_type >= fuzzy_match_case_insensitive &&
|
} else if (limit_type >= fuzzy_type_t::exact_icase &&
|
||||||
wcscasecmp(string.c_str(), match_against.c_str()) == 0) {
|
wcscasecmp(string.c_str(), match_against.c_str()) == 0) {
|
||||||
result.type = fuzzy_match_case_insensitive;
|
result.type = fuzzy_type_t::exact_icase;
|
||||||
} else if (limit_type >= fuzzy_match_prefix_case_insensitive &&
|
} else if (limit_type >= fuzzy_type_t::prefix_icase &&
|
||||||
string_prefixes_string_case_insensitive(string, match_against)) {
|
string_prefixes_string_case_insensitive(string, match_against)) {
|
||||||
result.type = fuzzy_match_prefix_case_insensitive;
|
result.type = fuzzy_type_t::prefix_icase;
|
||||||
assert(match_against.size() >= string.size());
|
assert(match_against.size() >= string.size());
|
||||||
result.match_distance_first = match_against.size() - string.size();
|
result.match_distance_first = match_against.size() - string.size();
|
||||||
} else if (limit_type >= fuzzy_match_substring &&
|
} else if (limit_type >= fuzzy_type_t::substr &&
|
||||||
(location = match_against.find(string)) != wcstring::npos) {
|
(location = match_against.find(string)) != wcstring::npos) {
|
||||||
// String is contained within match against.
|
// String is contained within match against.
|
||||||
result.type = fuzzy_match_substring;
|
result.type = fuzzy_type_t::substr;
|
||||||
assert(match_against.size() >= string.size());
|
assert(match_against.size() >= string.size());
|
||||||
result.match_distance_first = match_against.size() - string.size();
|
result.match_distance_first = match_against.size() - string.size();
|
||||||
result.match_distance_second = location; // prefer earlier matches
|
result.match_distance_second = location; // prefer earlier matches
|
||||||
} else if (limit_type >= fuzzy_match_substring_case_insensitive &&
|
} else if (limit_type >= fuzzy_type_t::substr_icase &&
|
||||||
(location = ifind(match_against, string, true)) != wcstring::npos) {
|
(location = ifind(match_against, string, true)) != wcstring::npos) {
|
||||||
// A case-insensitive version of the string is in the match against.
|
// A case-insensitive version of the string is in the match against.
|
||||||
result.type = fuzzy_match_substring_case_insensitive;
|
result.type = fuzzy_type_t::substr_icase;
|
||||||
assert(match_against.size() >= string.size());
|
assert(match_against.size() >= string.size());
|
||||||
result.match_distance_first = match_against.size() - string.size();
|
result.match_distance_first = match_against.size() - string.size();
|
||||||
result.match_distance_second = location; // prefer earlier matches
|
result.match_distance_second = location; // prefer earlier matches
|
||||||
} else if (limit_type >= fuzzy_match_subsequence_insertions_only &&
|
} else if (limit_type >= fuzzy_type_t::subseq && subsequence_in_string(string, match_against)) {
|
||||||
subsequence_in_string(string, match_against)) {
|
result.type = fuzzy_type_t::subseq;
|
||||||
result.type = fuzzy_match_subsequence_insertions_only;
|
|
||||||
assert(match_against.size() >= string.size());
|
assert(match_against.size() >= string.size());
|
||||||
result.match_distance_first = match_against.size() - string.size();
|
result.match_distance_first = match_against.size() - string.size();
|
||||||
// It would be nice to prefer matches with greater matching runs here.
|
// It would be nice to prefer matches with greater matching runs here.
|
||||||
|
|
|
@ -36,97 +36,91 @@ size_t ifind(const wcstring &haystack, const wcstring &needle, bool fuzzy = fals
|
||||||
size_t ifind(const std::string &haystack, const std::string &needle, bool fuzzy = false);
|
size_t ifind(const std::string &haystack, const std::string &needle, bool fuzzy = false);
|
||||||
|
|
||||||
// Ways that a string may fuzzily match another.
|
// Ways that a string may fuzzily match another.
|
||||||
enum fuzzy_match_type_t {
|
enum class fuzzy_type_t {
|
||||||
// We match the string exactly: FOOBAR matches FOOBAR.
|
// We match the string exactly: FOOBAR matches FOOBAR.
|
||||||
fuzzy_match_exact = 0,
|
exact,
|
||||||
|
|
||||||
// We match a prefix of the string: FO matches FOOBAR.
|
// We match a prefix of the string: FO matches FOOBAR.
|
||||||
fuzzy_match_prefix,
|
prefix,
|
||||||
|
|
||||||
// We match the string exactly, but in a case insensitive way: foobar matches FOOBAR.
|
// We match the string exactly, but in a case insensitive way: foobar matches FOOBAR.
|
||||||
fuzzy_match_case_insensitive,
|
exact_icase,
|
||||||
|
|
||||||
// We match a prefix of the string, in a case insensitive way: foo matches FOOBAR.
|
// We match a prefix of the string, in a case insensitive way: foo matches FOOBAR.
|
||||||
fuzzy_match_prefix_case_insensitive,
|
prefix_icase,
|
||||||
|
|
||||||
// We match a substring of the string: OOBA matches FOOBAR.
|
// We match a substring of the string: OOBA matches FOOBAR.
|
||||||
fuzzy_match_substring,
|
substr,
|
||||||
|
|
||||||
// We match a substring of the string: ooBA matches FOOBAR.
|
// We match a substring of the string: ooBA matches FOOBAR.
|
||||||
fuzzy_match_substring_case_insensitive,
|
substr_icase,
|
||||||
|
|
||||||
// A subsequence match with insertions only: FBR matches FOOBAR.
|
// A subsequence match with insertions only: FBR matches FOOBAR.
|
||||||
fuzzy_match_subsequence_insertions_only,
|
subseq,
|
||||||
|
|
||||||
// We don't match the string.
|
// We don't match the string.
|
||||||
fuzzy_match_none
|
none,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Indicates where a match type requires replacing the entire token.
|
/// Indicates where a match type requires replacing the entire token.
|
||||||
static inline bool match_type_requires_full_replacement(fuzzy_match_type_t t) {
|
static inline bool match_type_requires_full_replacement(fuzzy_type_t t) {
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case fuzzy_match_exact:
|
case fuzzy_type_t::exact:
|
||||||
case fuzzy_match_prefix: {
|
case fuzzy_type_t::prefix:
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
case fuzzy_match_case_insensitive:
|
case fuzzy_type_t::exact_icase:
|
||||||
case fuzzy_match_prefix_case_insensitive:
|
case fuzzy_type_t::prefix_icase:
|
||||||
case fuzzy_match_substring:
|
case fuzzy_type_t::substr:
|
||||||
case fuzzy_match_substring_case_insensitive:
|
case fuzzy_type_t::substr_icase:
|
||||||
case fuzzy_match_subsequence_insertions_only:
|
case fuzzy_type_t::subseq:
|
||||||
case fuzzy_match_none: {
|
case fuzzy_type_t::none:
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
default: {
|
|
||||||
DIE("Unreachable");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
DIE("Unreachable");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicates where a match shares a prefix with the string it matches.
|
/// Indicates where a match shares a prefix with the string it matches.
|
||||||
static inline bool match_type_shares_prefix(fuzzy_match_type_t t) {
|
static inline bool match_type_shares_prefix(fuzzy_type_t t) {
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case fuzzy_match_exact:
|
case fuzzy_type_t::exact:
|
||||||
case fuzzy_match_prefix:
|
case fuzzy_type_t::prefix:
|
||||||
case fuzzy_match_case_insensitive:
|
case fuzzy_type_t::exact_icase:
|
||||||
case fuzzy_match_prefix_case_insensitive: {
|
case fuzzy_type_t::prefix_icase:
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
case fuzzy_match_substring:
|
case fuzzy_type_t::substr:
|
||||||
case fuzzy_match_substring_case_insensitive:
|
case fuzzy_type_t::substr_icase:
|
||||||
case fuzzy_match_subsequence_insertions_only:
|
case fuzzy_type_t::subseq:
|
||||||
case fuzzy_match_none: {
|
case fuzzy_type_t::none:
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
default: {
|
|
||||||
DIE("Unreachable");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
DIE("Unreachable");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test if string is a fuzzy match to another.
|
/// Test if string is a fuzzy match to another.
|
||||||
struct string_fuzzy_match_t {
|
struct string_fuzzy_match_t {
|
||||||
enum fuzzy_match_type_t type;
|
enum fuzzy_type_t type;
|
||||||
|
|
||||||
// Strength of the match. The value depends on the type. Lower is stronger.
|
// Strength of the match. The value depends on the type. Lower is stronger.
|
||||||
size_t match_distance_first;
|
size_t match_distance_first;
|
||||||
size_t match_distance_second;
|
size_t match_distance_second;
|
||||||
|
|
||||||
// Constructor.
|
// Constructor.
|
||||||
explicit string_fuzzy_match_t(enum fuzzy_match_type_t t, size_t distance_first = 0,
|
explicit string_fuzzy_match_t(enum fuzzy_type_t t, size_t distance_first = 0,
|
||||||
size_t distance_second = 0);
|
size_t distance_second = 0);
|
||||||
|
|
||||||
// Return -1, 0, 1 if this match is (respectively) better than, equal to, or worse than rhs.
|
// Return -1, 0, 1 if this match is (respectively) better than, equal to, or worse than rhs.
|
||||||
int compare(const string_fuzzy_match_t &rhs) const;
|
int compare(const string_fuzzy_match_t &rhs) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Compute a fuzzy match for a string. If maximum_match is not fuzzy_match_none, limit the type to
|
/// Compute a fuzzy match for a string. If maximum_match is not fuzzy_match_t::none, limit the type
|
||||||
/// matches at or below that type.
|
/// to matches at or below that type.
|
||||||
string_fuzzy_match_t string_fuzzy_match_string(const wcstring &string,
|
string_fuzzy_match_t string_fuzzy_match_string(const wcstring &string,
|
||||||
const wcstring &match_against,
|
const wcstring &match_against,
|
||||||
fuzzy_match_type_t limit_type = fuzzy_match_none);
|
fuzzy_type_t limit_type = fuzzy_type_t::none);
|
||||||
|
|
||||||
/// Split a string by a separator character.
|
/// Split a string by a separator character.
|
||||||
wcstring_list_t split_string(const wcstring &val, wchar_t sep);
|
wcstring_list_t split_string(const wcstring &val, wchar_t sep);
|
||||||
|
|
|
@ -98,14 +98,14 @@ bool wildcard_has(const wcstring &str, bool internal) {
|
||||||
/// \param wc The wildcard.
|
/// \param wc The wildcard.
|
||||||
/// \param leading_dots_fail_to_match Whether files beginning with dots should not be matched
|
/// \param leading_dots_fail_to_match Whether files beginning with dots should not be matched
|
||||||
/// against wildcards.
|
/// against wildcards.
|
||||||
static enum fuzzy_match_type_t wildcard_match_internal(const wcstring &str, const wcstring &wc,
|
static enum fuzzy_type_t wildcard_match_internal(const wcstring &str, const wcstring &wc,
|
||||||
bool leading_dots_fail_to_match) {
|
bool leading_dots_fail_to_match) {
|
||||||
// Hackish fix for issue #270. Prevent wildcards from matching . or .., but we must still allow
|
// Hackish fix for issue #270. Prevent wildcards from matching . or .., but we must still allow
|
||||||
// literal matches.
|
// literal matches.
|
||||||
if (leading_dots_fail_to_match && str[0] == L'.' &&
|
if (leading_dots_fail_to_match && str[0] == L'.' &&
|
||||||
(str[1] == L'\0' || (str[1] == L'.' && str[2] == L'\0'))) {
|
(str[1] == L'\0' || (str[1] == L'.' && str[2] == L'\0'))) {
|
||||||
// The string is '.' or '..' so the only possible match is an exact match.
|
// The string is '.' or '..' so the only possible match is an exact match.
|
||||||
return str == wc ? fuzzy_match_exact : fuzzy_match_none;
|
return str == wc ? fuzzy_type_t::exact : fuzzy_type_t::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Near Linear implementation as proposed here https://research.swtch.com/glob.
|
// Near Linear implementation as proposed here https://research.swtch.com/glob.
|
||||||
|
@ -121,13 +121,13 @@ static enum fuzzy_match_type_t wildcard_match_internal(const wcstring &str, cons
|
||||||
if (*wc_x == ANY_STRING || *wc_x == ANY_STRING_RECURSIVE) {
|
if (*wc_x == ANY_STRING || *wc_x == ANY_STRING_RECURSIVE) {
|
||||||
// Ignore hidden file
|
// Ignore hidden file
|
||||||
if (leading_dots_fail_to_match && is_first && str[0] == L'.') {
|
if (leading_dots_fail_to_match && is_first && str[0] == L'.') {
|
||||||
return fuzzy_match_none;
|
return fuzzy_type_t::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common case of * at the end. In that case we can early out since we know it will
|
// Common case of * at the end. In that case we can early out since we know it will
|
||||||
// match.
|
// match.
|
||||||
if (wc_x[1] == L'\0') {
|
if (wc_x[1] == L'\0') {
|
||||||
return fuzzy_match_exact;
|
return fuzzy_type_t::exact;
|
||||||
}
|
}
|
||||||
// Try to match at str_x.
|
// Try to match at str_x.
|
||||||
// If that doesn't work out, restart at str_x+1 next.
|
// If that doesn't work out, restart at str_x+1 next.
|
||||||
|
@ -138,7 +138,7 @@ static enum fuzzy_match_type_t wildcard_match_internal(const wcstring &str, cons
|
||||||
continue;
|
continue;
|
||||||
} else if (*wc_x == ANY_CHAR && *str_x != 0) {
|
} else if (*wc_x == ANY_CHAR && *str_x != 0) {
|
||||||
if (is_first && *str_x == L'.') {
|
if (is_first && *str_x == L'.') {
|
||||||
return fuzzy_match_none;
|
return fuzzy_type_t::none;
|
||||||
}
|
}
|
||||||
wc_x++;
|
wc_x++;
|
||||||
str_x++;
|
str_x++;
|
||||||
|
@ -155,10 +155,10 @@ static enum fuzzy_match_type_t wildcard_match_internal(const wcstring &str, cons
|
||||||
str_x = restart_str_x;
|
str_x = restart_str_x;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return fuzzy_match_none;
|
return fuzzy_type_t::none;
|
||||||
}
|
}
|
||||||
// Matched all of pattern to all of name. Success.
|
// Matched all of pattern to all of name. Success.
|
||||||
return fuzzy_match_exact;
|
return fuzzy_type_t::exact;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This does something horrible refactored from an even more horrible function.
|
// This does something horrible refactored from an even more horrible function.
|
||||||
|
@ -192,7 +192,7 @@ static bool has_prefix_match(const completion_list_t *comps, size_t first) {
|
||||||
if (comps != nullptr) {
|
if (comps != nullptr) {
|
||||||
const size_t after_count = comps->size();
|
const size_t after_count = comps->size();
|
||||||
for (size_t j = first; j < after_count; j++) {
|
for (size_t j = first; j < after_count; j++) {
|
||||||
if (comps->at(j).match.type <= fuzzy_match_prefix) {
|
if (comps->at(j).match.type <= fuzzy_type_t::prefix) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,7 +245,7 @@ static bool wildcard_complete_internal(const wchar_t *const str, size_t str_len,
|
||||||
// If we're allowing fuzzy match, any match is OK. Otherwise we require a prefix match.
|
// If we're allowing fuzzy match, any match is OK. Otherwise we require a prefix match.
|
||||||
bool match_acceptable;
|
bool match_acceptable;
|
||||||
if (params.expand_flags & expand_flag::fuzzy_match) {
|
if (params.expand_flags & expand_flag::fuzzy_match) {
|
||||||
match_acceptable = match.type != fuzzy_match_none;
|
match_acceptable = match.type != fuzzy_type_t::none;
|
||||||
} else {
|
} else {
|
||||||
match_acceptable = match_type_shares_prefix(match.type);
|
match_acceptable = match_type_shares_prefix(match.type);
|
||||||
}
|
}
|
||||||
|
@ -356,8 +356,8 @@ bool wildcard_complete(const wcstring &str, const wchar_t *wc,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wildcard_match(const wcstring &str, const wcstring &wc, bool leading_dots_fail_to_match) {
|
bool wildcard_match(const wcstring &str, const wcstring &wc, bool leading_dots_fail_to_match) {
|
||||||
enum fuzzy_match_type_t match = wildcard_match_internal(str, wc, leading_dots_fail_to_match);
|
enum fuzzy_type_t match = wildcard_match_internal(str, wc, leading_dots_fail_to_match);
|
||||||
return match != fuzzy_match_none;
|
return match != fuzzy_type_t::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fast_waccess(const struct stat &stat_buf, uint8_t mode) {
|
static int fast_waccess(const struct stat &stat_buf, uint8_t mode) {
|
||||||
|
@ -817,7 +817,7 @@ void wildcard_expander_t::expand_literal_intermediate_segment_with_fuzz(const wc
|
||||||
// Skip cases that don't match or match exactly. The match-exactly case was handled directly
|
// Skip cases that don't match or match exactly. The match-exactly case was handled directly
|
||||||
// in expand().
|
// in expand().
|
||||||
const string_fuzzy_match_t match = string_fuzzy_match_string(wc_segment, name_str);
|
const string_fuzzy_match_t match = string_fuzzy_match_string(wc_segment, name_str);
|
||||||
if (match.type == fuzzy_match_none || match.type == fuzzy_match_exact) {
|
if (match.type == fuzzy_type_t::none || match.type == fuzzy_type_t::exact) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user