From 9b9dcc146ba8132ef02afd12f20b302a78c7bbe2 Mon Sep 17 00:00:00 2001
From: =?utf8?q?Harald=20J=C3=B6rg?= <haj@posteo.de>
Date: Sun, 2 Jul 2023 00:35:31 +0200
Subject: [PATCH] ; cperl-mode.el: Fix two indentation bugs (Bug#11733)

* lisp/progmodes/cperl-mode.el (cperl-sniff-for-indent): Detect
whether we have a label or a regex/string.
(cperl-calculate-indent): Check for things which look like labels
but aren't.

* test/lisp/progmodes/cperl-mode-tests.el (cperl-test-bug-11733):
Test the examples provided in the bug report.

* test/lisp/progmodes/cperl-mode-resources/cperl-bug-11733.pl:
Examples from the bug report.
---
 lisp/progmodes/cperl-mode.el                  | 10 ++--
 .../cperl-mode-resources/cperl-bug-11733.pl   | 50 +++++++++++++++++++
 test/lisp/progmodes/cperl-mode-tests.el       | 11 ++++
 3 files changed, 68 insertions(+), 3 deletions(-)
 create mode 100644 test/lisp/progmodes/cperl-mode-resources/cperl-bug-11733.pl

diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el
index c1e55944b7e..1abe57c15ea 100644
--- a/lisp/progmodes/cperl-mode.el
+++ b/lisp/progmodes/cperl-mode.el
@@ -2866,10 +2866,13 @@ Will not look before LIM."
 		   ;; Back up over label lines, since they don't
 		   ;; affect whether our line is a continuation.
 		   ;; (Had \, too)
-                   (while (and (eq (preceding-char) ?:)
+                   (while (save-excursion
+                            (and (eq (preceding-char) ?:)
                                  (re-search-backward
                                   (rx (sequence (eval cperl--label-rx) point))
-                                  nil t))
+                                  nil t)
+                                 ;; Ignore if in comment or RE
+                                 (not (nth 3 (syntax-ppss)))))
 		     ;; This is always FALSE?
 		     (if (eq (preceding-char) ?\,)
 			 ;; Will go to beginning of line, essentially.
@@ -3129,7 +3132,8 @@ and closing parentheses and brackets."
 	       ;; Now it is a hash reference
 	       (+ cperl-indent-level cperl-close-paren-offset))
 	     ;; Labels do not take :: ...
-	     (if (looking-at "\\(\\w\\|_\\)+[ \t]*:[^:]")
+	     (if (and (looking-at "\\(\\w\\|_\\)+[ \t]*:[^:]")
+                      (not (looking-at (rx (eval cperl--false-label-rx)))))
 		 (if (> (current-indentation) cperl-min-label-indent)
 		     (- (current-indentation) cperl-label-offset)
 		   ;; Do not move `parse-data', this should
diff --git a/test/lisp/progmodes/cperl-mode-resources/cperl-bug-11733.pl b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-11733.pl
new file mode 100644
index 00000000000..a474e431222
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-11733.pl
@@ -0,0 +1,50 @@
+# This resource file can be run with cperl--run-testcases from
+# cperl-tests.el and works with both perl-mode and cperl-mode.
+
+# -------- Multiline declaration: input -------
+#!/usr/bin/env perl
+# -*- mode: cperl -*-
+
+sub foo
+  {
+  }
+
+sub bar
+  {
+  }
+# -------- Multiline declaration: expected output -------
+#!/usr/bin/env perl
+# -*- mode: cperl -*-
+
+sub foo
+{
+}
+
+sub bar
+{
+}
+# -------- Multiline declaration: end -------
+
+# -------- Fred Colon at work: input --------
+#!/usr/bin/env perl
+# -*- mode: cperl -*-
+
+while (<>)
+{
+m:^  \d+ p:
+or die;
+m:^  \d+ :
+or die;
+}
+# -------- Fred Colon at work: expected output --------
+#!/usr/bin/env perl
+# -*- mode: cperl -*-
+
+while (<>)
+  {
+    m:^  \d+ p:
+      or die;
+    m:^  \d+ :
+      or die;
+  }
+# -------- Fred Colon at work: end --------
diff --git a/test/lisp/progmodes/cperl-mode-tests.el b/test/lisp/progmodes/cperl-mode-tests.el
index fced2171767..8162953cefb 100644
--- a/test/lisp/progmodes/cperl-mode-tests.el
+++ b/test/lisp/progmodes/cperl-mode-tests.el
@@ -855,6 +855,17 @@ under timeout control."
       (should (string-match
                "poop ('foo', \n      'bar')" (buffer-string))))))
 
+(ert-deftest cperl-test-bug-11733 ()
+  "Verify indentation of braces after newline and non-labels."
+  (skip-unless (eq cperl-test-mode #'cperl-mode))
+  (cperl--run-test-cases
+   (ert-resource-file "cperl-bug-11733.pl")
+   (goto-char (point-min))
+   (while (null (eobp))
+     (cperl-indent-command)
+     (forward-line 1))))
+
+
 (ert-deftest cperl-test-bug-11996 ()
   "Verify that we give the right syntax property to a backslash operator."
   (with-temp-buffer
-- 
2.39.5