mirror of
https://github.com/vim/vim.git
synced 2025-08-23 19:34:27 -04:00
patch 9.1.1646: MS-Windows: completion cannot handle implicit drive letters
Problem: MS-Windows: completion cannot handle implicit drive letters Solution: Consider paths like \folder and /folder as absolute (Miguel Barro). closes: #17829 Co-authored-by: zeertzjq <zeertzjq@outlook.com> Signed-off-by: Miguel Barro <miguel.barro@live.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
parent
59799f3afa
commit
a2f13bf782
@ -1,4 +1,4 @@
|
||||
*version9.txt* For Vim version 9.1. Last change: 2025 Aug 16
|
||||
*version9.txt* For Vim version 9.1. Last change: 2025 Aug 17
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@ -41745,6 +41745,8 @@ Others: ~
|
||||
Unicode 16.
|
||||
- Two additional digraphs have been added: LEFT ANGLE BRACKET "<[" and RIGHT
|
||||
ANGLE BRACKET "]>".
|
||||
- MS-Winodws: Paths like "\Windows" and "/Windows" are now considered to be
|
||||
absolute paths (to the current drive) and no longer relative.
|
||||
|
||||
*added-9.2*
|
||||
Added ~
|
||||
|
@ -5472,7 +5472,8 @@ fix_fname(char_u *fname)
|
||||
* Also expand when there is ".." in the file name, try to remove it,
|
||||
* because "c:/src/../README" is equal to "c:/README".
|
||||
* Similarly "c:/src//file" is equal to "c:/src/file".
|
||||
* For MS-Windows also expand names like "longna~1" to "longname".
|
||||
* For MS-Windows also expand names like "longna~1" to "longname"
|
||||
* and provide drive letter for all absolute paths.
|
||||
*/
|
||||
#ifdef UNIX
|
||||
return FullName_save(fname, TRUE);
|
||||
@ -5485,6 +5486,8 @@ fix_fname(char_u *fname)
|
||||
# endif
|
||||
# if defined(MSWIN)
|
||||
|| vim_strchr(fname, '~') != NULL
|
||||
|| fname[0] == '/'
|
||||
|| fname[0] == '\\'
|
||||
# endif
|
||||
)
|
||||
return FullName_save(fname, FALSE);
|
||||
|
@ -359,7 +359,11 @@ repeat:
|
||||
}
|
||||
|
||||
// FullName_save() is slow, don't use it when not needed.
|
||||
if (*p != NUL || !vim_isAbsName(*fnamep))
|
||||
if (*p != NUL || !vim_isAbsName(*fnamep)
|
||||
#ifdef MSWIN // enforce drive letter on windows paths
|
||||
|| **fnamep == '/' || **fnamep == '\\'
|
||||
#endif
|
||||
)
|
||||
{
|
||||
*fnamep = FullName_save(*fnamep, *p != NUL);
|
||||
vim_free(*bufp); // free any allocated file name
|
||||
@ -3110,6 +3114,42 @@ vim_fnamencmp(char_u *x, char_u *y, size_t len)
|
||||
int cx = NUL;
|
||||
int cy = NUL;
|
||||
|
||||
#ifdef MSWIN
|
||||
/*
|
||||
* To allow proper comparisson of absolute paths:
|
||||
* - one with explicit drive letter C:\xxx
|
||||
* - another with implicit drive letter \xxx
|
||||
* advance the pointer, of the explicit one, to skip the drive
|
||||
*/
|
||||
for (int swap = 0, drive = NUL; swap < 2; ++swap)
|
||||
{
|
||||
// Handle absolute paths with implicit drive letter
|
||||
cx = PTR2CHAR(px);
|
||||
cy = PTR2CHAR(py);
|
||||
|
||||
if ((cx == '/' || cx == '\\') && ASCII_ISALPHA(cy))
|
||||
{
|
||||
drive = MB_TOUPPER(cy) - 'A' + 1;
|
||||
|
||||
// Check for the colon
|
||||
py += mb_ptr2len(py);
|
||||
cy = PTR2CHAR(py);
|
||||
if (cy == ':' && drive == _getdrive())
|
||||
{ // skip the drive for comparisson
|
||||
py += mb_ptr2len(py);
|
||||
break;
|
||||
}
|
||||
else // ignore
|
||||
py -= mb_ptr2len(py);
|
||||
}
|
||||
|
||||
// swap pointers
|
||||
char_u *tmp = px;
|
||||
px = py;
|
||||
py = tmp;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
cx = PTR2CHAR(px);
|
||||
|
@ -398,18 +398,6 @@ vim_findfile_init(
|
||||
search_ctx->ffsc_start_dir.length);
|
||||
if (search_ctx->ffsc_start_dir.string == NULL)
|
||||
goto error_return;
|
||||
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
// A path that starts with "/dir" is relative to the drive, not to the
|
||||
// directory (but not for "//machine/dir"). Only use the drive name.
|
||||
if ((*path == '/' || *path == '\\')
|
||||
&& path[1] != path[0]
|
||||
&& search_ctx->ffsc_start_dir.string[1] == ':')
|
||||
{
|
||||
search_ctx->ffsc_start_dir.string[2] = NUL;
|
||||
search_ctx->ffsc_start_dir.length = 2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -319,6 +319,7 @@ mch_FullName(
|
||||
mch_isFullName(char_u *fname)
|
||||
{
|
||||
// A name like "d:/foo" and "//server/share" is absolute. "d:foo" is not.
|
||||
// /foo and \foo are absolute too because windows keeps a current drive.
|
||||
// Another way to check is to use mch_FullName() and see if the result is
|
||||
// the same as the name or mch_FullName() fails. However, this has quite a
|
||||
// bit of overhead, so let's not do that.
|
||||
@ -326,7 +327,7 @@ mch_isFullName(char_u *fname)
|
||||
return FALSE;
|
||||
return ((ASCII_ISALPHA(fname[0]) && fname[1] == ':'
|
||||
&& (fname[2] == '/' || fname[2] == '\\'))
|
||||
|| (fname[0] == fname[1] && (fname[0] == '/' || fname[0] == '\\')));
|
||||
|| (fname[0] == '/' || fname[0] == '\\'));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -221,6 +221,39 @@ func Test_cd_completion()
|
||||
call assert_equal('"' .. cmd .. ' XComplDir1/ XComplDir2/ XComplDir3/', @:)
|
||||
endfor
|
||||
set cdpath&
|
||||
|
||||
if has('win32')
|
||||
" Test windows absolute path completion
|
||||
" Retrieve a suitable dir in the current drive
|
||||
let dir = readdir('/', 'isdirectory("/" .. v:val) && len(v:val) > 2')[-1]
|
||||
" Get partial path
|
||||
let partial = dir[0:-2]
|
||||
" Get the current drive letter
|
||||
let old = chdir('/' . dir)
|
||||
let full = getcwd()
|
||||
let drive = full[0]
|
||||
call chdir(old)
|
||||
|
||||
for cmd in ['cd', 'chdir', 'lcd', 'lchdir', 'tcd', 'tchdir']
|
||||
for sep in [ '/', '\']
|
||||
|
||||
" Explicit drive letter
|
||||
call feedkeys(':' .. cmd .. ' ' .. drive .. ':' .. sep ..
|
||||
\ partial .. "\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||
call assert_match(full, @:)
|
||||
|
||||
" Implicit drive letter
|
||||
call feedkeys(':' .. cmd .. ' ' .. sep .. partial .. "\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||
call assert_match('/' .. dir .. '/', @:)
|
||||
|
||||
" UNC path
|
||||
call feedkeys(':' .. cmd .. ' ' .. sep .. sep .. $COMPUTERNAME .. sep ..
|
||||
\ drive .. '$' .. sep .. partial .."\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||
call assert_match('//' .. $COMPUTERNAME .. '/' .. drive .. '$/' .. dir .. '/' , @:)
|
||||
|
||||
endfor
|
||||
endfor
|
||||
endif
|
||||
endfunc
|
||||
|
||||
func Test_cd_unknown_dir()
|
||||
|
@ -4106,7 +4106,8 @@ func Test_isabsolutepath()
|
||||
call assert_true(isabsolutepath('A:\Foo'))
|
||||
call assert_true(isabsolutepath('A:/Foo'))
|
||||
call assert_false(isabsolutepath('A:Foo'))
|
||||
call assert_false(isabsolutepath('\Windows'))
|
||||
call assert_true(isabsolutepath('\Windows'))
|
||||
call assert_true(isabsolutepath('/Windows'))
|
||||
call assert_true(isabsolutepath('\\Server2\Share\Test\Foo.txt'))
|
||||
else
|
||||
call assert_true(isabsolutepath('/'))
|
||||
|
@ -719,6 +719,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1646,
|
||||
/**/
|
||||
1645,
|
||||
/**/
|
||||
|
@ -479,13 +479,7 @@ handle_import(
|
||||
res = handle_import_fname(from_name, is_autoload, &sid);
|
||||
vim_free(from_name);
|
||||
}
|
||||
else if (mch_isFullName(tv.vval.v_string)
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
// On MS-Windows omitting the drive is still handled like an
|
||||
// absolute path, not using 'runtimepath'.
|
||||
|| *tv.vval.v_string == '/' || *tv.vval.v_string == '\\'
|
||||
#endif
|
||||
)
|
||||
else if (mch_isFullName(tv.vval.v_string))
|
||||
{
|
||||
// Absolute path: "/tmp/name.vim"
|
||||
res = handle_import_fname(tv.vval.v_string, is_autoload, &sid);
|
||||
|
Loading…
x
Reference in New Issue
Block a user