mirror of
https://github.com/neovim/neovim.git
synced 2025-11-14 14:29:02 +00:00
fix(completion): complete drive-letter filepath on Windows #36353
Problem: On MSWIN, file completion (CTRL-X CTRL-F) only works for the current drive (so not for actual absolute paths), since drive letters are never included in the completion pattern. e.g. when completing "F:\Hello" Nvim currently completes "\Hello" which is relative to the current drive/volume. vim solves this by adding ':' to the default 'isfname' value on mswin, but that causes issues as ':' is not a valid windows path char anywhere _except_ after the drive letter. Solution: detect drive letters in front of the path when creating the completion pattern.
This commit is contained in:
@@ -1679,7 +1679,7 @@ char *file_name_in_line(char *line, int col, int options, int count, char *rel_f
|
|||||||
|
|
||||||
// Search forward for the last char of the file name.
|
// Search forward for the last char of the file name.
|
||||||
// Also allow ":/" when ':' is not in 'isfname'.
|
// Also allow ":/" when ':' is not in 'isfname'.
|
||||||
len = path_has_drive_letter(ptr) ? 2 : 0;
|
len = path_has_drive_letter(ptr, strlen(ptr)) ? 2 : 0;
|
||||||
while (vim_isfilec((uint8_t)ptr[len]) || (ptr[len] == '\\' && ptr[len + 1] == ' ')
|
while (vim_isfilec((uint8_t)ptr[len]) || (ptr[len] == '\\' && ptr[len + 1] == ' ')
|
||||||
|| ((options & FNAME_HYP) && path_is_url(ptr + len))
|
|| ((options & FNAME_HYP) && path_is_url(ptr + len))
|
||||||
|| (is_url && vim_strchr(":?&=", (uint8_t)ptr[len]) != NULL)) {
|
|| (is_url && vim_strchr(":?&=", (uint8_t)ptr[len]) != NULL)) {
|
||||||
|
|||||||
@@ -5786,7 +5786,17 @@ static int get_filename_compl_info(char *line, int startcol, colnr_T curs_col)
|
|||||||
while (p > line && vim_isfilec(utf_ptr2char(p))) {
|
while (p > line && vim_isfilec(utf_ptr2char(p))) {
|
||||||
MB_PTR_BACK(line, p);
|
MB_PTR_BACK(line, p);
|
||||||
}
|
}
|
||||||
if (p == line && vim_isfilec(utf_ptr2char(p))) {
|
bool p_is_filec = false;
|
||||||
|
#ifdef MSWIN
|
||||||
|
// check for drive letters on mswin
|
||||||
|
if (p > line && path_has_drive_letter(p - 1, line + startcol - (p - 1))) {
|
||||||
|
p -= p == line + 1 ? 1 : 2;
|
||||||
|
p_is_filec = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
p_is_filec = p_is_filec || vim_isfilec(utf_ptr2char(p));
|
||||||
|
|
||||||
|
if (p == line && p_is_filec) {
|
||||||
startcol = 0;
|
startcol = 0;
|
||||||
} else {
|
} else {
|
||||||
startcol = (int)(p - line) + 1;
|
startcol = (int)(p - line) + 1;
|
||||||
|
|||||||
@@ -1715,13 +1715,13 @@ size_t simplify_filename(char *filename)
|
|||||||
/// Checks for a Windows drive letter ("C:/") at the start of the path.
|
/// Checks for a Windows drive letter ("C:/") at the start of the path.
|
||||||
///
|
///
|
||||||
/// @see https://url.spec.whatwg.org/#start-with-a-windows-drive-letter
|
/// @see https://url.spec.whatwg.org/#start-with-a-windows-drive-letter
|
||||||
bool path_has_drive_letter(const char *p)
|
bool path_has_drive_letter(const char *p, size_t path_len)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
return strlen(p) >= 2
|
return path_len >= 2
|
||||||
&& ASCII_ISALPHA(p[0])
|
&& ASCII_ISALPHA(p[0])
|
||||||
&& (p[1] == ':' || p[1] == '|')
|
&& (p[1] == ':' || p[1] == '|')
|
||||||
&& (strlen(p) == 2 || ((p[2] == '/') | (p[2] == '\\') | (p[2] == '?') | (p[2] == '#')));
|
&& (path_len == 2 || ((p[2] == '/') | (p[2] == '\\') | (p[2] == '?') | (p[2] == '#')));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the ":/" of a URL is at the pointer, return URL_SLASH.
|
// Check if the ":/" of a URL is at the pointer, return URL_SLASH.
|
||||||
@@ -1758,7 +1758,7 @@ int path_with_url(const char *fname)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path_has_drive_letter(fname)) {
|
if (path_has_drive_letter(fname, strlen(fname))) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,16 @@ describe('completion', function()
|
|||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('ctrl-x_ctrl-f completes Windows drive letter', function()
|
||||||
|
if not t.is_os('win') then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
feed('iblablaC:/W<C-x><C-f>')
|
||||||
|
screen:expect {
|
||||||
|
any = [[C:\Windows\]],
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
describe('v:completed_item', function()
|
describe('v:completed_item', function()
|
||||||
it('is empty dict until completion', function()
|
it('is empty dict until completion', function()
|
||||||
eq({}, eval('v:completed_item'))
|
eq({}, eval('v:completed_item'))
|
||||||
|
|||||||
Reference in New Issue
Block a user