Subject: Re: bug#79047: Add some multi-character pairs to some major modes.

From: Alan Mackenzie <[email-masked]>
Date: Thu, 24 Jul 2025 13:39:16 +0000

Hello Elijah.

On Tue, Jul 22, 2025 at 17:03:34 -0600, Elijah Gabe Pérez wrote:
> Alan Mackenzie <[email-masked]> writes:

[ .... ]

> > Are you sure about this?  ....

[ .... ]

> That is the wrong NEWS entry of the feature.
> The real one is this:

>   *** Electric Pair mode now supports multi-character paired delimiters.
>   'electric-pair-pairs' and 'electric-pair-text-pairs' now allow using
>   strings for multi-character paired delimiters.

Apologies.  I missed this one, somehow.  This NEWS entry is part of 

commit 60fbeda771639ded68ffd0666df340c7a06cafcf
Author: Elías Gabriel Pérez <[email-masked]>
Date:   Thu Apr 24 17:34:58 2025 -0600

    Support strings for electric pairs (bug#78053)

..  This commit appears to me to be incomplete.  In particular:

(i) The doc string of electric-pair-syntax-info hasn't been modified to
  reflect the result component SYNTAX possibly being the symbol `str'.

(ii) The insertion of string pairs at ~L692 in
  electric-pair-post-self-insert-function neglects to check
  electric-pair-inhibit-predicate.  It's unclear why this isn't done, but
  if there's a good reason it should be documented somewhere (if it isn't
  already; I haven't actually checked).  e-p-inhibit-predicate gets used,
  and not handling it makes the insertion of string pairs inconsistent
  with the rest of electric-pair mode and less useful.

(iii) I don't think you've documented anywhere that the first string in
  an entry in electric-pair-pairs is actually a regular expression.
  (Again, I haven't rigorously searched for such documentation.)

>   To use this, add a list to both electric pair user options: '("/*" . "*/")'.

>   You can also specify to insert an extra space after the first string
>   pair: '("/*" " */" t)'.

[ .... ]

> I've tested the feature, it's possible to achieve it:

[ .... ]

Yes, sort of.  But electric pair mode's implementation violates an
(unwritten) Emacs convention about hooks, i.e. that a hook function
doesn't mess with the functionality that invoked it.  For example, a
function in window-scroll-functions may not change the scrolling state of
a window, and an after-change-functions function never changes the text
of a buffer.

By contrast, electric-pair-post-self-insert-function does mess with the
invoking functionality, namely self-insert-command; it inserts further
characters.  From the point of view of a Lisp program, this makes
self-insert-function an undefined function - what it does varies from
time to time and from buffer to buffer.

CC Mode has had to implement a workaround for this, namely binding
post-self-insert-function to nil (to get defined functionality for
self-insert-command), then later calling
electric-pair-post-self-insert-function by hand, to get the electric pair
functionality.  It's ugly and anything but robust.

So, yes, it is possible to get the functionality in CC Mode with ("/\\*"
" */" t), but it is not entirely trivial.

> -- 
> - E.G via GNU Emacs and Org.

-- 
Alan Mackenzie (Nuremberg, Germany).