Subject: bug#50538: [PATCH] 28.0.50; electric-pair-mode fails to pair double quotes in some cases in CC mode

From: Alan Mackenzie <[email-masked]>
Date: Thu, 16 Sep 2021 19:05:56 +0000

Hello, João.

On Thu, Sep 16, 2021 at 18:04:53 +0100, João Távora wrote:
> Lars Ingebrigtsen <[email-masked]> writes:

> > Dmitry Gutov <[email-masked]> writes:

> >>>> I don't use this minor mode, so I don't think my opinion on this
> >>>> matters much.  I will defer to Lars and Alan here.
> >>> I seldom use electric-pair-mode, and since this touches cc-mode, I'll
> >>> defer to Alan.:-)
> >>> Alan?

> >> At risk of reigniting an old disagreement, perhaps we should ask Joao?

> > Sure; added to the CCs.  João, do you have an opinion here?

> I couldn't understand the initial issue fully, but I can only confirm
> that the relationship between cc-mode and electric-pair-mode has been
> rocky.  I think the situation is similar with electric-layout-mode and
> with electric-indent-mode, to a certain degree (though I am not sure for
> this last one).

I think it is up to both of us to make this relationship less rocky.

> I don't think there are any easy technical solutions for it. I certainly
> cannot invest the effort in any of them right now.

> It wasn't like this from the beginning: when I first created
> electric-pair-mode it worked mostly if not fully fine with cc-mode, like
> one expects e-p-m to work in other modes (ruby, python, js, elisp, rust,
> perl, even non-programming modes).

> At times, compatibility deteriorated as cc-mode added mechanisms for
> solving electricity problems or related problems in an idiosyncratic
> way.  Sometimes these changes broke e-p-m's tests and the solution was
> -- incorrectly in my view --to disable the tests "temporarily".  I see
> that for one of them at least, the test has been re-instated.  A good
> sign, maybe.  

> Regardless of history and current state of affairs, my personal solution
> to C in Emacs is to use a hand-rolled mode, a so-called plainer-cc-mode.
> The goal is to make it behave like most other modes w.r.t
> electric-pair-mode and keep the basic c syntax and indentation.  I've
> used it reasonably successfully with C and C++.  Here it is in its
> entirety.  I think I use something similar for c++-mode.

>    (define-derived-mode plainer-c-mode c-mode "pC"
>      "A plainer C-mode with no internal electric machinery."
>      (c-toggle-electric-state -1)
>      (setq-local electric-indent-local-mode-hook nil)
>      (setq-local electric-indent-mode-hook nil)
>      (electric-indent-local-mode 1)
>      (dolist (key '(?\" ?\' ?\{ ?\} ?\( ?\) ?\[ ?\]))
>        (local-set-key (vector key) 'self-insert-command)))

> Among other simpler things, this makes the major mode not bind special
> keys to special commands.  They are all bound to `self-insert-command`
> like most major modes.  This simplifies electric-pair-mode, as far as I
> remember.

> The above is a hack, but not very dirty one.  The one below much more so.
> It's a brute-force hack for solving electricity problems.  It simply
> disables some cc internal functions.  May be out of date by now, YMMV, 
> warranty void, etc, as they say.

>    (defun joaot/disable-some-cc-things ()
>      (interactive)
>      (dolist (name '(c-restore-string-fences
>                      c-remove-string-fences
>                      c-before-change-check-unbalanced-strings
>                      c-after-change-mark-abnormal-strings
>                      c-after-change-escape-NL-in-string))
>        (advice-add name :override #'ignore '((name . joaot/remove-disable-some-cc-things)))
>        (add-hook 'c-mode-common-hook
>                  (lambda ()
>                    (kill-local-variable 'electric-pair-inhibit-predicate)))))

Needless to say, my point of view with respect to the above is somewhat
different.  Succinctly put, the minor modes electric-.... are MINOR
modes, and are quite new.  They were implemented in a way which
interfered with major modes, and I can't see there was any need for
this.  In particular, they interfered with CC Mode features which had
existed for 20 years at the time.

> On the C++/C editing-front, I am eagerly waiting for Treesitter to
> arrive so that is it becomes possible to write a new major mode for c++
> and c from scratch.

I am also looking forward to Treesitter, though I think starting a new
C++ Mode from scratch would not be a good use of time, and would be
needlessly disruptive for current CC Mode users.

> Reusing solid and efficient parsing logic based on language grammars.
> Another more closely available option, is to simply use LSP for
> indentation and fontification.  Though that is almost certainly slower
> and less confortable/portable/etc... Anyway, whatever the solution,
> I'm quite confident that such a mode won't have these characteristics
> that cc-mode has when used with `electric-pair-mode`.

> If you're writing C, and not C++, my also try Stefan Monnier's aptly
> named sm-c-mode, installable via M-x package-install RET sm-c-mode.
> Works fine with electric-pair-mode, but seems to indent very oddly for
> some reason.

I would rather suggest using straight C Mode, which works and works
well.  If there are incompatibilities between CC Mode and
electric-pair-mode, and it seems there are, let's get these fixed.

> Hope this helps.  I'm sorry I can't offer any better solutions.

Could you please express your expert view?  In Jim's opening post he
implies that:
(i) electric-pair-mode should be active inside comments.
(ii) In some circumstances at least, typing a " immediately in front
  of another " causes two "s to be inserted.  Are these circumstances
  spelt out anywhere?
(iii) Typing a " inside a string causes two "s to be inserted, leaving
  point between the two new adjacent strings formed.  This feature is
  not intended to work in C++ raw strings, or other similar multi-line
  strings in other CC Mode modes.

Are these three features all intended in electric-pair-mode?

Thanks!

> João

-- 
Alan Mackenzie (Nuremberg, Germany).