Subject: Re: bug#77876: 31.0.50; elec-pair --- `electric-pair-inhibit-predicate' ignored for `electric-pair-pairs'

From: Stefan Monnier <[email-masked]>
Date: Sun, 25 May 2025 10:09:40 -0400

> Although I believe this was a design decision, in my view, the
> `electric-pair-inhibit-predicate' function should also apply to
> characters in the `electric-pair-pairs' list.

Currently, there the `electric-pair-inhibit-predicate` is called only
for pairs that come fro the syntax-table and not for those in
`electric-pair-pairs`, and this is by design, as you noted.

I can't remember how we ended up with this design, but if you look at
the code, the default `electric-pair-inhibit-if-helps-balance` presumes
that it's called for a char that has a specific meaning in the
syntax-table.

And the use of `unconditional` that you remove is the only use of that
value, which was computed for a reason.

Maybe a good way forward is to call `electric-pair-inhibit-predicate`
"unconditionally", but to pass it somehow the information whether the
pair comes from `electric-pair-pairs` or not, so
`electric-pair-inhibit-if-helps-balance` can skip trying to
preserve balance?

Ideally, the way this information is passed could be (re)used in
bug#78053.  E.g. maybe pass it a string instead of a char?
This would be backward incompatible, so it's not ideal.

Another approach could be to replace the

    (CHAR . CHAR)

syntax of `electric-pair-pairs` with a new syntax

    (CHAR CHAR ...)

where the `...` could be used to hold information such as a predicate to
decide when this pair can be used, so you could use something like:

    (setq-local electric-pair-pairs
                '((?* ?* :predicate region-active-p)
                  (?/ ?/ :predicate region-active-p)
                  (?_ ?_ :predicate region-active-p)
                  (?= ?= :predicate region-active-p)
                  (?~ ?~ :predicate region-active-p)
                  (?+ ?+ :predicate region-active-p)))

- Stefan