all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Alan Mackenzie <acm@muc.de>
To: Jim Porter <jporterbugs@gmail.com>
Cc: acm@muc.de, 50538@debbugs.gnu.org
Subject: bug#50538: [PATCH] 28.0.50; electric-pair-mode fails to pair double quotes in some cases in CC mode
Date: Thu, 16 Sep 2021 20:49:20 +0000	[thread overview]
Message-ID: <YUOt0GbHZET3sHE6@ACM> (raw)
In-Reply-To: <94c7b4ec-813b-515f-d947-116c294dd74b@gmail.com>

Hello, Jim.

On Sun, Sep 12, 2021 at 11:05:17 -0700, Jim Porter wrote:
> On 9/11/2021 11:26 PM, Eli Zaretskii wrote:
> >> From: Jim Porter <jporterbugs@gmail.com>
> >> Date: Sat, 11 Sep 2021 20:58:47 -0700

> >> There are a few related issues with pairing double quotes in CC mode
> >> while using `electric-pair-mode'. Hopefully the steps to reproduce below
> >> will explain the issues. In all the cases, I'd expect
> >> `electric-pair-mode' to insert a closing quote, but it doesn't.

OK.  Just for context, I'm the maintainer of CC Mode, but I don't use
electric-pair-mode in my day-to-day editing.

> > Your expected results seem to expect Emacs to assume that a new string
> > will be inserted, but is that an assumption that is always true?

> In these cases, I believe that's true (with the default 
> `electric-pair-mode' settings, that is). More broadly, the goal of the 
> patch is to ensure that pairing of double quotes works the same in CC 
> mode as it does in other modes (`ruby-mode', `python-mode', `js-mode', 
> `emacs-lisp-mode', etc), which is why I added `c-mode' to the list of 
> modes to test in `test/lisp/electric-tests.el'.

The goal should be to make all these modes work correctly with respect
to e-p-m, for whatever value of correctly we decide upon.

> That said, there's one potential case I didn't account for (mostly 
> because it wasn't accounted for in the patch for bug#36474): if a user 
> customizes `electric-pair-inhibit-predicate' to inhibit cases like (2) 
> or (3) in my original message, that won't work right in CC modes, since 
> the default value of `electric-pair-inhibit-predicate' (set by the user) 
> won't be called.

> Attached is an updated patch that changes the logic of 
> `c-electric-pair-inhibit-predicate' to either a) inhibit insertion of 
> the closing quote, or b) call the default-value of 
> `electric-pair-inhibit-predicate' to determine what to do. This should 
> give users more consistent behavior when customizing 
> `electric-pair-inhibit-predicate'.

There were two or three minor problems with the patch:

1-/.  CC Mode doesn't use syntax-ppss at all.  This was because way back
when, syntax-ppss was buggy, and even now doesn't do the right thing for
CC Mode in some edge cases (e.g. with the buffer narrowed and point-min
inside a string or comment).  Instead it uses its own internal syntactic
cacheing, largely centred around the function c-semi-pp-to-literal.

2/-  Rather than using get-text-property and friends directly, CC Mode
uses the macros c-get-char-property, etc.  This is (?was) to maintain
compatibility with XEmacs.

3/- (A bit more serious) The patch looks for the last " in the current
line without taking account of any escaped new lines.  There is already
a CC Mode macro which does all the work here, c-point, which can be given
the argument 'eoll for "end of logical line".

Incorporating all these points into the macro (which I admit I haven't
tested) the function would look something like this:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Connection with Emacs's electric-pair-mode
(defun c-electric-pair-inhibit-predicate (char)
  "Return t to inhibit the insertion of a second copy of CHAR.

At the time of call, point is just after the newly inserted CHAR.

When CHAR is \" and not within a comment, t will be returned if
the quotes on the current line are already balanced (i.e. if the
last \" is not marked with a string fence syntax-table text
property).  For other cases, the default value of
`electric-pair-inhibit-predicate' is called and its value
returned.

This function is the appropriate value of
`electric-pair-inhibit-predicate' for CC Mode modes, which mark
invalid strings with such a syntax table text property on the
opening \" and the next unescaped end of line."
  (or (and (eq char ?\")
           (not (memq (cadr (c-semi-pp-to-literal (1- (point)))) '(c c++)))
           (not (equal (c-get-char-property (c-point 'eoll) 'c-fl-syn-tab)
                       '(15))))
      (funcall (default-value 'electric-pair-inhibit-predicate) char)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

> The tests still pass, although I wasn't able to figure out a good way to 
> add a test for setting `electric-pair-inhibit-predicate' that works with 
> how CC mode overrides it (using `:bindings' in 
> `define-electric-pair-test' didn't work, since the binding is set too 
> late). Hopefully that's ok; if not, I can try and see about making some 
> more extensive changes to the tests to account for this.

> Note however that this solution isn't perfect: it means a user's custom 
> `electric-pair-inhibit-predicate' can only inhibit *more* than CC mode's 
> default behavior, not less. I think that's a reasonable compromise 
> though, and users who want more direct control can set 
> `electric-pair-inhibit-predicate' inside `c-mode-common-hook'. A 
> "perfect" solution here would probably require adding new customization 
> points to `electric-pair-mode' (e.g. a way for major modes to override 
> how the syntax is analyzed), and I'm not sure the added complexity would 
> be worth it, especially since this code is already a bit tricky.

Indeed so.  ;-)

-- 
Alan Mackenzie (Nuremberg, Germany).





  parent reply	other threads:[~2021-09-16 20:49 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-12  3:58 bug#50538: [PATCH] 28.0.50; electric-pair-mode fails to pair double quotes in some cases in CC mode Jim Porter
2021-09-12  6:26 ` Eli Zaretskii
2021-09-12 18:05   ` Jim Porter
2021-09-15 22:17     ` Jim Porter
2021-09-16  5:25       ` Eli Zaretskii
2021-09-16 12:40         ` Lars Ingebrigtsen
2021-09-16 12:59           ` Dmitry Gutov
2021-09-16 13:17             ` Lars Ingebrigtsen
2021-09-16 17:04               ` João Távora
2021-09-16 17:11                 ` Eli Zaretskii
2021-09-16 17:33                   ` João Távora
2021-09-16 17:29                 ` Jim Porter
2021-09-16 19:05                 ` Alan Mackenzie
2021-09-16 20:51                   ` João Távora
2021-09-17 18:12                     ` Alan Mackenzie
2021-09-16 18:26         ` Alan Mackenzie
2021-09-16 20:49     ` Alan Mackenzie [this message]
2021-09-16 21:36       ` Jim Porter
2021-09-17 17:08         ` Alan Mackenzie
2021-09-23  2:01           ` bug#50538: [PATCH v3] " Jim Porter
2021-09-26 20:58             ` Alan Mackenzie
2021-09-28  4:57               ` bug#50538: [PATCH v4] " Jim Porter
2021-10-03 17:58                 ` bug#50538: [PATCH v5] " Jim Porter
2021-11-06  0:22                   ` bug#50538: [PATCH] " Lars Ingebrigtsen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YUOt0GbHZET3sHE6@ACM \
    --to=acm@muc.de \
    --cc=50538@debbugs.gnu.org \
    --cc=jporterbugs@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.