1
0
forked from aniani/vim

patch 8.2.0208: fnamemodify() does not apply ":~" when followed by ":."

Problem:    Fnamemodify() does not apply ":~" when followed by ":.".
Solution:   Don't let a failing ":." cause the ":~" to be skipped. (Yasuhiro
            Matsumoto, closes #5577)
This commit is contained in:
Bram Moolenaar
2020-02-04 22:23:09 +01:00
parent bfe1204312
commit d816cd94d8
4 changed files with 39 additions and 6 deletions

View File

@@ -933,8 +933,7 @@ These modifiers can be given, in this order:
directory. directory.
:. Reduce file name to be relative to current directory, if :. Reduce file name to be relative to current directory, if
possible. File name is unmodified if it is not below the possible. File name is unmodified if it is not below the
current directory, but on MS-Windows the drive is removed if current directory.
it is the current drive.
For maximum shortness, use ":~:.". For maximum shortness, use ":~:.".
:h Head of the file name (the last component and any separators :h Head of the file name (the last component and any separators
removed). Cannot be used with :e, :r or :t. removed). Cannot be used with :e, :r or :t.

View File

@@ -301,6 +301,7 @@ modify_fname(
char_u dirname[MAXPATHL]; char_u dirname[MAXPATHL];
int c; int c;
int has_fullname = 0; int has_fullname = 0;
int has_homerelative = 0;
#ifdef MSWIN #ifdef MSWIN
char_u *fname_start = *fnamep; char_u *fname_start = *fnamep;
int has_shortname = 0; int has_shortname = 0;
@@ -412,7 +413,7 @@ repeat:
} }
pbuf = NULL; pbuf = NULL;
// Need full path first (use expand_env() to remove a "~/") // Need full path first (use expand_env() to remove a "~/")
if (!has_fullname) if (!has_fullname && !has_homerelative)
{ {
if (c == '.' && **fnamep == '~') if (c == '.' && **fnamep == '~')
p = pbuf = expand_env_save(*fnamep); p = pbuf = expand_env_save(*fnamep);
@@ -428,11 +429,28 @@ repeat:
{ {
if (c == '.') if (c == '.')
{ {
size_t namelen;
mch_dirname(dirname, MAXPATHL); mch_dirname(dirname, MAXPATHL);
s = shorten_fname(p, dirname); if (has_homerelative)
if (s != NULL)
{ {
*fnamep = s; s = vim_strsave(dirname);
if (s != NULL)
{
home_replace(NULL, s, dirname, MAXPATHL, TRUE);
vim_free(s);
}
}
namelen = STRLEN(dirname);
// Do not call shorten_fname() here since it removes the prefix
// even though the path does not have a prefix.
if (fnamencmp(p, dirname, namelen) == 0)
{
p += namelen;
while (*p && vim_ispathsep(*p))
++p;
*fnamep = p;
if (pbuf != NULL) if (pbuf != NULL)
{ {
vim_free(*bufp); // free any allocated file name vim_free(*bufp); // free any allocated file name
@@ -453,6 +471,7 @@ repeat:
*fnamep = s; *fnamep = s;
vim_free(*bufp); vim_free(*bufp);
*bufp = s; *bufp = s;
has_homerelative = TRUE;
} }
} }
} }
@@ -701,6 +720,7 @@ f_chdir(typval_T *argvars, typval_T *rettv)
rettv->vval.v_string = NULL; rettv->vval.v_string = NULL;
if (argvars[0].v_type != VAR_STRING) if (argvars[0].v_type != VAR_STRING)
// Returning an empty string means it failed.
return; return;
// Return the current directory // Return the current directory

View File

@@ -3,8 +3,10 @@
func Test_fnamemodify() func Test_fnamemodify()
let save_home = $HOME let save_home = $HOME
let save_shell = &shell let save_shell = &shell
let save_shellslash = &shellslash
let $HOME = fnamemodify('.', ':p:h:h') let $HOME = fnamemodify('.', ':p:h:h')
set shell=sh set shell=sh
set shellslash
call assert_equal('/', fnamemodify('.', ':p')[-1:]) call assert_equal('/', fnamemodify('.', ':p')[-1:])
call assert_equal('r', fnamemodify('.', ':p:h')[-1:]) call assert_equal('r', fnamemodify('.', ':p:h')[-1:])
@@ -28,6 +30,15 @@ func Test_fnamemodify()
call assert_equal('fb2.tar.gz', fnamemodify('abc.fb2.tar.gz', ':e:e:e:e')) call assert_equal('fb2.tar.gz', fnamemodify('abc.fb2.tar.gz', ':e:e:e:e'))
call assert_equal('tar', fnamemodify('abc.fb2.tar.gz', ':e:e:r')) call assert_equal('tar', fnamemodify('abc.fb2.tar.gz', ':e:e:r'))
let cwd = getcwd()
call mkdir($HOME . '/XXXXXXXX/a', 'p')
call mkdir($HOME . '/XXXXXXXX/b', 'p')
call chdir($HOME . '/XXXXXXXX/a/')
call assert_equal('foo', fnamemodify($HOME . '/XXXXXXXX/a/foo', ':p:~:.'))
call assert_equal('~/XXXXXXXX/b/foo', fnamemodify($HOME . '/XXXXXXXX/b/foo', ':p:~:.'))
call chdir(cwd)
call delete($HOME . '/XXXXXXXX', 'rf')
call assert_equal('''abc def''', fnamemodify('abc def', ':S')) call assert_equal('''abc def''', fnamemodify('abc def', ':S'))
call assert_equal('''abc" "def''', fnamemodify('abc" "def', ':S')) call assert_equal('''abc" "def''', fnamemodify('abc" "def', ':S'))
call assert_equal('''abc"%"def''', fnamemodify('abc"%"def', ':S')) call assert_equal('''abc"%"def''', fnamemodify('abc"%"def', ':S'))
@@ -44,6 +55,7 @@ func Test_fnamemodify()
let $HOME = save_home let $HOME = save_home
let &shell = save_shell let &shell = save_shell
let &shellslash = save_shellslash
endfunc endfunc
func Test_fnamemodify_er() func Test_fnamemodify_er()

View File

@@ -742,6 +742,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
208,
/**/ /**/
207, 207,
/**/ /**/