From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: =?UTF-8?B?Sm/Do28gVMOhdm9yYQ==?= Newsgroups: gmane.emacs.devel Subject: Re: Subprojects in project.el (Was: Eglot, project.el, and python virtual environments) Date: Wed, 23 Nov 2022 20:33:04 +0000 Message-ID: References: <87zgcq68zp.fsf@ericabrahamsen.net> <878rkale3l.fsf@dfreeman.email> <4c5f4b07-3df6-d700-83f8-9a9d1b684afc@yandex.ru> <84781346-5b88-2be5-38bb-02696fcf1364@yandex.ru> <87o7t2vj19.fsf@dfreeman.email> <877czqtyfy.fsf@dfreeman.email> <87zgcml7g7.fsf@gmail.com> <2ba04533-097a-a1da-ff3f-2c9506fd488e@yandex.ru> <875yf9bbzb.fsf@gmail.com> <87wn7oa0aw.fsf@gmail.com> <7a5b76fd-fb15-8c1e-ea29-bf11f7e0d2ae@yandex.ru> <87bkoya815.fsf@gmail.com> <0024a67d-b8e5-b35c-1b22-82541a170eb3@yandex.ru> <871qptai4d.fsf_-_@gmail.com> Mime-Version: 1.0 Content-Type: multipart/alternative; boundary="0000000000001a9b5505ee292eb6" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="30186"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Stefan Monnier , Danny Freeman , Eric Abrahamsen , emacs-devel To: Dmitry Gutov Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Wed Nov 23 21:32:53 2022 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oxwQN-0007Z1-CV for ged-emacs-devel@m.gmane-mx.org; Wed, 23 Nov 2022 21:32:51 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oxwQ2-0003Ep-K1; Wed, 23 Nov 2022 15:32:32 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oxwPo-000395-7Y for emacs-devel@gnu.org; Wed, 23 Nov 2022 15:32:16 -0500 Original-Received: from mail-oa1-x33.google.com ([2001:4860:4864:20::33]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1oxwPf-00057J-Fg for emacs-devel@gnu.org; Wed, 23 Nov 2022 15:32:16 -0500 Original-Received: by mail-oa1-x33.google.com with SMTP id 586e51a60fabf-1432a5f6468so3878140fac.12 for ; Wed, 23 Nov 2022 12:32:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=edXlvWs6e7tw0i8Zu28BwhNj9Es8j9PWidTKnJ1s/2U=; b=X6wh++vOjNeMil5+zFDq4Aqt5GWfmly5iPsE5LArt+MRCy/nBxc9xY2HJZ8FeJH33y vm02SlspEyZYHfOX91Mea1zcNEchjr5nqntruRxK179kRa0veJvs8JAGLxbV86F1OrZH Hnyp0G7uDdZwP5kU1AaVabOq9EoavObgdEL67RyoDCgpyEy7VrraQboYRLoALn9c1eyp dF+ZBKPAG44j5hIAODbylyGX16FNn0KJ+ZOGFJ3+ZATV/YTKOVKvQ3UL67xG8HvUgXI3 oXxkoiSHoaQU8rR/2nQYepjXaxWXoB8d5EwXypOiMVr7fkFNhvT2k+BUXMvHeyG5CA+3 erPg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=edXlvWs6e7tw0i8Zu28BwhNj9Es8j9PWidTKnJ1s/2U=; b=X6CB7xa1jN0N+tra39Gn3Xxsx/A8tzr0/FEwr/huL/ILIkZJUldRHap1wlGI86Q+JP lQp8e69snbd8xxqRSpMf5dpnAPCYa+afTZLxNc87SR1JdOlswqSbYOPztxbzRCBymK3p AkOBbRkAggixHiTxchjIW9NWSdtvlc6JpKEvlWWVi6VrVDz5Cr7D8qturHIMuUppRBaq OMLpEQfeGNQCunA5syuEcF2SU1Ndw9jVto3X76ZsiAcDVaibUyBydtA5ONcvQsSR53fG PteCYLh17VNhZv9dwKYotq5w0kkcu8imNSx6OivAwMT16b4vv5+xiIYnAfRVjdqaPD/5 +1XQ== X-Gm-Message-State: ANoB5pkq0tusUswETiGO3UoaP5DZ/7ZN9Bp9Zxnnt/C9K1w6U9k2jSM+ Wm3fzClvoZUYBaYdsjsww+az6q6+V74+f28HPMA= X-Google-Smtp-Source: AA0mqf7DKpvPRFfJNVv9IqRwblyZOCeZ2cwTN+IOD22xkGySIJt82ud2k+wut54iqZ30Ztm8ZAU8lDB/cLMa1MLgqaU= X-Received: by 2002:a05:6870:6688:b0:13b:5ffe:ff70 with SMTP id ge8-20020a056870668800b0013b5ffeff70mr18852973oab.171.1669235518117; Wed, 23 Nov 2022 12:31:58 -0800 (PST) In-Reply-To: <871qptai4d.fsf_-_@gmail.com> Received-SPF: pass client-ip=2001:4860:4864:20::33; envelope-from=joaotavora@gmail.com; helo=mail-oa1-x33.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:300409 Archived-At: --0000000000001a9b5505ee292eb6 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi, In the previous email, my pseudo-code was all botched, as usual when writing imaginationware. Better back up my ideas with real code. The patch after my sig allows these kinds of customizations: (defun joaot/sub-projects (dir) (let* ((super (project-current)) (super-root (project-root super)) (relative (file-relative-name dir super-root)) (d (car (split-string relative "/")))) (when (member d '("lisp" "src")) (cons 'transient (expand-file-name (concat d "/") super-root))))) (add-hook 'project-find-functions 'joaot/sub-projects t nil) This will define two subprojects inside Emacs's tree. The "lisp" and "src" projects. It's not particularly useful for Emacs, but I hope it illustrates what I want to do. Of course, I still haven't coded any commands to access the "super project" so all commands work on the innermost sub-project, but they do seem to work unproblematically. To get the super-project, a seemingly robust way is: (project-current nil (file-name-directory (directory-file-name (project-root (project-current))))) But I've yet to find where to plug it. Maybe tomorrow I'll spend some more time playing around with this. Jo=C3=A3o This is the project.el patch: diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index c7b2c386ccd..1903b7f622f 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -196,13 +196,13 @@ project-current See the doc string of `project-find-functions' for the general form of the project instance object." (unless directory (setq directory default-directory)) - (let ((pr (project--find-in-directory directory))) + (let ((pr (car (project--find-in-directory directory)))) (cond (pr) ((unless project-current-inhibit-prompt maybe-prompt) (setq directory (project-prompt-project-dir) - pr (project--find-in-directory directory)))) + pr (car (project--find-in-directory directory))))) (when maybe-prompt (if pr (project-remember-project pr) @@ -211,8 +211,22 @@ project-current (setq pr (cons 'transient directory)))) pr)) +(defvar project--overriding-projects nil) + (defun project--find-in-directory (dir) - (run-hook-with-args-until-success 'project-find-functions dir)) + "Find projects that directory DIR belongs to. +Return them as a list. If more than one is found, the first is +usually the innermost." + (or project--overriding-projects + (let (projects) + (run-hook-wrapped + 'project-find-functions + (lambda (fn) + (let* ((project--overriding-projects projects) + (prj (funcall fn dir))) + (when prj (push prj projects))) + nil)) + projects))) (defvar project--within-roots-fallback nil) On Wed, Nov 23, 2022 at 1:56 PM Jo=C3=A3o T=C3=A1vora wrote: > Dmitry Gutov writes: > > >> I've just described in the other thread that I would like to have > >> finding references and finding files to be able to operate on either > >> sub-projects or super-projects on demand. This is the problem I'm > >> facing, and it's not new. For example, there is only: find file in th= e > >> very large project, and find file in the current directory. There is = no > >> "find file in this section of the repo, which is a sub-project in > >> itself". > > > > It would be much more helpful in a dedicated bug report where we could > > discuss the details, collect the votes and see what kind of design > > will ultimately satisfy the requirements. Instead of drowning it all > > in this thread, which is only moderately related. > > I think we're doing fine here but I've changed the subject line to > "unbury" it from the thread. > > >> IMO, it's not "improper" to describe problems and use cases: in fact I > >> prefer that people describe over jumping to vapourware solutions. But > >> if you're really looking for a suggestion as to _how_ to design it, I > >> suppose my problem would be well dealt with a negative prefix on C-x p= g > >> and C-x p f giving me a choice of which project to operate on. But th= at > >> is only one possibility: new commands are also acceptable. > > > > Note that you can more-or-less do this now: press 'C-x p p', select > > the parent project from the list, then choose 'f' or 'g' to run the > > command there. So to justify the added complexity one should say that > > they do want to use this feature frequently enough to justify the > > added complexity (which will reduce the number of keystrokes). > > Both cases -- focus on super-project/focus on sub-project -- are > definitely common. I have no problem in using an existing interface, > even if it idiosyncratic. > > So if the inner-most sub-project is the default but somehow I can > explicitly call up a "project picker" that shows me the super-project as > one of the first options, that probably works fine. > > > And even if we do, we might not need the additional notion of > > sub-projects. E.g. 'search in the parent project (if any)' might work > > as "take the root, go up a directory, search for a project there; if > > it exists, use it". Though Stephen L. might want a generic for that, > > since his projects do not correlate with directory tree. > > And in my case, sub-projects don't necessarily exist exactly one-level > down super-project's root. Sometimes they do, but now always. > > Of course, just as data point, I've been solving all my problems outside > project.el for a good long while now, even before I was faced with this > gigantic monorepo and even before project.el was a thing. I use Leo > Liu's ack-el.el, which greps from the super-project's root by default, > and from wherever I want given enough C-u. And I have a similar > separate command for finding files from arbitrary points in the > hierarchy. And I have a similar command for compiling. I just happen > to think having this in project.el would make a lot of sense. I've > recently experimented with it and found the new project.el features > pleasant to work in smaller or well-behaved projects. It's not powerful > enough for the big stuff, but it ought to be. > > > OTOH, if one of the operations will require a step "get all > > subprojects of the current project", then a separate notion might be > > required, with a separate hook. > > > >> As to how one defines sub-projects, I think having > >> project-find-functions be used to compose a list of projects (as oppos= ed > >> to to stopping after finding one) would be a nice way. It would be ni= ce > >> if the elements of project-find-functions could be informed of the > >> projects found so far. But keeping the "stop after first" behaviour a= nd > >> having members return a more complex object is maybe also good. I > >> really don't care much what you eventually choose, as long as I can > >> solve my problem. > > > > If we wanted to define projects and subprojects through the same hook, > > the step "get all subprojects of the current project" might not be > > feasible to implement. Because of performance-related considerations. > > Those remain to be seen, I can't guess what things you're imagining. > > I'm not sure we need that step at all. After all there is no "get me > all the projects in my hard drive" either, and at least I haven't missed > it. > > Anyway, from my POV this type of sub-project definition would not be > very nice. > > (add-hook 'some-new-subproject-find-hook > (lambda (dir) > (cons 'super-project > > (some-code-which-scans-and-returns-a-list-of-subprojects)))) > > I would prefer this, which I think is more readable and in-line with > current project.el: > > (add-hook 'project-find-functions > (lambda (dir) > (let ((super (project-current))) > (when (and super > (string=3D (file-name-directory > (directory-file-name dir)) > (project-root super)) > (my-special-condition dir)) > (cons 'transient dir))))) > > > Maybe 'my-special-condition' could read a directory local variable to > decide if sub-projects are enabled or not. > > For my idea to work, project-current would have to be changed to > > 1. Call all members of project-find-functions: return the innermost > project found thus far. > 2. Not call project-find-functions recursively when called from within a > function > in project-find-functions, just return the innermost project found > thus far. > > I don't see any big performance problems in this alternative. > > But, again, the above are suggestions: _any_ alternative that lets me > define inner sub-projects within a larger super-project and let me > choose where I want to grep, find-file, compile, would be an > improvement. > > Jo=C3=A3o > --=20 Jo=C3=A3o T=C3=A1vora --0000000000001a9b5505ee292eb6 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi,

In the previous email, my pseudo-code was all b= otched, as usual when
writing imaginationware.=C2=A0 Better back up= my ideas with real code.=C2=A0 The
patch after my sig allow= s these kinds of customizations:

=C2=A0 (defun joaot/sub-proje= cts (dir)
=C2=A0 =C2=A0 (let* ((super (project-current))
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(super-root (project-root super))
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(relative (file-relative-name dir super-r= oot))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(d (car (split-string rel= ative "/"))))
=C2=A0 =C2=A0 =C2=A0 (when (member d '("= ;lisp" "src"))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 (cons 'tra= nsient (expand-file-name (concat d "/") super-root)))))
=C2=A0= =C2=A0
=C2=A0 (add-hook 'project-find-functions
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 'joaot/sub-projects
=C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 t nil)

This will define two subprojects inside= Emacs's tree.=C2=A0 The "lisp" and
"src" projec= ts.=C2=A0 It's not particularly useful for Emacs, but I hope it
illu= strates what I want to do.

Of course, I still haven't coded any = commands to access the "super
project" so all commands work on= the innermost sub-project, but they
do seem to work unproblematically.<= br>
To get the super-project, a seemingly robust way is:

=C2=A0 (= project-current nil
=C2=A0 =C2=A0 (file-name-directory
=C2=A0 = =C2=A0 =C2=A0 =C2=A0(directory-file-name (project-root (project-current))))= )

But I've yet to find where to plug it.=C2=A0= Maybe tomorrow I'll spend
some more time playing around with= this.

Jo=C3=A3o

This is the project.= el patch:

diff --git a/lisp/progmodes/project.el b/lisp/progmodes/pr= oject.el
index c7b2c386ccd..1903b7f622f 100644
--- a/lisp/progmodes/p= roject.el
+++ b/lisp/progmodes/project.el
@@ -196,13 +196,13 @@ proje= ct-current
=C2=A0See the doc string of `project-find-functions' for = the general form
=C2=A0of the project instance object."
=C2=A0 = =C2=A0(unless directory (setq directory default-directory))
- =C2=A0(let= ((pr (project--find-in-directory directory)))
+ =C2=A0(let ((pr (car (p= roject--find-in-directory directory))))
=C2=A0 =C2=A0 =C2=A0(cond
=C2= =A0 =C2=A0 =C2=A0 (pr)
=C2=A0 =C2=A0 =C2=A0 ((unless project-current-inh= ibit-prompt
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0maybe-prompt)
=C2=A0 = =C2=A0 =C2=A0 =C2=A0(setq directory (project-prompt-project-dir)
- =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0pr (project--find-in-directory direct= ory))))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0pr (car (project--fin= d-in-directory directory)))))
=C2=A0 =C2=A0 =C2=A0(when maybe-prompt
= =C2=A0 =C2=A0 =C2=A0 =C2=A0(if pr
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0(project-remember-project pr)
@@ -211,8 +211,22 @@ project-current=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq pr (cons 'transient directory)= )))
=C2=A0 =C2=A0 =C2=A0pr))
=C2=A0
+(defvar project--overriding-p= rojects nil)
+
=C2=A0(defun project--find-in-directory (dir)
- =C2= =A0(run-hook-with-args-until-success 'project-find-functions dir))
+= =C2=A0"Find projects that directory DIR belongs to.
+Return them a= s a list.=C2=A0 If more than one is found, the first is
+usually the inn= ermost."
+ =C2=A0(or project--overriding-projects
+ =C2=A0 =C2= =A0 =C2=A0(let (projects)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0(run-hook-wrapped=
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 'project-find-functions
+ =C2=A0 = =C2=A0 =C2=A0 =C2=A0 (lambda (fn)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (= let* ((project--overriding-projects projects)
+ =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(prj (funcall fn dir)))
+ =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (when prj (push prj projects)))
+ =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 nil))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0proje= cts)))
=C2=A0
=C2=A0(defvar project--within-roots-fallback nil)
=
On Wed= , Nov 23, 2022 at 1:56 PM Jo=C3=A3o T=C3=A1vora <joaotavora@gmail.com> wrote:
Dmitry Gutov <dgutov@yandex.ru> writes:

>> I've just described in the other thread that I would like to h= ave
>> finding references and finding files to be able to operate on eith= er
>> sub-projects or super-projects on demand.=C2=A0 This is the proble= m I'm
>> facing, and it's not new.=C2=A0 For example, there is only: fi= nd file in the
>> very large project, and find file in the current directory.=C2=A0 = There is no
>> "find file in this section of the repo, which is a sub-projec= t in
>> itself".
>
> It would be much more helpful in a dedicated bug report where we could=
> discuss the details, collect the votes and see what kind of design
> will ultimately satisfy the requirements. Instead of drowning it all > in this thread, which is only moderately related.

I think we're doing fine here but I've changed the subject line to<= br> "unbury" it from the thread.

>> IMO, it's not "improper" to describe problems and us= e cases: in fact I
>> prefer that people describe over jumping to vapourware solutions.= =C2=A0 But
>> if you're really looking for a suggestion as to _how_ to desig= n it, I
>> suppose my problem would be well dealt with a negative prefix on C= -x p g
>> and C-x p f giving me a choice of which project to operate on.=C2= =A0 But that
>> is only one possibility: new commands are also acceptable.
>
> Note that you can more-or-less do this now: press 'C-x p p', s= elect
> the parent project from the list, then choose 'f' or 'g= 9; to run the
> command there. So to justify the added complexity one should say that<= br> > they do want to use this feature frequently enough to justify the
> added complexity (which will reduce the number of keystrokes).

Both cases -- focus on super-project/focus on sub-project -- are
definitely common.=C2=A0 I have no problem in using an existing interface,<= br> even if it idiosyncratic.

So if the inner-most sub-project is the default but somehow I can
explicitly call up a "project picker" that shows me the super-pro= ject as
one of the first options, that probably works fine.

> And even if we do, we might not need the additional notion of
> sub-projects. E.g. 'search in the parent project (if any)' mig= ht work
> as "take the root, go up a directory, search for a project there;= if
> it exists, use it". Though Stephen L. might want a generic for th= at,
> since his projects do not correlate with directory tree.

And in my case, sub-projects don't necessarily exist exactly one-level<= br> down super-project's root.=C2=A0 Sometimes they do, but now always.

Of course, just as data point, I've been solving all my problems outsid= e
project.el for a good long while now, even before I was faced with this
gigantic monorepo and even before project.el was a thing.=C2=A0 I use Leo Liu's ack-el.el, which greps from the super-project's root by defau= lt,
and from wherever I want given enough C-u.=C2=A0 And I have a similar
separate command for finding files from arbitrary points in the
hierarchy.=C2=A0 And I have a similar command for compiling.=C2=A0 I just h= appen
to think having this in project.el would make a lot of sense.=C2=A0 I'v= e
recently experimented with it and found the new project.el features
pleasant to work in smaller or well-behaved projects.=C2=A0 It's not po= werful
enough for the big stuff, but it ought to be.

> OTOH, if one of the operations will require a step "get all
> subprojects of the current project", then a separate notion might= be
> required, with a separate hook.
>
>> As to how one defines sub-projects, I think having
>> project-find-functions be used to compose a list of projects (as o= pposed
>> to to stopping after finding one) would be a nice way.=C2=A0 It wo= uld be nice
>> if the elements of project-find-functions could be informed of the=
>> projects found so far.=C2=A0 But keeping the "stop after firs= t" behaviour and
>> having members return a more complex object is maybe also good.=C2= =A0 I
>> really don't care much what you eventually choose, as long as = I can
>> solve my problem.
>
> If we wanted to define projects and subprojects through the same hook,=
> the step "get all subprojects of the current project" might = not be
> feasible to implement. Because of performance-related considerations.<= br>
Those remain to be seen, I can't guess what things you're imagining= .

I'm not sure we need that step at all.=C2=A0 After all there is no &quo= t;get me
all the projects in my hard drive" either, and at least I haven't = missed
it.

Anyway, from my POV this type of sub-project definition would not be
very nice.

=C2=A0 (add-hook 'some-new-subproject-find-hook
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (lambda (dir)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (cons 'super-project =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (some= -code-which-scans-and-returns-a-list-of-subprojects))))

I would prefer this, which I think is more readable and in-line with
current project.el:

=C2=A0 (add-hook 'project-find-functions
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (lambda (dir)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (let ((super (project-curr= ent)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (when (and super =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0(string=3D (file-name-directory
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(directory-file-= name dir))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (project-root super))<= br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0(my-special-condition dir))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (cons 't= ransient dir)))))


Maybe 'my-special-condition' could read a directory local variable = to
decide if sub-projects are enabled or not.

For my idea to work, project-current would have to be changed to

1. Call all members of project-find-functions: return the innermost
=C2=A0 =C2=A0project found thus far.
2. Not call project-find-functions recursively when called from within a fu= nction
=C2=A0 =C2=A0in project-find-functions, just return the innermost project f= ound
=C2=A0 =C2=A0thus far.

I don't see any big performance problems in this alternative.

But, again, the above are suggestions: _any_ alternative that lets me
define inner sub-projects within a larger super-project and let me
choose where I want to grep, find-file, compile, would be an
improvement.

Jo=C3=A3o


--
Jo=C3=A3o T=C3=A1vora
--0000000000001a9b5505ee292eb6--