mirror of
https://github.com/vim/vim.git
synced 2025-10-06 05:44:14 -04:00
Improvements for :find completion.
This commit is contained in:
177
src/misc1.c
177
src/misc1.c
@@ -9263,6 +9263,7 @@ is_unique(maybe_unique, gap, i)
|
||||
int candidate_len;
|
||||
int other_path_len;
|
||||
char_u **other_paths = (char_u **)gap->ga_data;
|
||||
char_u *rival;
|
||||
|
||||
for (j = 0; j < gap->ga_len && !got_int; j++)
|
||||
{
|
||||
@@ -9275,7 +9276,8 @@ is_unique(maybe_unique, gap, i)
|
||||
if (other_path_len < candidate_len)
|
||||
continue; /* it's different */
|
||||
|
||||
if (fnamecmp(maybe_unique, gettail(other_paths[j])) == 0)
|
||||
rival = other_paths[j] + other_path_len - candidate_len;
|
||||
if (fnamecmp(maybe_unique, rival) == 0)
|
||||
return FALSE; /* match */
|
||||
}
|
||||
|
||||
@@ -9301,8 +9303,6 @@ expand_path_option(curdir, gap)
|
||||
char_u *buf;
|
||||
char_u *p;
|
||||
|
||||
ga_init2(gap, (int)sizeof(char_u *), 1);
|
||||
|
||||
if ((buf = alloc((int)MAXPATHL)) == NULL)
|
||||
return;
|
||||
|
||||
@@ -9357,7 +9357,7 @@ expand_path_option(curdir, gap)
|
||||
*
|
||||
* path: /foo/bar/baz
|
||||
* fname: /foo/bar/baz/quux.txt
|
||||
* returns: ^this
|
||||
* returns: ^this
|
||||
*/
|
||||
static char_u *
|
||||
get_path_cutoff(fname, gap)
|
||||
@@ -9413,15 +9413,21 @@ uniquefy_paths(gap, pattern)
|
||||
int i;
|
||||
int len;
|
||||
char_u **fnames = (char_u **)gap->ga_data;
|
||||
int sort_again = 0;
|
||||
int sort_again = FALSE;
|
||||
char_u *pat;
|
||||
char_u *file_pattern;
|
||||
char_u *curdir = NULL;
|
||||
regmatch_T regmatch;
|
||||
garray_T path_ga;
|
||||
char_u **in_curdir = NULL;
|
||||
char_u *short_name;
|
||||
|
||||
sort_strings(fnames, gap->ga_len);
|
||||
remove_duplicates(gap);
|
||||
if (gap->ga_len == 0)
|
||||
return;
|
||||
|
||||
ga_init2(&path_ga, (int)sizeof(char_u *), 1);
|
||||
|
||||
/*
|
||||
* We need to prepend a '*' at the beginning of file_pattern so that the
|
||||
@@ -9447,17 +9453,21 @@ uniquefy_paths(gap, pattern)
|
||||
return;
|
||||
|
||||
if ((curdir = alloc((int)(MAXPATHL))) == NULL)
|
||||
return;
|
||||
goto theend;
|
||||
mch_dirname(curdir, MAXPATHL);
|
||||
|
||||
expand_path_option(curdir, &path_ga);
|
||||
in_curdir = (char_u **)alloc(gap->ga_len * sizeof(char_u *));
|
||||
if (in_curdir == NULL)
|
||||
goto theend;
|
||||
|
||||
for (i = 0; i < gap->ga_len; i++)
|
||||
{
|
||||
char_u *path = fnames[i];
|
||||
int is_in_curdir;
|
||||
char_u *dir_end = gettail(path);
|
||||
char_u *short_name;
|
||||
char_u *pathsep_p;
|
||||
char_u *path_cutoff;
|
||||
|
||||
len = (int)STRLEN(path);
|
||||
while (dir_end > path &&
|
||||
@@ -9468,77 +9478,29 @@ uniquefy_paths(gap, pattern)
|
||||
#endif
|
||||
)
|
||||
mb_ptr_back(path, dir_end);
|
||||
is_in_curdir = STRNCMP(curdir, path, dir_end - path) == 0
|
||||
is_in_curdir = fnamencmp(curdir, path, dir_end - path) == 0
|
||||
&& curdir[dir_end - path] == NUL;
|
||||
|
||||
/*
|
||||
* If the file is in the current directory,
|
||||
* and it is not unique,
|
||||
* reduce it to ./{filename}
|
||||
* FIXME ^ Is this portable?
|
||||
*
|
||||
* Note: If the full filename is /curdir/foo/bar/{filename}, we don't
|
||||
* want to shorten it to ./foo/bar/{filename} yet because 'path' might
|
||||
* contain ". / * *", in which case the shortened filename could be
|
||||
* shorter than ./foo/bar/{filename}.
|
||||
*/
|
||||
if (is_in_curdir)
|
||||
{
|
||||
char_u *rel_path;
|
||||
|
||||
short_name = shorten_fname(path, curdir);
|
||||
if (short_name == NULL)
|
||||
short_name = path;
|
||||
if (is_unique(short_name, gap, i))
|
||||
{
|
||||
STRMOVE(path, short_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
rel_path = alloc((int)(STRLEN(short_name)
|
||||
+ STRLEN(PATHSEPSTR) + 2));
|
||||
if (rel_path == NULL)
|
||||
goto theend;
|
||||
|
||||
/* FIXME Is "." a portable way of denoting the current directory? */
|
||||
STRCPY(rel_path, ".");
|
||||
add_pathsep(rel_path);
|
||||
STRCAT(rel_path, short_name);
|
||||
|
||||
if (len < (int)STRLEN(rel_path))
|
||||
{
|
||||
vim_free(fnames[i]);
|
||||
fnames[i] = alloc((int)(STRLEN(rel_path) + 1));
|
||||
if (fnames[i] == NULL)
|
||||
{
|
||||
vim_free(rel_path);
|
||||
goto theend;
|
||||
}
|
||||
}
|
||||
|
||||
STRCPY(fnames[i], rel_path);
|
||||
vim_free(rel_path);
|
||||
sort_again = 1;
|
||||
}
|
||||
in_curdir[i] = vim_strsave(path);
|
||||
else
|
||||
{
|
||||
/* Shorten the filename while maintaining its uniqueness */
|
||||
char_u *pathsep_p;
|
||||
char_u *path_cutoff = get_path_cutoff(path, &path_ga);
|
||||
in_curdir[i] = NULL;
|
||||
|
||||
/* we start at the end of the path */
|
||||
pathsep_p = path + len - 1;
|
||||
/* Shorten the filename while maintaining its uniqueness */
|
||||
path_cutoff = get_path_cutoff(path, &path_ga);
|
||||
|
||||
while (find_previous_pathsep(path, &pathsep_p))
|
||||
if (vim_regexec(®match, pathsep_p + 1, (colnr_T)0)
|
||||
&& is_unique(pathsep_p + 1, gap, i)
|
||||
&& path_cutoff != NULL && pathsep_p + 1 >= path_cutoff)
|
||||
{
|
||||
sort_again = 1;
|
||||
mch_memmove(path, pathsep_p + 1, STRLEN(pathsep_p));
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* we start at the end of the path */
|
||||
pathsep_p = path + len - 1;
|
||||
|
||||
while (find_previous_pathsep(path, &pathsep_p))
|
||||
if (vim_regexec(®match, pathsep_p + 1, (colnr_T)0)
|
||||
&& is_unique(pathsep_p + 1, gap, i)
|
||||
&& path_cutoff != NULL && pathsep_p + 1 >= path_cutoff)
|
||||
{
|
||||
sort_again = TRUE;
|
||||
mch_memmove(path, pathsep_p + 1, STRLEN(pathsep_p));
|
||||
break;
|
||||
}
|
||||
|
||||
if (mch_isFullName(path))
|
||||
{
|
||||
@@ -9548,11 +9510,11 @@ uniquefy_paths(gap, pattern)
|
||||
* 1. It is under the current directory.
|
||||
* 2. The result is actually shorter than the original.
|
||||
*
|
||||
* Before curdir After
|
||||
* /foo/bar/file.txt /foo/bar ./file.txt
|
||||
* c:\foo\bar\file.txt c:\foo\bar .\file.txt
|
||||
* /file.txt / /file.txt
|
||||
* c:\file.txt c:\ .\file.txt
|
||||
* Before curdir After
|
||||
* /foo/bar/file.txt /foo/bar ./file.txt
|
||||
* c:\foo\bar\file.txt c:\foo\bar .\file.txt
|
||||
* /file.txt / /file.txt
|
||||
* c:\file.txt c:\ .\file.txt
|
||||
*/
|
||||
short_name = shorten_fname(path, curdir);
|
||||
if (short_name != NULL && short_name > path + 1)
|
||||
@@ -9564,8 +9526,68 @@ uniquefy_paths(gap, pattern)
|
||||
}
|
||||
}
|
||||
|
||||
/* Shorten filenames in /in/current/directory/{filename} */
|
||||
for (i = 0; i < gap->ga_len; i++)
|
||||
{
|
||||
char_u *rel_path;
|
||||
char_u *path = in_curdir[i];
|
||||
|
||||
if (path == NULL)
|
||||
continue;
|
||||
/*
|
||||
* If the file is in the current directory,
|
||||
* and it is not unique,
|
||||
* reduce it to ./{filename}
|
||||
* FIXME ^ Is this portable?
|
||||
* else reduce it to {filename}
|
||||
*
|
||||
* Note: If the full filename is /curdir/foo/bar/{filename}, we don't
|
||||
* want to shorten it to ./foo/bar/{filename} yet because 'path' might
|
||||
* contain ". / * *", in which case the shortened filename could be
|
||||
* shorter than ./foo/bar/{filename}.
|
||||
*/
|
||||
short_name = shorten_fname(path, curdir);
|
||||
if (short_name == NULL)
|
||||
short_name = path;
|
||||
if (is_unique(short_name, gap, i))
|
||||
{
|
||||
STRCPY(fnames[i], short_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
rel_path = alloc((int)(STRLEN(short_name) + STRLEN(PATHSEPSTR) + 2));
|
||||
if (rel_path == NULL)
|
||||
goto theend;
|
||||
|
||||
/* FIXME Is "." a portable way of denoting the current directory? */
|
||||
STRCPY(rel_path, ".");
|
||||
add_pathsep(rel_path);
|
||||
STRCAT(rel_path, short_name);
|
||||
|
||||
if (len < (int)STRLEN(rel_path))
|
||||
{
|
||||
vim_free(fnames[i]);
|
||||
fnames[i] = alloc((int)(STRLEN(rel_path) + 1));
|
||||
if (fnames[i] == NULL)
|
||||
{
|
||||
vim_free(rel_path);
|
||||
goto theend;
|
||||
}
|
||||
}
|
||||
|
||||
STRCPY(fnames[i], rel_path);
|
||||
vim_free(rel_path);
|
||||
sort_again = TRUE;
|
||||
}
|
||||
|
||||
theend:
|
||||
vim_free(curdir);
|
||||
if (in_curdir != NULL)
|
||||
{
|
||||
for (i = 0; i < gap->ga_len; i++)
|
||||
vim_free(in_curdir[i]);
|
||||
vim_free(in_curdir);
|
||||
}
|
||||
ga_clear_strings(&path_ga);
|
||||
vim_free(regmatch.regprog);
|
||||
|
||||
@@ -9598,6 +9620,7 @@ expand_in_path(gap, pattern, flags)
|
||||
return 0;
|
||||
mch_dirname(curdir, MAXPATHL);
|
||||
|
||||
ga_init2(&path_ga, (int)sizeof(char_u *), 1);
|
||||
expand_path_option(curdir, &path_ga);
|
||||
vim_free(curdir);
|
||||
if (path_ga.ga_len == 0)
|
||||
|
Reference in New Issue
Block a user