[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: Fri, 08 Jan 2016 13:11:20 -0600
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.5 (windows-nt)

Dmitry Gutov <address@hidden> writes:

> On 01/07/2016 10:58 PM, Stephen Leake wrote:
>>> Thanks, I'll have to play with it.
>>> Does it handle ignores?
>> Yes, in the path iterator object.
> Tried it, and it did what advertised after I added (find-file ...) to
> the locate-uniquified-file's definition. 

Hmm? the doc string of `locate-uniquified-file' says "return an
absolute-filename", not "visit a file".

Here's how I implement find-file-in-project:

(cl-defgeneric project-find-file (prj filename)
  "Find FILENAME with completion in project PRJ."
  (let* ((iter (make-path-iterator
                :user-path-non-recursive nil
                :user-path-recursive (project-all-roots prj)
                :ignore-function (lambda (dir) (project-ignore-dir prj dir))))
         (pred (lambda (abs-file-name)
                 (not (string-match
                       ;; FIXME: this assumes `project-ignores' can accept dir 
that is not root
                       (project-ignores-regexp prj (file-name-directory 
         (absfilename (locate-uniquified-file-iter iter pred filename)))

    (if (file-readable-p absfilename)
        (find-file absfilename)
      ;; FIXME: need human-readable name for project
      (error "'%s' not found/readable in project." filename)))

(defun find-file-in-project (filename)
  "Find FILENAME (default prompt) with completion in current project.
With prefix arg, FILENAME defaults to filename at point."
  (interactive (list (when current-prefix-arg (thing-at-point 'filename))))
  (project-find-file (project-current) filename))

> As written, though, it only lists files at the top-level of load-path,
> without recursing. 

Yes, that's consistent with `locate-file', and all other uses of

To add all directories that contain elisp files, you need to build the
path iterator directly:

(let ((emacs-root
         (file-name-directory (locate-library "man"))))))
     (concat emacs-root "test/automated")
     (concat emacs-root "lisp/term")))
   (list (concat emacs-root "lisp/cedet")))

> Note that it doesn't list lisp/cedet/ede/locate.el that you brought up
> as an example earlier (maybe because I don't have EDE loaded).

Because you did not add the "cedet/ede" directory to the path iterator.

As we have discussed before, the user must tell the code what
directories in `load-path' should be treated recursively.

> FWIW, I'm not partial to the suffix-style of uniquification.

Right; one of these days I'll see if I can convert that to prefix. But
the completion code makes the assumption that the prefix of the strings
match, so it would be a big change.

But once you get used to it, you'll find that you simply don't care
about the directory; you really only need it to disambiguate colliding
names. So the suffix style makes sense.

>>> How's the performance in the Emacs repository?
>> There is a noticeable delay, mostly due to computing the partial
>> completion (before I added that, there was no noticeable delay).
> Did you try that using an iterator that visits the whole of Emacs
> repo, not just load-path? E.g., I can't visit xdisp.c this way.

Yes; I use a variant of the above path-iterator constructor that adds
the C directories. But that also requires the project code to know about
multiple languages, so it's part of a multi-language project package.

>> This is a pure elisp implementation. However, the path iterator object
>> could provide the directory list to the subprocess find function as
>> well.
> Will Emacs then call `find' for each of the "shallow" directories in
> the list? 

Only if you write the code that way. The path-iterator constructor takes
both recursive and non-recursive arguments.

'find' requires a single recursive root plus ignores, so to be really
useful with 'find', the path-iterator object would have to be enhanced
to return those values.

-- Stephe

reply via email to

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