patch 9.1.1646: MS-Windows: completion cannot handle implicit drive letters
Commit: https://github.com/vim/vim/commit/a2f13bf782f723e116c5d4cc7d79a23e918a24db Author: Miguel Barro <miguel.ba...@live.com> Date: Sun Aug 17 22:04:24 2025 +0200 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 older and /folder as absolute (Miguel Barro). closes: #17829 Co-authored-by: zeertzjq <zeert...@outlook.com> Signed-off-by: Miguel Barro <miguel.ba...@live.com> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index 17be46d03..6dcce6bec 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -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 ~ diff --git a/src/buffer.c b/src/buffer.c index 5937a9e12..0feafc590 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -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); diff --git a/src/filepath.c b/src/filepath.c index 0ef77f9d8..fc3caaf08 100644 --- a/src/filepath.c +++ b/src/filepath.c @@ -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); diff --git a/src/findfile.c b/src/findfile.c index 0f5f2dc62..008338cda 100644 --- a/src/findfile.c +++ b/src/findfile.c @@ -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 } /* diff --git a/src/os_mswin.c b/src/os_mswin.c index c2c1bd0c2..405a6c5c1 100644 --- a/src/os_mswin.c +++ b/src/os_mswin.c @@ -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 oo 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] == '\')); } /* diff --git a/src/testdir/test_cd.vim b/src/testdir/test_cd.vim index 1b7777e1b..78c6c577e 100644 --- a/src/testdir/test_cd.vim +++ b/src/testdir/test_cd.vim @@ -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() diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index fccd5af49..ca54d3729 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -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('/')) diff --git a/src/version.c b/src/version.c index fe5d37cda..fd7849cba 100644 --- a/src/version.c +++ b/src/version.c @@ -719,6 +719,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1646, /**/ 1645, /**/ diff --git a/src/vim9script.c b/src/vim9script.c index ece4a3acf..e526637e2 100644 --- a/src/vim9script.c +++ b/src/vim9script.c @@ -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); -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1unjmS-003Sn3-FH%40256bit.org.