diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp index 64de41d36..bd9bbb910 100644 --- a/src/fish_tests.cpp +++ b/src/fish_tests.cpp @@ -1181,7 +1181,7 @@ static void test_expand() { expand_test(L"foo\\$bar", EXPAND_SKIP_VARIABLES, L"foo$bar", 0, L"Failed to handle dollar sign in variable-skipping expansion"); - // b + // bb // x // bar // baz @@ -1193,18 +1193,24 @@ static void test_expand() { // nub // q // .foo + // aaa + // aaa2 + // x if (system("mkdir -p /tmp/fish_expand_test/")) err(L"mkdir failed"); - if (system("mkdir -p /tmp/fish_expand_test/b/")) err(L"mkdir failed"); + if (system("mkdir -p /tmp/fish_expand_test/bb/")) err(L"mkdir failed"); if (system("mkdir -p /tmp/fish_expand_test/baz/")) err(L"mkdir failed"); if (system("mkdir -p /tmp/fish_expand_test/bax/")) err(L"mkdir failed"); if (system("mkdir -p /tmp/fish_expand_test/lol/nub/")) err(L"mkdir failed"); + if (system("mkdir -p /tmp/fish_expand_test/aaa/")) err(L"mkdir failed"); + if (system("mkdir -p /tmp/fish_expand_test/aaa2/")) err(L"mkdir failed"); if (system("touch /tmp/fish_expand_test/.foo")) err(L"touch failed"); - if (system("touch /tmp/fish_expand_test/b/x")) err(L"touch failed"); + if (system("touch /tmp/fish_expand_test/bb/x")) err(L"touch failed"); if (system("touch /tmp/fish_expand_test/bar")) err(L"touch failed"); if (system("touch /tmp/fish_expand_test/bax/xxx")) err(L"touch failed"); if (system("touch /tmp/fish_expand_test/baz/xxx")) err(L"touch failed"); if (system("touch /tmp/fish_expand_test/baz/yyy")) err(L"touch failed"); if (system("touch /tmp/fish_expand_test/lol/nub/q")) err(L"touch failed"); + if (system("touch /tmp/fish_expand_test/aaa2/x")) err(L"touch failed"); // This is checking that .* does NOT match . and .. // (https://github.com/fish-shell/fish-shell/issues/270). But it does have to match literal @@ -1228,18 +1234,18 @@ static void test_expand() { expand_test(L"/tmp/fish_expand_test////baz/xxx", 0, L"/tmp/fish_expand_test////baz/xxx", wnull, L"Glob did the wrong thing 3"); - expand_test(L"/tmp/fish_expand_test/b**", 0, L"/tmp/fish_expand_test/b", - L"/tmp/fish_expand_test/b/x", L"/tmp/fish_expand_test/bar", + expand_test(L"/tmp/fish_expand_test/b**", 0, L"/tmp/fish_expand_test/bb", + L"/tmp/fish_expand_test/bb/x", L"/tmp/fish_expand_test/bar", L"/tmp/fish_expand_test/bax", L"/tmp/fish_expand_test/bax/xxx", L"/tmp/fish_expand_test/baz", L"/tmp/fish_expand_test/baz/xxx", L"/tmp/fish_expand_test/baz/yyy", wnull, L"Glob did the wrong thing 4"); // A trailing slash should only produce directories. - expand_test(L"/tmp/fish_expand_test/b*/", 0, L"/tmp/fish_expand_test/b/", + expand_test(L"/tmp/fish_expand_test/b*/", 0, L"/tmp/fish_expand_test/bb/", L"/tmp/fish_expand_test/baz/", L"/tmp/fish_expand_test/bax/", wnull, L"Glob did the wrong thing 5"); - expand_test(L"/tmp/fish_expand_test/b**/", 0, L"/tmp/fish_expand_test/b/", + expand_test(L"/tmp/fish_expand_test/b**/", 0, L"/tmp/fish_expand_test/bb/", L"/tmp/fish_expand_test/baz/", L"/tmp/fish_expand_test/bax/", wnull, L"Glob did the wrong thing 6"); @@ -1254,10 +1260,10 @@ static void test_expand() { L"/tmp/fish_expand_test/bax/", L"/tmp/fish_expand_test/baz/", wnull, L"Case insensitive test did the wrong thing"); - expand_test(L"/tmp/fish_expand_test/b/yyy", EXPAND_FOR_COMPLETIONS, + expand_test(L"/tmp/fish_expand_test/bb/yyy", EXPAND_FOR_COMPLETIONS, /* nothing! */ wnull, L"Wrong fuzzy matching 1"); - expand_test(L"/tmp/fish_expand_test/b/x", EXPAND_FOR_COMPLETIONS | EXPAND_FUZZY_MATCH, L"", + expand_test(L"/tmp/fish_expand_test/bb/x", EXPAND_FOR_COMPLETIONS | EXPAND_FUZZY_MATCH, L"", wnull, // we just expect the empty string since this is an exact match L"Wrong fuzzy matching 2"); @@ -1271,6 +1277,12 @@ static void test_expand() { expand_test(L"/tmp/fish_expand_test/b/yyy", EXPAND_FOR_COMPLETIONS | EXPAND_FUZZY_MATCH, L"/tmp/fish_expand_test/baz/yyy", wnull, L"Wrong fuzzy matching 4"); + + expand_test(L"/tmp/fish_expand_test/aa/x", EXPAND_FOR_COMPLETIONS | EXPAND_FUZZY_MATCH, + L"/tmp/fish_expand_test/aaa2/x", wnull, L"Wrong fuzzy matching 5"); + + expand_test(L"/tmp/fish_expand_test/aaa/x", EXPAND_FOR_COMPLETIONS | EXPAND_FUZZY_MATCH, + wnull, L"Wrong fuzzy matching 6 - shouldn't remove valid directory names (#3211)"); if (!expand_test(L"/tmp/fish_expand_test/.*", 0, L"/tmp/fish_expand_test/.foo", 0)) { err(L"Expansion not correctly handling dotfiles"); diff --git a/src/wildcard.cpp b/src/wildcard.cpp index 94058c7ed..980bea677 100644 --- a/src/wildcard.cpp +++ b/src/wildcard.cpp @@ -824,16 +824,21 @@ void wildcard_expander_t::expand(const wcstring &base_dir, const wchar_t *wc, // (issue #2099). assert(next_slash != NULL); + // Absolute path of the intermediate directory + const wcstring intermediate_dirpath = base_dir + wc_segment + L'/'; + // This just trumps everything. size_t before = this->resolved_completions->size(); - this->expand(base_dir + wc_segment + L'/', wc_remainder, - effective_prefix + wc_segment + L'/'); + this->expand(intermediate_dirpath, wc_remainder, effective_prefix + wc_segment + L'/'); // Maybe try a fuzzy match (#94) if nothing was found with the literal match. Respect // EXPAND_NO_DIRECTORY_ABBREVIATIONS (issue #2413). + // Don't do fuzzy matches if the literal segment was valid (#3211) bool allow_fuzzy = (this->flags & (EXPAND_FUZZY_MATCH | EXPAND_NO_FUZZY_DIRECTORIES)) == EXPAND_FUZZY_MATCH; - if (allow_fuzzy && this->resolved_completions->size() == before) { + if (allow_fuzzy && + this->resolved_completions->size() == before && + waccess(intermediate_dirpath, F_OK) != 0) { assert(this->flags & EXPAND_FOR_COMPLETIONS); DIR *base_dir_fd = open_dir(base_dir); if (base_dir_fd != NULL) {