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

From: João Távora <[email-masked]>
Date: Thu, 16 Sep 2021 18:04:53 +0100

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 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)))))

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.  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.

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

João