Subject: RE: bug#11520: 24.1.50; delete-selection-mode conflicts with electric-pair-mode

From: "Drew Adams" <[email-masked]>
Date: Sun, 20 May 2012 09:31:50 -0700

> Thanks for the recipe.  I'm not sure yet how best to solve
> this problem.  Basically, the issue is that delete-selection-mode
> operates before the ( is processed, so it has to "guess" what 
> ( will do.
> 
> Most likely the cleanest solution will be to add some
> "delete-selection-predicates" hook that electric-pair-mode can use to
> explain when to inhibit delete-selection.

I hesitate to jump in here.  I like `d-s' mode, and I hope we do not radically
alter its design (which keys off of certain command symbol properties, and which
takes place pre-command).

I don't claim expertise here; I just like the way `d-s' handles and is easy to
configure.  It essentially hooks into specific commands, taking effect just
before they do.

`e-p-m' does not change the bindings of self-inserting keys - they are still
bound to `self-insert-command'.  And `d-s-m' treats that command as it should:
the self-insertion is preceded by deletion of the region.

`d-s' mode determines the particular behavior from the command.  Its behavior is
easily changeable by setting different properties on the command symbol.  But a
given command (e.g. `self-insert-command') has a single delete-selection
behavior.

`d-s' takes effect _before_ the affected command (on `pre-command-hook'), not
after it.  `e-p', on the contrary, does its thing _after_ the command (there is
apparently only one such command, so far: `self-insert-command').

`e-p' depends on `post-self-insert-hook', which is new in Emacs 24.  I see that
this hook is also used by other things in Emacs 24.  Dunno whether those other
cases might also be problematic for use with d-s mode.

`e-p', like `d-s', is command-driven - it is associated with only one command,
in a hard-coded way rather than by looking up command-symbol properties.  Its
behavior is thus not variable depending on the command (only one command, only
one behavior).  But this difference is not really important here, I think.

The real difference is when the special effect takes place: before or after the
affected command (`self-insert-command', in this case).

Since `d-s' does its thing (deletion) before the relevant command, it is natural
that it take effect pre-command.  Since `e-p' does its thing (insertion) after
the relevant command (`self-insert-command' only), it is natural that it take
effect post-command.

But as you say, Stefan, a pre-command approach like d-s knows nothing about what
might be expected to happen after the command is done.

It could be possible to let `e-p' know what `d-s' has already done, but I do not
see how it is possible/practical to let `d-s' know what `e-p' will do.  We could
make `d-s' aware that `e-p' mode is turned on, and we could even try to let it
know exactly what `e-p' mode does (not a very modular approach, but perhaps
doable).

But knowing that, `d-s' would have to not only test for `self-insert-command'
but also test the character to be inserted.  We would end up, I'm afraid,
duplicating nearly all of the `e-p' logic inside `d-s'.  (But perhaps I don't
understand well what you had in mind.)

Anyway, that mismatch (pre-command control vs post) is I guess the problem here.
If so, it might be seen to be more general than `d-s' vs `e-p'.

I don't really have a solution.  (Mainly I have a concern that `d-s' mode not be
altered radically.)

Wrt your proposal: I don't quite understand.  `e-p' wants to inhibit `d-s'
deletion only in the case where a `(' (or whatever else, such as `"') is
inserted.  It does not want to inhibit it generally, correct?

If so, how can it possibly inhibit it in only some cases, if it does not even
take effect until after the `(' command (= `self-insert-command') is finished?

I don't see how `e-p', acting post-command, can _inhibit_ something that happens
pre-command.  `d-s' could perhaps be made aware that `e-p' is coming up, but to
make `d-s' DTRT I would think that it would need to know nearly everything about
`e-p'.

`e-p' could, however undo/reverse what `d-s' did.  In the case of killing this
would be simple, I imagine, but it might not be quite so trivial in other `d-s'
cases.  Perhaps `d-s' could save some "undoing" info for the eventuality that
some post-command action (e.g. `e-p') might want to reverse what `d-s' did.

That's probably what I would propose: have `e-p' somehow undo what `d-s' did.

But I'm sure you know more about this than I.  My real concern is that we not
lose any of the basic design of `d-s': pre-command & driven by properties on
command symbols.