Subject: Re: bug#78587: [PATCH] TeX-find-macro-end

From: "Paul D. Nelson" <[email-masked]>
Date: Tue, 27 May 2025 16:56:53 +0200

Hi Arash,

Thanks, that suggestion is helpful, and seems to take care of the issue
you noted.  Please find attached an updated patch, to which I also added
a test.

thanks, best,

Paul

>From 65906577241bda8d7321d0ef33f0808944d06bed Mon Sep 17 00:00:00 2001
From: Paul Nelson <[email-masked]>
Date: Sun, 25 May 2025 17:11:49 +0200
Subject: [PATCH] Fix TeX macro end detection in some edge cases

* tex.el (TeX-find-macro-end-helper): Use
TeX-search-syntax-table with square brackets when calling
forward-sexp.  This fixes parsing of optional arguments
containing other unmatched delimiters, such as
\begin{enumerate}[a)], where the search would stop at ')'
instead of ']'.  We take further care to treat examples like
\begin{enumerate}[a{]}].

* tests/latex/latex-test.el
(TeX-find-macro-end-with-complicated-optional-args): New test
concerning the above issue.
---
 tests/latex/latex-test.el | 13 +++++++++++++
 tex.el                    | 16 +++++++++++++---
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/tests/latex/latex-test.el b/tests/latex/latex-test.el
index b68ea3b8..92b7c530 100644
--- a/tests/latex/latex-test.el
+++ b/tests/latex/latex-test.el
@@ -761,4 +761,17 @@ check the indentation for optional argument of \\usepackage."
                (buffer-string)
                "sab\n")))))
 
+(ert-deftest TeX-find-macro-end-with-complicated-optional-args ()
+  "Check that end of macro is determined correctly."
+  ;; (bug#78587)
+  (dolist (str '("\begin{enumerate}[a]"
+                 "\begin{enumerate}[(a)]"
+                 "\begin{enumerate}[a)]"
+                 "\begin{enumerate}[a{]}]"))
+    (with-temp-buffer
+      (insert str)
+      (LaTeX-mode)
+      (should (equal (point-max)
+                     (TeX-find-macro-end-helper (point-min)))))))
+
 ;;; latex-test.el ends here
diff --git a/tex.el b/tex.el
index e90252d8..62fc217b 100644
--- a/tex.el
+++ b/tex.el
@@ -5866,9 +5866,19 @@ those will be considered part of it."
                        (forward-line 1)
                        (looking-at "[ \t]*\\(\\[\\)"))))
             (goto-char (match-beginning 1))
-            (condition-case nil
-                (forward-sexp)
-              (scan-error (throw 'found (point)))))
+            (goto-char (match-beginning 1))
+            ;; Imitate `font-latex-find-matching-close', motivated by
+            ;; examples like \begin{enumerate}[a{]}].
+            (let* ((syntax (TeX-search-syntax-table ?\[ ?\]))
+                   (parse-sexp-ignore-comments
+                    (not (eq major-mode 'docTeX-mode))))
+              (modify-syntax-entry ?\{ "|" syntax)
+              (modify-syntax-entry ?\} "|" syntax)
+              (modify-syntax-entry ?\\ "/" syntax)
+              (condition-case nil
+                  (with-syntax-table syntax
+                    (forward-sexp))
+                (scan-error (throw 'found (point))))))
            ;; Skip over pairs of curly braces
            ((or (looking-at "[ \t]*\n?[ \t]*{") ; Be conservative: Consider
                                         ; only consecutive lines.
-- 
2.39.3 (Apple Git-145)