Subject: Re: bug#15478: cc-mode does not obey electric-indent-mode

From: Josh <[email-masked]>
Date: Sun, 6 Oct 2013 10:45:59 -0700

On Sat, Oct 5, 2013 at 9:50 AM, Alan Mackenzie <[email-masked]> wrote:
> On Fri, Oct 04, 2013 at 02:21:22PM -0700, Josh wrote:
> > On Thu, Oct 3, 2013 at 7:32 AM, Stefan Monnier <[email-masked]
>
> > wrote:
> > > > What I'm suggesting is some sort of hook so that
> > > > electric-indent-mode (and electric-layout-mode, too, I suppose)
> > > > invokes the "electric engine" in CC Mode rather than trying to do
> > > > the electric indentation itself.
> > > Sounds OK.
>
> > Unless I'm misunderstanding, the indentation hook you're describing
> > seems very close to `electric-indent-functions':
> I'd say it's moderately close rather than very close.  At the moment CC
> Mode does its own electric indentation entirely, and I'd like things to
> stay that way, so as to minimise incompatibility between versions, to
> avoid breaking existing users' setups and so on.

Sorry, I don't follow.  Why "moderately close" instead of "very
close"?  The docstring of `electric-indent-functions' suggests that
its members are called after the insertion of every character.

If CC Mode performs indentation only after character insertion,
why couldn't it continue to do its own electric indentation entirely
after being actuated by this hook, returning `no-indent' to ensure it
had complete control?

If CC Mode reindentation is additionally or only triggered by events
other than character insertion, what are those events?  Timers?
Hooks?  This is what I was getting at when I asked how the existing
delegation mechanisms fall short.

> >     electric-indent-functions is a variable defined in `electric.el'.
> >     Its value is nil
> >       This variable may be risky if used as a file-local variable.
> >     Documentation:
> >     Special hook run to decide whether to auto-indent.
> >     Each function is called with one argument (the inserted char), with
> >     point right after that char, and it should return t to cause
> > indentation,
> >     `no-indent' to prevent indentation or nil to let other functions
decide.
>
> > Is there a reason why CC Mode couldn't supply a function here that
> > would perform appropriate indentation and then return `no-indent' to
> > stop traversal of electric-indent-functions?
> It would be a lot of work to rearrange things, and it might leave the
> Emacs 24.4 version incompatible with other CC Mode versions.

My previous question was based on a supposition (perhaps naive, as I'm
not at all familiar with the CC Mode code) that its indentation
functionality was either already centralized into a some "indent this
line properly" function or that it would be desirable and feasible to
make it so.  If that were so, it seemed to me that such a function
could be pressed into service as an electric-indent-function without
too much trouble.  The fact that you say it would be a lot of work to
rearrange things leads me to believe that my supposition may have been
incorrect, though that does not affect my view that global electricity
settings should govern electricity behavior globally.

> > Delegation of newline insertion decisions is similarly already supported
> > via `electric-layout-rules':
>
> >     electric-layout-rules
> >     electric-layout-rules is a variable defined in `electric.el'.
> >     Its value is nil
> >     Documentation:
> >     List of rules saying where to automatically insert newlines.
> >     Each rule has the form (CHAR . WHERE) where CHAR is the char
> >     that was just inserted and WHERE specifies where to insert newlines
> >     and can be: nil, `before', `after', `around', or a function of no
> >     arguments that returns one of those symbols.
>
> > If either or both of these delegation mechanisms are insufficient to
> > satisfy CC Mode's requirements, it would be interesting to hear how they
> > fall short.
> CC Mode already does electric actions by other means, and users setups
> depend on these.  I don't want to break these existing setups.
> Integrating CC Mode's ways with these new mechanisms is a challenge.

Since you didn't point out any shortcomings of these mechanisms or
describe these "other means" or why it would be so difficult to
integrate them with global electricity settings, I see no way to
continue this line of discussion.

> > Although I agree with your earlier point that major modes are best
> > suited to make decisions about /how/ to perform electric behavior for
> > their specific domains, which also seems to be borne out by the existing
> > delegation support, I've seen no justification for a major mode deciding
> > to disregard (!) my configuration of /whether/ to perform it at all.
> Currently, that configuration is done by setting `c-electric-flag',
> either in your .emacs or by C-c C-l.  `electric-indent-mode' is the new
> kid on the block.  Concrete suggestions for integrating `c-electric-flag'
> and `electric-indent-mode' haven't been copious up till now.  I've one or
> two ideas myself, but it's not trivial.

Indeed, it would have been better for this discussion to have taken
place concurrently with the introduction of a piece of global
configuration specifying default behavior at odds with that of
existing mode-granular configuration, but that's water under the
bridge.  As for their integration, I have already confessed to being
unfamiliar with CC Mode code, but perhaps until a better long-term
solution has been specified and implemented a reasonable stopgap
measure would be to set the default value of c-electric-flag to

  (or c-force-electric-flag electric-layout-mode electric-indent-mode)

with a corresponding

  (defcustom c-force-electric-flag nil
    "*If non-nil, force electric indentation and newline insertion
enablement.

  Otherwise, the default state of this behavior is to be enabled if either
  `electric-layout-mode' or `electric-indent-mode' are enabled.

  Note: regardless of any of the above settings, `c-toggle-electric-state'
  can toggle enablement of this feature on a buffer-granular basis."
    :type 'boolean
    :group 'c)

though this is imperfect since it loses information when the two
global configuration values differ.  Even so, it would be a vast
improvement for newbies who do not want this behavior.  Another
possible flaw with this approach is that runtime changes to global
electricity enablement would not affect CC Mode's behavior, which
doesn't matter to me but might to others.

> > I read the electric-*-mode docstrings describing the exact behavior in
> > question and I disabled it.  That should be the end of the story.
> Yes.  But there's a difference between you disabling it and merely using
> the default value.  Since the current default is already nil, it's not
> clear what you mean by "disabling" it.

You're right; I should have said, "I ensured that it was disabled."  I
meant that I had read the relevant documentation and verified that the
all of the related configuration reflected my wishes.  In this case
because the defaults already did so I did not have to change anything.

> Perhaps there need to be three
> values here, 'default, t and nil.

Perhaps so, but until that time I expect my global configuration
settings to be observed regardless of whether they remain at the
default values or whether the developers of some mode or library
I'm using think those defaults are sensible.

> It's also still up for discussion how
> you {en,dis}able electric-indent-mode buffer locally, which is a sensible
> thing to want to do.

I believe even the stopgap measure I suggested would permit changing
that behavior buffer-locally.