[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: find-file-project

From: Stephen Leake
Subject: Re: find-file-project
Date: Wed, 16 Sep 2015 16:01:57 -0500
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.5 (windows-nt)

Dmitry Gutov <address@hidden> writes:

> On 09/16/2015 07:41 PM, Stephen Leake wrote:
>> By "root" I guess you mean the argument "dir", since that is an element
>> of the recursive project-search-path.
> Yes. A root, or a search-path element.
>> project-search-path returns (".../dir1" ".../dir2" ".../dir3"); thus
> As documented, project-search-path should return absolute file names.

That's what the "..." is supposed to mean. I guess I was not being
"really clear". Sorry.

In the following, let's assume that "..." is "c:/project1".

>> project-ignores is only called with one of these three values. (I'm
>> ignoring project-roots, because I don't understand when it would be
>> different from project-search-path).
> Indeed, the logic should be pretty similar. But the external
> project-search-path entries usually doesn't have any ignored
> directories, whereas there are often ignored dirs inside
> project-roots, usually configured via .gitignore or the project file.

You've lost me here.

There is an ignored dir in this example; c:/project1/dir2/dir21/obj/.

Is that supposed to be in the result of project-ignores or not?

Does this mean file name completion should search on project-roots, not
project-search-path, for this use case?

xref-find-regexp searches on both, which is redundant. For example, for
a file in Emacs core, using only project-try-vc in project-find-files,
project-roots returns ("c:/Projects/emacs/master/"), and
project-search-path includes that directory along with others.

As we have discussed, in general a recursive path requires ignored
directories in order to be accurate. So since project-search-path is
recursive, it must always be used together with ignores; that means
project-ignores must return c:/project1/dir2/dir21/obj/ in this example.

>> The user wants to ignore "*/*.elc", "*/*.dvi", "*/*.exe",
>> "dir2/dir21/obj/*", "dir2/dir21/*.text", "dir3/dir31/*.dvi".
>> So one implementation of project-ignores could be:
>> (cond
>>   ((string-equal dir ".../dir1")
>>    '("*.elc" "*.dvi" "*.exe"))
>>   ((string-equal dir ".../dir2")
>>    '("*.elc" "*.dvi" "*.exe" "./dir2/dir21/obj/" "dir2/dir21/*.text"))
>>   ((string-equal dir ".../dir3")
>>    '("*.elc" "*.dvi" "*.exe" "./dir3/dir31/*.dvi"))
>> )
> I suppose. 

Sorry, I need "yes" or "no"; this either meets the spec (and intended
semantics) of project-ignores, or it doesn't.

> Or you could simply return the whole list each time, and
> leave it to 'find' to apply the ignores appropriately. Not sure what
> the performance hit will be. There might be false positives as well.

I'm guessing this means "yes, it meets the intended semantics". I did
say "one implementation could be". Optimization can be left for later,
if performance is at all an issue.

>> Then find-file-path-completion-table could take a recursive
>> project-search-path as the "path" argument, and recurse thru the
>> directory tree, calling project-ignores at each directory, with a parent
>> directory from project-search-path as the argument, and comparing the
>> path of each file - relative to the parent directory - to the glob
>> patterns.
> I would just call 'find' for each "root" directory, pass it the
> appropriate ignores each time, and then parse its output.

Hmm. I had not considered that approach. It could well be that spawning
"find" is faster than iterating over the disk in elisp.

However, I don't want to rely on "find.exe" on Windows boxes, so I'll
stick with an all elisp solution.

>> For example, when processing dir2/dir21, it calls (project-ignores
>> "dir2"), and compares "./dir2/dir21/obj/" to "dir2/dir21/obj", and
>> "*.exe" to "dir2/dir21/foo.exe", both yeilding "ignore".
>> Is that right?
> It could, though the paths will be absolute.

The argument to project-ignores will be "c:/project1/dir2"; I got that

I guess you are also saying that the elisp functions for getting a list of
files in a directory will return absolute paths, so this will actually
be comparing "./dir2/dir21/obj/"
to "c:/project1/dir2/dir21/obj". Which can be accomplished by first
expanding the glob pattern relative to the current root.

That would be one way to implement it.

>> Since the compare for directories is different from that for files, it
>> would simplify the use of project-ignores (at least for this use case)
>> if it was split into project-ignore-files and project-ignore-dirs. Or
>> took an arg to specify that.
> Well... an entry that doesn't end with a slash, in .gitignore, will
> ignore both files and directories with that name.

Ah, that is what the doc string says; I was misreading it.

>> I was stuck on using a flat path for find-file-path-completion-table
>> because I started out trying to reuse locate-file-completion-table. But
>> now that I'm implementing the completion function from scratch, and it
>> is reading the disk and ignoring some files anyway, it does make more
>> sense start with a recursive path.
> Thank you. I was hoping you'd come to that conclusion.

You could have been more constructive in getting there.

-- Stephe

reply via email to

[Prev in Thread] Current Thread [Next in Thread]