[Top][All Lists]

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

Re: project.el semantics

From: Stephen Leake
Subject: Re: project.el semantics
Date: Thu, 12 Nov 2015 13:28:13 -0600
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.5 (windows-nt)

Dmitry Gutov <address@hidden> writes:

> On 11/12/2015 08:44 AM, Stephen Leake wrote:
>> But then there is also, orthogonal to category:
>> editable (or read-write)
>> read-only
> Is it orthogonal, though? I'd think top-level or other-dependency
> means "read-write", and the rest is "read-only".

Why define that in the API? Let the user do whatever they want.

Maybe the user is only allowed to review the code, not change it.

Maybe the user is responsible for one of the dependencies, and is 
reviewing how the top-level uses that dependency, so they are not
allowed to edit the top-level, but they can edit the dependency. 

> But if it is orthogonal in some cases, I doubt a project backend can
> choose which directories are read-write. Then we don't need to
> document these, and leave them as possibly user-defined categories,
> for later.

I don't follow. The point is to list metadata that a user might want to
know, that the backend might be able to provide.

Clearly, read/write is a useful item. One way the user can set it is via

>> So you are focusing on the "read-only" vs "read/write" aspect.
> I'm focusing on the "edited together" relation. Not on whether you can
> write to a particular directory.

I'm assuming the "edited together" comment on `project-roots' implies
"don't edit" on `project-library-roots'. Thus project-roots is
read-write, and project-library-roots is read-only.

Note that I am not talking about OS level file permissions, but about
the logical use of those directories in the context of the project.

If that's not the case, then I'm back to being totally confused.

>> The user should be able to specify a subset of the search path for each
>> search, at run-time. Having only project-roots and project-library-roots
>> available is too limiting.
> Let's be realistic. I doubt most people are going to use arbitrary
> predicates and searches that only touch some of the library-roots, as
> well as some of project-roots but other others, often. So we can serve
> the simplest case first.

I agree. But the simplest case is to always search all the directories
(ie project-root and project-library-root). You are allowing that, plus
one other case.

In other words, I also doubt most people will want to search only
project-roots or only project-library-roots. But I do agree those are
reasonable use cases, among many other similar ones. So the API should
provide for them.

>> Not with the current API:
>> (defun project-find-regexp (regexp)
>> ...)
>> How would I specify a single root or directory?
> Like I said: "C-u M-x". Use the prefix argument; it's documented in
> its docstring. 

Ah, I missed that.

> The API doesn't factor into it.

That's bad; you should not be able to do something interactively that
you cannot do programmatically. This should be:

(defun project-find-regexp (regexp &optional dir)
  "Find all matches for REGEXP in the current project.
If DIR is non-nil (default prefix arg), search in that instead.
If DIR is \\[universal-argument], prompts for DIR."

I'll have to play with that to get the interactive behavior; I don't see
how to do it right now. It might be best to provide a (slightly) higher
level function that provides the interactive UI.

The prompt for dir should use completing-read on project-roots and
project-library-roots; project-ignores should not have to cope with dir
outside that list.

This can also be implemented via a predicate arg to project-find-regexp;
then project-find-regexp-dir can prompt for a directory and construct
the appropriate predicate.

>>> I can display all available metadata to the user, and ask: directories
>>> with which pieces of metadata set do you want to search? The user
>>> enters the category names, separated by spaces, and the search
>>> proceeds.
>> That would be a dialog-box style UI, yes.
> I was thinking more of completing-read.

Ok, that's another UI.

>> The dialog box uses the user input to construct a predicate, which it
>> passes to the project.el UI.
> What kind of input? How does in turn into a predicate? Does the user
> write a whole predicate function in there?

The code writes the predicate function, not the user.

I'll just pick the "read-only" metadata for an example:

-*- lexical-binding: t; -*-

(let* ((read-only (completing-read "read-only?" '(t nil)))
         (lambda (dir)
           (eq read-only (metadata-read-only (project-metadata project dir))))))
   (project-find-regexp regexp predicate))

This could be extended to include the rest of the defined metadata.

>> The alternative to an arbitrary predicate function is to hard-code some
>> set of possible choices in the search code. Any such set is limiting.
> You see, the usage of predicate will not be coded into the API either
> way; there's no need for it, the API doesn't care, it just returns
> directories the consumer will call predicates on.

Well, that's one choice. But I'd prefer the predicate in the API, so I
don't have to implement the same predicate-calling code in each
higher-level function.

We can leave that for later, to see how often it really gets used.

I think completion tables is a good precedent here; they provide for an
arbitrary predicate, that could just as easily be implemented one level

On the other hand, the user code can just as easily distinguish
project-roots from project-library-roots; so why is that in the API?

You can't have it both ways; project-roots and project-libarary-roots is
just one special predicate.

> But unless we document the properties the predicates can rely on, it
> amounts to exposing no information at all.

Yes, we want to document those properties. That's why I'm pushing so
hard to find out what "project-root" means; I'm trying to find out what
properties of the project you actually care about.

We seem to have settled on "read-only".

>> On the GDS project, one search we repeated often was for FIXME:
>> comments; we had some structure in them, identifying which release it
>> had to be fixed for, who was assigned to fix it, etc. So I could have
>> written a few predicates that take advantage of the structure, and used
>> a menu to select among them for a search.
> To find all FIXMEs, you have to run the search on all directories
> first, don't you? And then, when you get the results, you can filter
> down the matches. That has nothing to do with which directories to
> search, I think.

True, this is not a directory level filter; bad example.

Still, it illustrates the need for another predicate on the result;
that could also be in the API, or at the client level.

>> Yes. Metadata query functions and search predicates work for a very
>> large variety of UIs (menus, dialog boxes, Siri), as well as a very
>> large variety of searches. "project-roots vs project-library-roots"
>> works for a similar set of UIs but a much smaller set of searches.
> If we go the project-directory-metadata route, what other accessors
> will be left? You want to remove project-library-roots, right?

Yes, and merge its content into project-roots.

> Will project-roots retain its name?

Yes, that's fine.

-- Stephe

reply via email to

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