patch 8.1.0211: expanding a file name "~" results in $HOME
Problem: Expanding a file name "~" results in $HOME. (Aidan Shafran)
Solution: Change "~" to "./~" before expanding. (closes #3072)
diff --git a/src/eval.c b/src/eval.c
index ef25a3f..6034cd2 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -9690,11 +9690,12 @@
*/
int
modify_fname(
- char_u *src, /* string with modifiers */
- int *usedlen, /* characters after src that are used */
- char_u **fnamep, /* file name so far */
- char_u **bufp, /* buffer for allocated file name or NULL */
- int *fnamelen) /* length of fnamep */
+ char_u *src, // string with modifiers
+ int tilde_file, // "~" is a file name, not $HOME
+ int *usedlen, // characters after src that are used
+ char_u **fnamep, // file name so far
+ char_u **bufp, // buffer for allocated file name or NULL
+ int *fnamelen) // length of fnamep
{
int valid = 0;
char_u *tail;
@@ -9724,8 +9725,8 @@
|| (*fnamep)[1] == '\\'
# endif
|| (*fnamep)[1] == NUL)
-
#endif
+ && !(tilde_file && (*fnamep)[1] == NUL)
)
{
*fnamep = expand_env_save(*fnamep);
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 97242f6..a9f6c5b 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -3801,7 +3801,7 @@
else
{
len = (int)STRLEN(fname);
- (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len);
+ (void)modify_fname(mods, FALSE, &usedlen, &fname, &fbuf, &len);
}
rettv->v_type = VAR_STRING;
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 4b3fdac..0094cdb 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -10654,6 +10654,7 @@
int resultlen;
buf_T *buf;
int valid = VALID_HEAD + VALID_PATH; /* assume valid result */
+ int tilde_file = FALSE;
int spec_idx;
#ifdef FEAT_MODIFY_FNAME
int skip_mod = FALSE;
@@ -10720,7 +10721,10 @@
valid = 0; /* Must have ":p:h" to be valid */
}
else
+ {
result = curbuf->b_fname;
+ tilde_file = STRCMP(result, "~") == 0;
+ }
break;
case SPEC_HASH: /* '#' or "#99": alternate file */
@@ -10784,7 +10788,10 @@
valid = 0; /* Must have ":p:h" to be valid */
}
else
+ {
result = buf->b_fname;
+ tilde_file = STRCMP(result, "~") == 0;
+ }
}
break;
@@ -10877,7 +10884,7 @@
#ifdef FEAT_MODIFY_FNAME
else if (!skip_mod)
{
- valid |= modify_fname(src, usedlen, &result, &resultbuf,
+ valid |= modify_fname(src, tilde_file, usedlen, &result, &resultbuf,
&resultlen);
if (result == NULL)
{
diff --git a/src/if_cscope.c b/src/if_cscope.c
index 986663d..d621a14 100644
--- a/src/if_cscope.c
+++ b/src/if_cscope.c
@@ -519,7 +519,7 @@
#ifdef FEAT_MODIFY_FNAME
len = (int)STRLEN(fname);
fbuf = (char_u *)fname;
- (void)modify_fname((char_u *)":p", &usedlen,
+ (void)modify_fname((char_u *)":p", FALSE, &usedlen,
(char_u **)&fname, &fbuf, &len);
if (fname == NULL)
goto add_err;
diff --git a/src/misc1.c b/src/misc1.c
index f0e629b..ab5f6f7 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -4908,7 +4908,7 @@
char_u *fbuf = NULL;
flen = (int)STRLEN(homedir_env);
- (void)modify_fname((char_u *)":p", &usedlen,
+ (void)modify_fname((char_u *)":p", FALSE, &usedlen,
&homedir_env, &fbuf, &flen);
flen = (int)STRLEN(homedir_env);
if (flen > 0 && vim_ispathsep(homedir_env[flen - 1]))
diff --git a/src/proto/eval.pro b/src/proto/eval.pro
index 0906a68..98f6656 100644
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -136,7 +136,7 @@
int typval_compare(typval_T *typ1, typval_T *typ2, exptype_T type, int type_is, int ic);
char_u *typval_tostring(typval_T *arg);
int var_exists(char_u *var);
-int modify_fname(char_u *src, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen);
+int modify_fname(char_u *src, int tilde_file, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen);
char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, typval_T *expr, char_u *flags);
void filter_map(typval_T *argvars, typval_T *rettv, int map);
/* vim: set ft=c : */
diff --git a/src/testdir/test_expand.vim b/src/testdir/test_expand.vim
index c099eda..b4f1363 100644
--- a/src/testdir/test_expand.vim
+++ b/src/testdir/test_expand.vim
@@ -39,3 +39,11 @@
call delete('Xdir ~ dir', 'd')
call assert_false(isdirectory('Xdir ~ dir'))
endfunc
+
+func Test_expand_tilde_filename()
+ split ~
+ call assert_equal('~', expand('%'))
+ call assert_notequal(expand('%:p'), expand('~/'))
+ call assert_match('\~', expand('%:p'))
+ bwipe!
+endfunc
diff --git a/src/version.c b/src/version.c
index 456dc12..24753d1 100644
--- a/src/version.c
+++ b/src/version.c
@@ -794,6 +794,8 @@
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 211,
+/**/
210,
/**/
209,