Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
V
Vim
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Someone-Else
Vim
Commits
0be992e3
Commit
0be992e3
authored
14 years ago
by
Bram Moolenaar
Browse files
Options
Downloads
Patches
Plain Diff
Improvements for :find completion.
parent
d7b734a4
Loading
Loading
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
runtime/doc/todo.txt
+3
-1
3 additions, 1 deletion
runtime/doc/todo.txt
src/misc1.c
+98
-75
98 additions, 75 deletions
src/misc1.c
src/testdir/test73.in
+75
-20
75 additions, 20 deletions
src/testdir/test73.in
src/testdir/test73.ok
+6
-0
6 additions, 0 deletions
src/testdir/test73.ok
with
182 additions
and
96 deletions
runtime/doc/todo.txt
+
3
−
1
View file @
0be992e3
*todo.txt* For Vim version 7.3f. Last change: 2010 Aug 1
0
*todo.txt* For Vim version 7.3f. Last change: 2010 Aug 1
2
VIM REFERENCE MANUAL by Bram Moolenaar
...
...
@@ -32,6 +32,8 @@ be worked on, but only if you sponsor Vim development. See |sponsor|.
'cursorline' stops too early in a help file, caused by conceal feature.
Have a close look at :find completion, anything that could be wrong?
Test 73 fails on MS-Windows when compiled with DJGPP.
:find completion with 'path' set to "./**" results in full path for
"./subdir/file", should shorten to start with "./".
...
...
This diff is collapsed.
Click to expand it.
src/misc1.c
+
98
−
75
View file @
0be992e3
...
...
@@ -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,78 +9478,30 @@ 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;
}
in_curdir[i] = vim_strsave(path);
else
in_curdir[i] = NULL;
rel_path = alloc((int)(STRLEN(short_name)
+ STRLEN(PATHSEPSTR) + 2));
if (rel_path == NULL)
goto theend;
/* Shorten the filename while maintaining its uniqueness */
path_cutoff = get_path_cutoff(path, &path_ga);
/* FIXME Is "." a portable way of denoting the current directory? */
STRCPY(rel_path, ".");
add_pathsep(rel_path);
STRCAT(rel_path, short_name);
/* we start at the end of the path */
pathsep_p = path + len - 1;
if (len < (int)STRLEN(rel_path))
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)
{
vim_free(fnames[i]);
fnames[i] = alloc((int)(STRLEN(rel_path) + 1));
if (fnames[i] == NULL)
{
vim_free(rel_path);
goto theend;
}
sort_again = TRUE;
mch_memmove(path, pathsep_p + 1, STRLEN(pathsep_p));
break;
}
STRCPY(fnames[i], rel_path);
vim_free(rel_path);
sort_again = 1;
}
else
{
/* Shorten the filename while maintaining its uniqueness */
char_u *pathsep_p;
char_u *path_cutoff = get_path_cutoff(path, &path_ga);
/* 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 = 1;
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)
...
...
This diff is collapsed.
Click to expand it.
src/testdir/test73.in
+
75
−
20
View file @
0be992e3
...
...
@@ -6,7 +6,8 @@ STARTTEST
:" delete the Xfind directory during cleanup
:"
:" This will cause a few errors, do it silently.
:set nocp viminfo+=nviminfo visualbell
:set visualbell
:set nocp viminfo+=nviminfo
:"
:function! DeleteDirectory(dir)
: if has("win16") || has("win32") || has("win64") || has("dos16") || has("dos32")
...
...
@@ -20,32 +21,33 @@ STARTTEST
:call DeleteDirectory("Xfind")
:new
:let cwd=getcwd()
:!mkdir Xfind
:let test_out = cwd . '/test.out'
:silent !mkdir Xfind
:cd Xfind
:set path=
:find
:
w! ../
test
.
out
:
exec "w! " .
test
_
out
:close
:new
:set path=.
:find
:
w >>../
test
.
out
:
exec "w >>" .
test
_
out
:close
:new
:set path=.,,
:find
:
w >>../
test
.
out
:
exec "w >>" .
test
_
out
:close
:new
:set path=./**
:find
:
w >>../
test
.
out
:
exec "w >>" .
test
_
out
:close
:new
:" We shouldn't find any file at this point,
../
test.out must be empty.
:!mkdir in
:" We shouldn't find any file at this point, test.out must be empty.
:
silent
!mkdir in
:cd in
:!mkdir path
:
silent
!mkdir path
:exec "cd " . cwd
:e Xfind/file.txt
SHoly Grail:w
...
...
@@ -57,40 +59,93 @@ SAnother Holy Grail:w
SE.T.:w
:set path=Xfind/**
:find file
:w >> test
.
out
:
exec "
w >>
" .
test
_
out
:find file
:
w >>
test
.
out
:
exec "w >>" .
test
_
out
:find file
:
w >>
test
.
out
:
exec "w >>" .
test
_
out
:" Rerun the previous three find completions, using fullpath in 'path'
:exec "set path=" . cwd . "/Xfind/**"
:find file
:
w >>
test
.
out
:
exec "w >>" .
test
_
out
:find file
:
w >>
test
.
out
:
exec "w >>" .
test
_
out
:find file
:
w >>
test
.
out
:
exec "w >>" .
test
_
out
:" Same steps again, using relative and fullpath items that point to the same
:" recursive location.
:" This is to test that there are no duplicates in the completion list.
:exec "set path+=Xfind/**"
:find file
:
w >>
test
.
out
:
exec "w >>" .
test
_
out
:find file
:
w >>
test
.
out
:
exec "w >>" .
test
_
out
:find file
:
w >>
test
.
out
:
exec "w >>" .
test
_
out
:find file
:" Test find completion for directory of current buffer, which at this point
:" is Xfind/in/file.txt.
:set path=.
:find st
:
w >>
test
.
out
:
exec "w >>" .
test
_
out
:" Test find completion for empty path item ",," which is the current directory
:cd Xfind
:set path=,,
:find f
:w >> ../test.out
:exec "w >>" . test_out
:" Test shortening of
:"
:" foo/x/bar/voyager.txt
:" foo/y/bar/voyager.txt
:"
:" When current directory is above foo/ they should be shortened to (in order
:" of appearance):
:"
:" x/bar/voyager.txt
:" y/bar/voyager.txt
:silent !mkdir foo
:cd foo
:silent !mkdir x
:silent !mkdir y
:cd x
:silent !mkdir bar
:cd ..
:cd y
:silent !mkdir bar
:cd ..
:cd ..
:" We should now be in the Xfind directory
:e foo/x/bar/voyager.txt
SVoyager 1:w
:e foo/y/bar/voyager.txt
SVoyager 2:w
:exec "set path=" . cwd . "/Xfind/**"
:find voyager
:exec "w >>" . test_out
:find voyager
:exec "w >>" . test_out
:"
:" When current directory is .../foo/y/bar they should be shortened to (in
:" order of appearance):
:"
:" ./voyager.txt
:" x/bar/voyager.txt
:cd foo
:cd y
:cd bar
:find voyager
:exec "w >> " . test_out
:find voyager
:exec "w >> " . test_out
:" Check the opposite too:
:cd ..
:cd ..
:cd x
:cd bar
:find voyager
:exec "w >> " . test_out
:find voyager
:exec "w >> " . test_out
:cd ..
:q
:call DeleteDirectory("Xfind")
...
...
This diff is collapsed.
Click to expand it.
src/testdir/test73.ok
+
6
−
0
View file @
0be992e3
...
...
@@ -9,3 +9,9 @@ Jimmy Hoffa
E.T.
Another Holy Grail
Holy Grail
Voyager 1
Voyager 2
Voyager 2
Voyager 1
Voyager 1
Voyager 2
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment