0
0
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:
Bram Moolenaar
2010-08-12 21:50:51 +02:00
parent d7b734a493
commit 0be992e347
4 changed files with 184 additions and 98 deletions

View File

@@ -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(&regmatch, 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(&regmatch, 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)