Bram,
there seems to be a problem with backslash escaped strings when using
expand(), glob() or globpath():
#v+
cb@host: mkdir -p /tmp/test
ch@host: touch /tmp/test/bar /tmp/teest/foo\\1
cb@host: vim -u NONE -U NONE -N -c ':e /tmp/test/bar|echo
expand(@#)|echo expand("#")' /tmp/test/foo\\1
#v-
This outputs:
"/tmp/test/bar" 0L, 0C
test/foo1
test/foo\1
The problem is, you can't rely on expand() to skip one backslash,
because on Windows it behaves correctly (e.g. expand('foobar\1') on
Windows returns 'foobar\1' while on Unixs returns 'foobar1').
Also, you can't use glob('/tmp/test/foo\\1') to return the correct
result, and if you use glob(expand(path)) where path contains a
backslash, glob() won't return the empty string.
This is problematic because glob() is mentioned below :h filereadable()
to check for the existence of a file.
Here is a patch, that fixes this problematic behaviour and makes it at
least consistent to the Windows behaviour. But ... it is a backward
incompatible change and probably breaks a lot of plugins, that work
around that bug by using something like
if glob(expand(escape(filename, '\\')))
" file exists
…
else
" create file
…
endif
Nevertheless, I tend to consider this as a bug and would like it to work
consistently on all plattforms.
regards,
Christian
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
diff --git a/src/eval.c b/src/eval.c
--- a/src/eval.c
+++ b/src/eval.c
@@ -781,6 +781,7 @@
static char_u *get_tv_string __ARGS((typval_T *varp));
static char_u *get_tv_string_buf __ARGS((typval_T *varp, char_u *buf));
static char_u *get_tv_string_buf_chk __ARGS((typval_T *varp, char_u *buf));
+static char_u *escape_backslash __ARGS((char_u *buf));
static dictitem_T *find_var __ARGS((char_u *name, hashtab_T **htp));
static dictitem_T *find_var_in_ht __ARGS((hashtab_T *ht, char_u *varname, int writing));
static hashtab_T *find_var_ht __ARGS((char_u *name, char_u **varname));
@@ -11952,13 +11953,13 @@
if (p_wic)
options += WILD_ICASE;
if (rettv->v_type == VAR_STRING)
- rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]),
+ rettv->vval.v_string = ExpandOne(&xpc, escape_backslash(get_tv_string(&argvars[0])),
NULL, options, WILD_ALL);
else if (rettv_list_alloc(rettv) != FAIL)
{
int i;
- ExpandOne(&xpc, get_tv_string(&argvars[0]),
+ ExpandOne(&xpc, escape_backslash(get_tv_string(&argvars[0])),
NULL, options, WILD_ALL_KEEP);
for (i = 0; i < xpc.xp_numfiles; i++)
list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1);
@@ -11992,7 +11993,7 @@
if (file == NULL || error)
rettv->vval.v_string = NULL;
else
- rettv->vval.v_string = globpath(get_tv_string(&argvars[0]), file,
+ rettv->vval.v_string = globpath(escape_backslash(get_tv_string(&argvars[0])), file,
flags);
}
@@ -19910,6 +19911,19 @@
return NULL;
}
+ static char_u *
+escape_backslash(buf)
+ char_u *buf;
+{
+ char_u bslash = '\\';
+ /* on Windows, filenames can't contains backslashes */
+#if defined(WIN3264) || defined(MSDOS)
+ return buf;
+#else
+ return vim_strsave_escaped(buf, &bslash);
+#endif
+}
+
/*
* Find variable "name" in the list of variables.
* Return a pointer to it if found, NULL if not found.
diff --git a/src/misc1.c b/src/misc1.c
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -10520,10 +10520,14 @@
#endif
/* When EW_NOTFOUND is used, always add files and dirs. Makes
* "vim c:/" work. */
- if (flags & EW_NOTFOUND)
+ if (flags & EW_NOTFOUND && mch_getperm(t) >= 0)
addfile(&ga, t, flags | EW_DIR | EW_FILE);
+ else if (flags & EW_NOTFOUND)
+ addfile(&ga, p, flags | EW_DIR | EW_FILE);
else if (mch_getperm(t) >= 0)
addfile(&ga, t, flags);
+ else if (mch_getperm(p) >= 0)
+ addfile(&ga, p, flags);
vim_free(t);
}