Subject: bug#37127: [PATCH] cperl-mode: Suppress a misleading message

From: [email-masked] (Harald Jörg)
Date: Thu, 29 Oct 2020 22:11:58 +0100

The unjustified message about a missing end of a RE is rather harmless,
it goes away after the next keystroke.  Nevertheless, this can be fixed.
It also happens in several related situations.

The message has its cause in the apparently totally unrelated function
'blink-matching-open'.  Whenever a closing paren is inserted, this
function highlights the corresponding opening paren for a short time.
As part of its processing, it narrows the buffer so that it ends with
the closing paren - thereby excluding the end of the regular expression.

In this state, it calls 'syntax-propertize', which in turn runs through
the cperl-mode functions for syntaxification, ending up eventually in
'cperl-forward-re' - which fails to find the end of the regular
expression in the narrowed buffer.

The patch suppresses the message if the following conditions are met:
   1) The buffer is currently narrowed
   2) We are at the end of the (narrowed) buffer
   3) The error in question is of type 'scan-error

The patch also contains a test to verify that the message isn't written
in the situation given in the bug report, and also that the message is
written if we do indeed have an unterminated regular expression.
--
Cheers,
haj
>From 85b8ccab3d5e43a4a3d4e622529248973b606a04 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Harald=20J=C3=B6rg?= <[email-masked]>
Date: Thu, 29 Oct 2020 21:03:12 +0100
Subject: [PATCH] ; Suppress a misleading message when closing a paren in a
 regex

* lisp/progmodes/cperl-mode.el (cperl-forward-re): Suppress an
error message about "End of string/RE not found" when we are
at the end of a narrowed buffer where the end of a RE is
temporarily unavailable (Bug#37127).

* test/lisp/progmodes/cperl-mode-tests.el (cperl-bug37127):
Add a test to verify that the message is suppressed when
inappropriate, but appears when the RE *is* incomplete.
---
 lisp/progmodes/cperl-mode.el            |  7 ++++++
 test/lisp/progmodes/cperl-mode-tests.el | 29 +++++++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el
index ebbea6bed9..94f42cb2bc 100644
--- a/lisp/progmodes/cperl-mode.el
+++ b/lisp/progmodes/cperl-mode.el
@@ -3225,6 +3225,13 @@ cperl-forward-re
 		 (and cperl-brace-recursing
 		      (or (eq ostart  ?\{)
 			  (eq starter ?\{)))
+		 ;; If we are at the end of a narrowed buffer, then a
+		 ;; scan error should not be reported to the user.
+		 ;; This situation actually happens when a closing
+		 ;; paren is entered in a regular expression.
+		 ;; Reported in Bug#37127.
+		 (and (eobp) (buffer-narrowed-p)
+		      (equal (car bb) 'scan-error))
 		 (message
 		  "End of `%s%s%c ... %c' string/RE not found: %s"
 		  argument
diff --git a/test/lisp/progmodes/cperl-mode-tests.el b/test/lisp/progmodes/cperl-mode-tests.el
index e67678cf6b..4b949bc9a7 100644
--- a/test/lisp/progmodes/cperl-mode-tests.el
+++ b/test/lisp/progmodes/cperl-mode-tests.el
@@ -218,4 +218,33 @@ cperl-mode-fontify-punct-vars
         (should (equal (nth 3 (syntax-ppss)) nil))
         (should (equal (nth 4 (syntax-ppss)) t))))))
 
+(ert-deftest cperl-bug37127 ()
+  "Verify that closing a paren in a regex goes without a message.
+Also check that the message is issued if the regex terminator is
+missing."
+  (let (collected-messages)
+    ;; Part one: Regex is ok, no messages
+    (ert-with-message-capture collected-messages
+      (with-temp-buffer
+        (insert "$_ =~ /(./;")
+        (cperl-mode)
+        (goto-char (point-min))
+        (search-forward ".")
+        (let ((last-command-event ?\)))
+          (cperl-electric-rparen 1)
+          (cperl-find-pods-heres (point-min) (point-max) t)))
+      (should (string-equal collected-messages "")))
+    ;; part two: Regex terminator missing -> message
+    (ert-with-message-capture collected-messages
+      (with-temp-buffer
+        (insert "$_ =~ /(..;")
+        (goto-char (point-min))
+        (cperl-mode)
+        (search-forward ".")
+        (let ((last-command-event ?\)))
+          (cperl-electric-rparen 1)
+          (cperl-find-pods-heres (point-min) (point-max) t)))
+      (should (string-match "^End of .* string/RE"
+                            collected-messages)))))
+
 ;;; cperl-mode-tests.el ends here
-- 
2.20.1