emacs-devel
[Top][All Lists]
Advanced

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

Re: IDE


From: Lluís
Subject: Re: IDE
Date: Sun, 18 Oct 2015 20:21:45 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux)

Dmitry Gutov writes:

> 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.

No, I mean something as simple as concatenating the project's root with a
non-absolute path given as an argument. Search or include paths are specific to
the organization of the project at hand (e.g., on a C project not every
directory should be searched for an include), but could be implemented on top of
the "find path" functionality.


> 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.

That's one of my concerns with the project concept. As you pointed out,
behaviour can change, for example, based on the mode of the file you're working
on. This can be the case for projects that contain code in multiple languages,
so that each can be treated slightly differently.

The question is thus, for example, how do we fit the major-mode variable into
this scheme? The problem becomes multi-dimensional, and I'm not sure how to
specify that. Should some service-types be dependant on the major-mode, such
that a project can have mutiple services for the same type but for different
major-modes?

If that sounds reasonable, then why not also account for the path of the current
file? The same project might have different file search paths for different
files...


>>> 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)?

Both are collections of services. I was thinking of the project as a collection
of project-types too, so that you can combine multiple of them.


[...]
>> 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.

I was thinking of service-types as providing multiple methods (hook variables),
one per function it exposes.


>>> 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?

Suppose you have project-type T1 that provides service 1 (S1) but not S2. As you
said, xref-find-regexp will fail.

Now, there can be some best-effort project-type T0 that provides a brain-dead S2
that looks at all sub-directories. If you create your project overlaying T0 and
T1, you can always get some best-effort functionality in case you're not using
any well-known project type.

Note that some other project-type might provide a more intelligent S2 that, for
example, takes information from a compilation database.


>> 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?

Does the previous paragraph answer it now?


>>> 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?

Suppose these three project-types:

* project-type-scons
* project-type-make
* project-type-linux

Each provides only the build-tool service, and you open a file from the linux
kernel. The type project-type-scons does not apply, but the other two do. If we
can assign some priority to them, we will end up with project-type-linux.


>> 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?

I'd say there's no way out of this one. What troubles me the most is nesting,
where each sub-directory might need to behave differently (e.g., have files for
different programming languages). Would then each file or directory have a
potentially different project instance? Or should the project abstraction
account for different services on different paths?


>>> [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.

I'm still not sure about this one.


>> 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.

I'd prefer the system to be able to auto-detect the proper type whenever
possible, instead of relying on the user establishing order for each possible
directory.


Thanks,
  Lluis

-- 
"And it's much the same thing with knowledge, for whenever you learn
something new, the whole world becomes that much richer."
-- The Princess of Pure Reason, as told by Norton Juster in The Phantom
Tollbooth



reply via email to

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