all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Improving Emacs for writing code
@ 2008-04-22 10:06 joakim
  2008-04-22 15:49 ` David Hansen
                   ` (2 more replies)
  0 siblings, 3 replies; 24+ messages in thread
From: joakim @ 2008-04-22 10:06 UTC (permalink / raw)
  To: emacs-devel

Emacs does a lot of things uniquely well, but we can still learn from
other code writing environments how to improve the code writing
experience in Emacs.

These are concrete proposals I'm prepared to invest time in:

- Merge Cedet in Emacs.

Cedet provides many facilities necessary to emulate other modern IDE:s,
for instance language parsers in lisp. I think Cedet is nicely written,
and that it wouldn't be a great problem to merge it if a decision to do
it was reached. I've contributed things to the package and I'm prepared
to help with any grunt work necessary for the merge, for instance
discussing issues from emacs-devel with the packages principal authors.

- Provide some ECB like features in Emacs.

ECB provides the typical IDE workspace view in Emacs, but achieves this
by advising Emacs core functions a lot.

In another thread on this list RMS identified the following core C level
features to be implemented for this feature(slightly edited by me):

---------------
Perhaps the cleanest way is to give each window a plist to specify
whether various operations should consider it.  It could have a:
- `delete-other-windows' property and a
- `select-window' property and a
- `display-buffer' property, and the values of these properties would
control whether those operations can use this window.
(this last one can be postponed, since "dedicted" does the same)

The new `display-buffer' property could be equivalent to the existing
"dedicated" flag.  That would mean it affects some other primitives
aside from `display-buffer', but that is ok.  There is no need to be
rigid about the relationship between these properties and primitives
they affect.
---------------------

I'm interested in working on initially implementing the first 2 flags in
this list. The display-buffer property could be implemented later, since
the current "window dedication" feature does the same.

-- 
Joakim Verona




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Improving Emacs for writing code
  2008-04-22 10:06 Improving Emacs for writing code joakim
@ 2008-04-22 15:49 ` David Hansen
  2008-04-22 21:49   ` Re[2]: " Eric M. Ludlam
  2008-04-22 16:02 ` Stefan Monnier
  2008-04-22 20:08 ` Richard Stallman
  2 siblings, 1 reply; 24+ messages in thread
From: David Hansen @ 2008-04-22 15:49 UTC (permalink / raw)
  To: emacs-devel

On Tue, 22 Apr 2008 12:06:58 +0200 joakim@verona.se wrote:

> Emacs does a lot of things uniquely well, but we can still learn from
> other code writing environments how to improve the code writing
> experience in Emacs.
>
> These are concrete proposals I'm prepared to invest time in:
>
> - Merge Cedet in Emacs.

I would really like to see this happen.  We do have some time till the
next release and I think this would add quite some "super features" to
emacs that will attract not only the old farts here.

For sure a bigger user base will help the CEDET project to improve.  But
lets hear what the CEDET author thinks (hope this works, how do I post
to a newsgroup and send the same message via mail using gnus?).

David





^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Improving Emacs for writing code
  2008-04-22 10:06 Improving Emacs for writing code joakim
  2008-04-22 15:49 ` David Hansen
@ 2008-04-22 16:02 ` Stefan Monnier
  2008-04-22 16:54   ` klaus.berndl
  2008-04-22 20:08 ` Richard Stallman
  2 siblings, 1 reply; 24+ messages in thread
From: Stefan Monnier @ 2008-04-22 16:02 UTC (permalink / raw)
  To: joakim; +Cc: emacs-devel

> Emacs does a lot of things uniquely well, but we can still learn from
> other code writing environments how to improve the code writing
> experience in Emacs.

> These are concrete proposals I'm prepared to invest time in:

> - Merge Cedet in Emacs.

> Cedet provides many facilities necessary to emulate other modern IDE:s,
> for instance language parsers in lisp. I think Cedet is nicely written,
> and that it wouldn't be a great problem to merge it if a decision to do
> it was reached. I've contributed things to the package and I'm prepared
> to help with any grunt work necessary for the merge, for instance
> discussing issues from emacs-devel with the packages principal authors.

IDE-style features are sorely needed I think, so I am in favor of adding
such things to Emacs.  I do not know enough about the current state of
CEDET to know how easy it would be to integrate it.  Problems I envision
are mostly:

1 - Getting the copyright paperwork done: the CEDET project has existed
    for a long time now, so it likely has had many contributors over the
    years, making it that much more difficult to get all the relevant
    paperwork.

2 - Making sure CEDET does not affect Emacs globally: last time I tried
    CEDET (admittedly, several years ago), it had the nasty tendency to
    "take over Emacs", so I couldn't use it for Java without also having
    it messing with my Elisp buffers.

> - Provide some ECB like features in Emacs.

> ECB provides the typical IDE workspace view in Emacs, but achieves this
> by advising Emacs core functions a lot.

> In another thread on this list RMS identified the following core C level
> features to be implemented for this feature(slightly edited by me):

> ---------------
> Perhaps the cleanest way is to give each window a plist to specify
> whether various operations should consider it.  It could have a:
> - `delete-other-windows' property and a
> - `select-window' property and a
> - `display-buffer' property, and the values of these properties would
> control whether those operations can use this window.
> (this last one can be postponed, since "dedicted" does the same)

> The new `display-buffer' property could be equivalent to the existing
> "dedicated" flag.  That would mean it affects some other primitives
> aside from `display-buffer', but that is ok.  There is no need to be
> rigid about the relationship between these properties and primitives
> they affect.
> ---------------------

> I'm interested in working on initially implementing the first 2 flags in
> this list. The display-buffer property could be implemented later, since
> the current "window dedication" feature does the same.

It is probably a good idea to try out such an implementation.  I'm not
sure if it will work well, but it is worth a try.  I would like also to
see some description of the advice used by ECB, to better a better idea
of what kind of features are needed.  I tried to look at the code, but
it uses so many pieces of advice, that it's difficult for me to
get a feel for what they do overall.


        Stefan




^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: Improving Emacs for writing code
  2008-04-22 16:02 ` Stefan Monnier
@ 2008-04-22 16:54   ` klaus.berndl
  2008-04-22 17:07     ` Lennart Borgman (gmail)
  0 siblings, 1 reply; 24+ messages in thread
From: klaus.berndl @ 2008-04-22 16:54 UTC (permalink / raw)
  To: monnier, joakim; +Cc: emacs-devel

Stefan Monnier wrote:
>> Emacs does a lot of things uniquely well, but we can still learn from
>> other code writing environments how to improve the code writing
>> experience in Emacs.
> 
>> These are concrete proposals I'm prepared to invest time in:
> 
>> - Merge Cedet in Emacs.
> 
>> Cedet provides many facilities necessary to emulate other modern
>> IDE:s, for instance language parsers in lisp. I think Cedet is
>> nicely written, and that it wouldn't be a great problem to merge it
>> if a decision to do it was reached. I've contributed things to the
>> package and I'm prepared to help with any grunt work necessary for
>> the merge, for instance discussing issues from emacs-devel with the
>> packages principal authors. 
> 
> IDE-style features are sorely needed I think, so I am in favor of
> adding such things to Emacs.  I do not know enough about the current
> state of CEDET to know how easy it would be to integrate it. 
> Problems I envision are mostly:
> 
> 1 - Getting the copyright paperwork done: the CEDET project has
>     existed for a long time now, so it likely has had many
>     contributors over the years, making it that much more difficult
>     to get all the relevant paperwork.
> 
> 2 - Making sure CEDET does not affect Emacs globally: last time I
>     tried CEDET (admittedly, several years ago), it had the nasty
>     tendency to "take over Emacs", so I couldn't use it for Java
>     without also having it messing with my Elisp buffers.
> 
>> - Provide some ECB like features in Emacs.
> 
>> ECB provides the typical IDE workspace view in Emacs, but achieves
>> this by advising Emacs core functions a lot.
> 
>> In another thread on this list RMS identified the following core C
>> level features to be implemented for this feature(slightly edited by
>> me): 
> 
>> ---------------
>> Perhaps the cleanest way is to give each window a plist to specify
>> whether various operations should consider it.  It could have a:
>> - `delete-other-windows' property and a
>> - `select-window' property and a
>> - `display-buffer' property, and the values of these properties would
>> control whether those operations can use this window.
>> (this last one can be postponed, since "dedicted" does the same)
> 
>> The new `display-buffer' property could be equivalent to the existing
>> "dedicated" flag.  That would mean it affects some other primitives
>> aside from `display-buffer', but that is ok.  There is no need to be
>> rigid about the relationship between these properties and primitives
>> they affect. ---------------------
> 
>> I'm interested in working on initially implementing the first 2
>> flags in this list. The display-buffer property could be implemented
>> later, since the current "window dedication" feature does the same.
> 
> It is probably a good idea to try out such an implementation.  I'm not
> sure if it will work well, but it is worth a try.  I would like also
> to see some description of the advice used by ECB, to better a better
> idea of what kind of features are needed.  I tried to look at the
> code, but it uses so many pieces of advice, that it's difficult for
> me to 
> get a feel for what they do overall.

From the maintainer of ECB: I remember these discussions with RMS some time
ago - i agree 100% that it would be great if Emacs could offer some core-
functionality so a lot of the currently needed ECB-advices would become
obsolet... i can try to cluster the advices for you - but in the latest
beta i have restructured all the advice-stuff much more robustly - here is
the related NEWS-section:

** Much saver advice-backbone for all advices needed by ECB

   This is not a user-visible change but enhances the stability of ECB by
   using now a new advice-backbone which guarantes that all ecb-advices are
   enabled rsp. disabled correctly depending on the surrounding context.
   Introducing three new macros `defecb-advice-set', `defecb-advice' and
   `ecb-with-original-adviced-function-set'.

I have uploaded this 2.33beta1 version as a new CVS-snapshot to ecb.sf.net
(see Download-section)

All advice-sets of ECB are now defined with the macro defecb-advice-set...
For the layout engine the advice-set `ecb-basic-adviced-functions'
is the most important one - here is the value:

((set-window-configuration . after)
 (current-window-configuration . after)
 (balance-windows . around)
 (other-window-for-scrolling . around)
 (switch-to-buffer . around)
 (switch-to-buffer-other-window . around)
 (split-window . around)
 (split-window-vertically . around)
 (split-window-horizontally . around)
 (delete-other-windows . around)
 (delete-window . around)
 (delete-windows-on . around)
 (other-window . around)
 (display-buffer . around)
 (pop-to-buffer . around)
 (resize-temp-buffer-window . around)
 (shrink-window-if-larger-than-buffer . around)
 (shrink-window . around)
 (enlarge-window . around)
 (mouse-drag-mode-line . around)
 (mouse-drag-vertical-line . around)
 (scroll-other-window . around)
 (compilation-set-window-height . around)
 (delete-frame . around))

these are the functions ECB advices for its layout engine and some (lot?)
of these advices can probably be eliminated when Emacs offers the
+mentioned new c-core-functionality (as joakim has described above)
All of the advices are well documented!

But do not hesitate to ask me if you need further explanations or help!
I'm quite busy but i will do my best to support you in understanding
ECB for the sake of integrating it (or some of it's functionality) into
Emacs...

Klaus

> 
> 
>         Stefan




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Improving Emacs for writing code
  2008-04-22 16:54   ` klaus.berndl
@ 2008-04-22 17:07     ` Lennart Borgman (gmail)
  2008-04-23  8:26       ` klaus.berndl
  0 siblings, 1 reply; 24+ messages in thread
From: Lennart Borgman (gmail) @ 2008-04-22 17:07 UTC (permalink / raw)
  To: klaus.berndl; +Cc: monnier, joakim, emacs-devel

klaus.berndl@sdm.de wrote:
> I have uploaded this 2.33beta1 version as a new CVS-snapshot to ecb.sf.net
> (see Download-section)


Can you please give a more exact link? I can't find 2.33beta1




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Improving Emacs for writing code
  2008-04-22 10:06 Improving Emacs for writing code joakim
  2008-04-22 15:49 ` David Hansen
  2008-04-22 16:02 ` Stefan Monnier
@ 2008-04-22 20:08 ` Richard Stallman
  2 siblings, 0 replies; 24+ messages in thread
From: Richard Stallman @ 2008-04-22 20:08 UTC (permalink / raw)
  To: joakim; +Cc: emacs-devel

    - Merge Cedet in Emacs.

    Cedet provides many facilities necessary to emulate other modern IDE:s,
    for instance language parsers in lisp. I think Cedet is nicely written,
    and that it wouldn't be a great problem to merge it if a decision to do
    it was reached. I've contributed things to the package and I'm prepared
    to help with any grunt work necessary for the merge, for instance
    discussing issues from emacs-devel with the packages principal authors.

That is a good thing to do.  To start, how about seeing if we have
papers from all the contributors of nontrivial code in Cedet?




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re[2]: Improving Emacs for writing code
  2008-04-22 15:49 ` David Hansen
@ 2008-04-22 21:49   ` Eric M. Ludlam
  2008-04-23  1:33     ` Stefan Monnier
  0 siblings, 1 reply; 24+ messages in thread
From: Eric M. Ludlam @ 2008-04-22 21:49 UTC (permalink / raw)
  To: David Hansen; +Cc: emacs-devel

>>> David Hansen <david.hansen@gmx.net> seems to think that:
>The following message is a courtesy copy of an article
>that has been posted to gmane.emacs.devel as well.
>
>On Tue, 22 Apr 2008 12:06:58 +0200 joakim@verona.se wrote:
>
>> Emacs does a lot of things uniquely well, but we can still learn from
>> other code writing environments how to improve the code writing
>> experience in Emacs.
>>
>> These are concrete proposals I'm prepared to invest time in:
>>
>> - Merge Cedet in Emacs.
>
>I would really like to see this happen.  We do have some time till the
>next release and I think this would add quite some "super features" to
>emacs that will attract not only the old farts here.
>
>For sure a bigger user base will help the CEDET project to improve.  But
>lets hear what the CEDET author thinks (hope this works, how do I post
>to a newsgroup and send the same message via mail using gnus?).

Hi,

  I would be happy to see CEDET in Emacs.  It has always been a goal
of mine, but I also know my long-term vision for CEDET does not always
map onto what others want to see, and picking out only the tasty bits
of CEDET may be hard without using the entire thing.

Here is the good news:

* All paperwork needed for all the contributions should be in order
  for core CEDET.  Items for which there is no paper work is in a
  "contrib" directory to help me keep them separate.

* I do my hacking on CEDET in a mostly up-to-date version of Emacs
  from CVS, so it should work straight away.

* For the first time in a long long time, I'm happy with the current
  state of CEDET and how it works with code-completion.  For most folks,
  code completion is the only reason to use CEDET.  It feels ready.
  I've been going through my pre-release checklist lately to get a
  release of my own done.

Maintenance issues:

  I do not have a blanket release from my employer to provide changes
to Emacs whenever I want, and I cannot get one.  I can get a new
time-bound release whenever I want, but it's a pain.  An ideal
situation would be one where I can keep hacking CEDET at will, and
provide periodic updates back into Emacs core without having to go
through a merge phase.

  Speedbar is in Emacs in a way that requires merging between our CVS
trees.  The merges are difficult, which means I don't do them very
often, because I can't really contribute to speedbar in Emacs proper.

  I would like to continue to work on CEDET, but I don't want to deal
with the merge issues I've dealt with for speedbar.

  Also, I try to keep CEDET working w/ XEmacs.  This basically
involves accepting the occasional patch.

Emacs issues:

  There are a few sub-tools in CEDET that probably need care when
merging.  When I needed convenience functions in CEDET for a specific
tool, I usually focused on making them generically useful.  As such,
each such tool should probably be examined to see if that is a feature
Emacs wants.  One item that comes to mind is the mode-local variables
and functions that has been discussed here at least twice.

CEDET initialization:

  Right now, CEDET installs assuming you want to use it.  This may not
be the case in core Emacs.  Making the features accessible has been a
struggle.  Stefan touched on one such issue in his post.  I have no
good answers.


Thats it.  The biggest concern I have is the maintenance issue I
discussed above.  If there is a good way to handle the two
repositories, or provide a way for me to check stuff into a GNU
repository when I'm not actively covered by an employer release, I'd
like to know about it.

Thanks
Eric

-- 
          Eric Ludlam:                       eric@siege-engine.com
   Siege: www.siege-engine.com          Emacs: http://cedet.sourceforge.net




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Improving Emacs for writing code
  2008-04-22 21:49   ` Re[2]: " Eric M. Ludlam
@ 2008-04-23  1:33     ` Stefan Monnier
  2008-04-23  5:10       ` Chong Yidong
  2008-04-23 15:00       ` Re[2]: " Eric M. Ludlam
  0 siblings, 2 replies; 24+ messages in thread
From: Stefan Monnier @ 2008-04-23  1:33 UTC (permalink / raw)
  To: Eric M. Ludlam; +Cc: David Hansen, emacs-devel

>   I would be happy to see CEDET in Emacs.  It has always been a goal
> of mine, but I also know my long-term vision for CEDET does not always
> map onto what others want to see, and picking out only the tasty bits
> of CEDET may be hard without using the entire thing.

> Here is the good news:

> * All paperwork needed for all the contributions should be in order
>   for core CEDET.  Items for which there is no paper work is in a
>   "contrib" directory to help me keep them separate.

Excellent.

> * I do my hacking on CEDET in a mostly up-to-date version of Emacs
>   from CVS, so it should work straight away.

> * For the first time in a long long time, I'm happy with the current
>   state of CEDET and how it works with code-completion.  For most folks,
>   code completion is the only reason to use CEDET.  It feels ready.
>   I've been going through my pre-release checklist lately to get a
>   release of my own done.

Good to hear.

> Maintenance issues:

>   I do not have a blanket release from my employer to provide changes
> to Emacs whenever I want, and I cannot get one.  I can get a new
> time-bound release whenever I want, but it's a pain.  An ideal
> situation would be one where I can keep hacking CEDET at will, and
> provide periodic updates back into Emacs core without having to go
> through a merge phase.

>   Speedbar is in Emacs in a way that requires merging between our CVS
> trees.  The merges are difficult, which means I don't do them very
> often, because I can't really contribute to speedbar in Emacs proper.

Yes, it's been problematic.

I do think this problem can be significantly reduced on your side by
simply regularly merging from the Emacs-CVS tree, so the Emacs-CVS tree
may not always be up-to-date with yours, but yours is, so whenever we
need to sync the two, the merge has already been done.

If you use some of the non-CVS mirrors of Emacs (Arch, Bzr, Hg, Git),
the merges can be tracked by the tool, so you can do them "daily" with
no hassle (note that those mirrors are only readable, but that's OK for
your use).

>   There are a few sub-tools in CEDET that probably need care when
> merging.  When I needed convenience functions in CEDET for a specific
> tool, I usually focused on making them generically useful.  As such,
> each such tool should probably be examined to see if that is a feature
> Emacs wants.  One item that comes to mind is the mode-local variables
> and functions that has been discussed here at least twice.

Do these use advices or similar redefinitions?  If not, it shouldn't be
a problem.

>   Right now, CEDET installs assuming you want to use it.  This may not
> be the case in core Emacs.  Making the features accessible has been a
> struggle.  Stefan touched on one such issue in his post.  I have no
> good answers.

The first step is to make sure that when installing CEDET in Emacs we
get 2 things:
1 - CEDET is easy to enable.
2 - CEDET doesn't affect anyone who doesn't enable it.
That is a strict necessity before we can install it.  The second step is:
- Make it possible to disable CEDET after enabling it.
- Make it possible to enable CEDET in some buffers without it affecting
  all others.
These are very important as well, tho it might be OK to live without
them at first, as long as there's a clear commitment to address them.

> repositories, or provide a way for me to check stuff into a GNU
> repository when I'm not actively covered by an employer release, I'd
> like to know about it.

As long as your own repository has clear information about its
relationship with the Emacs-CVS code (I don't mean info for humans, but
for tools, in terms of history and ancestry), then I think it's livable.


        Stefan




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Improving Emacs for writing code
  2008-04-23  1:33     ` Stefan Monnier
@ 2008-04-23  5:10       ` Chong Yidong
  2008-04-23 14:05         ` Re[2]: " Eric M. Ludlam
  2008-04-23 15:00       ` Re[2]: " Eric M. Ludlam
  1 sibling, 1 reply; 24+ messages in thread
From: Chong Yidong @ 2008-04-23  5:10 UTC (permalink / raw)
  To: Eric M. Ludlam; +Cc: David Hansen, Stefan Monnier, emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>>   I would be happy to see CEDET in Emacs.  It has always been a goal
>> of mine, but I also know my long-term vision for CEDET does not always
>> map onto what others want to see, and picking out only the tasty bits
>> of CEDET may be hard without using the entire thing.
>
>>   Speedbar is in Emacs in a way that requires merging between our CVS
>> trees.  The merges are difficult, which means I don't do them very
>> often, because I can't really contribute to speedbar in Emacs proper.
>
> Yes, it's been problematic.
>
> I do think this problem can be significantly reduced on your side by
> simply regularly merging from the Emacs-CVS tree, so the Emacs-CVS tree
> may not always be up-to-date with yours, but yours is, so whenever we
> need to sync the two, the merge has already been done.

If this is agreeable, what's the next step?  Is CEDET in a state where
we can dump it into the Emacs CVS tree, then work out whatever details
need to be worked out?  That would be the fastest way to get things
started up and running.

Also, I'm not too clear about your explanation about the legal problem
you mentioned.  If CEDET is added to Emacs, would your existing
copyright assignment already cover it, or is there some other paperwork
we need to work out?




^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: Improving Emacs for writing code
  2008-04-22 17:07     ` Lennart Borgman (gmail)
@ 2008-04-23  8:26       ` klaus.berndl
  2008-04-23 10:26         ` Nick Roberts
  0 siblings, 1 reply; 24+ messages in thread
From: klaus.berndl @ 2008-04-23  8:26 UTC (permalink / raw)
  To: lennart.borgman; +Cc: monnier, joakim, emacs-devel

Here it is: http://ecb.sourceforge.net/cvs_snapshots/ecb.tar.gz

This is 2.33beta1

Lennart Borgman (gmail) wrote:
> klaus.berndl@sdm.de wrote:
>> I have uploaded this 2.33beta1 version as a new CVS-snapshot to
>> ecb.sf.net (see Download-section)
> 
> 
> Can you please give a more exact link? I can't find 2.33beta1




^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: Improving Emacs for writing code
  2008-04-23  8:26       ` klaus.berndl
@ 2008-04-23 10:26         ` Nick Roberts
  2008-04-23 11:59           ` klaus.berndl
  2008-04-23 12:12           ` Neal Becker
  0 siblings, 2 replies; 24+ messages in thread
From: Nick Roberts @ 2008-04-23 10:26 UTC (permalink / raw)
  To: klaus.berndl; +Cc: lennart.borgman, monnier, joakim, emacs-devel

 > Here it is: http://ecb.sourceforge.net/cvs_snapshots/ecb.tar.gz

I realise that I should check for myself, but to save me time, does it use
tree-widget.el for displaying tree structures or does it have it's own
lisp functions?

The reason I ask is that I currently use the speedbar to display watch
expressions as a tree-like structure in a Gdb session in Emacs (gdb-ui.el) and
it's not really suitable.  I want to use more than window and the use of a
timer in the speedbar makes updating awkward at times.

Also if other things like CEDET are going to be merged into Emacs and they use
the speedbar, I may have to undo any damage that I have done to it getting
it to work for watch expressions, so an alternative mechanism would be useful.

I'm not very familiar with ECB but perhaps it could work with gdb-ui.el in a
manner similar to Eclipse: ECB being one 'perspective', gdb-ui another,

-- 
Nick                                           http://www.inet.net.nz/~nickrob




^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: Improving Emacs for writing code
  2008-04-23 10:26         ` Nick Roberts
@ 2008-04-23 11:59           ` klaus.berndl
  2008-04-23 13:00             ` Nick Roberts
  2008-04-23 12:12           ` Neal Becker
  1 sibling, 1 reply; 24+ messages in thread
From: klaus.berndl @ 2008-04-23 11:59 UTC (permalink / raw)
  To: nickrob; +Cc: lennart.borgman, monnier, joakim, emacs-devel

Nick Roberts wrote:
>  > Here it is: http://ecb.sourceforge.net/cvs_snapshots/ecb.tar.gz
> 
> I realise that I should check for myself, but to save me time, does
> it use tree-widget.el for displaying tree structures or does it have
> it's own 
> lisp functions?

no, it has it's own tree-library tree-buffer.el which offers as well
as tree-widget.el powerful ascii- and graphical tree-displays...
But i have to admit, the main reason why ECB uses its own tree-library
is cause of historical reasons, i.e. ECB exists long before tree-widget.el
comes up... and it's too much effort to rewrite ECB with tree-widget.el
and IMHO it's not worth the effort...

> 
> The reason I ask is that I currently use the speedbar to display watch
> expressions as a tree-like structure in a Gdb session in Emacs
> (gdb-ui.el) and it's not really suitable.  I want to use more than
> window and the use of a timer in the speedbar makes updating awkward
> at times. 
> 
> Also if other things like CEDET are going to be merged into Emacs and
> they use the speedbar, I may have to undo any damage that I have done
> to it getting 
> it to work for watch expressions, so an alternative mechanism would
> be useful. 
> 
> I'm not very familiar with ECB but perhaps it could work with
> gdb-ui.el in a manner similar to Eclipse: ECB being one
> 'perspective', gdb-ui another, 

Yes, this would be possible - ECB more or less is just a 'displayor' or
layout-engine which can display any stuff like parsing-informations from
CEDET or also debugging stuff from gdb... but i do not know gdb-ui.el to
give an exact answer... but to give another example: ECB works very well with
screen/window-managers like escreen.el or winring.el... maybe this helps
you a little bit to better judge the interaction between ECB and gdb-ui.el...

Klaus




^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: Improving Emacs for writing code
  2008-04-23 10:26         ` Nick Roberts
  2008-04-23 11:59           ` klaus.berndl
@ 2008-04-23 12:12           ` Neal Becker
  2008-04-23 12:19             ` klaus.berndl
  1 sibling, 1 reply; 24+ messages in thread
From: Neal Becker @ 2008-04-23 12:12 UTC (permalink / raw)
  To: emacs-devel

This is exciting.  Is there something ready to test, (with emacs recent
cvs)?





^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: Improving Emacs for writing code
  2008-04-23 12:12           ` Neal Becker
@ 2008-04-23 12:19             ` klaus.berndl
  2008-04-23 12:28               ` Neal Becker
  0 siblings, 1 reply; 24+ messages in thread
From: klaus.berndl @ 2008-04-23 12:19 UTC (permalink / raw)
  To: ndbecker2, emacs-devel

what is exiting and what should be ready to test?

Neal Becker wrote:
> This is exciting.  Is there something ready to test, (with emacs
> recent cvs)?




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Improving Emacs for writing code
  2008-04-23 12:19             ` klaus.berndl
@ 2008-04-23 12:28               ` Neal Becker
  2008-04-23 21:34                 ` Stephen J. Turnbull
  0 siblings, 1 reply; 24+ messages in thread
From: Neal Becker @ 2008-04-23 12:28 UTC (permalink / raw)
  To: klaus.berndl; +Cc: emacs-devel

On Wednesday 23 April 2008, klaus.berndl@sdm.de wrote:
> what is exiting and what should be ready to test?
>
> Neal Becker wrote:
> > This is exciting.  Is there something ready to test, (with emacs
> > recent cvs)?


I haven't looked into any details, but the discussion of a more advanced IDE 
using emacs is exciting.  




^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: Improving Emacs for writing code
  2008-04-23 11:59           ` klaus.berndl
@ 2008-04-23 13:00             ` Nick Roberts
  0 siblings, 0 replies; 24+ messages in thread
From: Nick Roberts @ 2008-04-23 13:00 UTC (permalink / raw)
  To: klaus.berndl; +Cc: lennart.borgman, monnier, joakim, emacs-devel

 > no, it has it's own tree-library tree-buffer.el which offers as well
 > as tree-widget.el powerful ascii- and graphical tree-displays...

If ECB gets imported into Emacs, then I'll use tree-buffer.el.


 >...
 > > I'm not very familiar with ECB but perhaps it could work with
 > > gdb-ui.el in a manner similar to Eclipse: ECB being one
 > > 'perspective', gdb-ui another, 
 > 
 > Yes, this would be possible - ECB more or less is just a 'displayor' or
 > layout-engine which can display any stuff like parsing-informations from
 > CEDET or also debugging stuff from gdb... but i do not know gdb-ui.el to
 > give an exact answer... but to give another example: ECB works very well with
 > screen/window-managers like escreen.el or winring.el... maybe this helps
 > you a little bit to better judge the interaction between ECB and gdb-ui.el...

gdb-ui.el uses dedicated windows and I have heard that ECB does too, which
I think is why there have been reports of conflicts, e.g,

http://groups.google.co.nz/group/comp.emacs/browse_thread/thread/b824e4052d7df237/add8b897ae4b7ab3?hl=en&lnk=st&q=gdb+ecb#add8b897ae4b7ab3

One way to avoid conflicts presumably would be stop them sharing the same
frame, as with perspectives.

-- 
Nick                                           http://www.inet.net.nz/~nickrob




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re[2]: Improving Emacs for writing code
  2008-04-23  5:10       ` Chong Yidong
@ 2008-04-23 14:05         ` Eric M. Ludlam
  2008-04-23 14:23           ` Chong Yidong
  2008-04-23 17:29           ` Stefan Monnier
  0 siblings, 2 replies; 24+ messages in thread
From: Eric M. Ludlam @ 2008-04-23 14:05 UTC (permalink / raw)
  To: Chong Yidong; +Cc: david.hansen, monnier, emacs-devel

>>> Chong Yidong <cyd@stupidchicken.com> seems to think that:
>Stefan Monnier <monnier@iro.umontreal.ca> writes:
>
>>>   I would be happy to see CEDET in Emacs.  It has always been a goal
>>> of mine, but I also know my long-term vision for CEDET does not always
>>> map onto what others want to see, and picking out only the tasty bits
>>> of CEDET may be hard without using the entire thing.
>>
>>>   Speedbar is in Emacs in a way that requires merging between our CVS
>>> trees.  The merges are difficult, which means I don't do them very
>>> often, because I can't really contribute to speedbar in Emacs proper.
>>
>> Yes, it's been problematic.
>>
>> I do think this problem can be significantly reduced on your side by
>> simply regularly merging from the Emacs-CVS tree, so the Emacs-CVS tree
>> may not always be up-to-date with yours, but yours is, so whenever we
>> need to sync the two, the merge has already been done.
>
>If this is agreeable, what's the next step?  Is CEDET in a state where
>we can dump it into the Emacs CVS tree, then work out whatever details
>need to be worked out?  That would be the fastest way to get things
>started up and running.
>
>Also, I'm not too clear about your explanation about the legal problem
>you mentioned.  If CEDET is added to Emacs, would your existing
>copyright assignment already cover it, or is there some other paperwork
>we need to work out?

Hi,

  All the core bits of CEDET from other authors should have up-to-date
papers for them, or are trivial.  All bits written by me need an
updated Employer disclaimer.

  If I get updated papers now, then any bug-fixing I do during the
merge will need yet more papers later, or I'll have to not
participate.  (I'm still cleaning up little things trying to put my
own release out.)

  The question isn't really "can" I get up to date papers, but how to
do a merge like this without getting lots and lots of papers.  I was
going to ask if I could get the typical time-bound release today, but
with a date a few months into the future, but the person I need to
talk to is on vacation this week.

  If it is possible to do a merge where the active truth is in the
CEDET sourceforge repository, that would likely make things much
easier for me in the short term.  When everyone feels it's "ready",
then I'll update my disclaimer, and it could be moved to it's new
home.

  Unfortunately, merging the build harness will not be easy, or really
possible in CEDET CVS tree since a goal for me will be at least one
more CEDET release for older Emacsen.

  Then there is the ongoing maintenance.  I'm not sure how Stefan's
suggestion would work for me.  I can imagine it being ok for a while
when all the changes are small.  I believe in periodic refactoring
which would make this more challenging.  If some smallish utility
outgrows its original purpose, I'll start moving and renaming large
chunks of code so things are more clear.  This would make
cross-merging difficult soon afterward.

  Also, unless it is fully automated, a daily or even weekly merge is
not reasonable for me.  My ability to work on Emacs related things is
sparse, and seasonal.  I typically go several months every fall and
other random times where I have trouble just keeping up with email.
See http://www.siege-engine.com for more on why that may be.

  There are also issues with the build harness, and how someone would
use the most recent "Eric" version against the most recent "Emacs"
version.

  I would very much like to find a way to have a single VC truth where
I can hack freely without impinging the rest of Emacs.  I can imagine
two ways to do this:

1) Truth is in the Emacs, and I find some way to participate there, or
   there is a branch where I can work.

2) Truth is in SourceForge, and changes by Emacs developers are
   checked into SourceForge.  I'd then need to find a way to get
   releases that allow a periodic mass-copy into the Emacs tree.

  Naturally, I like #2 the best, and you all will like #1 the best.

  Another option would be that I "eject" big parts out of CEDET.  I've
been thinking of ejecting speedbar for a while, as I really haven't
needed to change anything in there directly in a long time.  This has
a lot to do with ECB doing such a good job.  This could shrink the
overall size of CEDET to the areas with high-churn, and make merging
tasks smaller.

  This could all be a moot issue if someone wanted to volunteer as a
CEDET merge master keeping the repositories and build systems up to
date beyond the first merge stage.

  I apologize for making what should be a simple thing difficult.

  Eric

-- 
          Eric Ludlam:                       eric@siege-engine.com
   Siege: www.siege-engine.com          Emacs: http://cedet.sourceforge.net




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Improving Emacs for writing code
  2008-04-23 14:05         ` Re[2]: " Eric M. Ludlam
@ 2008-04-23 14:23           ` Chong Yidong
  2008-04-23 17:29           ` Stefan Monnier
  1 sibling, 0 replies; 24+ messages in thread
From: Chong Yidong @ 2008-04-23 14:23 UTC (permalink / raw)
  To: Eric M. Ludlam; +Cc: david.hansen, monnier, emacs-devel

"Eric M. Ludlam" <eric@siege-engine.com> writes:

>   Unfortunately, merging the build harness will not be easy, or really
> possible in CEDET CVS tree since a goal for me will be at least one
> more CEDET release for older Emacsen.

There are lots of packages in Emacs that contain compatibility code for
older Emacsen and/or XEmacs: CC mode, Gnus, etc.  AFAICT, the existence
of such code is not a problem for merging.

Adding CEDET to Emacs might involve several changes up-front to make
CEDET mesh better with existing Emacs features (this code can be
enclosed, where necessary, in compatiblity wrappers, so it can exist in
both trees).  Thereafter, any changes coming from our end are likely to
be smallish bug-fixes which should be easily merged into your tree.  Big
changes coming from your end can be periodically copied, as a whole,
into our tree (e.g., every major Emacs release).  I believe this is
similar to the way Alan works on CC mode, for example.

> 1) Truth is in the Emacs, and I find some way to participate there, or
>    there is a branch where I can work.
>
> 2) Truth is in SourceForge, and changes by Emacs developers are
>    checked into SourceForge.  I'd then need to find a way to get
>    releases that allow a periodic mass-copy into the Emacs tree.

We could easily set up a CEDET branch of Emacs for you to work on, if
you feel that's convenient.  But once we're done making the
aforementioned initial changes to mesh CEDET with Emacs features,
periodic mass-copying shouldn't be difficult.




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re[2]: Improving Emacs for writing code
  2008-04-23  1:33     ` Stefan Monnier
  2008-04-23  5:10       ` Chong Yidong
@ 2008-04-23 15:00       ` Eric M. Ludlam
  2008-04-23 17:45         ` Stefan Monnier
  2008-04-23 19:05         ` Richard M Stallman
  1 sibling, 2 replies; 24+ messages in thread
From: Eric M. Ludlam @ 2008-04-23 15:00 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: david.hansen, emacs-devel

>>> Stefan Monnier <monnier@iro.umontreal.ca> seems to think that:
  [ ... ]
>>   There are a few sub-tools in CEDET that probably need care when
>> merging.  When I needed convenience functions in CEDET for a specific
>> tool, I usually focused on making them generically useful.  As such,
>> each such tool should probably be examined to see if that is a feature
>> Emacs wants.  One item that comes to mind is the mode-local variables
>> and functions that has been discussed here at least twice.
>
>Do these use advices or similar redefinitions?  If not, it shouldn't be
>a problem.

There is advice in CEDET, though not much.  Most advice deals with
`describe-function' and similar help routines that are not inherently
extensible.  Other advice is tied to some minor-mode or other.

>>   Right now, CEDET installs assuming you want to use it.  This may not
>> be the case in core Emacs.  Making the features accessible has been a
>> struggle.  Stefan touched on one such issue in his post.  I have no
>> good answers.
>
>The first step is to make sure that when installing CEDET in Emacs we
>get 2 things:
>1 - CEDET is easy to enable.
>2 - CEDET doesn't affect anyone who doesn't enable it.
>That is a strict necessity before we can install it.  The second step is:
>- Make it possible to disable CEDET after enabling it.
>- Make it possible to enable CEDET in some buffers without it affecting
>  all others.
>These are very important as well, tho it might be OK to live without
>them at first, as long as there's a clear commitment to address them.

Everything in CEDET that changes or augments a behavior is activated
by hooks, or something in a user's .emacs file.  The CEDET build
system automatically adds (add-hook ...) type items into the loaddefs
file which is what you had encountered.  The goal of the CEDET install
is to minimize the amount of hacking around users have to do to get
the system up and running.

The semantic parser and tools work like this:

* A mode hook sets up variables about how to do parsing.

* A change-mode hook (and a couple other hooks) enables "semantic" on
  any buffer with the right variables set up.

* Any tool that requires semantic can automatically enable itself via
  the semantic init hook


The default right now is that all mode hooks are enabled by default.
The Semantic setup from the mode-hook itself won't change any
behavior.  It is the tools that enable themselves via the semantic
init hook that change behavior, and those tools are turned on via a
`global-whatever-mode' type function which must be put into a .emacs
file.

If you want some tools on in C mode but not in Emacs Lisp, you would
not use `global-whatever-mode', but instead create a semantic init
hook that turns some minor-mode on with `whatever-mode' conditionally.
You might be able to enable some modes in a mode-hook, but I haven't
tried it.  Some may depend on semantic initialization completing
first.

As such, what you are requesting is possible, and follows typical
conventions, but just requires more INSTALL explanation.  I am
hesitant to add such discussion because the current install
instruction is short and simple, and discussing all those options
would make it much less so.  I've batched many modes together into
"turn on lots of related things" functions which means all sub modes
would need explaining for basic install.

I'm open to any changes in this area to make this easier, as long as
there continues to be a simple "just make it go" feature.

Eric

-- 
          Eric Ludlam:                       eric@siege-engine.com
   Siege: www.siege-engine.com          Emacs: http://cedet.sourceforge.net




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Improving Emacs for writing code
  2008-04-23 14:05         ` Re[2]: " Eric M. Ludlam
  2008-04-23 14:23           ` Chong Yidong
@ 2008-04-23 17:29           ` Stefan Monnier
  1 sibling, 0 replies; 24+ messages in thread
From: Stefan Monnier @ 2008-04-23 17:29 UTC (permalink / raw)
  To: Eric M. Ludlam; +Cc: Chong Yidong, david.hansen, emacs-devel

>   If it is possible to do a merge where the active truth is in the
> CEDET sourceforge repository, that would likely make things much
> easier for me in the short term.  When everyone feels it's "ready",
> then I'll update my disclaimer, and it could be moved to it's new
> home.

I suggest the following:
1 - make a local branch of Emacs using Bzr or Git.
3 - install CEDET inside it.
2 - publish it.

With those tools, merging changes from Emacs's trunk is about as hard as:

     % bzr merge --show-base
     ...resolve conflicts...
     % bzr commit -m 'Merge from trunk'

People can then try out "Emacs+CEDET" from your tree and send you
patches to install.  Once it looks good enough, you can get the
paperwork and we then install it into Emacs's CVS.

>   Unfortunately, merging the build harness will not be easy, or really
> possible in CEDET CVS tree since a goal for me will be at least one
> more CEDET release for older Emacsen.

As Chong explained, compatibility code is fine.  But you may be
referring to the tricker part of all the install&build scripts, which
will indeed be quite different.  You could install those scripts into
an emacs/admin/cedet directory (the `admin' subdir is not included in
the Emacs tarballs).

>   Then there is the ongoing maintenance.  I'm not sure how Stefan's
> suggestion would work for me.  I can imagine it being ok for a while
> when all the changes are small.  I believe in periodic refactoring
> which would make this more challenging.  If some smallish utility
> outgrows its original purpose, I'll start moving and renaming large
> chunks of code so things are more clear.  This would make
> cross-merging difficult soon afterward.

When cross-merging gets difficult, it's time to sync again: get the
new paperwork and update the Emacs-CVS.

>   There are also issues with the build harness, and how someone would
> use the most recent "Eric" version against the most recent "Emacs"
> version.

Just make sure you split your files into 3 disjoint sets:
1 - files used for all versions.
2 - files used only for the version bundled with Emacs.
2 - files used only for the unbundled version.

>   I would very much like to find a way to have a single VC truth where
> I can hack freely without impinging the rest of Emacs.  I can imagine
> two ways to do this:

> 1) Truth is in the Emacs, and I find some way to participate there, or
>    there is a branch where I can work.

As long as you can't get time-unbound paperwork, I'm afraid you won't be
able to work directly on the main Emacs branch.

But with distributed revision control you can have your own branch
of Emacs with 100% complete control over it, but with all the
merge&change tracking done as if it were within the same repository.

> 2) Truth is in SourceForge, and changes by Emacs developers are
>    checked into SourceForge.

Some developers may be willing to do that, but some changes will be done
on the Emacs trunk.  So you'll need to merge changes from Emacs's trunk
every once in a while.  IIUC Sourceforge only provides CVS and SVN
services, and merging between repositories using those VCS is rather
painful, so I recommend you use something else.

>    I'd then need to find a way to get
>    releases that allow a periodic mass-copy into the Emacs tree.

That's a given, no matter what setup we end up using.


        Stefan




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Improving Emacs for writing code
  2008-04-23 15:00       ` Re[2]: " Eric M. Ludlam
@ 2008-04-23 17:45         ` Stefan Monnier
  2008-04-24  2:41           ` Re[2]: " Eric M. Ludlam
  2008-04-23 19:05         ` Richard M Stallman
  1 sibling, 1 reply; 24+ messages in thread
From: Stefan Monnier @ 2008-04-23 17:45 UTC (permalink / raw)
  To: Eric M. Ludlam; +Cc: david.hansen, emacs-devel

>> The first step is to make sure that when installing CEDET in Emacs we
>> get 2 things:
>> 1 - CEDET is easy to enable.
>> 2 - CEDET doesn't affect anyone who doesn't enable it.
>> That is a strict necessity before we can install it.  The second step is:
>> - Make it possible to disable CEDET after enabling it.
>> - Make it possible to enable CEDET in some buffers without it affecting
>> all others.
>> These are very important as well, tho it might be OK to live without
>> them at first, as long as there's a clear commitment to address them.

> Everything in CEDET that changes or augments a behavior is activated
> by hooks, or something in a user's .emacs file.  The CEDET build
> system automatically adds (add-hook ...) type items into the loaddefs
> file which is what you had encountered.  The goal of the CEDET install
> is to minimize the amount of hacking around users have to do to get
> the system up and running.

> The semantic parser and tools work like this:

> * A mode hook sets up variables about how to do parsing.

IIUC this is code similar to what sets up font-lock-defaults or
imenu-generic-expression, right?  I.e. it is conceptually part of the
major mode rather than of CEDET.

> * A change-mode hook (and a couple other hooks) enables "semantic" on
>   any buffer with the right variables set up.

I.e. this is like

  (define-globalized-minor-mode global-semantic-mode semantic-mode
     (lambda () (if vars are set up (semantic-mode 1))))

?

> * Any tool that requires semantic can automatically enable itself via
>   the semantic init hook

I do not understand this: do you mean that a tool can call
(semantic-mode 1), or that a tool can register itself so that whenever
semantic-mode is ON, then that tool is activated as well?
I'll assume you mean the latter.

> As such, what you are requesting is possible, and follows typical
> conventions, but just requires more INSTALL explanation.  I am
> hesitant to add such discussion because the current install
> instruction is short and simple, and discussing all those options
> would make it much less so.  I've batched many modes together into
> "turn on lots of related things" functions which means all sub modes
> would need explaining for basic install.

So IIUC semantic-mode does not in itself affect the behavior, but
because of how features on top of Semantic register themselves in
semantic-init-hook, the mere fact of activating semantic-mode ends up
activating a lot more.

I guess that's fine for now.  All we really need is a way to only enable
semantic (and accompagnying features) in some modes.  E.g. the user can do

  (global-semantic-mode 1)

to get CEDET everywhere, or just:

  (add-hook 'java-mode-hook (lambda () (semantic-mode 1)))

to only get it in in Java mode.  Would that be difficult?  It seems like
you're saying it wouldn't.

> I'm open to any changes in this area to make this easier, as long as
> there continues to be a simple "just make it go" feature.

Sounds good to me,


        Stefan




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Improving Emacs for writing code
  2008-04-23 15:00       ` Re[2]: " Eric M. Ludlam
  2008-04-23 17:45         ` Stefan Monnier
@ 2008-04-23 19:05         ` Richard M Stallman
  1 sibling, 0 replies; 24+ messages in thread
From: Richard M Stallman @ 2008-04-23 19:05 UTC (permalink / raw)
  To: Eric M. Ludlam; +Cc: david.hansen, monnier, emacs-devel

    There is advice in CEDET, though not much.  Most advice deals with
    `describe-function' and similar help routines that are not inherently
    extensible.  Other advice is tied to some minor-mode or other.

Can someone please rewrite these as changes to the functions
in question, or to use hooks (either existing or new)?




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Improving Emacs for writing code
  2008-04-23 12:28               ` Neal Becker
@ 2008-04-23 21:34                 ` Stephen J. Turnbull
  0 siblings, 0 replies; 24+ messages in thread
From: Stephen J. Turnbull @ 2008-04-23 21:34 UTC (permalink / raw)
  To: Neal Becker; +Cc: emacs-devel, klaus.berndl

Neal Becker writes:
 > On Wednesday 23 April 2008, klaus.berndl@sdm.de wrote:
 > > what is exiting and what should be ready to test?
 > >
 > > Neal Becker wrote:
 > > > This is exciting.  Is there something ready to test, (with emacs
 > > > recent cvs)?

Just download tarballs and untar into site-lisp for Emacs, any version
from this millennium, I would suppose.  Maybe you need to set up a
couple autoloads in .emacs.

 > I haven't looked into any details, but the discussion of a more
 > advanced IDE using emacs is exciting.

??  This stuff is not new.  JDE and ECB are available in the default
XEmacs+SUMO installation, and has been for several years.  CEDET is
now available as an XEmacs package, too, although that's recent enough
that maybe it's not in Linux distro PMSes yet.  But this is tested
and released technology, eg, JDE now depends on CEDET, Semantic, and
EIEIO.





^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re[2]: Improving Emacs for writing code
  2008-04-23 17:45         ` Stefan Monnier
@ 2008-04-24  2:41           ` Eric M. Ludlam
  0 siblings, 0 replies; 24+ messages in thread
From: Eric M. Ludlam @ 2008-04-24  2:41 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: david.hansen, emacs-devel

>>> Stefan Monnier <monnier@iro.umontreal.ca> seems to think that:
>>> The first step is to make sure that when installing CEDET in Emacs we
>>> get 2 things:
>>> 1 - CEDET is easy to enable.
>>> 2 - CEDET doesn't affect anyone who doesn't enable it.
>>> That is a strict necessity before we can install it.  The second step is:
>>> - Make it possible to disable CEDET after enabling it.
>>> - Make it possible to enable CEDET in some buffers without it affecting
>>> all others.
>>> These are very important as well, tho it might be OK to live without
>>> them at first, as long as there's a clear commitment to address them.
>
>> Everything in CEDET that changes or augments a behavior is activated
>> by hooks, or something in a user's .emacs file.  The CEDET build
>> system automatically adds (add-hook ...) type items into the loaddefs
>> file which is what you had encountered.  The goal of the CEDET install
>> is to minimize the amount of hacking around users have to do to get
>> the system up and running.
>
>> The semantic parser and tools work like this:
>
>> * A mode hook sets up variables about how to do parsing.
>
>IIUC this is code similar to what sets up font-lock-defaults or
>imenu-generic-expression, right?  I.e. it is conceptually part of the
>major mode rather than of CEDET.

Yes.  Here is a typical function for C.

-------

;;;###autoload
(defun semantic-default-c-setup ()
  "Set up a buffer for semantic parsing of the C language."
  (semantic-c-by--install-parser)
  (setq semantic-lex-syntax-modifications '((?> ".")
                                            (?< ".")
                                            )
        )
  
  (setq semantic-lex-analyzer #'semantic-c-lexer)
  (add-hook 'semantic-lex-reset-hooks 'semantic-lex-spp-reset-hook nil t)
  )

------

where semantic-c-by--install-parser is a generated function that does
a setq.  As such, no Emacs behavior is modified.

>> * A change-mode hook (and a couple other hooks) enables "semantic" on
>>   any buffer with the right variables set up.
>
>I.e. this is like
>
>  (define-globalized-minor-mode global-semantic-mode semantic-mode
>     (lambda () (if vars are set up (semantic-mode 1))))
  [ ... ]

Not really.  There is no "semantic-mode".  I looked up the actual code
which I wrote many years ago.  It is this:

-------

(defun semantic-new-buffer-fcn ()
  "Setup the current buffer to use Semantic.
If the major mode is ready for Semantic, and no
`semantic-inhibit-functions' disabled it, the current buffer is setup
to use Semantic, and `semantic-init-hook' is run."
  ;; Do stuff if semantic was activated by a mode hook in this buffer,
  ;; and not afterwards disabled.
  (when (and semantic--parse-table
             (not (semantic-active-p))
             (not (run-hook-with-args-until-success
                   'semantic-inhibit-functions)))
    ;; Specify that this function has done it's work.  At this point
    ;; we can consider that semantic is active in this buffer.
    (setq semantic-new-buffer-fcn-was-run t)
    ;; Here are some buffer local variables we can initialize ourselves
    ;; of a mode does not choose to do so.
    (semantic-lex-init)
    ;; Force this buffer to have its cache refreshed.
    (semantic-clear-toplevel-cache)
    ;; Call DB hooks before regular init hooks
    (run-hooks 'semantic-init-db-hooks)
    ;; Lastly, set up semantic modes
    (run-hooks 'semantic-init-hooks)
    ))

(add-hook 'mode-local-init-hook 'semantic-new-buffer-fcn)

--------

As you can see it's mostly a "get a bunch of variables set up"
function to simplify a mode-author's support requirements.  It also
(more critically) calls the db-hooks, and init-hooks for semantic.
The key input is that `semantic--parse-table' has a value.  I also
just noticed `semantic-inhibit-functions' which would allow you to
selectively disable a particular mode.  I seem to learn something new
about Emacs every day.

Also, the `mode-local-init-hook' is a spiffy feature of `mode-local'
which runs after a new major mode is enabled.  I'll append the whole
thing at the end of this message.  David Ponce wrote most of it based
on some core routines I wrote for a similar feature for semantic.

>> * Any tool that requires semantic can automatically enable itself via
>>   the semantic init hook
>
>I do not understand this: do you mean that a tool can call
>(semantic-mode 1), or that a tool can register itself so that whenever
>semantic-mode is ON, then that tool is activated as well?
>I'll assume you mean the latter.

Semantic has its own global mode setup.  Its function for doing a
setup looks like this.

-------

(defun semantic-toggle-minor-mode-globally (mode &optional arg)
  "Toggle minor mode MODE in every Semantic enabled buffer.
Return non-nil if MODE is turned on in every Semantic enabled buffer.
If ARG is positive, enable, if it is negative, disable.  If ARG is
nil, then toggle.  Otherwise do nothing.  MODE must be a valid minor
mode defined in `minor-mode-alist' and must be too an interactive
function used to toggle the mode."
  (or (and (fboundp mode) (assq mode minor-mode-alist))
      (error "Semantic minor mode %s not found" mode))
  (if (not arg)
      (if (memq mode semantic-init-hooks)
	  (setq arg -1)
	(setq arg 1)))
  ;; Add or remove the MODE toggle function from
  ;; `semantic-init-hooks'.  Then turn MODE on or off in every
  ;; Semantic enabled buffer.
  (cond
   ;; Turn off if ARG < 0
   ((< arg 0)
    (remove-hook 'semantic-init-hooks mode)
    (semantic-map-buffers #'(lambda () (funcall mode -1)))
    nil)
   ;; Turn on if ARG > 0
   ((> arg 0)
    (add-hook 'semantic-init-hooks mode)
    (semantic-map-buffers #'(lambda () (funcall mode 1)))
    t)
   ;; Otherwise just check MODE state
   (t
    (memq mode semantic-init-hooks))
   ))

---------------

So all semantic specific modes use this, and this function activates
that routine via `semantic-init-hooks' which I mentioned earlier.

Thus, creating one of these `global' modes that only works if semantic
is active uses this, and gets called at the right time.  All modes
that define a parser therefore get this mode activated.

I therefore expect that if you want one of the semantic minor modes
for some other specific mode you would just enable it in a mode hook,
but that mode hook must be an append to make sure it runs after the
parser is initialized, such as:

(add-hook 'c-mode-hook 'semantic-some-mode t)

Other modes that keep semantic working, such as idle-time parsing or
semanticdb really ought to run against everything to keep stuff
consistent.


What most folks probably think of as `semantic-mode' is some subset of
the 15 minor modes.


>> As such, what you are requesting is possible, and follows typical
>> conventions, but just requires more INSTALL explanation.  I am
>> hesitant to add such discussion because the current install
>> instruction is short and simple, and discussing all those options
>> would make it much less so.  I've batched many modes together into
>> "turn on lots of related things" functions which means all sub modes
>> would need explaining for basic install.
>
>So IIUC semantic-mode does not in itself affect the behavior, but
>because of how features on top of Semantic register themselves in
>semantic-init-hook, the mere fact of activating semantic-mode ends up
>activating a lot more.
>
>I guess that's fine for now.  All we really need is a way to only enable
>semantic (and accompagnying features) in some modes.

A user could customize semantic on a per-mode basis like this:

(add-hook 'mode-1-hook (lambda ()
	  	      	 (semantic-this-mode 1)
 			 (semantic-that-mode 1))
  	  t)

(add-hook 'mode-2-hook (lambda ()
	  	      	 (semantic-foo-mode 1)
 			 (semantic-bar-mode 1))
  	  t)

though some core modes, like the idle timer and database mode should
be activated semantic/globally.

Also, to be clear, the core timer is for idle time parsing only.  The
idle modes, like idle-summary-mode, are separately controllable.

Eric

------------------

Here is mode-local.  It's been discussed on this list a couple times,
and includes a couple pieces of advice you had asked about in a
different message.

I really like mode-local, and highly recommend it as a way of adding
behavior for a specific mode.

------------------
;;; mode-local.el --- Support for mode local facilities
;;
;; Copyright (C) 2007, 2008 Eric M. Ludlam
;; Copyright (C) 2004, 2005 David Ponce
;;
;; Author: David Ponce <david@dponce.com>
;; Maintainer: David Ponce <david@dponce.com>
;; Created: 27 Apr 2004
;; Keywords: syntax
;; X-RCS: $Id: mode-local.el,v 1.11 2008/01/25 19:33:30 zappo Exp $
;;
;; This file is not part of GNU Emacs.
;;
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2, or (at
;; your option) any later version.
;;
;; This software is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.

;;; Commentary:
;;
;; Each major mode will want to support a specific set of behaviors.
;; Usually generic behaviors that need just a little bit of local
;; specifics.
;;
;; This library permits the setting of override functions for tasks of
;; that nature, and also provides reasonable defaults.
;;
;; There are buffer local variables, and frame local variables.
;; This library give the illusion of mode specific variables.
;;
;; You should use a mode-local variable or override to allow extension
;; only if you expect a mode author to provide that extension.  If a
;; user might wish to customize a give variable or function then
;; the existing customization mechanism should be used.

;; To Do:
;; Allow customization of a variable for a specific mode?
;;
;; Add mecro for defining the '-default' functionality.

;;; History:
;;

;;; Code:
(eval-when-compile (require 'cl))

;;; Compatibility
;;
(defun mode-local-define-derived-mode-needed-p ()
  "Return non-nil if mode local has to fix `define-derived-mode'.
That is, if `define-derived-mode' does not set `derived-mode-parent'."
  (let ((body (cdr (macroexpand '(define-derived-mode c p ""))))
        (bad t))
    (while (and body bad)
      (if (equal (car body) '(put 'c 'derived-mode-parent 'p))
          (setq bad nil)
        (setq body (cdr body))))
    bad))

(when (mode-local-define-derived-mode-needed-p)
  ;; Workaround a bug in some (XEmacs) versions of
  ;; `define-derived-mode' that don't set the `derived-mode-parent'
  ;; property, and break mode-local.
  (defadvice define-derived-mode
    (after mode-local-define-derived-mode activate)
    "Fix missing `derived-mode-parent' property on child."
    (unless (eq 'fundamental-mode (ad-get-arg 1))
      (let ((form (cdr ad-return-value)))
        (setq ad-return-value nil)
        (while form
          (and (eq 'defun (car-safe (car form)))
               (eq (ad-get-arg 0) (car (cdr-safe (car form))))
               (push `(or (get ',(ad-get-arg 0) 'derived-mode-parent)
                          (put ',(ad-get-arg 0) 'derived-mode-parent
                               ',(ad-get-arg 1)))
                     ad-return-value))
          (push (car form) ad-return-value)
          (setq form (cdr form)))
        (setq ad-return-value `(progn ,@(nreverse ad-return-value)))
        )))
  )

;;; Misc utilities
;;
(defun mode-local-map-file-buffers (function &optional predicate buffers)
  "Run FUNCTION on every file buffer found.
FUNCTION does not have arguments; when it is entered `current-buffer'
is the currently selected file buffer.
If optional argument PREDICATE is non nil, only select file buffers
for which the function PREDICATE return non-nil.
If optional argument BUFFERS is non-nil, it is a list of buffers to
walk through.  It defaults to `buffer-list'."
  (dolist (b (or buffers (buffer-list)))
    (and (buffer-live-p b) (buffer-file-name b)
         (with-current-buffer b
           (when (or (not predicate) (funcall predicate))
             (funcall function))))))

(defun mode-local-map-mode-buffers (function modes)
  "Run FUNCTION on every file buffer with major mode in MODES.
MODES can be a symbol or a list of symbols.
FUNCTION does not have arguments."
  (or (listp modes) (setq modes (list modes)))
  (mode-local-map-file-buffers
   function #'(lambda () (memq major-mode modes))))
\f
;;; Hook machinery
;;
(defvar mode-local-init-hook nil
  "Hook run after a new file buffer is created.
The current buffer is the newly created file buffer.")

(defvar mode-local-changed-mode-buffers nil
  "List of buffers whose `major-mode' has changed recently.")

(defvar mode-local--init-mode nil)

(defsubst mode-local-initialized-p ()
  "Return non-nil if mode local is initialized in current buffer.
That is, if the current `major-mode' is equal to the major mode for
which mode local bindings have been activated."
  (eq mode-local--init-mode major-mode))

(defun mode-local-post-major-mode-change ()
  "`post-command-hook' run when there is a `major-mode' change.
This makes sure mode local init type stuff can occur."
  (remove-hook 'post-command-hook 'mode-local-post-major-mode-change)
  (let ((buffers mode-local-changed-mode-buffers))
    (setq mode-local-changed-mode-buffers nil)
    (mode-local-map-file-buffers
     #'(lambda ()
         ;; Make sure variables are set up for this mode.
         (activate-mode-local-bindings)
         (run-hooks 'mode-local-init-hook))
     #'(lambda ()
         (not (mode-local-initialized-p)))
     buffers)))

(defun mode-local-on-major-mode-change ()
  "Function called in `change-major-mode-hook'."
  (add-to-list 'mode-local-changed-mode-buffers (current-buffer))
  (add-hook 'post-command-hook 'mode-local-post-major-mode-change))

(add-hook 'find-file-hooks 'mode-local-post-major-mode-change)
(add-hook 'change-major-mode-hook 'mode-local-on-major-mode-change)
\f
;;; Core bindings API
;;
(defsubst set-mode-local-parent (mode parent)
  "Set parent of major mode MODE to PARENT mode.
To work properly, this function should be called after PARENT mode
local variables have been defined."
  (put mode 'mode-local-parent parent)
  ;; Refresh mode bindings to get mode local variables inherited from
  ;; PARENT. To work properly, the following should be called after
  ;; PARENT mode local variables have been defined.
  (mode-local-map-mode-buffers mode 'activate-mode-local-bindings))

(defsubst get-mode-local-parent (mode)
  "Return the mode parent of the major mode MODE.
Return nil if MODE has no parent."
  (or (get mode 'mode-local-parent)
      (get mode 'derived-mode-parent)))

(defmacro define-child-mode (mode parent &optional docstring)
  "Make major mode MODE inherits behavior from PARENT mode.
DOCSTRING is optional and not used.
To work properly, this should be put after PARENT mode local variables
definition."
  `(set-mode-local-parent ',mode ',parent))

(defvar mode-local-symbol-table nil
  "Buffer local mode bindings.
These symbols provide a hook for a `major-mode' to specify specific
behaviors.  Use the function `mode-local-bind' to define new bindings.")
(make-variable-buffer-local 'mode-local-symbol-table)

(defvar mode-local-active-mode nil
  "Major mode in which bindings are active.")

(defsubst new-mode-local-bindings ()
  "Return a new empty mode bindings symbol table."
  (make-vector 13 0))

(defun mode-local-bind (bindings &optional plist mode)
  "Define BINDINGS in the specified environment.
BINDINGS is a list of (VARIABLE . VALUE).
Optional argument PLIST is a property list each VARIABLE symbol will
be set to.  The following properties have special meaning:

- `constant-flag' if non-nil, prevent to rebind variables.
- `mode-variable-flag' if non-nil, define mode variables.
- `override-flag' if non-nil, define override functions.

The `override-flag' and `mode-variable-flag' properties are mutually
exclusive.

If optional argument MODE is non-nil, it must be a major mode symbol.
BINDINGS will be defined globally for this major mode.  If MODE is
nil, BINDINGS will be defined locally in the current buffer, in
variable `mode-local-symbol-table'.  The later should be done in MODE
hook."
  ;; Check plist consistency
  (and (plist-get plist 'mode-variable-flag)
       (plist-get plist 'override-flag)
       (error "Bindings can't be both overrides and mode variables"))
  (let (table variable varname value binding)
    (if mode
        (progn
          ;; Install in given MODE symbol table.  Create a new one if
          ;; needed.
          (setq table (or (get mode 'mode-local-symbol-table)
                          (new-mode-local-bindings)))
          (put mode 'mode-local-symbol-table table))
      ;; Fail if trying to bind mode variables in local context!
      (if (plist-get plist 'mode-variable-flag)
          (error "Mode required to bind mode variables"))
      ;; Install in buffer local symbol table.  Create a new one if
      ;; needed.
      (setq table (or mode-local-symbol-table
                      (setq mode-local-symbol-table
                            (new-mode-local-bindings)))))
    (while bindings
      (setq binding  (car bindings)
            bindings (cdr bindings)
            varname  (symbol-name (car binding))
            value    (cdr binding))
      (if (setq variable (intern-soft varname table))
          ;; Binding already exists
          ;; Check rebind consistency
          (cond
           ((equal (symbol-value variable) value)
            ;; Just ignore rebind with the same value.
            )
           ((get variable 'constant-flag)
            (error "Can't change the value of constant `%s'"
                   variable))
           ((and (get variable 'mode-variable-flag)
                 (plist-get plist 'override-flag))
            (error "Can't rebind override `%s' as a mode variable"
                   variable))
           ((and (get variable 'override-flag)
                 (plist-get plist 'mode-variable-flag))
            (error "Can't rebind mode variable `%s' as an override"
                   variable))
           (t
            ;; Merge plist and assign new value
            (setplist variable (append plist (symbol-plist variable)))
            (set variable value)))
        ;; New binding
        (setq variable (intern varname table))
        ;; Set new plist and assign initial value
        (setplist variable plist)
        (set variable value)))
    ;; Return the symbol table used
    table))

(defsubst mode-local-symbol (symbol &optional mode)
  "Return the mode local symbol bound with SYMBOL's name.
Return nil if the  mode local symbol doesn't exist.
If optional argument MODE is nil, lookup first into locally bound
symbols, then in those bound in current `major-mode' and its parents.
If MODE is non-nil, lookup into symbols bound in that major mode and
its parents."
  (let ((name (symbol-name symbol)) bind)
    (or mode
        (setq mode mode-local-active-mode)
        (setq mode major-mode
              bind (and mode-local-symbol-table
                        (intern-soft name mode-local-symbol-table))))
    (while (and mode (not bind))
      (or (and (get mode 'mode-local-symbol-table)
               (setq bind (intern-soft
                           name (get mode 'mode-local-symbol-table))))
          (setq mode (get-mode-local-parent mode))))
    bind))

(defsubst mode-local-symbol-value (symbol &optional mode property)
  "Return the value of the mode local symbol bound with SYMBOL's name.
If optional argument MODE is non-nil, restrict lookup to that mode and
its parents (see the function `mode-local-symbol' for more details).
If optional argument PROPERTY is non-nil the mode local symbol must
have that property set.  Return nil if the symbol doesn't exist, or
doesn't have PROPERTY set."
  (and (setq symbol (mode-local-symbol symbol mode))
       (or (not property) (get symbol property))
       (symbol-value symbol)))
\f
;;; Mode local variables
;;
(defun activate-mode-local-bindings (&optional mode)
  "Activate variables defined locally in MODE and its parents.
That is, copy mode local bindings into corresponding buffer local
variables.
If MODE is not specified it defaults to current `major-mode'.
Return the alist of buffer-local variables that have been changed.
Elements are (SYMBOL . PREVIOUS-VALUE), describing one variable."
  (let (modes table old-locals)
    (unless mode
      (set (make-local-variable 'mode-local--init-mode) major-mode)
      (setq mode major-mode))
    ;; Get MODE's parents & MODE in the right order.
    (while mode
      (setq modes (cons mode modes)
            mode  (get-mode-local-parent mode)))
    ;; Activate mode bindings following parent modes order.
    (dolist (mode modes)
      (when (setq table (get mode 'mode-local-symbol-table))
        (mapatoms
         #'(lambda (var)
             (when (get var 'mode-variable-flag)
               (let ((v (intern (symbol-name var))))
                 ;; Save the current buffer-local value of the
                 ;; mode-local variable.
                 (and (local-variable-p v (current-buffer))
                      (push (cons v (symbol-value v)) old-locals))
                 (set (make-local-variable v) (symbol-value var)))))
         table)))
    old-locals))

(defun deactivate-mode-local-bindings (&optional mode)
  "Deactivate variables defined locally in MODE and its parents.
That is, kill buffer local variables set from the corresponding mode
local bindings.
If MODE is not specified it defaults to current `major-mode'."
  (unless mode
    (kill-local-variable 'mode-local--init-mode)
    (setq mode major-mode))
  (let (table)
    (while mode
      (when (setq table (get mode 'mode-local-symbol-table))
        (mapatoms
         #'(lambda (var)
             (when (get var 'mode-variable-flag)
               (kill-local-variable (intern (symbol-name var)))))
         table))
      (setq mode (get-mode-local-parent mode)))))

(defmacro with-mode-local (mode &rest body)
   "With the local bindings of MODE, evaluate BODY.
The current mode bindings are saved, BODY is evaluated, and the saved
bindings are restored, even in case of an abnormal exit.
Value is what BODY returns."
   (let ((old-mode  (make-symbol "mode"))
         (old-locals (make-symbol "old-locals"))
         (local (make-symbol "local")))
     `(let ((,old-mode mode-local-active-mode)
            (,old-locals nil))
        (unwind-protect
            (progn
              (deactivate-mode-local-bindings ,old-mode)
              (setq mode-local-active-mode ',mode)
              ;; Save the previous value of buffer-local variables
              ;; changed by `activate-mode-local-bindings'.
              (setq ,old-locals (activate-mode-local-bindings ',mode))
              ,@body)
          (deactivate-mode-local-bindings ',mode)
          ;; Restore the previous value of buffer-local variables.
          (dolist (,local ,old-locals)
            (set (car ,local) (cdr ,local)))
          ;; Restore the mode local variables.
          (setq mode-local-active-mode ,old-mode)
          (activate-mode-local-bindings ,old-mode)))))
(put 'with-mode-local 'lisp-indent-function 1)

(defsubst mode-local-value (mode sym)
  "Return the value of the MODE local variable SYM."
  (or mode (error "Missing major mode symbol"))
  (mode-local-symbol-value sym mode 'mode-variable-flag))

(defmacro setq-mode-local (mode &rest args)
  "Assign new values to variables local in MODE.
MODE must be a major mode symbol.
ARGS is a list (SYM VAL SYM VAL ...).
The symbols SYM are variables; they are literal (not evaluated).
The values VAL are expressions; they are evaluated.
Set each SYM to the value of its VAL, locally in buffers already in
MODE, or in buffers switched to that mode.
Return the value of the last VAL."
  (when args
    (let (i ll bl sl tmp sym val)
      (setq i 0)
      (while args
        (setq tmp  (make-symbol (format "tmp%d" i))
              i    (1+ i)
              sym  (car args)
              val  (cadr args)
              ll   (cons (list tmp val) ll)
              bl   (cons `(cons ',sym ,tmp) bl)
              sl   (cons `(set (make-local-variable ',sym) ,tmp) sl)
              args (cddr args)))
      `(let* ,(nreverse ll)
         ;; Save mode bindings
         (mode-local-bind (list ,@bl) '(mode-variable-flag t) ',mode)
         ;; Assign to local variables in all existing buffers in MODE
         (mode-local-map-mode-buffers #'(lambda () ,@sl) ',mode)
         ;; Return the last value
         ,tmp)
      )))

(defmacro defvar-mode-local (mode sym val &optional docstring)
  "Define MODE local variable SYM with value VAL.
DOCSTRING is optional."
  `(progn
     (setq-mode-local ,mode ,sym ,val)
     (put (mode-local-symbol ',sym ',mode)
          'variable-documentation ,docstring)
     ',sym))
(put 'defvar-mode-local 'lisp-indent-function 'defun)

(defmacro defconst-mode-local (mode sym val &optional docstring)
  "Define MODE local constant SYM with value VAL.
DOCSTRING is optional."
  (let ((tmp (make-symbol "tmp")))
    `(let (,tmp)
       (setq-mode-local ,mode ,sym ,val)
       (setq ,tmp (mode-local-symbol ',sym ',mode))
       (put ,tmp 'constant-flag t)
       (put ,tmp 'variable-documentation ,docstring)
       ',sym)))
(put 'defconst-mode-local 'lisp-indent-function 'defun)
\f
;;; Function overloading
;;
(defun make-obsolete-overload (old new)
  "Mark OLD overload as obsoleted by NEW overload."
  (put old 'overload-obsoleted-by new)
  (put old 'mode-local-overload t)
  (put new 'overload-obsolete old))

(defsubst overload-obsoleted-by (overload)
  "Get the overload symbol obsoleted by OVERLOAD.
Return the obsolete symbol or nil if not found."
  (get overload 'overload-obsolete))

(defsubst overload-that-obsolete (overload)
  "Return the overload symbol that obsoletes OVERLOAD.
Return the symbol found or nil if OVERLOAD is not obsolete."
  (get overload 'overload-obsoleted-by))

(defsubst fetch-overload (overload)
  "Return the current OVERLOAD function, or nil if not found.
First, lookup for OVERLOAD into locally bound mode local symbols, then
in those bound in current `major-mode' and its parents."
  (or (mode-local-symbol-value overload nil 'override-flag)
      ;; If an obsolete overload symbol exists, try it.
      (and (overload-obsoleted-by overload)
           (mode-local-symbol-value
            (overload-obsoleted-by overload) nil 'override-flag))))

(defun mode-local--override (name args body)
  "Return the form that handles overloading of function NAME.
ARGS are the arguments to the function.
BODY is code that would be run when there is no override defined.  The
default is to call the function `NAME-default' with the appropriate
arguments.
See also the function `define-overload'."
  (let* ((default (intern (format "%s-default" name)))
         (overargs (delq '&rest (delq '&optional (copy-sequence args))))
         (override (make-symbol "override")))
    `(let ((,override (fetch-overload ',name)))
       (if ,override
           (funcall ,override ,@overargs)
         ,@(or body `((,default ,@overargs)))))
    ))

(defun mode-local--expand-overrides (name args body)
  "Expand override forms that overload function NAME.
ARGS are the arguments to the function NAME.
BODY is code where override forms are searched for expansion.
Return result of expansion, or BODY if no expansion occurred.
See also the function `define-overload'."
  (let ((forms body)
        (ditto t)
        form xbody)
    (while forms
      (setq form (car forms))
      (cond
       ((atom form))
       ((eq (car form) :override)
        (setq form (mode-local--override name args (cdr form))))
       ((eq (car form) :override-with-args)
        (setq form (mode-local--override name (cadr form) (cddr form))))
       ((setq form (mode-local--expand-overrides name args form))))
      (setq ditto (and ditto (eq (car forms) form))
            xbody (cons form xbody)
            forms (cdr forms)))
    (if ditto body (nreverse xbody))))

(defun mode-local--overload-body (name args body)
  "Return the code that implements overloading of function NAME.
ARGS are the arguments to the function NAME.
BODY specifies the overload code.
See also the function `define-overload'."
  (let ((result (mode-local--expand-overrides name args body)))
    (if (eq body result)
        (list (mode-local--override name args body))
      result)))

(defmacro define-overload (name args docstring &rest body)
  "Define a new function, as with `defun' which can be overloaded.
NAME is the name of the function to create.
ARGS are the arguments to the function.
DOCSTRING is a documentation string to describe the function.  The
docstring will automatically had details about its overload symbol
appended to the end.
BODY is code that would be run when there is no override defined.  The
default is to call the function `NAME-default' with the appropriate
arguments.

BODY can also include an override form that specifies which part of
BODY is specifically overridden.  This permits to specify common code
run for both default and overridden implementations.
An override form is one of:

  1. (:override [OVERBODY])
  2. (:override-with-args OVERARGS [OVERBODY])

OVERBODY is the code that would be run when there is no override
defined.  The default is to call the function `NAME-default' with the
appropriate arguments deduced from ARGS.
OVERARGS is a list of arguments passed to the override and
`NAME-default' function, in place of those deduced from ARGS."
  `(eval-and-compile
     (defun ,name ,args
       ,docstring
       ,@(mode-local--overload-body name args body))
     (put ',name 'mode-local-overload t)))
(put :override-with-args 'lisp-indent-function 1)

(defsubst function-overload-p (symbol)
  "Return non-nil if SYMBOL is a function which can be overloaded."
  (and symbol (symbolp symbol) (get symbol 'mode-local-overload)))

(defmacro define-mode-local-override
  (name mode args docstring &rest body)
  "Define a mode specific override of the function overload NAME.
Has meaning only if NAME has been created with `define-overload'.
MODE is the major mode this override is being defined for.
ARGS are the function arguments, which should match those of the same
named function created with `define-overload'.
DOCSTRING is the documentation string.
BODY is the implementation of this function."
  (let ((newname (intern (format "%s-%s" name mode))))
    `(progn
       (eval-and-compile
	 (defun ,newname ,args
	   ,(format "%s\n\nOverride %s in `%s' buffers."
		    docstring name mode)
	   ;; The body for this implementation
	   ,@body)
         ;; For find-func to locate the definition of NEWNAME.
         (put ',newname 'definition-name ',name))
       (mode-local-bind '((,name . ,newname))
                        '(override-flag t)
                        ',mode))
    ))
\f
;;; Read/Query Support
;;
;;;###autoload
(defun mode-local-read-function (prompt &optional initial hist default)
  "Interactively read in the name of a mode-local function.
PROMPT, INITIAL, HIST, and DEFAULT are the same as for `completing-read'."
  (completing-read prompt obarray 'function-overload-p t initial hist default))
\f
;;; Help support
;;
(defun overload-docstring-extension (overload)
  "Return the doc string that augments the description of OVERLOAD."
  (let ((doc "\n\This function can be overloaded\
 (see `define-mode-local-override' for details).")
        (sym (overload-obsoleted-by overload)))
    (when sym
      (setq doc (format "%s\nIt makes the overload `%s' obsolete."
                        doc sym)))
    (setq sym (overload-that-obsolete overload))
    (when sym
      (setq doc (format "%s\nThis overload is obsoletes;\nUse `%s' instead."
                        doc sym)))
    doc))

(defun mode-local-augment-function-help (symbol)
  "Augment the *Help* buffer for SYMBOL.
SYMBOL is a function that can be overridden."
  (with-current-buffer "*Help*"
    (pop-to-buffer (current-buffer))
    (unwind-protect
	(progn
	  (toggle-read-only -1)
          (goto-char (point-min))
          (unless (re-search-forward "^$" nil t)
            (goto-char (point-max))
            (beginning-of-line)
            (forward-line -1))
          (insert (overload-docstring-extension symbol) "\n")
	  ;; NOTE TO SELF:
	  ;; LIST ALL LOADED OVERRIDES FOR SYMBOL HERE
	  )
      (toggle-read-only 1))))

;; Help for Overload functions.  Need to advise help.
(defadvice describe-function (around mode-local-help activate)
  "Display the full documentation of FUNCTION (a symbol).
Returns the documentation as a string, also."
  (prog1
      ad-do-it
    (if (function-overload-p (ad-get-arg 0))
	(mode-local-augment-function-help (ad-get-arg 0)))))

;; Help for mode-local bindings.
(defun mode-local-print-binding (symbol)
  "Print the SYMBOL binding."
  (let ((value (symbol-value symbol)))
    (princ (format "\n     `%s' value is\n       " symbol))
    (if (and value (symbolp value))
        (princ (format "`%s'" value))
      (let ((pt (point)))
        (pp value)
        (save-excursion
          (goto-char pt)
          (indent-sexp))))
    (or (bolp) (princ "\n"))))

(defun mode-local-print-bindings (table)
  "Print bindings in TABLE."
  (let (us ;; List of unpecified symbols
        mc ;; List of mode local constants
        mv ;; List of mode local variables
        ov ;; List of overloaded functions
        fo ;; List of final overloaded functions
        )
    ;; Order symbols by type
    (mapatoms
     #'(lambda (s)
         (add-to-list (cond
                       ((get s 'mode-variable-flag)
                        (if (get s 'constant-flag) 'mc 'mv))
                       ((get s 'override-flag)
                        (if (get s 'constant-flag) 'fo 'ov))
                       ('us))
                      s))
     table)
    ;; Print symbols by type
    (when us
      (princ "\n  !! Unpecified symbols\n")
      (mapc 'mode-local-print-binding us))
    (when mc
      (princ "\n  ** Mode local constants\n")
      (mapc 'mode-local-print-binding mc))
    (when mv
      (princ "\n  ** Mode local variables\n")
      (mapc 'mode-local-print-binding mv))
    (when fo
      (princ "\n  ** Final overloaded functions\n")
      (mapc 'mode-local-print-binding fo))
    (when ov
      (princ "\n  ** Overloaded functions\n")
      (mapc 'mode-local-print-binding ov))
    ))

(defun mode-local-describe-bindings-2 (buffer-or-mode)
  "Display mode local bindings active in BUFFER-OR-MODE."
  (let (table mode)
    (princ "Mode local bindings active in ")
    (cond
     ((bufferp buffer-or-mode)
      (with-current-buffer buffer-or-mode
        (setq table mode-local-symbol-table
              mode major-mode))
      (princ (format "%S\n" buffer-or-mode))
      )
     ((symbolp buffer-or-mode)
      (setq mode buffer-or-mode)
      (princ (format "`%s'\n" buffer-or-mode))
      )
     ((signal 'wrong-type-argument
              (list 'buffer-or-mode buffer-or-mode))))
    (when table
      (princ "\n- Buffer local\n")
      (mode-local-print-bindings table))
    (while mode
      (setq table (get mode 'mode-local-symbol-table))
      (when table
        (princ (format "\n- From `%s'\n" mode))
        (mode-local-print-bindings table))
      (setq mode (get-mode-local-parent mode)))))

(defun mode-local-describe-bindings-1 (buffer-or-mode &optional interactive-p)
  "Display mode local bindings active in BUFFER-OR-MODE.
Optional argument INTERACTIVE-P is non-nil if the calling command was
invoked interactively."
  (if (fboundp 'with-displaying-help-buffer)
      ;; XEmacs
      (with-displaying-help-buffer
       #'(lambda ()
           (with-current-buffer standard-output
             (mode-local-describe-bindings-2 buffer-or-mode)
             (when (fboundp 'frob-help-extents)
               (goto-char (point-min))
               (frob-help-extents standard-output)))))
    ;; GNU Emacs
    (when (fboundp 'help-setup-xref)
      (help-setup-xref
       (list 'mode-local-describe-bindings-1 buffer-or-mode)
       interactive-p))
    (with-output-to-temp-buffer "*Help*"
      (with-current-buffer standard-output
        (mode-local-describe-bindings-2 buffer-or-mode)))))

(defun describe-mode-local-bindings (buffer)
  "Display mode local bindings active in BUFFER."
  (interactive "b")
  (when (setq buffer (get-buffer buffer))
    (mode-local-describe-bindings-1 buffer (interactive-p))))

(defun describe-mode-local-bindings-in-mode (mode)
  "Display mode local bindings active in MODE hierarchy."
  (interactive
   (list (completing-read
          "Mode: " obarray
          #'(lambda (s) (get s 'mode-local-symbol-table))
          t (symbol-name major-mode))))
  (when (setq mode (intern-soft mode))
    (mode-local-describe-bindings-1 mode (interactive-p))))
\f
;;; Font-lock support
;;
(defconst mode-local-font-lock-keywords
  (eval-when-compile
    (let* (
           ;; Variable declarations
           (kv (regexp-opt
                '(
                  "defconst-mode-local"
                  "defvar-mode-local"
                  ) t))
           ;; Function declarations
           (kf (regexp-opt
                '(
                  "define-mode-local-override"
                  "define-child-mode"
                  "define-overload"
                  ;;"make-obsolete-overload"
                  "with-mode-local"
                  ) t))
           ;; Regexp depths
           (kv-depth (regexp-opt-depth kv))
           (kf-depth (regexp-opt-depth kf))
           )
      `((,(concat
           ;; Declarative things
           "(\\(" kv "\\|" kf "\\)"
           ;; Whitespaces & names
           "\\>[ \t]*\\(\\sw+\\)?[ \t]*\\(\\sw+\\)?"
           )
         (1 font-lock-keyword-face)
         (,(+ 1 kv-depth kf-depth 1)
          (cond ((match-beginning 2)
                 font-lock-type-face)
                ((match-beginning ,(+ 1 kv-depth 1))
                 font-lock-function-name-face)
                )
          nil t)
         (,(+ 1 kv-depth kf-depth 1 1)
          (cond ((match-beginning 2)
                 font-lock-variable-name-face)
                )
          nil t)))
      ))
  "Highlighted keywords.")

\f
;;; find-func support (Emacs 21.4, or perhaps 22.1)
;;
(condition-case nil
    ;; Try to get find-func so we can modify it.
    (require 'find-func)
  (error nil))

(when (boundp 'find-function-regexp)
  (unless (string-match "ine-overload" find-function-regexp)
    (if (string-match "(def\\\\(" find-function-regexp)
	(let ((end (match-end 0))
	      )
	  (setq find-function-regexp
		(concat (substring find-function-regexp 0 end)
			"ine-overload\\|ine-mode-local-override\\|"
			"ine-child-mode\\|"
			(substring find-function-regexp end)))))
    )
  ;; The regexp for variables is a little more kind.
  )

;; TODO: Add XEmacs support
(when (fboundp 'font-lock-add-keywords)
  (font-lock-add-keywords 'emacs-lisp-mode
                          mode-local-font-lock-keywords))
\f
;;; edebug support
;;
(defun mode-local-setup-edebug-specs ()
  "Define edebug specification for mode local macros."
  (def-edebug-spec setq-mode-local
    (symbolp (&rest symbolp form))
    )
  (def-edebug-spec defvar-mode-local
    (&define symbolp name def-form [ &optional stringp ] )
    )
  (def-edebug-spec defconst-mode-local
    defvar-mode-local
    )
  (def-edebug-spec define-overload
    (&define name lambda-list stringp def-body)
    )
  (def-edebug-spec define-mode-local-override
    (&define name symbolp lambda-list stringp def-body)
    )
  )

(add-hook 'edebug-setup-hook 'mode-local-setup-edebug-specs)

(provide 'mode-local)

;;; mode-local.el ends here

-- 
          Eric Ludlam:                       eric@siege-engine.com
   Siege: www.siege-engine.com          Emacs: http://cedet.sourceforge.net




^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2008-04-24  2:41 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-04-22 10:06 Improving Emacs for writing code joakim
2008-04-22 15:49 ` David Hansen
2008-04-22 21:49   ` Re[2]: " Eric M. Ludlam
2008-04-23  1:33     ` Stefan Monnier
2008-04-23  5:10       ` Chong Yidong
2008-04-23 14:05         ` Re[2]: " Eric M. Ludlam
2008-04-23 14:23           ` Chong Yidong
2008-04-23 17:29           ` Stefan Monnier
2008-04-23 15:00       ` Re[2]: " Eric M. Ludlam
2008-04-23 17:45         ` Stefan Monnier
2008-04-24  2:41           ` Re[2]: " Eric M. Ludlam
2008-04-23 19:05         ` Richard M Stallman
2008-04-22 16:02 ` Stefan Monnier
2008-04-22 16:54   ` klaus.berndl
2008-04-22 17:07     ` Lennart Borgman (gmail)
2008-04-23  8:26       ` klaus.berndl
2008-04-23 10:26         ` Nick Roberts
2008-04-23 11:59           ` klaus.berndl
2008-04-23 13:00             ` Nick Roberts
2008-04-23 12:12           ` Neal Becker
2008-04-23 12:19             ` klaus.berndl
2008-04-23 12:28               ` Neal Becker
2008-04-23 21:34                 ` Stephen J. Turnbull
2008-04-22 20:08 ` Richard Stallman

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.