diff options
Diffstat (limited to 'src/nvim/path.c')
-rw-r--r-- | src/nvim/path.c | 59 |
1 files changed, 39 insertions, 20 deletions
diff --git a/src/nvim/path.c b/src/nvim/path.c index 1c787e3a1d..31318f6bea 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -51,9 +51,10 @@ /// expanded. /// @param s2 Second file name. /// @param checkname When both files don't exist, only compare their names. +/// @param expandenv Whether to expand environment variables in file names. /// @return Enum of type FileComparison. @see FileComparison. FileComparison path_full_compare(char_u *const s1, char_u *const s2, - const bool checkname) + const bool checkname, const bool expandenv) { assert(s1 && s2); char_u exp1[MAXPATHL]; @@ -61,7 +62,11 @@ FileComparison path_full_compare(char_u *const s1, char_u *const s2, char_u full2[MAXPATHL]; FileID file_id_1, file_id_2; - expand_env(s1, exp1, MAXPATHL); + if (expandenv) { + expand_env(s1, exp1, MAXPATHL); + } else { + xstrlcpy((char *)exp1, (const char *)s1, MAXPATHL - 1); + } bool id_ok_1 = os_fileid((char *)exp1, &file_id_1); bool id_ok_2 = os_fileid((char *)s2, &file_id_2); if (!id_ok_1 && !id_ok_2) { @@ -333,9 +338,9 @@ int path_fnamencmp(const char *const fname1, const char *const fname2, && (p_fic ? (c1 != c2 && CH_FOLD(c1) != CH_FOLD(c2)) : c1 != c2)) { break; } - len -= (size_t)MB_PTR2LEN((const char_u *)p1); - p1 += MB_PTR2LEN((const char_u *)p1); - p2 += MB_PTR2LEN((const char_u *)p2); + len -= (size_t)utfc_ptr2len((const char_u *)p1); + p1 += utfc_ptr2len((const char_u *)p1); + p2 += utfc_ptr2len((const char_u *)p2); } return c1 - c2; #else @@ -1115,10 +1120,22 @@ static bool has_env_var(char_u *p) static bool has_special_wildchar(char_u *p) { for (; *p; MB_PTR_ADV(p)) { - // Allow for escaping - if (*p == '\\' && p[1] != NUL) { + // Disallow line break characters. + if (*p == '\r' || *p == '\n') { + break; + } + // Allow for escaping. + if (*p == '\\' && p[1] != NUL && p[1] != '\r' && p[1] != '\n') { p++; } else if (vim_strchr((char_u *)SPECIAL_WILDCHAR, *p) != NULL) { + // A { must be followed by a matching }. + if (*p == '{' && vim_strchr(p, '}') == NULL) { + continue; + } + // A quote and backtick must be followed by another one. + if ((*p == '`' || *p == '\'') && vim_strchr(p, *p) == NULL) { + continue; + } return true; } } @@ -1161,7 +1178,7 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file, */ if (recursive) #ifdef SPECIAL_WILDCHAR - return mch_expand_wildcards(num_pat, pat, num_file, file, flags); + return os_expand_wildcards(num_pat, pat, num_file, file, flags); #else return FAIL; #endif @@ -1176,7 +1193,7 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file, for (int i = 0; i < num_pat; i++) { if (has_special_wildchar(pat[i]) && !(vim_backtick(pat[i]) && pat[i][1] == '=')) { - return mch_expand_wildcards(num_pat, pat, num_file, file, flags); + return os_expand_wildcards(num_pat, pat, num_file, file, flags); } } #endif @@ -1203,7 +1220,7 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file, } } else { // First expand environment variables, "~/" and "~user/". - if (has_env_var(p) || *p == '~') { + if ((has_env_var(p) && !(flags & EW_NOTENV)) || *p == '~') { p = expand_env_save_opt(p, true); if (p == NULL) p = pat[i]; @@ -1216,8 +1233,8 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file, else if (has_env_var(p) || *p == '~') { xfree(p); ga_clear_strings(&ga); - i = mch_expand_wildcards(num_pat, pat, num_file, file, - flags | EW_KEEPDOLLAR); + i = os_expand_wildcards(num_pat, pat, num_file, file, + flags | EW_KEEPDOLLAR); recursive = false; return i; } @@ -1905,16 +1922,16 @@ int pathcmp(const char *p, const char *q, int maxlen) : c1 - c2; // no match } - i += MB_PTR2LEN((char_u *)p + i); - j += MB_PTR2LEN((char_u *)q + j); + i += utfc_ptr2len((char_u *)p + i); + j += utfc_ptr2len((char_u *)q + j); } if (s == NULL) { // "i" or "j" ran into "maxlen" return 0; } c1 = PTR2CHAR((char_u *)s + i); - c2 = PTR2CHAR((char_u *)s + i + MB_PTR2LEN((char_u *)s + i)); - /* ignore a trailing slash, but not "//" or ":/" */ + c2 = PTR2CHAR((char_u *)s + i + utfc_ptr2len((char_u *)s + i)); + // ignore a trailing slash, but not "//" or ":/" if (c2 == NUL && i > 0 && !after_pathsep((char *)s, (char *)s + i) @@ -1923,10 +1940,12 @@ int pathcmp(const char *p, const char *q, int maxlen) #else && c1 == '/' #endif - ) - return 0; /* match with trailing slash */ - if (s == q) - return -1; /* no match */ + ) { + return 0; // match with trailing slash + } + if (s == q) { + return -1; // no match + } return 1; } |