emacs-devel
[Top][All Lists]
Advanced

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

Re: IDE


From: Dmitry Gutov
Subject: Re: IDE
Date: Sun, 18 Oct 2015 02:11:33 +0300
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:42.0) Gecko/20100101 Thunderbird/42.0

On 10/17/2015 08:18 PM, Lluís wrote:

I didn't think of the "find path" functionality, but it does seem to make sense
to fold it into the "root path" service type.

You mean "find search path", right? Another name if it is "include path", and that's different from the executable path.

I think I've formed an idea how separating it from the find-root(s) service would be useful. Currently, we have this awkward project-search-path-function, which can be defined in a major mode (we want this kind of functionality to be major mode-providable).

But if it were a separate service, that would be tidier. Introduce project-search-path-functions, which would take the current project as an argument and return an object that contains the search path (and, as a bonus, maybe knows how to resolve a relative import string).

Then ruby-mode won't have to define a separate project type. It'll just add to project-search-path-functions that checks that there is a Gemfile somewhere above the current directory and below the project root, and use the information from it. The fact that returned object can also resolve imports is nice, because I wasn't sure where to put that behavior.

In general, though, this might be problematic when a language L will simply read its search path from an environment variable, and doesn't require a presence of any "bundle" file. Does it provide its search-path to absolutely any project? We might need a "list of project languages" accessor on the "root" service instances. User-customizable, of course.

On the flip side, if there are no B implementations that can work with the
currently detected R service r1, but there's a certain b2 in service-b-functions
that would work with r2 (currently shadowed by r1), we may be missing out.

Exactly. I started prototyping a few interfaces where all requests go through
the public interfaces. A project-type acts similarly to your "service locator"
link, and projects are simply a service locator that manage multiple
project-type instances grouped by the project.

You mean different project-types are like entirely different collections of services? Why call them project-types at all? I'm lost.

Isn't a project a collection of services (of different service-types)?

More specifically, I was thinking about the following for deciding how to manage
results when information comes from different service implementations given a
service-type: for each public method of a service type, have a prioritized list
of method implementations, plus a property that tells us how to merge their
results.

We're unlikely to have too many service-types. No need for a property, merging could be done by a respective utility function (like `project-current', but for other services). Priority comes from the order of the elements in a hook.

Possible properties would be returning the first non-error result from
the possible method instances or returning a concatenation of all non-error
results from all method instances.

Those are the two main options. Not sure if we'll ever really need anything else.

While prototyping it, I actually decided it makes sense to implement this
functionality on the service-type. It should know how to merge results from
multiple services, and every service must declare what service-type it provides.

How about we reframe the description in terms of hooks? service-type is a hook variable, services are elements in it. You can call the elements of a hook in a sequence until one returns non-nil, or you can call all of them and combine.

Having to declare each combination of service-types that a project can provide
still seems unnecessarily limiting (and tedious). But that's what project-types
would be for, right?

Exactly. My idea was that common project types would be written once declaring
all the service types they provide and through what service
implementations.

So, why?

Take a look at xref-find-regexp. It looks up the current project, takes its roots (service 1) and its search-path (service 2). If either of the services can be undefined in the current project, what would xref-find-regexp be supposed to do?

And what is the use of several common project types? Could you give an example?

I'm not sure I follow, but maybe I responded you on my previous paragraphs.

How would a random command that needs certain info from services x, y and z, use this API?

Next, suppose a project instance can tell whether it provides a "build tool"
service. What does a "call build task" command does? Looks for the current
project and gives up if it doesn't provide the required service, or specifically
asks the locator for a project implementation that does provide that service?

I'd say both. My idea is that all project-types provide an auto-detection
function; given a path, tell me if it conforms to this project-type.

In Emacs parlance, a "path" is a list of directories (see exec-path or compilation-search-path).

The call-build-type needs the build-tool service. What project-type does it use, and why?

Then, if we
do not know of any project instance for that path, build a new one that contains
instances of all project-types that match with it.

What if we already have a project instance for that directory, but it doesn't provide that service?

[0] http://martinfowler.com/articles/injection.html#ADynamicServiceLocator

Building a project from all matching project-types provides a clean solution to
this. But to be honest, I'm not sure if it makes much sense beyond taking a
single auto-detected project type plus an optional overlaid project-type that
contains user customizations.

I don't think user customizations should be a project-type. Rather, they can be applied via .dir-locals.el, inside each service-type utility function.

For example, we could have a fallback "project-type-generic", a makefile-based
"project-type-make" and a very specific "project-type-linux". Should we overlay
all of them or just take the most "specific" one? (aka linux).

The one that comes first in the hook. Hook entries from minor modes usually come before the hook entries from major modes, and it's user's responsibility not to enable several minor modes at once that share the same responsibility.




reply via email to

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