I built a new (MacVim) binary using the latest source and noticed that
command autocompletion is behaving strangely. Here's an example:
Start Vim, cd to ~/temp which contains the files (among others)
"appkit.h" and "applicatives.hs", enter ":f ap". It then
autocompletes as follows:
apache2/ appkit.h applicatives.hs
appkit.h applicatives.hs apr-1/
Some comments:
- the "apache2" and "apr-1" directories are under /usr/include !?
- there are doubles of the files that really are in the folder
(appkit.h and applicatives.hs)
I cannot begin to guess what is going on here. I have tried getting
rid of my .vim folder and .vimrc/.gvimrc files with no change. Same
behavior in console mode as in GUI mode.
Any ideas what's going here?
Björn
Looks like the new :find completion. It completes files that would be
found when executing the ":find" command. Did you intend to use ":edit"
instead?
The duplicates shouldn't be there, that's a bug.
--
ARTHUR: What?
BLACK KNIGHT: None shall pass.
ARTHUR: I have no quarrel with you, good Sir knight, but I must cross
this bridge.
BLACK KNIGHT: Then you shall die.
The Quest for the Holy Grail (Monty Python)
/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ download, build and distribute -- http://www.A-A-P.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
[snip]
> Looks like the new :find completion. It completes files that would be
> found when executing the ":find" command. Did you intend to use ":edit"
> instead?
>
> The duplicates shouldn't be there, that's a bug.
I'm the one to blame :)
Björn, could you let me know what your 'path' setting is?
That would help in troubleshooting the duplicates.
Just to be sure: did you really see two "appkit.h", and not "include/appkit.h"
and "appkit.h"?
The function "uniquefy_paths" in misc1.c is the one responsible for shortening
the paths while still maintaning their uniqueness. If there is any duplicates
then this function is the first suspect. In retrospect, the name should really
be something like "shorten_and_uniquefy_paths".
nazri.
b.t.w: Thanks a lot for writing up the vim-hg-git guide . It is really useful
to me as I don't grok mercurial as good as I do git.
I guess...I usually use ":f" instead of ":e" to avoid inadvertently
opening a new buffer in case I mistyped the filename.
>>
>> The duplicates shouldn't be there, that's a bug.
>
> I'm the one to blame :)
>
> Björn, could you let me know what your 'path' setting is?
:set path?
path=.,/usr/include,,
(Look at that -- another option I didn't know about! ;-)
>
> Just to be sure: did you really see two "appkit.h", and not "include/appkit.h"
> and "appkit.h"?
There's only one file. To double check I renamed the file
"appkitborkborkbork.h" (I know for sure there is no other file called
that on my filesystem) and I get
:tabf ap
apache2/ appkitborkborkbork.h applicatives.hs
appkitborkborkbork.h applicatives.hs apr-1/
However, If I use :f the situation changes (I just noticed this)!
:f app
appkitborkborkbork.h applicatives.hs
So it would seem the bug is in ":tabf" but not ":f".
>
> b.t.w: Thanks a lot for writing up the vim-hg-git guide . It is really useful
> to me as I don't grok mercurial as good as I do git.
I'm glad it is of use!
Björn
To clarify: in the second example I actually typed ":f ap" and it
completed to ":f app" ignoring the previous matches from
"/usr/include". So it seems ":f" ignores 'path' whereas 'tabf'
doesn't.
Björn
Oh, I didn't realize that. Well, I can confirm that ":fin" behaves
identical to ":tabf" (duplicate entries).
Björn
I can reproduce the duplicate entries.
I'll look into this.
nazri.
Attached patch solves the duplicate entry.
While fixing this bug I found another:
If you have these files:
$HOME/a/Makefile
$HOME/a/b/Makefile
and your path is set to '$HOME/a/**',
and your CWD is $HOME/a,
doing :find Make<tab>
will show "a/Makefile" (correct) and "b/Makefile" (WRONG) as the
possible completions.
"b/Makefile" should really be "Makefile".
The function uniquefy_paths in misc1.c shortens the list of full path
file names without taking into account the values in 'path' option.
I'll look into fixing this too.
nazri.
I can confirm that this patch solves the problem with duplicate entries for me.
Thanks,
Björn
[snipped description of bug due to ...]
>> The function uniquefy_paths in misc1.c shortens the list of full path
>> file names without taking into account the values in 'path' option.
>>
>> I'll look into fixing this too.
>
> Thanks, this works better. I included this patch and made a few
> cosmetical changes.
>
> I also see duplicates in the form "./term.h" and "term.h". The "./" has
> no effect, thus these two names are the same. The complete list is:
>
> ./term.h include/term.h term.h
Attached are four patches that fix the above problem and refine the behavior of
the find/sfind/tabfind completion. Also I've added note to the documentation on
the limitation of the completion when 'path' has url and directory limiter
(/usr/**2) and upward search (;) notations.
Note that with this patch, the previous (duplicate) completions (done
in vim's src
directory with default 'path' setting):
> ./term.h include/term.h term.h
are now "reduced" to:
term.h
and it does not differentiate between "include/term.h" and "./term.h" due to
because doing ":find include/term.h" would fail with the default 'path' setting
(".,/usr/include,,").
nazri.
Oh, I actually liked having both "term.h" and "include/term.h".
It's very difficult to get to the second one otherwise.
If the price to pay is to also have "./term.h" then so be it. But
perhaps it can be more clever to recognize that "./term.h" and "term.h"
are actually the same. I suppose the latter needs to be removed then.
":find include/term.h" doesn't work though. I would think ":find
../include/term.h" works, but it doesn't. Keeping the full path is
another solution.
Perhaps the algorithm can remove the path when there is only one choice,
but keep a longer path otherwise. This also depends on the first entry
in 'path'. Usually it's ".", thus if "./{shortened-match}" exists and
is different from the long name then it can't be shortened.
--
BEDEVERE: Look! It's the old man from scene 24 - what's he Doing here?
ARTHUR: He is the keeper of the Bridge. He asks each traveler five
questions ...
GALAHAD: Three questions.
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
Here's the ideal behavior that I'm aiming for:
instead of
./term.h include/term.h term.h
It should be
./term.h /usr/include/term.h
Or possibly
./term.h /usr/include/term.h foo/term.h
when you have another term.h in some subdirectories of your path setting, say
".,/usr/include,/home/user/project/**,,".
In summary for duplicate filenames don't "basename" them, instead make them
uniquely "find-able" while keeping the names as short as possible and when that
is not possible use the fullpath instead.
My initial attempt at fixing the duplicates was roughly in that
direction but was
stalled because the other (non-)solution that I posted seemed simpler
to implement.
I'll look into this again sometime next week.
nazri.
It's done.
Please have a look at the patches - 0001 is the major one (have a look at the
two FIXMEs), while 0002 and 0003 are the minor fixes and documentation update
on the limitation of the completion when 'path' has upward search (;) and
directory limiter (/usr/**N) notations.
I'm sorry that I don't have access to a windows machine at the moment to
investigate the bug reports that people are reporting [1].
If anyone want to give a shot at fixing the bug the following information might
be useful:
The completion for find/sfind/tabfind is first handled by
misc1.c:expand_in_path() - it does the following:
1. Expand relative path entries in your 'path' setting into a list of
their equivalent full path directories:
"." is expanded to the directory of the current file
",," (empty) is expanded to the current directory
foo is expanded to /current/directory/foo
The non-relative entries are left intact.
2. Joins the full path names in the previous step (with ",") and calls
globpath().
3. The matching list of full path file names are filtered through
misc1.c:uniquefy_paths() to shorten the filename while still keeping
them unique. If that is not possible then the fullname is used
instead.
If you would like to help making the completion works for the upward search (;)
and directory limiter notations (/usr/**N) the place to modify is the function
misc1.c:expand_path_option().
nazri.
I noticed a leak. The fix is attached, to be applied after 0001.
nazri.
One teeny fix for 0001:
for (i = 0; i < gap->ga_len; i++)
{
- path = fnames[i];
+ char_u *path = fnames[i];
+ int is_in_curdir;
len = (int)STRLEN(path);
- /* we start at the end of the path */
- pathsep_p = path + len - 1;
+ char_u *dir_end = gettail(path);
^^^^^^ Move this line one or two lines up. Sorry I'm a bit
spoiled by C++ :)
nazri