Merge pull request #17263 from zeertzjq/vim-8.2.0208

vim-patch:8.2.{0208,0215,0942,3824,3939}: fnamemodify() patches
This commit is contained in:
zeertzjq 2022-02-07 07:13:13 +08:00 committed by GitHub
commit cf86adba61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 57 additions and 21 deletions

View File

@ -908,8 +908,7 @@ These modifiers can be given, in this order:
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.

View File

@ -10624,12 +10624,13 @@ int modify_fname(char_u *src, bool tilde_file, size_t *usedlen, char_u **fnamep,
char_u *s, *p, *pbuf;
char_u dirname[MAXPATHL];
int c;
int has_fullname = 0;
bool has_fullname = false;
bool has_homerelative = false;
repeat:
// ":p" - full path/file_name
if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p') {
has_fullname = 1;
has_fullname = true;
valid |= VALID_PATH;
*usedlen += 2;
@ -10698,8 +10699,8 @@ repeat:
}
pbuf = NULL;
// Need full path first (use expand_env() to remove a "~/")
if (!has_fullname) {
if (c == '.' && **fnamep == '~') {
if (!has_fullname && !has_homerelative) {
if ((c == '.' || c == '~') && **fnamep == '~') {
p = pbuf = expand_env_save(*fnamep);
} else {
p = pbuf = (char_u *)FullName_save((char *)*fnamep, FALSE);
@ -10708,20 +10709,35 @@ repeat:
p = *fnamep;
}
has_fullname = 0;
has_fullname = false;
if (p != NULL) {
if (c == '.') {
os_dirname(dirname, MAXPATHL);
s = path_shorten_fname(p, dirname);
if (s != NULL) {
*fnamep = s;
if (has_homerelative) {
s = vim_strsave(dirname);
home_replace(NULL, s, dirname, MAXPATHL, true);
xfree(s);
}
size_t 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;
if (vim_ispathsep(*p)) {
while (*p && vim_ispathsep(*p)) {
p++;
}
*fnamep = p;
if (pbuf != NULL) {
xfree(*bufp); // free any allocated file name
// free any allocated file name
xfree(*bufp);
*bufp = pbuf;
pbuf = NULL;
}
}
}
} else {
home_replace(NULL, p, dirname, MAXPATHL, true);
// Only replace it when it starts with '~'
@ -10730,6 +10746,7 @@ repeat:
*fnamep = s;
xfree(*bufp);
*bufp = s;
has_homerelative = true;
}
}
xfree(pbuf);

View File

@ -1111,10 +1111,9 @@ size_t home_replace(const buf_T *const buf, const char_u *src, char_u *const dst
*dst_p++ = '~';
}
// If it's just the home directory, add "/".
if (!vim_ispathsep(src[0]) && --dstlen > 0) {
*dst_p++ = '/';
}
// Do not add directory separator into dst, because dst is
// expected to just return the directory name without the
// directory separator '/'.
break;
}
if (p == homedir_env_mod) {

View File

@ -1521,7 +1521,7 @@ void simplify_filename(char_u *filename)
p = filename;
#ifdef BACKSLASH_IN_FILENAME
if (p[1] == ':') { // skip "x:"
if (p[0] != NUL && p[1] == ':') { // skip "x:"
p += 2;
}
#endif
@ -2402,9 +2402,11 @@ static int path_to_absolute(const char_u *fname, char_u *buf, size_t len, int fo
int path_is_absolute(const char_u *fname)
{
#ifdef WIN32
if (*fname == NUL) {
return false;
}
// A name like "d:/foo" and "//server/share" is absolute
return ((isalpha(fname[0]) && fname[1] == ':'
&& vim_ispathsep_nocolon(fname[2]))
return ((isalpha(fname[0]) && fname[1] == ':' && vim_ispathsep_nocolon(fname[2]))
|| (vim_ispathsep_nocolon(fname[0]) && fname[0] == fname[1]));
#else
// UNIX: This just checks if the file name starts with '/' or '~'.

View File

@ -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:])
@ -27,6 +29,21 @@ func Test_fnamemodify()
call assert_equal('fb2.tar.gz', fnamemodify('abc.fb2.tar.gz', ':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(getcwd(), fnamemodify('', ':p:h'))
let cwd = getcwd()
call chdir($HOME)
call assert_equal('foobar', fnamemodify('~/foobar', ':~:.'))
call chdir(cwd)
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 mkdir($HOME . '/XXXXXXXX/a.ext', 'p')
call assert_equal('~/XXXXXXXX/a.ext/foo', fnamemodify($HOME . '/XXXXXXXX/a.ext/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'))
@ -44,6 +61,7 @@ func Test_fnamemodify()
let $HOME = save_home
let &shell = save_shell
let &shellslash = save_shellslash
endfunc
func Test_fnamemodify_er()
@ -73,6 +91,7 @@ func Test_fnamemodify_er()
call assert_equal('b.c', fnamemodify('a.b.c.d.e', ':r:r:e:e:e'))
call assert_equal('b.c', fnamemodify('a.b.c.d.e', ':r:r:e:e:e:e'))
call assert_equal('', fnamemodify('', ':p:t'))
call assert_equal('', fnamemodify(v:_null_string, v:_null_string))
endfunc