fix: gf fails on "foo/bar.txt:1:2" on Windows

Problem:
On Windows, "gf" fails on a filepath that has a line:column suffix.
Example:

    E447: Can't find file "src/app/core/services/identity/identity.service.ts:64:23"

Solution:
- Remove ":" from 'isfname' on Windows. Colon is not a valid filename
  character (except for the drive-letter).
- Handle drive letters specially in file_name_in_line().

Fixes #25160
This commit is contained in:
Leonardo Mello
2023-09-18 16:50:47 -03:00
committed by Justin M. Keyes
parent 4e4ad4312e
commit 1dd700a8d9
7 changed files with 92 additions and 8 deletions

View File

@@ -6943,11 +6943,12 @@ char *file_name_in_line(char *line, int col, int options, int count, char *rel_f
bool is_url = false;
// Search backward for first char of the file name.
// Go one char back to ":" before "//" even when ':' is not in 'isfname'.
// Go one char back to ":" before "//", or to the drive letter before ":\" (even if ":"
// is not in 'isfname').
while (ptr > line) {
if ((len = (size_t)(utf_head_off(line, ptr - 1))) > 0) {
ptr -= len + 1;
} else if (vim_isfilec((uint8_t)ptr[-1])
} else if (vim_isfilec((uint8_t)ptr[-1]) || path_has_drive_letter(ptr - 2)
|| ((options & FNAME_HYP) && path_is_url(ptr - 1))) {
ptr--;
} else {
@@ -6957,14 +6958,13 @@ 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.
// Also allow ":/" when ':' is not in 'isfname'.
len = 0;
len = path_has_drive_letter(ptr) ? 2 : 0;
while (vim_isfilec((uint8_t)ptr[len]) || (ptr[len] == '\\' && ptr[len + 1] == ' ')
|| ((options & FNAME_HYP) && path_is_url(ptr + len))
|| (is_url && vim_strchr(":?&=", (uint8_t)ptr[len]) != NULL)) {
// After type:// we also include :, ?, & and = as valid characters, so that
// http://google.com:8080?q=this&that=ok works.
if ((ptr[len] >= 'A' && ptr[len] <= 'Z')
|| (ptr[len] >= 'a' && ptr[len] <= 'z')) {
if ((ptr[len] >= 'A' && ptr[len] <= 'Z') || (ptr[len] >= 'a' && ptr[len] <= 'z')) {
if (in_type && path_is_url(ptr + len + 1)) {
is_url = true;
}