# HG changeset patch # User Bram Moolenaar # Date 1580851803 -3600 # Node ID 8b710057093cf396fd8840653a736886294564d9 # Parent 3b5c07c8e82badd16f30d07d70aecfa5189ef46a patch 8.2.0208: fnamemodify() does not apply ":~" when followed by ":." Commit: https://github.com/vim/vim/commit/d816cd94d87afb73c505bf1e5cd5e07522482113 Author: Bram Moolenaar Date: Tue Feb 4 22:23:09 2020 +0100 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) diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -933,8 +933,7 @@ These modifiers can be given, in this or directory. :. Reduce file name to be relative to current directory, if possible. File name is unmodified if it is not below the - current directory, but on MS-Windows the drive is removed if - it is the current drive. + current directory. For maximum shortness, use ":~:.". :h Head of the file name (the last component and any separators removed). Cannot be used with :e, :r or :t. diff --git a/src/filepath.c b/src/filepath.c --- a/src/filepath.c +++ b/src/filepath.c @@ -301,6 +301,7 @@ modify_fname( char_u dirname[MAXPATHL]; int c; int has_fullname = 0; + int has_homerelative = 0; #ifdef MSWIN char_u *fname_start = *fnamep; int has_shortname = 0; @@ -412,7 +413,7 @@ repeat: } pbuf = NULL; // Need full path first (use expand_env() to remove a "~/") - if (!has_fullname) + if (!has_fullname && !has_homerelative) { if (c == '.' && **fnamep == '~') p = pbuf = expand_env_save(*fnamep); @@ -428,11 +429,28 @@ repeat: { if (c == '.') { + size_t namelen; + mch_dirname(dirname, MAXPATHL); - s = shorten_fname(p, dirname); - if (s != NULL) + if (has_homerelative) { - *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) { vim_free(*bufp); // free any allocated file name @@ -453,6 +471,7 @@ repeat: *fnamep = s; vim_free(*bufp); *bufp = s; + has_homerelative = TRUE; } } } @@ -701,6 +720,7 @@ f_chdir(typval_T *argvars, typval_T *ret rettv->vval.v_string = NULL; if (argvars[0].v_type != VAR_STRING) + // Returning an empty string means it failed. return; // Return the current directory diff --git a/src/testdir/test_fnamemodify.vim b/src/testdir/test_fnamemodify.vim --- a/src/testdir/test_fnamemodify.vim +++ b/src/testdir/test_fnamemodify.vim @@ -3,8 +3,10 @@ func Test_fnamemodify() let save_home = $HOME let save_shell = &shell + let save_shellslash = &shellslash let $HOME = fnamemodify('.', ':p:h:h') set shell=sh + set shellslash call assert_equal('/', fnamemodify('.', ':p')[-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('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')) @@ -44,6 +55,7 @@ func Test_fnamemodify() let $HOME = save_home let &shell = save_shell + let &shellslash = save_shellslash endfunc func Test_fnamemodify_er() diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -743,6 +743,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 208, +/**/ 207, /**/ 206,