>>>>> Ikumi Keita <ik...@ikumi.que.jp> writes:
> Thanks for your comments. I'll install the proposed fix as well as
> macrocode*? support, unless Mosè or Tassilo objects explicitly.
> Since `LaTeX-find-matching-begin' and `LaTeX-current-environment' is
> very similar in their task in implementation, I probably factor out the
> common code and simplify.

My current status is the attached patch, but it fails with regression
test `LaTeX-change-environment-with-esc', of course. Mosè, Tassilo, do
you think that `LaTeX-modify-environment' should keep the ability to
change environment named "\foo{bar}"?

Regards,
Ikumi Keita
#StandWithUkraine #StopWarInUkraine

diff --git a/latex.el b/latex.el
index 29ac9502..f0dc898c 100644
--- a/latex.el
+++ b/latex.el
@@ -910,34 +910,45 @@ environment in commented regions with the same comment prefix.
 
 The functions `LaTeX-find-matching-begin' and `LaTeX-find-matching-end'
 work analogously."
+  (or (save-excursion (LaTeX-backward-up-environment arg t))
+      "document"))
+
+(defun LaTeX-backward-up-environment (&optional arg want-name)
+  "Move backward out of the enclosing environment.
+With optional ARG>=1, find that outer level.
+Return non-nil if the operation succeeded.
+Return the (outermost) environment name if WANT-NAME is non-nil.
+
+Assume the current point is on neither \"begin{foo}\" nor \"end{foo}\"."
   (setq arg (if arg (if (< arg 1) 1 arg) 1))
   (let* ((in-comment (TeX-in-commented-line))
          (comment-prefix (and in-comment (TeX-comment-prefix)))
          (case-fold-search nil))
-    (save-excursion
-      (while (and (/= arg 0)
-                  (re-search-backward
-                   "\\\\\\(begin\\|end\\) *{\\([^}]+\\)}" nil t))
-        (when (or (and LaTeX-syntactic-comments
-                       (eq in-comment (TeX-in-commented-line))
-                       (or (not in-comment)
-                           ;; Consider only matching prefixes in the
-                           ;; commented case.
-                           (string= comment-prefix (TeX-comment-prefix))))
-                  (and (not LaTeX-syntactic-comments)
-                       (not (TeX-in-commented-line)))
-                  ;; macrocode*? in docTeX-mode is special since we
-                  ;; have also regular code lines not starting with a
-                  ;; comment-prefix.  Hence, the next check just looks
-                  ;; if we're inside such a group and returns t to
-                  ;; recognize such a situation.
-                  (and (eq major-mode 'doctex-mode)
-                       (member (match-string-no-properties 2)
-                               '("macrocode" "macrocode*"))))
-          (setq arg (if (string= (match-string 1) "end") (1+ arg) (1- arg)))))
-      (if (/= arg 0)
-          "document"
-        (match-string-no-properties 2)))))
+    (while (and (/= arg 0)
+                (re-search-backward
+                 "\\\\\\(begin\\|end\\) *{\\([^}]+\\)}" nil t))
+      (when (or (and LaTeX-syntactic-comments
+                     (eq in-comment (TeX-in-commented-line))
+                     (or (not in-comment)
+                         ;; Consider only matching prefixes in the
+                         ;; commented case.
+                         (string= comment-prefix (TeX-comment-prefix))))
+                (and (not LaTeX-syntactic-comments)
+                     (not (TeX-in-commented-line)))
+                ;; macrocode*? in docTeX-mode is special since we have
+                ;; also regular code lines not starting with a
+                ;; comment-prefix.  Hence, the next check just looks
+                ;; if we're inside such a group and returns non-nil to
+                ;; recognize such a situation.
+                (and (eq major-mode 'doctex-mode)
+                     (member (match-string-no-properties 2)
+                             '("macrocode" "macrocode*"))))
+        (setq arg (if (= (char-after (match-beginning 1)) ?e)
+                      (1+ arg)
+                    (1- arg)))))
+    (if (= arg 0)
+        (or (not want-name)
+            (match-string-no-properties 2)))))
 
 (defun docTeX-in-macrocode-p ()
   "Determine if point is inside a macrocode environment."
@@ -5263,18 +5274,23 @@ If function is called inside a comment and
 `LaTeX-syntactic-comments' is enabled, try to find the
 environment in commented regions with the same comment prefix."
   (interactive)
-  (let* ((regexp (concat (regexp-quote TeX-esc) "\\(begin\\|end\\)\\b"))
+  (let* ((regexp (concat (regexp-quote TeX-esc)
+                         "\\(begin\\|end\\) *{\\([^}]+\\)}"))
          (level 1)
          (in-comment (TeX-in-commented-line))
          (comment-prefix (and in-comment (TeX-comment-prefix)))
          (case-fold-search nil))
+    ;; The following code until `while' handles exceptional cases that
+    ;; the point is on "\begin{foo}" or "\end{foo}".
     (let ((pt (point)))
-      (skip-chars-backward (concat "a-zA-Z \t" (regexp-quote TeX-grop)))
+      (skip-chars-backward (concat "a-zA-Z* \t" TeX-grop))
       (unless (bolp)
         (backward-char 1)
         (if (and (looking-at regexp)
-                 (char-equal (char-after (1+ (match-beginning 0))) ?e))
-            (setq level 0)
+                 (char-equal (char-after (match-beginning 1)) ?e))
+            (progn
+              (setq level 0)
+              (goto-char (match-end 0)))
           (goto-char pt))))
     (while (and (> level 0) (re-search-forward regexp nil t))
       (when (or (and LaTeX-syntactic-comments
@@ -5284,14 +5300,21 @@ environment in commented regions with the same comment prefix."
                      (or (not in-comment)
                          (string= comment-prefix (TeX-comment-prefix))))
                 (and (not LaTeX-syntactic-comments)
-                     (not (TeX-in-commented-line))))
-        (if (= (char-after (1+ (match-beginning 0))) ?b) ;;begin
-            (setq level (1+ level))
-          (setq level (1- level)))))
-    (if (= level 0)
-        (re-search-forward
-         (concat TeX-grop (LaTeX-environment-name-regexp) TeX-grcl))
-      (error "Can't locate end of current environment"))))
+                     (not (TeX-in-commented-line)))
+                ;; macrocode*? in docTeX-mode is special since we have
+                ;; also regular code lines not starting with a
+                ;; comment-prefix.  Hence, the next check just looks
+                ;; if we're inside such a group and returns non-nil to
+                ;; recognize such a situation.
+                (and (eq major-mode 'doctex-mode)
+                     (member (match-string-no-properties 2)
+                             '("macrocode" "macrocode*"))))
+        (setq level
+              (if (= (char-after (match-beginning 1)) ?b) ;;begin
+                  (1+ level)
+                (1- level)))))
+    (or (= level 0)
+        (error "Can't locate end of current environment"))))
 
 (defun LaTeX-find-matching-begin ()
   "Move point to the \\begin of the current environment.
@@ -5300,30 +5323,17 @@ If function is called inside a comment and
 `LaTeX-syntactic-comments' is enabled, try to find the
 environment in commented regions with the same comment prefix."
   (interactive)
-  (let* ((regexp (concat (regexp-quote TeX-esc) "\\(begin\\|end\\)\\b"))
-         (level 1)
-         (in-comment (TeX-in-commented-line))
-         (comment-prefix (and in-comment (TeX-comment-prefix)))
-         (case-fold-search nil))
-    (skip-chars-backward (concat "a-zA-Z \t" (regexp-quote TeX-grop)))
+  (let ((regexp (concat (regexp-quote TeX-esc) "begin\\b"))
+        done)
+    ;; The following code until `or' handles exceptional cases that
+    ;; the point is on "\begin{foo}" or "\end{foo}".
+    (skip-chars-backward (concat "a-zA-Z* \t" TeX-grop))
     (unless (bolp)
       (backward-char 1)
       (and (looking-at regexp)
-           (char-equal (char-after (1+ (match-beginning 0))) ?b)
-           (setq level 0)))
-    (while (and (> level 0) (re-search-backward regexp nil t))
-      (when (or (and LaTeX-syntactic-comments
-                     (eq in-comment (TeX-in-commented-line))
-                     ;; If we are in a commented line, check if the
-                     ;; prefix matches the one we started out with.
-                     (or (not in-comment)
-                         (string= comment-prefix (TeX-comment-prefix))))
-                (and (not LaTeX-syntactic-comments)
-                     (not (TeX-in-commented-line))))
-        (if (= (char-after (1+ (match-beginning 0))) ?e) ;;end
-            (setq level (1+ level))
-          (setq level (1- level)))))
-    (or (= level 0)
+           (setq done t)))
+    (or done
+        (LaTeX-backward-up-environment)
         (error "Can't locate beginning of current environment"))))
 
 (defun LaTeX-mark-environment (&optional count)

Reply via email to