mirror of
https://github.com/neovim/neovim.git
synced 2026-10-25 23:20:23 -05:00
fix(path): normalize path slashes on Windows #37729
Problem: On Windows, path separators may become inconsistent for various reasons, which makes normalization quite painful. Solution: Normalize paths to `/` at the entry boundaries and always use it internally, converting back only in rare cases where `\` is really needed (e.g. cmd.exe/bat scripts?). This is the first commit in a series of incremental steps. Note: * some funcs won't respect shellslash. e.g. `expand/fnamemodify` * some funcs still respect shellslash, but will be updated in a follow PR. e.g. `ex_pwd/f_chdir/f_getcwd` * uv's built-in funcs always return `\`. e.g. `uv.cwd/uv.exepath` Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
This commit is contained in:
1 parent
27191e0f4f
commit
f130922744
41 files changed
+203
-216
No files matched your search
@@ -216,9 +216,6 @@ void alist_add(alist_T *al, char *fname, int set_fnum)
|
||||
arglist_locked = true;
|
||||
wp->w_locked++;
|
||||
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
slash_adjust(fname);
|
||||
#endif
|
||||
AARGLIST(al)[al->al_ga.ga_len].ae_fname = fname;
|
||||
if (set_fnum > 0) {
|
||||
AARGLIST(al)[al->al_ga.ga_len].ae_fnum =
|
||||
|
||||
@@ -75,13 +75,8 @@
|
||||
#define Ctrl__ 31
|
||||
|
||||
// Character that separates dir names in a path.
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
# define PATHSEP psepc
|
||||
# define PATHSEPSTR pseps
|
||||
#else
|
||||
# define PATHSEP '/'
|
||||
# define PATHSEPSTR "/"
|
||||
#endif
|
||||
#define PATHSEP '/'
|
||||
#define PATHSEPSTR "/"
|
||||
|
||||
/// Checks if `c` is a space or tab character.
|
||||
///
|
||||
|
||||
@@ -316,6 +316,7 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
|
||||
}
|
||||
// Translate string into pattern and expand it.
|
||||
const int use_options = (options
|
||||
| WILD_USE_COMPLETESLASH
|
||||
| WILD_HOME_REPLACE
|
||||
| WILD_ADD_SLASH
|
||||
| WILD_SILENT
|
||||
@@ -2725,16 +2726,13 @@ static int expand_files_and_dirs(expand_T *xp, char *pat, char ***matches, int *
|
||||
xfree(pat);
|
||||
}
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
if (p_csl[0] != NUL && (options & WILD_IGNORE_COMPLETESLASH) == 0) {
|
||||
if ((options & WILD_USE_COMPLETESLASH) && ((p_csl[0] == NUL && !p_ssl) || p_csl[0] == 'b')) {
|
||||
for (int j = 0; j < *numMatches; j++) {
|
||||
char *ptr = (*matches)[j];
|
||||
while (*ptr != NUL) {
|
||||
if (p_csl[0] == 's' && *ptr == '\\') {
|
||||
*ptr = '/';
|
||||
} else if (p_csl[0] == 'b' && *ptr == '/') {
|
||||
for (; *ptr; ptr++) {
|
||||
if (*ptr == '/') {
|
||||
*ptr = '\\';
|
||||
}
|
||||
ptr += utfc_ptr2len(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ enum {
|
||||
WILD_ESCAPE = 0x80,
|
||||
WILD_ICASE = 0x100,
|
||||
WILD_ALLLINKS = 0x200,
|
||||
WILD_IGNORE_COMPLETESLASH = 0x400,
|
||||
WILD_USE_COMPLETESLASH = 0x400,
|
||||
WILD_NOERROR = 0x800, ///< sets EW_NOERROR
|
||||
WILD_BUFLASTUSED = 0x1000,
|
||||
BUF_DIFF_FILTER = 0x2000,
|
||||
|
||||
+1
-7
@@ -462,12 +462,6 @@ void f_exepath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
|
||||
os_can_exe(tv_get_string(&argvars[0]), &path, true);
|
||||
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
if (path != NULL) {
|
||||
slash_adjust(path);
|
||||
}
|
||||
#endif
|
||||
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = path;
|
||||
}
|
||||
@@ -878,7 +872,7 @@ void f_glob(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
/// "globpath()" function
|
||||
void f_globpath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
{
|
||||
int flags = WILD_IGNORE_COMPLETESLASH; // Flags for globpath.
|
||||
int flags = 0; // Flags for globpath.
|
||||
bool error = false;
|
||||
|
||||
// Return a string, or a list if the optional third argument is non-zero.
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "nvim/log.h"
|
||||
#include "nvim/os/os.h"
|
||||
#include "nvim/os/os_defs.h"
|
||||
#include "nvim/path.h"
|
||||
#include "nvim/types_defs.h"
|
||||
#include "nvim/ui_client.h"
|
||||
|
||||
@@ -29,6 +30,8 @@ int libuv_proc_spawn(LibuvProc *uvproc)
|
||||
// expects a different syntax (must be prepared by the caller before now).
|
||||
if (os_shell_is_cmdexe(proc->argv[0])) {
|
||||
uvproc->uvopts.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS;
|
||||
// cmd.exe compatibility: backslashes required for path.
|
||||
TO_BACKSLASH(proc->argv[0]);
|
||||
}
|
||||
if (proc->detach) {
|
||||
uvproc->uvopts.flags |= UV_PROCESS_DETACHED;
|
||||
|
||||
+4
-2
@@ -4145,6 +4145,8 @@ int expand_filename(exarg_T *eap, char **cmdlinep, const char **errormsgp)
|
||||
}
|
||||
repl_cmdline(eap, eap->arg, strlen(eap->arg), p, cmdlinep);
|
||||
xfree(p);
|
||||
} else {
|
||||
TO_SLASH(eap->arg);
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
@@ -5673,7 +5675,7 @@ int expand_findfunc(char *pat, char ***files, int *numMatches)
|
||||
int idx = 0;
|
||||
TV_LIST_ITER_CONST(l, li, {
|
||||
if (TV_LIST_ITEM_TV(li)->v_type == VAR_STRING) {
|
||||
(*files)[idx] = xstrdup(TV_LIST_ITEM_TV(li)->vval.v_string);
|
||||
(*files)[idx] = TO_SLASH_SAVE(TV_LIST_ITEM_TV(li)->vval.v_string);
|
||||
idx++;
|
||||
}
|
||||
});
|
||||
@@ -5704,7 +5706,7 @@ static char *findfunc_find_file(char *findarg, size_t findarg_len, int count)
|
||||
} else {
|
||||
listitem_T *li = tv_list_find(fname_list, count - 1);
|
||||
if (li != NULL && TV_LIST_ITEM_TV(li)->v_type == VAR_STRING) {
|
||||
ret_fname = xstrdup(TV_LIST_ITEM_TV(li)->vval.v_string);
|
||||
ret_fname = TO_SLASH_SAVE(TV_LIST_ITEM_TV(li)->vval.v_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1593,6 +1593,7 @@ theend:
|
||||
char *grab_file_name(int count, linenr_T *file_lnum)
|
||||
{
|
||||
int options = FNAME_MESS | FNAME_EXP | FNAME_REL | FNAME_UNESC;
|
||||
char *fname;
|
||||
if (VIsual_active) {
|
||||
size_t len;
|
||||
char *ptr;
|
||||
@@ -1605,9 +1606,12 @@ char *grab_file_name(int count, linenr_T *file_lnum)
|
||||
|
||||
*file_lnum = getdigits_int32(&p, false, 0);
|
||||
}
|
||||
return find_file_name_in_path(ptr, len, options, count, curbuf->b_ffname);
|
||||
fname = find_file_name_in_path(ptr, len, options, count, curbuf->b_ffname);
|
||||
} else {
|
||||
fname = file_name_at_cursor(options | FNAME_HYP, count, file_lnum);
|
||||
}
|
||||
return file_name_at_cursor(options | FNAME_HYP, count, file_lnum);
|
||||
TO_SLASH(fname);
|
||||
return fname;
|
||||
}
|
||||
|
||||
/// Return the file name under or after the cursor.
|
||||
|
||||
+5
-30
@@ -4038,30 +4038,9 @@ static void get_next_filename_completion(void)
|
||||
int max_score = 0;
|
||||
Direction dir = compl_direction;
|
||||
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
char pathsep = (curbuf->b_p_csl[0] == 's')
|
||||
? '/' : (curbuf->b_p_csl[0] == 'b') ? '\\' : PATHSEP;
|
||||
#else
|
||||
char pathsep = PATHSEP;
|
||||
#endif
|
||||
|
||||
if (in_fuzzy_collect) {
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
if (curbuf->b_p_csl[0] == 's') {
|
||||
for (size_t i = 0; i < leader_len; i++) {
|
||||
if (leader[i] == '\\') {
|
||||
leader[i] = '/';
|
||||
}
|
||||
}
|
||||
} else if (curbuf->b_p_csl[0] == 'b') {
|
||||
for (size_t i = 0; i < leader_len; i++) {
|
||||
if (leader[i] == '/') {
|
||||
leader[i] = '\\';
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
char *last_sep = strrchr(leader, pathsep);
|
||||
TO_SLASH(leader);
|
||||
char *last_sep = strrchr(leader, PATHSEP);
|
||||
if (last_sep == NULL) {
|
||||
// No path separator or separator is the last character,
|
||||
// fuzzy match the whole leader
|
||||
@@ -4093,16 +4072,12 @@ static void get_next_filename_completion(void)
|
||||
// May change home directory back to "~".
|
||||
tilde_replace(compl_pattern.data, num_matches, matches);
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
if (curbuf->b_p_csl[0] != NUL) {
|
||||
if ((curbuf->b_p_csl[0] == NUL && !p_ssl) || curbuf->b_p_csl[0] == 'b') {
|
||||
for (int i = 0; i < num_matches; i++) {
|
||||
char *ptr = matches[i];
|
||||
while (*ptr != NUL) {
|
||||
if (curbuf->b_p_csl[0] == 's' && *ptr == '\\') {
|
||||
*ptr = '/';
|
||||
} else if (curbuf->b_p_csl[0] == 'b' && *ptr == '/') {
|
||||
for (char *ptr = matches[i]; *ptr; ptr++) {
|
||||
if (*ptr == '/') {
|
||||
*ptr = '\\';
|
||||
}
|
||||
ptr += utfc_ptr2len(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,6 +256,7 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
{
|
||||
argv0 = argv[0];
|
||||
TO_SLASH(argv0);
|
||||
|
||||
if (!appname_is_valid()) {
|
||||
fprintf(stderr, "$NVIM_APPNAME must be a name or relative path.\n");
|
||||
@@ -1461,6 +1462,7 @@ scripterror:
|
||||
break;
|
||||
case 'u': // "-u {vimrc}" vim inits file
|
||||
parmp->use_vimrc = argv[0];
|
||||
TO_SLASH(argv[0]);
|
||||
break;
|
||||
case 'U': // "-U {gvimrc}" gvim inits file
|
||||
break;
|
||||
@@ -1505,6 +1507,7 @@ scripterror:
|
||||
xfree(p);
|
||||
p = tilde_expanded;
|
||||
}
|
||||
TO_SLASH(p);
|
||||
#endif
|
||||
|
||||
if (parmp->diff_mode && os_isdir(p) && GARGCOUNT > 0
|
||||
|
||||
@@ -913,6 +913,7 @@ void ml_recover(bool checkext)
|
||||
|
||||
// If .swp file name given directly, use name from swapfile for buffer.
|
||||
if (directly) {
|
||||
TO_SLASH(b0p->b0_fname);
|
||||
expand_env(b0p->b0_fname, NameBuff, MAXPATHL);
|
||||
if (setfname(curbuf, NameBuff, NULL, true) == FAIL) {
|
||||
goto theend;
|
||||
@@ -3510,6 +3511,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
|
||||
fd = os_open(fname, O_RDONLY, 0);
|
||||
if (fd >= 0) {
|
||||
if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0)) {
|
||||
TO_SLASH(b0.b0_fname);
|
||||
proc_running = swapfile_proc_running(&b0, fname);
|
||||
|
||||
// If the swapfile has the same directory as the
|
||||
|
||||
+30
-4
@@ -365,7 +365,7 @@ void set_init_1(bool clean_arg)
|
||||
memmove(backupdir + 2, backupdir, backupdir_len + 1);
|
||||
memmove(backupdir, ".,", 2);
|
||||
set_string_default(kOptBackupdir, backupdir, true);
|
||||
set_string_default(kOptViewdir, stdpaths_user_state_subpath("view", 2, true),
|
||||
set_string_default(kOptViewdir, stdpaths_user_state_subpath("view", 2, false),
|
||||
true);
|
||||
set_string_default(kOptDirectory, stdpaths_user_state_subpath("swap", 2, true),
|
||||
true);
|
||||
@@ -2650,6 +2650,8 @@ static const char *did_set_scrollbind(optset_T *args)
|
||||
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
/// Process the updated 'shellslash' option value.
|
||||
/// TODO(ntdiary): Remove this once we're confident that the `shellslash`
|
||||
/// option is no longer needed.
|
||||
static const char *did_set_shellslash(optset_T *args FUNC_ATTR_UNUSED)
|
||||
{
|
||||
if (p_ssl) {
|
||||
@@ -2662,10 +2664,11 @@ static const char *did_set_shellslash(optset_T *args FUNC_ATTR_UNUSED)
|
||||
pseps[0] = '\\';
|
||||
}
|
||||
|
||||
// TODO(ntdiary): Remove these in the follow PR.
|
||||
// need to adjust the file name arguments and buffer names.
|
||||
buflist_slash_adjust();
|
||||
alist_slash_adjust();
|
||||
scriptnames_slash_adjust();
|
||||
// buflist_slash_adjust();
|
||||
// alist_slash_adjust();
|
||||
// scriptnames_slash_adjust();
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
@@ -3903,6 +3906,29 @@ static const char *set_option(const OptIndex opt_idx, OptVal value, int opt_flag
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
// Ensure "/" slashes in various options.
|
||||
uint32_t flags = options[opt_idx].flags;
|
||||
if ((flags & kOptFlagExpand)
|
||||
&& opt_idx != kOptEqualprg
|
||||
&& opt_idx != kOptFormatprg
|
||||
&& opt_idx != kOptGrepprg
|
||||
&& opt_idx != kOptKeywordprg
|
||||
&& opt_idx != kOptMakeprg
|
||||
&& opt_idx != kOptShell) {
|
||||
bool allow_comma = flags & kOptFlagComma;
|
||||
bool allow_space = (opt_idx == kOptCdpath || opt_idx == kOptPath || opt_idx == kOptTags);
|
||||
for (char *p = value.data.string.data; *p; p++) {
|
||||
if (*p != '\\'
|
||||
|| (p[1] == ',' && allow_comma)
|
||||
|| (p[1] == ' ' && allow_space)) {
|
||||
continue;
|
||||
}
|
||||
*p = '/';
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vimoption_T *opt = &options[opt_idx];
|
||||
const bool scope_local = opt_flags & OPT_LOCAL;
|
||||
const bool scope_global = opt_flags & OPT_GLOBAL;
|
||||
|
||||
+2
-15
@@ -618,6 +618,7 @@ size_t expand_env_esc(const char *restrict srcp, char *restrict dst, int dstlen,
|
||||
#endif
|
||||
*var = NUL;
|
||||
var = vim_getenv(dst);
|
||||
TO_SLASH(var);
|
||||
mustfree = true;
|
||||
#ifdef UNIX
|
||||
}
|
||||
@@ -661,21 +662,6 @@ size_t expand_env_esc(const char *restrict srcp, char *restrict dst, int dstlen,
|
||||
#endif // UNIX
|
||||
}
|
||||
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
// If 'shellslash' is set change backslashes to forward slashes.
|
||||
// Can't use slash_adjust(), p_ssl may be set temporarily.
|
||||
if (p_ssl && var != NULL && vim_strchr(var, '\\') != NULL) {
|
||||
char *p = xstrdup(var);
|
||||
|
||||
if (mustfree) {
|
||||
xfree(var);
|
||||
}
|
||||
var = p;
|
||||
mustfree = true;
|
||||
forward_slash(var);
|
||||
}
|
||||
#endif
|
||||
|
||||
// If "var" contains white space, escape it with a backslash.
|
||||
// Required for ":e ~/tt" when $HOME includes a space.
|
||||
if (esc && var != NULL && strpbrk(var, " \t") != NULL) {
|
||||
@@ -1034,6 +1020,7 @@ size_t home_replace(const buf_T *const buf, const char *src, char *const dst, si
|
||||
homedir_env = os_getenv("USERPROFILE");
|
||||
}
|
||||
#endif
|
||||
TO_SLASH(homedir_env);
|
||||
char *homedir_env_mod = homedir_env;
|
||||
bool must_free = false;
|
||||
|
||||
|
||||
+7
-1
@@ -113,6 +113,7 @@ int os_dirname(char *buf, size_t len)
|
||||
xstrlcpy(buf, uv_strerror(error_number), len);
|
||||
return FAIL;
|
||||
}
|
||||
TO_SLASH(buf);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -224,7 +225,9 @@ int os_nodetype(const char *name)
|
||||
int os_exepath(char *buffer, size_t *size)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
return uv_exepath(buffer, size);
|
||||
int r = uv_exepath(buffer, size);
|
||||
TO_SLASH(buffer);
|
||||
return r;
|
||||
}
|
||||
|
||||
/// Checks if the file `name` is executable.
|
||||
@@ -1112,6 +1115,7 @@ int os_mkdtemp(const char *templ, char *path)
|
||||
int result = uv_fs_mkdtemp(NULL, &request, templ, NULL);
|
||||
if (result == kLibuvSuccess) {
|
||||
xstrlcpy(path, request.path, TEMP_FILE_PATH_MAXLEN);
|
||||
TO_SLASH(path);
|
||||
}
|
||||
uv_fs_req_cleanup(&request);
|
||||
return result;
|
||||
@@ -1345,6 +1349,7 @@ char *os_realpath(const char *name, char *buf, size_t len)
|
||||
buf = xmalloc(len);
|
||||
}
|
||||
xstrlcpy(buf, request.ptr, len);
|
||||
TO_SLASH(buf);
|
||||
}
|
||||
uv_fs_req_cleanup(&request);
|
||||
return result == kLibuvSuccess ? buf : NULL;
|
||||
@@ -1430,6 +1435,7 @@ shortcut_end:
|
||||
}
|
||||
|
||||
CoUninitialize();
|
||||
TO_SLASH(rfname);
|
||||
return rfname;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "nvim/os/os.h"
|
||||
#include "nvim/os/pty_conpty_win.h"
|
||||
#include "nvim/os/pty_proc_win.h"
|
||||
#include "nvim/path.h"
|
||||
|
||||
#include "os/pty_proc_win.c.generated.h"
|
||||
|
||||
@@ -261,6 +262,9 @@ static int build_cmd_line(char **argv, wchar_t **cmd_line, bool is_cmdexe)
|
||||
arg_node->arg = xmalloc(buf_len);
|
||||
if (is_cmdexe) {
|
||||
xstrlcpy(arg_node->arg, *argv, buf_len);
|
||||
if (argc == 0) {
|
||||
TO_BACKSLASH(arg_node->arg);
|
||||
}
|
||||
} else {
|
||||
quote_cmd_arg(arg_node->arg, buf_len, *argv);
|
||||
}
|
||||
|
||||
+17
-19
@@ -43,10 +43,10 @@ static const char *const xdg_defaults_env_vars[] = {
|
||||
/// Used in case environment variables contain nothing. Need to be expanded.
|
||||
static const char *const xdg_defaults[] = {
|
||||
#ifdef MSWIN
|
||||
[kXDGConfigHome] = "~\\AppData\\Local",
|
||||
[kXDGDataHome] = "~\\AppData\\Local",
|
||||
[kXDGCacheHome] = "~\\AppData\\Local\\Temp",
|
||||
[kXDGStateHome] = "~\\AppData\\Local",
|
||||
[kXDGConfigHome] = "~/AppData/Local",
|
||||
[kXDGDataHome] = "~/AppData/Local",
|
||||
[kXDGCacheHome] = "~/AppData/Local/Temp",
|
||||
[kXDGStateHome] = "~/AppData/Local",
|
||||
[kXDGRuntimeDir] = NULL, // Decided by vim_mktempdir().
|
||||
[kXDGConfigDirs] = NULL,
|
||||
[kXDGDataDirs] = NULL,
|
||||
@@ -166,6 +166,7 @@ char *stdpaths_get_xdg_var(const XDGVarType idx)
|
||||
env_val = xstrdup("");
|
||||
}
|
||||
#endif
|
||||
TO_SLASH(env_val);
|
||||
|
||||
char *ret = NULL;
|
||||
if (env_val != NULL) {
|
||||
@@ -213,10 +214,6 @@ char *get_xdg_home(const XDGVarType idx)
|
||||
}
|
||||
#endif
|
||||
dir = concat_fnames_realloc(dir, IObuff, true);
|
||||
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
slash_adjust(dir);
|
||||
#endif
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
@@ -266,21 +263,22 @@ char *stdpaths_user_state_subpath(const char *fname, const size_t trailing_paths
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
|
||||
{
|
||||
char *ret = concat_fnames_realloc(get_xdg_home(kXDGStateHome), fname, true);
|
||||
const size_t len = strlen(ret);
|
||||
size_t len = strlen(ret);
|
||||
const size_t numcommas = (escape_commas ? memcnt(ret, ',', len) : 0);
|
||||
if (numcommas || trailing_pathseps) {
|
||||
ret = xrealloc(ret, len + trailing_pathseps + numcommas + 1);
|
||||
for (size_t i = 0; i < len + numcommas; i++) {
|
||||
if (ret[i] == ',') {
|
||||
memmove(ret + i + 1, ret + i, len - i + numcommas);
|
||||
ret[i] = '\\';
|
||||
i++;
|
||||
size_t newlen = len + numcommas + trailing_pathseps;
|
||||
ret = xrealloc(ret, newlen + 1);
|
||||
ret[newlen] = NUL;
|
||||
|
||||
memset(ret + len + numcommas, PATHSEP, trailing_pathseps);
|
||||
newlen -= trailing_pathseps;
|
||||
|
||||
while (numcommas && len > 0) {
|
||||
ret[--newlen] = ret[--len];
|
||||
if (ret[newlen] == ',') {
|
||||
ret[--newlen] = '\\';
|
||||
}
|
||||
}
|
||||
if (trailing_pathseps) {
|
||||
memset(ret + len + numcommas, PATHSEP, trailing_pathseps);
|
||||
}
|
||||
ret[len + trailing_pathseps + numcommas] = NUL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
+31
-12
@@ -537,7 +537,7 @@ char *FullName_save(const char *fname, bool force)
|
||||
char *buf = xmalloc(MAXPATHL);
|
||||
if (vim_FullName(fname, buf, MAXPATHL, force) == FAIL) {
|
||||
xfree(buf);
|
||||
return xstrdup(fname);
|
||||
return TO_SLASH_SAVE(fname);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
@@ -551,7 +551,7 @@ char *save_abs_path(const char *name)
|
||||
if (!path_is_absolute(name)) {
|
||||
return FullName_save(name, true);
|
||||
}
|
||||
return xstrdup(name);
|
||||
return TO_SLASH_SAVE(name);
|
||||
}
|
||||
|
||||
/// Checks if a path has a wildcard character including '~', unless at the end.
|
||||
@@ -1516,6 +1516,30 @@ void slash_adjust(char *p)
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Convert all slashes to backslashes in-place.
|
||||
char *path_to_backslash(char *p)
|
||||
{
|
||||
if (p != NULL) {
|
||||
strchrsub(p, PATHSEP, '\\');
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/// Convert all backslashes to forward slashes in-place.
|
||||
char *path_to_slash(char *p)
|
||||
{
|
||||
if (p != NULL) {
|
||||
strchrsub(p, '\\', PATHSEP);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/// Get an allocated copy of path to convert backslashes.
|
||||
char *path_to_slash_save(const char *p)
|
||||
{
|
||||
return p == NULL ? NULL : path_to_slash(xstrdup(p));
|
||||
}
|
||||
|
||||
/// Add a file to a file list. Accepted flags:
|
||||
/// EW_DIR add directories
|
||||
/// EW_FILE add files
|
||||
@@ -1561,9 +1585,7 @@ void addfile(garray_T *gap, char *f, int flags)
|
||||
char *p = xmalloc(strlen(f) + 1 + isdir);
|
||||
|
||||
STRCPY(p, f);
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
slash_adjust(p);
|
||||
#endif
|
||||
TO_SLASH(p);
|
||||
// Append a slash or backslash after directory names if none is present.
|
||||
if (isdir && (flags & EW_ADDSLASH)) {
|
||||
add_pathsep(p);
|
||||
@@ -1849,9 +1871,7 @@ int vim_FullName(const char *fname, char *buf, size_t len, bool force)
|
||||
|
||||
if (strlen(fname) > (len - 1)) {
|
||||
xstrlcpy(buf, fname, len); // truncate
|
||||
#ifdef MSWIN
|
||||
slash_adjust(buf);
|
||||
#endif
|
||||
TO_SLASH(buf);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
@@ -1864,9 +1884,7 @@ int vim_FullName(const char *fname, char *buf, size_t len, bool force)
|
||||
if (rv == FAIL) {
|
||||
xstrlcpy(buf, fname, len); // something failed; use the filename
|
||||
}
|
||||
#ifdef MSWIN
|
||||
slash_adjust(buf);
|
||||
#endif
|
||||
TO_SLASH(buf);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -1899,7 +1917,7 @@ char *fix_fname(const char *fname)
|
||||
return FullName_save(fname, false);
|
||||
}
|
||||
|
||||
fname = xstrdup(fname);
|
||||
fname = TO_SLASH_SAVE(fname);
|
||||
|
||||
# ifdef CASE_INSENSITIVE_FILENAME
|
||||
path_fix_case((char *)fname); // set correct case for file name
|
||||
@@ -2476,6 +2494,7 @@ void path_guess_exepath(const char *argv0, char *buf, size_t bufsize)
|
||||
xstrlcat(NameBuff, argv0, sizeof(NameBuff));
|
||||
if (os_can_exe(NameBuff, NULL, false)) {
|
||||
xstrlcpy(buf, NameBuff, bufsize);
|
||||
TO_SLASH(buf);
|
||||
return;
|
||||
}
|
||||
} while (iter != NULL);
|
||||
|
||||
@@ -41,4 +41,14 @@ typedef enum file_comparison {
|
||||
kEqualFileNames = 7, ///< Both don't exist and file names are same.
|
||||
} FileComparison;
|
||||
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
# define TO_SLASH(p) path_to_slash(p)
|
||||
# define TO_SLASH_SAVE(p) path_to_slash_save(p)
|
||||
# define TO_BACKSLASH(p) path_to_backslash(p)
|
||||
#else
|
||||
# define TO_SLASH(...)
|
||||
# define TO_SLASH_SAVE(p) xstrdup(p)
|
||||
# define TO_BACKSLASH(...)
|
||||
#endif
|
||||
|
||||
#include "path.h.generated.h"
|
||||
+1
-6
@@ -2314,12 +2314,6 @@ static int qf_get_fnum(qf_list_T *qfl, char *directory, char *fname)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
if (directory != NULL) {
|
||||
slash_adjust(directory);
|
||||
}
|
||||
slash_adjust(fname);
|
||||
#endif
|
||||
String fname_str = cstr_as_string(fname);
|
||||
if (directory != NULL && !vim_isAbsName(fname)) {
|
||||
ptr = concat_fnames(cstr_as_string(directory), fname_str, true);
|
||||
@@ -2341,6 +2335,7 @@ static int qf_get_fnum(qf_list_T *qfl, char *directory, char *fname)
|
||||
} else {
|
||||
bufname = fname_str;
|
||||
}
|
||||
TO_SLASH(bufname.data);
|
||||
|
||||
if (qf_last_bufname != NULL && strcmp(bufname.data, qf_last_bufname) == 0
|
||||
&& bufref_valid(&qf_last_bufref)) {
|
||||
|
||||
+4
-1
@@ -710,6 +710,7 @@ static ArrayOf(String) runtime_get_named_common(bool lua, Array pat, bool all,
|
||||
item->path, pat_item.data.string.data);
|
||||
if (size < buf_len) {
|
||||
if (os_file_is_readable(buf)) {
|
||||
TO_SLASH(buf);
|
||||
ADD_C(rv, CSTR_TO_ARENA_OBJ(arena, buf));
|
||||
if (!all) {
|
||||
goto done;
|
||||
@@ -1843,10 +1844,11 @@ char *runtimepath_default(bool clean_arg)
|
||||
char *const config_home = clean_arg
|
||||
? NULL
|
||||
: stdpaths_get_xdg_var(kXDGConfigHome);
|
||||
char *const vimruntime = vim_getenv("VIMRUNTIME");
|
||||
char *const libdir = get_lib_dir();
|
||||
char *const data_dirs = stdpaths_get_xdg_var(kXDGDataDirs);
|
||||
char *const config_dirs = stdpaths_get_xdg_var(kXDGConfigDirs);
|
||||
char *vimruntime = vim_getenv("VIMRUNTIME");
|
||||
TO_SLASH(vimruntime);
|
||||
#define SITE_SIZE (sizeof("site") - 1)
|
||||
#define AFTER_SIZE (sizeof("after") - 1)
|
||||
size_t data_len = 0;
|
||||
@@ -2537,6 +2539,7 @@ void ex_scriptnames(exarg_T *eap)
|
||||
} else {
|
||||
expand_env(eap->arg, NameBuff, MAXPATHL);
|
||||
eap->arg = NameBuff;
|
||||
TO_SLASH(eap->arg);
|
||||
}
|
||||
do_exedit(eap, NULL);
|
||||
}
|
||||
|
||||
@@ -3272,6 +3272,7 @@ shada_read_next_item_start:
|
||||
}
|
||||
if (HAS_KEY(&it, _shada_mark, f)) {
|
||||
entry->data.filemark.fname = xmemdupz(it.f.data, it.f.size);
|
||||
TO_SLASH(entry->data.filemark.fname);
|
||||
}
|
||||
|
||||
if (entry->data.filemark.fname == NULL) {
|
||||
@@ -3458,6 +3459,7 @@ shada_read_next_item_start:
|
||||
}
|
||||
if (HAS_KEY(&it, _shada_buflist_item, f)) {
|
||||
e->fname = xmemdupz(it.f.data, it.f.size);
|
||||
TO_SLASH(e->fname);
|
||||
}
|
||||
|
||||
if (e->pos.lnum <= 0) {
|
||||
|
||||
@@ -3985,6 +3985,8 @@ static void syn_cmd_include(exarg_T *eap, int syncing)
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
TO_SLASH(eap->arg);
|
||||
}
|
||||
|
||||
// Save and restore the existing top-level grouplist id and ":syn
|
||||
|
||||
+4
-12
@@ -2017,11 +2017,6 @@ static void findtags_add_match(findtags_state_T *st, tagptrs_T *tagpp, findtags_
|
||||
char *p = mfp;
|
||||
p[0] = (char)(mtt + 1);
|
||||
STRCPY(p + 1, st->tag_fname);
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
// Ignore differences in slashes, avoid adding
|
||||
// both path/file and path\file.
|
||||
slash_adjust(p + 1);
|
||||
#endif
|
||||
p[tag_fname_len + 1] = TAG_SEP;
|
||||
char *s = p + 1 + tag_fname_len + 1;
|
||||
STRCPY(s, st->lbuf);
|
||||
@@ -2438,9 +2433,6 @@ static bool found_tagfile_cb(int num_fnames, char **fnames, bool all, void *cook
|
||||
for (int i = 0; i < num_fnames; i++) {
|
||||
char *const tag_fname = xstrdup(fnames[i]);
|
||||
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
slash_adjust(tag_fname);
|
||||
#endif
|
||||
simplify_filename(tag_fname);
|
||||
GA_APPEND(char *, &tag_fnames, tag_fname);
|
||||
|
||||
@@ -2502,9 +2494,6 @@ int get_tagfname(tagname_T *tnp, int first, char *buf)
|
||||
tnp->tn_hf_idx++;
|
||||
xstrlcpy(buf, p_hf, MAXPATHL - STRLEN_LITERAL("tags"));
|
||||
STRCPY(path_tail(buf), "tags");
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
slash_adjust(buf);
|
||||
#endif
|
||||
simplify_filename(buf);
|
||||
|
||||
for (int i = 0; i < tag_fnames.ga_len; i++) {
|
||||
@@ -3075,6 +3064,8 @@ static char *expand_tag_fname(char *fname, char *const tag_fname, const bool exp
|
||||
char *expanded_fname = NULL;
|
||||
expand_T xpc;
|
||||
|
||||
fname = TO_SLASH_SAVE(fname);
|
||||
|
||||
// Expand file name (for environment variables) when needed.
|
||||
// Disallow backticks, they could execute arbitrary shell
|
||||
// commands. This is not needed for tag filenames.
|
||||
@@ -3084,6 +3075,7 @@ static char *expand_tag_fname(char *fname, char *const tag_fname, const bool exp
|
||||
expanded_fname = ExpandOne(&xpc, fname, NULL,
|
||||
WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE);
|
||||
if (expanded_fname != NULL) {
|
||||
xfree(fname);
|
||||
fname = expanded_fname;
|
||||
}
|
||||
}
|
||||
@@ -3101,7 +3093,7 @@ static char *expand_tag_fname(char *fname, char *const tag_fname, const bool exp
|
||||
retval = xstrdup(fname);
|
||||
}
|
||||
|
||||
xfree(expanded_fname);
|
||||
xfree(fname);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -5395,7 +5395,7 @@ describe('API', function()
|
||||
end, { nargs = 1 })
|
||||
]])
|
||||
eq(
|
||||
uv.cwd(),
|
||||
t.fix_slashes(assert(uv.cwd())),
|
||||
api.nvim_cmd(
|
||||
{ cmd = 'Foo', args = { '%:p:h' }, magic = { file = true } },
|
||||
{ output = true }
|
||||
|
||||
@@ -14,8 +14,7 @@ local rmdir = n.rmdir
|
||||
local write_file = t.write_file
|
||||
|
||||
local function join_path(...)
|
||||
local pathsep = (is_os('win') and '\\' or '/')
|
||||
return table.concat({ ... }, pathsep)
|
||||
return table.concat({ ... }, '/')
|
||||
end
|
||||
|
||||
describe('path collapse', function()
|
||||
|
||||
@@ -1628,7 +1628,7 @@ end)
|
||||
|
||||
describe('runtime:', function()
|
||||
local xhome = 'Xhome'
|
||||
local pathsep = n.get_pathsep()
|
||||
local pathsep = '/'
|
||||
local xconfig = xhome .. pathsep .. 'Xconfig'
|
||||
local xdata = xhome .. pathsep .. 'Xdata'
|
||||
local xenv = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata }
|
||||
|
||||
@@ -145,7 +145,7 @@ describe(':mksession', function()
|
||||
|
||||
it('restores buffers with tab-local CWD', function()
|
||||
local tmpfile_base = file_prefix .. '-tmpfile'
|
||||
local cwd_dir = fn.getcwd()
|
||||
local cwd_dir = t.fix_slashes(fn.getcwd())
|
||||
local session_path = cwd_dir .. get_pathsep() .. session_file
|
||||
|
||||
command('edit ' .. tmpfile_base .. '1')
|
||||
@@ -161,9 +161,9 @@ describe(':mksession', function()
|
||||
-- Use :silent to avoid hit-enter prompt due to long path
|
||||
command('silent source ' .. session_path)
|
||||
command('tabnext 1')
|
||||
eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '1', fn.expand('%:p'))
|
||||
eq(cwd_dir .. '/' .. tmpfile_base .. '1', fn.expand('%:p'))
|
||||
command('tabnext 2')
|
||||
eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '2', fn.expand('%:p'))
|
||||
eq(cwd_dir .. '/' .. tmpfile_base .. '2', fn.expand('%:p'))
|
||||
end)
|
||||
|
||||
it('restores CWD for :terminal buffers #11288', function()
|
||||
|
||||
@@ -47,7 +47,7 @@ describe(':source', function()
|
||||
os.remove(test_file)
|
||||
end)
|
||||
|
||||
it("changing 'shellslash' changes the result of expand()", function()
|
||||
it("changing 'shellslash' doesn't affect the result of expand()", function()
|
||||
t.skip(not is_os('win'), "N/A: 'shellslash' only works on Windows")
|
||||
|
||||
api.nvim_set_option_value('shellslash', false, {})
|
||||
@@ -66,9 +66,9 @@ describe(':source', function()
|
||||
|
||||
for _ = 1, 2 do
|
||||
command([[source Xshellslash/Xstack.vim]])
|
||||
matches([[Xshellslash\Xstack%.vim]], api.nvim_get_var('stack1'))
|
||||
matches([[Xshellslash/Xstack%.vim]], api.nvim_get_var('stack1'))
|
||||
matches([[Xshellslash/Xstack%.vim]], api.nvim_get_var('stack2'))
|
||||
matches([[Xshellslash\Xstack%.vim]], api.nvim_get_var('stack3'))
|
||||
matches([[Xshellslash/Xstack%.vim]], api.nvim_get_var('stack3'))
|
||||
end
|
||||
|
||||
write_file(
|
||||
@@ -84,9 +84,9 @@ describe(':source', function()
|
||||
|
||||
for _ = 1, 2 do
|
||||
command([[source Xshellslash/Xstack.lua]])
|
||||
matches([[Xshellslash\Xstack%.lua]], api.nvim_get_var('stack1'))
|
||||
matches([[Xshellslash/Xstack%.lua]], api.nvim_get_var('stack1'))
|
||||
matches([[Xshellslash/Xstack%.lua]], api.nvim_get_var('stack2'))
|
||||
matches([[Xshellslash\Xstack%.lua]], api.nvim_get_var('stack3'))
|
||||
matches([[Xshellslash/Xstack%.lua]], api.nvim_get_var('stack3'))
|
||||
end
|
||||
|
||||
rmdir('Xshellslash')
|
||||
@@ -326,14 +326,13 @@ describe(':source', function()
|
||||
end)
|
||||
|
||||
it('$HOME is not shortened in filepath in v:stacktrace from sourced file', function()
|
||||
local sep = n.get_pathsep()
|
||||
local xhome = table.concat({ vim.uv.cwd(), 'Xhome' }, sep)
|
||||
local xhome = t.fix_slashes(assert(vim.uv.cwd())) .. '/Xhome'
|
||||
mkdir(xhome)
|
||||
clear({ env = { HOME = xhome } })
|
||||
finally(function()
|
||||
rmdir(xhome)
|
||||
end)
|
||||
local filepath = table.concat({ xhome, 'Xstacktrace.vim' }, sep)
|
||||
local filepath = xhome .. '/Xstacktrace.vim'
|
||||
local script = [[
|
||||
func Xfunc()
|
||||
throw 'Exception from Xfunc'
|
||||
|
||||
@@ -17,9 +17,9 @@ local function last_set_lua_verbose_tests(cmd, v1)
|
||||
setup(function()
|
||||
clear(v1 and { args = { '-V1' } } or nil)
|
||||
script_file = 'test_verbose.lua'
|
||||
local current_dir = fn.getcwd()
|
||||
local current_dir = assert(t.fix_slashes(fn.getcwd()))
|
||||
current_dir = fn.fnamemodify(current_dir, ':~')
|
||||
script_location = table.concat({ current_dir, n.get_pathsep(), script_file })
|
||||
script_location = current_dir .. '/' .. script_file
|
||||
|
||||
write_file(
|
||||
script_file,
|
||||
@@ -326,9 +326,9 @@ describe(':verbose when using API from Vimscript', function()
|
||||
setup(function()
|
||||
clear()
|
||||
script_file = 'test_verbose.vim'
|
||||
local current_dir = fn.getcwd()
|
||||
local current_dir = assert(t.fix_slashes(fn.getcwd()))
|
||||
current_dir = fn.fnamemodify(current_dir, ':~')
|
||||
script_location = table.concat({ current_dir, n.get_pathsep(), script_file })
|
||||
script_location = current_dir .. '/' .. script_file
|
||||
|
||||
write_file(
|
||||
script_file,
|
||||
|
||||
@@ -41,15 +41,6 @@ describe('glob() and globpath()', function()
|
||||
|
||||
command([[$put =string(globpath('sautest\autoload', '*.vim'))]])
|
||||
command([[$put =string(globpath('sautest\autoload', '*.vim', 0, 1))]])
|
||||
expect([=[
|
||||
|
||||
|
||||
|
||||
Xxx{
|
||||
Xxx$
|
||||
'sautest\autoload\Test104.vim
|
||||
sautest\autoload\footest.vim'
|
||||
['sautest\autoload\Test104.vim', 'sautest\autoload\footest.vim']]=])
|
||||
else
|
||||
command([[$put =glob('Xxx\{')]])
|
||||
command([[$put =glob('Xxx\$')]])
|
||||
@@ -61,16 +52,16 @@ describe('glob() and globpath()', function()
|
||||
|
||||
command("$put =string(globpath('sautest/autoload', '*.vim'))")
|
||||
command("$put =string(globpath('sautest/autoload', '*.vim', 0, 1))")
|
||||
expect([=[
|
||||
|
||||
|
||||
|
||||
Xxx{
|
||||
Xxx$
|
||||
'sautest/autoload/Test104.vim
|
||||
sautest/autoload/footest.vim'
|
||||
['sautest/autoload/Test104.vim', 'sautest/autoload/footest.vim']]=])
|
||||
end
|
||||
expect([=[
|
||||
|
||||
|
||||
|
||||
Xxx{
|
||||
Xxx$
|
||||
'sautest/autoload/Test104.vim
|
||||
sautest/autoload/footest.vim'
|
||||
['sautest/autoload/Test104.vim', 'sautest/autoload/footest.vim']]=])
|
||||
end)
|
||||
|
||||
teardown(function()
|
||||
|
||||
@@ -291,10 +291,8 @@ describe('XDG defaults', function()
|
||||
clear()
|
||||
local rtp = eval('split(&runtimepath, ",")')
|
||||
local rv = {}
|
||||
local expected = (
|
||||
is_os('win') and { [[\nvim-data\site]], [[\nvim-data\site\after]] }
|
||||
or { '/nvim/site', '/nvim/site/after' }
|
||||
)
|
||||
local data_dir = is_os('win') and '/nvim-data' or '/nvim'
|
||||
local expected = { data_dir .. '/site', data_dir .. '/site/after' }
|
||||
|
||||
for _, v in ipairs(rtp) do
|
||||
local m = string.match(v, [=[[/\]nvim[^/\]*[/\]site.*$]=])
|
||||
@@ -695,7 +693,7 @@ describe('XDG defaults', function()
|
||||
|
||||
it('are escaped properly', function()
|
||||
local vimruntime, libdir = vimruntime_and_libdir()
|
||||
local path_sep = is_os('win') and '\\' or '/'
|
||||
local path_sep = '/'
|
||||
eq(
|
||||
(
|
||||
'\\, \\, \\,'
|
||||
@@ -869,17 +867,7 @@ describe('XDG defaults', function()
|
||||
.. (path_sep):rep(2),
|
||||
api.nvim_get_option_value('undodir', {})
|
||||
)
|
||||
eq(
|
||||
'\\,=\\,=\\,'
|
||||
.. path_sep
|
||||
.. ''
|
||||
.. state_dir
|
||||
.. ''
|
||||
.. path_sep
|
||||
.. 'view'
|
||||
.. (path_sep):rep(2),
|
||||
api.nvim_get_option_value('viewdir', {})
|
||||
)
|
||||
eq(',=,=,/' .. state_dir .. '/view//', api.nvim_get_option_value('viewdir', {}))
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -314,11 +314,7 @@ local function test_terminal_with_fake_shell(backslash)
|
||||
eq('term://', string.match(eval('bufname("%")'), '^term://'))
|
||||
feed([[<C-\><C-N>]])
|
||||
command([[find */Xuniquefile]])
|
||||
if is_os('win') then
|
||||
eq('Xsomedir\\Xuniquefile', eval('bufname("%")'))
|
||||
else
|
||||
eq('Xsomedir/Xuniquefile', eval('bufname("%")'))
|
||||
end
|
||||
eq('Xsomedir/Xuniquefile', eval('bufname("%")'))
|
||||
end)
|
||||
|
||||
it('works with gf', function()
|
||||
|
||||
@@ -21,7 +21,7 @@ describe('title', function()
|
||||
end)
|
||||
|
||||
it('defaults to "No Name" and the PWD in the title if the buffer is unnamed', function()
|
||||
local expected = (is_os('win') and '[No Name] (C:\\) - Nvim' or '[No Name] (/) - Nvim')
|
||||
local expected = (is_os('win') and '[No Name] (C:/) - Nvim' or '[No Name] (/) - Nvim')
|
||||
command(is_os('win') and 'cd C:\\' or 'cd /')
|
||||
command('set title')
|
||||
screen:expect(function()
|
||||
@@ -32,7 +32,7 @@ describe('title', function()
|
||||
it(
|
||||
'defaults to the filename and its directory in the title if the buffer is named as a path outside the PWD',
|
||||
function()
|
||||
local expected = (is_os('win') and 'myfile (C:\\mydir) - Nvim' or 'myfile (/mydir) - Nvim')
|
||||
local expected = (is_os('win') and 'myfile (C:/mydir) - Nvim' or 'myfile (/mydir) - Nvim')
|
||||
command('set title')
|
||||
command(is_os('win') and 'file C:\\mydir\\myfile' or 'file /mydir/myfile')
|
||||
screen:expect(function()
|
||||
@@ -44,7 +44,7 @@ describe('title', function()
|
||||
it(
|
||||
'defaults to the filename and the PWD in the title if the buffer is a file in the PWD',
|
||||
function()
|
||||
local expected = (is_os('win') and 'myfile (C:\\) - Nvim' or 'myfile (/) - Nvim')
|
||||
local expected = (is_os('win') and 'myfile (C:/) - Nvim' or 'myfile (/) - Nvim')
|
||||
command('set title')
|
||||
command(is_os('win') and 'cd C:\\' or 'cd /')
|
||||
command('file myfile')
|
||||
@@ -58,12 +58,12 @@ describe('title', function()
|
||||
command(is_os('win') and 'cd C:\\' or 'cd /')
|
||||
api.nvim_set_option_value('title', true, {})
|
||||
screen:expect(function()
|
||||
local expected = (is_os('win') and '[No Name] (C:\\) - Nvim' or '[No Name] (/) - Nvim')
|
||||
local expected = (is_os('win') and '[No Name] (C:/) - Nvim' or '[No Name] (/) - Nvim')
|
||||
eq(expected, screen.title)
|
||||
end)
|
||||
feed('ifoo')
|
||||
screen:expect(function()
|
||||
local expected = (is_os('win') and '[No Name] + (C:\\) - Nvim' or '[No Name] + (/) - Nvim')
|
||||
local expected = (is_os('win') and '[No Name] + (C:/) - Nvim' or '[No Name] + (/) - Nvim')
|
||||
eq(expected, screen.title)
|
||||
end)
|
||||
feed('<Esc>')
|
||||
@@ -126,7 +126,7 @@ describe('title', function()
|
||||
describe('is not changed by', function()
|
||||
local file1 = is_os('win') and 'C:\\mydir\\myfile1' or '/mydir/myfile1'
|
||||
local file2 = is_os('win') and 'C:\\mydir\\myfile2' or '/mydir/myfile2'
|
||||
local expected = (is_os('win') and 'myfile1 (C:\\mydir) - Nvim' or 'myfile1 (/mydir) - Nvim')
|
||||
local expected = (is_os('win') and 'myfile1 (C:/mydir) - Nvim' or 'myfile1 (/mydir) - Nvim')
|
||||
local buf2
|
||||
|
||||
before_each(function()
|
||||
|
||||
@@ -6,7 +6,6 @@ local clear = n.clear
|
||||
local fn = n.fn
|
||||
local api = n.api
|
||||
local command = n.command
|
||||
local get_pathsep = n.get_pathsep
|
||||
local rmdir = n.rmdir
|
||||
local pcall_err = t.pcall_err
|
||||
local mkdir = t.mkdir
|
||||
@@ -81,8 +80,8 @@ describe('bufname() function', function()
|
||||
it('returns expected buffer name', function()
|
||||
eq('', fn.bufname('%')) -- Buffer has no name yet
|
||||
command('file ' .. fname)
|
||||
local wd = vim.uv.cwd()
|
||||
local sep = get_pathsep()
|
||||
local wd = assert(t.fix_slashes(assert(vim.uv.cwd())))
|
||||
local sep = '/'
|
||||
local curdirname = fn.fnamemodify(wd, ':t')
|
||||
for _, arg in ipairs({ '%', 1, 'X', wd }) do
|
||||
eq(fname, fn.bufname(arg))
|
||||
|
||||
@@ -85,7 +85,7 @@ describe('backtick expansion', function()
|
||||
eq({ 'file2' }, eval('argv()'))
|
||||
if t.is_os('win') then
|
||||
command(':silent args `dir /s/b *4`')
|
||||
eq({ 'subdir\\file4' }, eval('map(argv(), \'fnamemodify(v:val, ":.")\')'))
|
||||
eq({ 'subdir/file4' }, eval('map(argv(), \'fnamemodify(v:val, ":.")\')'))
|
||||
else
|
||||
command(':silent args `echo */*4`')
|
||||
eq({ 'subdir/file4' }, eval('argv()'))
|
||||
|
||||
@@ -19,13 +19,13 @@ describe('executable()', function()
|
||||
end)
|
||||
|
||||
if is_os('win') then
|
||||
it('exepath respects shellslash', function()
|
||||
it('exepath returns consistent slashes #13787', function()
|
||||
-- test/ cannot be a symlink in this test.
|
||||
n.api.nvim_set_current_dir(t.paths.test_source_path)
|
||||
|
||||
command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
|
||||
eq(
|
||||
[[test\functional\fixtures\bin\null.CMD]],
|
||||
[[test/functional/fixtures/bin/null.CMD]],
|
||||
call('fnamemodify', call('exepath', 'null'), ':.')
|
||||
)
|
||||
command('set shellslash')
|
||||
@@ -35,12 +35,12 @@ describe('executable()', function()
|
||||
)
|
||||
end)
|
||||
|
||||
it('stdpath respects shellslash', function()
|
||||
it('stdpath returns consistent slashes #13787', function()
|
||||
-- Needs to check paths relative to repo root dir.
|
||||
n.api.nvim_set_current_dir(t.paths.test_source_path)
|
||||
|
||||
t.matches(
|
||||
[[build\Xtest_xdg[%w_]*\share\nvim%-data]],
|
||||
[[build/Xtest_xdg[%w_]*/share/nvim%-data]],
|
||||
call('fnamemodify', call('stdpath', 'data'), ':.')
|
||||
)
|
||||
command('set shellslash')
|
||||
|
||||
@@ -29,21 +29,20 @@ describe('fnamemodify()', function()
|
||||
end)
|
||||
|
||||
it('handles the root path', function()
|
||||
local root = n.pathroot()
|
||||
local root = assert(t.fix_slashes(n.pathroot()))
|
||||
eq(root, fnamemodify([[/]], ':p:h'))
|
||||
eq(root, fnamemodify([[/]], ':p'))
|
||||
if is_os('win') then
|
||||
eq(root, fnamemodify([[\]], ':p:h'))
|
||||
eq(root, fnamemodify([[\]], ':p'))
|
||||
command('set shellslash')
|
||||
root = string.sub(root, 1, -2) .. '/'
|
||||
eq(root, fnamemodify([[\]], ':p:h'))
|
||||
eq(root, fnamemodify([[\]], ':p'))
|
||||
eq(root, fnamemodify([[/]], ':p:h'))
|
||||
eq(root, fnamemodify([[/]], ':p'))
|
||||
|
||||
local letter_colon = root:sub(1, 2)
|
||||
local old_dir = getcwd() .. '/'
|
||||
local old_dir = t.fix_slashes(getcwd()) .. '/'
|
||||
local foo_dir = old_dir .. 'foo/'
|
||||
eq(old_dir, fnamemodify(letter_colon, ':p'))
|
||||
eq(old_dir, fnamemodify(letter_colon .. '.', ':p'))
|
||||
|
||||
@@ -72,12 +72,12 @@ func Test_expand_sfile_and_stack()
|
||||
let g:stack3 = expand('<stack>')
|
||||
END
|
||||
call writefile(lines, 'Xshellslash/Xstack')
|
||||
" Test that changing 'shellslash' always affects the result of expand()
|
||||
" Test that changing 'shellslash' doesn't affect the result of expand()
|
||||
" when sourcing a script multiple times.
|
||||
for i in range(2)
|
||||
source Xshellslash/Xstack
|
||||
call assert_match('\<Xshellslash/Xstack\[1\]$', g:stack1)
|
||||
call assert_match('\<Xshellslash\\Xstack\[3\]$', g:stack2)
|
||||
call assert_match('\<Xshellslash/Xstack\[3\]$', g:stack2)
|
||||
call assert_match('\<Xshellslash/Xstack\[5\]$', g:stack3)
|
||||
unlet g:stack1
|
||||
unlet g:stack2
|
||||
|
||||
@@ -3671,9 +3671,10 @@ func Test_glob2()
|
||||
call assert_equal([], (glob('abc[glob]def\*', 0, 1)))
|
||||
call assert_equal([], (glob('\[XglobDir]\*', 0, 1)))
|
||||
call assert_equal([], (glob('abc\[glob]def\*', 0, 1)))
|
||||
" Test that changing 'shellslash' doesn't affect the result of glob()
|
||||
set noshellslash
|
||||
call assert_equal(['[XglobDir]\Xglob'], (glob('[[]XglobDir]/*', 0, 1)))
|
||||
call assert_equal(['abc[glob]def\Xglob'], (glob('abc[[]glob]def/*', 0, 1)))
|
||||
call assert_equal(['[XglobDir]/Xglob'], (glob('[[]XglobDir]/*', 0, 1)))
|
||||
call assert_equal(['abc[glob]def/Xglob'], (glob('abc[[]glob]def/*', 0, 1)))
|
||||
set shellslash
|
||||
call assert_equal(['[XglobDir]/Xglob'], (glob('[[]XglobDir]/*', 0, 1)))
|
||||
call assert_equal(['abc[glob]def/Xglob'], (glob('abc[[]glob]def/*', 0, 1)))
|
||||
|
||||
@@ -940,9 +940,10 @@ func Test_ins_completeslash()
|
||||
%bw!
|
||||
call delete('Xdir', 'rf')
|
||||
|
||||
" globpath() should always return forward slash separator
|
||||
set noshellslash
|
||||
set completeslash=slash
|
||||
call assert_true(stridx(globpath(&rtp, 'syntax/*.vim', 1, 1)[0], '\') != -1)
|
||||
set completeslash=backslash
|
||||
call assert_true(stridx(globpath(&rtp, 'syntax/*.vim', 1, 1)[0], '\') == -1)
|
||||
|
||||
let &shellslash = orig_shellslash
|
||||
set completeslash=
|
||||
@@ -1553,13 +1554,10 @@ endfunc
|
||||
func Test_issue_7021()
|
||||
CheckMSWindows
|
||||
|
||||
let orig_shellslash = &shellslash
|
||||
set noshellslash
|
||||
" Test that 'completeslash' doesn't affect the result of expand()
|
||||
set completeslash=backslash
|
||||
call assert_false(expand('~') =~ '\\')
|
||||
|
||||
set completeslash=slash
|
||||
call assert_false(expand('~') =~ '/')
|
||||
|
||||
let &shellslash = orig_shellslash
|
||||
set completeslash=
|
||||
endfunc
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ endfunc
|
||||
|
||||
func CheckHome(exp, ...)
|
||||
call assert_equal(a:exp, $HOME)
|
||||
call assert_equal(a:exp, expand('~', ':p'))
|
||||
call assert_equal(substitute(a:exp, '\\', '/', 'g'), expand('~', ':p'))
|
||||
if !a:0
|
||||
call CheckHomeIsMissingFromSubprocessEnvironment()
|
||||
else
|
||||
|
||||
Reference in new issue
Block a user