Don't block "hidden files" for wildcard expansions that aren't files (like case)

https://github.com/fish-shell/fish-shell/issues/667
This commit is contained in:
ridiculousfish 2013-04-20 12:41:02 -07:00
parent e285d2939b
commit b65f8d81fc
2 changed files with 23 additions and 27 deletions

View file

@ -143,15 +143,13 @@ int wildcard_has(const wchar_t *str, int internal)
\param wc The wildcard. \param wc The wildcard.
\param is_first Whether files beginning with dots should not be matched against wildcards. \param is_first Whether files beginning with dots should not be matched against wildcards.
*/ */
static bool wildcard_match2(const wchar_t *str, static bool wildcard_match_internal(const wchar_t *str, const wchar_t *wc, bool leading_dots_fail_to_match, bool is_first)
const wchar_t *wc,
bool is_first)
{ {
if (*str == 0 && *wc==0) if (*str == 0 && *wc==0)
return true; return true;
/* Hackish fix for https://github.com/fish-shell/fish-shell/issues/270 . Prevent wildcards from matching . or .., but we must still allow literal matches. */ /* Hackish fix for https://github.com/fish-shell/fish-shell/issues/270 . Prevent wildcards from matching . or .., but we must still allow literal matches. */
if (is_first && contains(str, L".", L"..")) if (leading_dots_fail_to_match && is_first && contains(str, L".", L".."))
{ {
/* The string is '.' or '..'. Return true if the wildcard exactly matches. */ /* The string is '.' or '..'. Return true if the wildcard exactly matches. */
return ! wcscmp(str, wc); return ! wcscmp(str, wc);
@ -160,7 +158,7 @@ static bool wildcard_match2(const wchar_t *str,
if (*wc == ANY_STRING || *wc == ANY_STRING_RECURSIVE) if (*wc == ANY_STRING || *wc == ANY_STRING_RECURSIVE)
{ {
/* Ignore hidden file */ /* Ignore hidden file */
if (is_first && *str == L'.') if (leading_dots_fail_to_match && is_first && *str == L'.')
{ {
return false; return false;
} }
@ -168,7 +166,7 @@ static bool wildcard_match2(const wchar_t *str,
/* Try all submatches */ /* Try all submatches */
do do
{ {
if (wildcard_match2(str, wc+1, false)) if (wildcard_match_internal(str, wc+1, leading_dots_fail_to_match, false))
return true; return true;
} }
while (*(str++) != 0); while (*(str++) != 0);
@ -190,11 +188,11 @@ static bool wildcard_match2(const wchar_t *str,
return false; return false;
} }
return wildcard_match2(str+1, wc+1, false); return wildcard_match_internal(str+1, wc+1, leading_dots_fail_to_match, false);
} }
if (*wc == *str) if (*wc == *str)
return wildcard_match2(str+1, wc+1, false); return wildcard_match_internal(str+1, wc+1, leading_dots_fail_to_match, false);
return false; return false;
} }
@ -310,9 +308,9 @@ bool wildcard_complete(const wcstring &str,
} }
bool wildcard_match(const wcstring &str, const wcstring &wc) bool wildcard_match(const wcstring &str, const wcstring &wc, bool leading_dots_fail_to_match)
{ {
return wildcard_match2(str.c_str(), wc.c_str(), true); return wildcard_match_internal(str.c_str(), wc.c_str(), leading_dots_fail_to_match, true /* first */);
} }
/** /**
@ -821,20 +819,19 @@ static int wildcard_expand_internal(const wchar_t *wc,
/* /*
This is the last wildcard segment, and it is not empty. Match files/directories. This is the last wildcard segment, and it is not empty. Match files/directories.
*/ */
wcstring next; wcstring name_str;
while (wreaddir(dir, next)) while (wreaddir(dir, name_str))
{ {
const wchar_t * const name = next.c_str();
if (flags & ACCEPT_INCOMPLETE) if (flags & ACCEPT_INCOMPLETE)
{ {
const wcstring long_name = make_path(base_dir, next); const wcstring long_name = make_path(base_dir, name_str);
/* /*
Test for matches before stating file, so as to minimize the number of calls to the much slower stat function Test for matches before stating file, so as to minimize the number of calls to the much slower stat function
*/ */
std::vector<completion_t> test; std::vector<completion_t> test;
if (wildcard_complete(name, if (wildcard_complete(name_str,
wc, wc,
L"", L"",
0, 0,
@ -845,7 +842,7 @@ static int wildcard_expand_internal(const wchar_t *wc,
{ {
wildcard_completion_allocate(out, wildcard_completion_allocate(out,
long_name, long_name,
name, name_str,
wc, wc,
flags); flags);
@ -854,9 +851,9 @@ static int wildcard_expand_internal(const wchar_t *wc,
} }
else else
{ {
if (wildcard_match2(name, wc, true)) if (wildcard_match(name_str, wc, true /* skip files with leading dots */))
{ {
const wcstring long_name = make_path(base_dir, next); const wcstring long_name = make_path(base_dir, name_str);
int skip = 0; int skip = 0;
if (is_recursive) if (is_recursive)
@ -940,16 +937,14 @@ static int wildcard_expand_internal(const wchar_t *wc,
wcscpy(new_dir, base_dir); wcscpy(new_dir, base_dir);
wcstring next; wcstring name_str;
while (wreaddir(dir, next)) while (wreaddir(dir, name_str))
{ {
const wchar_t *name = next.c_str();
/* /*
Test if the file/directory name matches the whole Test if the file/directory name matches the whole
wildcard element, i.e. regular matching. wildcard element, i.e. regular matching.
*/ */
int whole_match = wildcard_match2(name, wc_str, true); int whole_match = wildcard_match(name_str, wc_str, true /* ignore leading dots */);
int partial_match = 0; int partial_match = 0;
/* /*
@ -962,7 +957,7 @@ static int wildcard_expand_internal(const wchar_t *wc,
{ {
const wchar_t *end = wcschr(wc, ANY_STRING_RECURSIVE); const wchar_t *end = wcschr(wc, ANY_STRING_RECURSIVE);
wchar_t *wc_sub = wcsndup(wc, end-wc+1); wchar_t *wc_sub = wcsndup(wc, end-wc+1);
partial_match = wildcard_match2(name, wc_sub, true); partial_match = wildcard_match(name_str, wc_sub, true /* ignore leading dots */);
free(wc_sub); free(wc_sub);
} }
@ -973,7 +968,7 @@ static int wildcard_expand_internal(const wchar_t *wc,
int stat_res; int stat_res;
int new_res; int new_res;
wcscpy(&new_dir[base_len], name); wcscpy(&new_dir[base_len], name_str.c_str());
dir_str = wcs2str(new_dir); dir_str = wcs2str(new_dir);
if (dir_str) if (dir_str)

View file

@ -73,9 +73,10 @@ int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, expand_
\param str The string to test \param str The string to test
\param wc The wildcard to test against \param wc The wildcard to test against
\param leading_dots_fail_to_match if set, strings with leading dots are assumed to be hidden files and are not matched
\return true if the wildcard matched \return true if the wildcard matched
*/ */
bool wildcard_match(const wcstring &str, const wcstring &wc); bool wildcard_match(const wcstring &str, const wcstring &wc, bool leading_dots_fail_to_match = false);
/** /**