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)