unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Jim Porter <jporterbugs@gmail.com>
To: Alan Mackenzie <acm@muc.de>
Cc: 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 14:36:06 -0700	[thread overview]
Message-ID: <456ed31d-77dc-cc2d-2fe9-8fcd379e04c6@gmail.com> (raw)
In-Reply-To: <YUOt0GbHZET3sHE6@ACM>

[-- Attachment #1: Type: text/plain, Size: 1983 bytes --]

On 9/16/2021 1:49 PM, Alan Mackenzie wrote:
> 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".

Thanks, I've incorporated all these changes into the attached patch. The 
only difference between my patch and the version you provided was to 
keep the `(search-backward "\"")' portion from my patch, since the code 
needs to find the last double-quote, not the end of line.

As an aside, it's probably worth explaining why my patch searches for 
the last double-quote in the first place. As far as I understand CC 
Mode, when there's an unterminated double-quote on a line, both the 
quote and the newline have a string fence property applied to them. This 
means we could check the newline for that property, *but* there's no 
guarantee a newline actually exists: `(c-point 'eoll)' could actually 
point to the end of the buffer. To get around that, we search backwards 
for the last double-quote of the (logical) line, since that's guaranteed 
to exist.

If we wanted to, we could avoid searching backwards for the last 
double-quote when a newline exists, but I'm not sure the gain in 
performance (likely very small) is worth the extra code complexity.

[-- Attachment #2: 0001-Improve-behavior-of-electric-pair-mode-in-cc-mode.patch --]
[-- Type: text/plain, Size: 3293 bytes --]

From 4759ed0c8fa7fa8fafd47d166b3f126e606ffe84 Mon Sep 17 00:00:00 2001
From: Jim Porter <jporterbugs@gmail.com>
Date: Thu, 16 Sep 2021 14:32:17 -0700
Subject: [PATCH] Improve behavior of 'electric-pair-mode' in 'cc-mode'

This ensures that quotes are paired correctly within comments, allows for
insertion of quote pairs immediately before another quote, and allows
inserting quote pairs within a string (thus splitting the string in two).

* lisp/progmodes/cc-mode.el (c-electric-pair-inhibit-predicate):
Inhibit insertion of paired quote in fewer cases.
* test/lisp/electric-tests.el (define-electric-pair-test):
Add 'c-mode' to list of modes to test by default.
---
 lisp/progmodes/cc-mode.el   | 22 +++++++++++++++-------
 test/lisp/electric-tests.el |  5 ++++-
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 057d292246..60cea0b858 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -2550,18 +2550,26 @@ c-electric-pair-inhibit-predicate
 
 At the time of call, point is just after the newly inserted CHAR.
 
-When CHAR is \", t will be returned unless the \" is marked with
-a string fence syntax-table text property.  For other characters,
-the default value of `electric-pair-inhibit-predicate' is called
-and its value returned.
+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."
-  (if (eq char ?\")
-      (not (equal (get-text-property (1- (point)) 'c-fl-syn-tab) '(15)))
-    (funcall (default-value 'electric-pair-inhibit-predicate) char)))
+  (or (and (eq char ?\")
+	   (not (memq (cadr (c-semi-pp-to-literal (1- (point)))) '(c c++)))
+	   (let ((last-quote (save-match-data
+			       (save-excursion
+				 (goto-char (c-point 'eoll))
+				 (search-backward "\"")))))
+	     (not (equal (c-get-char-property last-quote 'c-fl-syn-tab)
+			 '(15)))))
+      (funcall (default-value 'electric-pair-inhibit-predicate) char)))
 
 \f
 ;; Support for C
diff --git a/test/lisp/electric-tests.el b/test/lisp/electric-tests.el
index 666de89c53..35516a9f0b 100644
--- a/test/lisp/electric-tests.el
+++ b/test/lisp/electric-tests.el
@@ -32,6 +32,9 @@
 (require 'elec-pair)
 (require 'cl-lib)
 
+;; When running tests in c-mode, use single-line comments (//).
+(add-hook 'c-mode-hook (lambda () (c-toggle-comment-style -1)))
+
 (defun call-with-saved-electric-modes (fn)
   (let ((saved-electric (if electric-pair-mode 1 -1))
         (saved-layout (if electric-layout-mode 1 -1))
@@ -173,7 +176,7 @@ define-electric-pair-test
           expected-string
           expected-point
           bindings
-          (modes '(quote (ruby-mode js-mode)))
+          (modes '(quote (ruby-mode js-mode c-mode)))
           (test-in-comments t)
           (test-in-strings t)
           (test-in-code t)
-- 
2.25.1


  reply	other threads:[~2021-09-16 21:36 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
2021-09-16 21:36       ` Jim Porter [this message]
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

  List information: https://www.gnu.org/software/emacs/

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

  git send-email \
    --in-reply-to=456ed31d-77dc-cc2d-2fe9-8fcd379e04c6@gmail.com \
    --to=jporterbugs@gmail.com \
    --cc=50538@debbugs.gnu.org \
    --cc=acm@muc.de \
    /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 public inbox

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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).