An improved patch so that AUCTeX properly parses ConTeXt LMTX error
messages.

Aside from the required lisp code, I took the liberty of adding some
comments in relevant places to assist the next person who might try to
modify this code.

                        Jim
>From 97790acadfc4e6c0fc29280c8e63d49e9398aaba Mon Sep 17 00:00:00 2001
From: Jim Diamond <[email protected]>
Date: Tue, 10 Mar 2026 14:04:10 -0300
Subject: [PATCH] Fix parsing of error messages for ConTeXt LMTX

* tex.el (TeX-parse-error): change the big regexp so that it also
matches ConTeXt LMTX error messages.  Add code to the processing
of the matches of this regexp to handle the ConTeXt case.
(TeX-error): add a condition and tweak a regexp to match the way
ConTeXt LMTX reports errors.  Add some new comments to assist
future maintainers and fix some other comments.
(TeX-find-display-help): add a comment for future maintainers.
(TeX-help-error): add a section of code to find the given error
in the ConTeXt output.  (Bug#80350)
* context.el (TeX-ConTeXt-sentinel-check): the output of ConTeXt
LMTX is very different than that of pdftex et al; consequently,
modifying `TeX-sentinel-check' to understand LMTX output might
lead to an unmaintainable mess.  Instead, create a new function.
(TeX-ConTeXt-sentinel): rewrite to reflect ConTeXt LMTX error
messages and to use `TeX-ConTeXt-sentinel-check' instead of
`TeX-TeX-sentinel-check'.  Remove deprecated Mark II code.
(Bug#80350)
---
 context.el | 124 +++++++++++++++++++++++++++++++++++++----------------
 tex.el     | 122 ++++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 181 insertions(+), 65 deletions(-)

diff --git a/context.el b/context.el
index 84b3efef..64f1179a 100644
--- a/context.el
+++ b/context.el
@@ -567,45 +567,93 @@ for a label to be inserted after the sectioning command."
 
 
 ;; Various
+
+;; This function is called with (current-buffer) = the output buffer.
+(defun TeX-ConTeXt-sentinel-check (process name)
+  "Check ConTeXt (LMTX) output buffer after running TeX.
+Return t if errors were found."
+  ;; Set TeX-current-page to (effectively) match what
+  ;; TeX-TeX-sentinel-check does:
+  ;; -> if no errors, the number of pages shipped out; and
+  ;; -> if errors, the number of pages shipped out + 1.
+  ;; Also determine the extension of the output file.
+  (save-excursion
+    (goto-char (point-max))
+    (if (re-search-backward " > flushing realpage \\([0-9]+\\), " nil t)
+        (setq TeX-current-page (TeX-match-buffer 1))
+      (setq TeX-current-page "0"))
+    ;; If running in "don't quit on error" mode, there will be a
+    ;; '^pages .* > flushing realpage' message after the '^tex error'
+    ;; message.  In this case, no need to add 1.
+    (goto-char (point-min))
+    (if (re-search-forward "^tex error" nil t)
+        (if (re-search-forward "^pages .* > flushing realpage" nil t)
+            nil
+          (setq TeX-current-page (number-to-string
+                                  (1+ (string-to-number TeX-current-page))))))
+    (setq TeX-current-page (concat "{" TeX-current-page "}"))
+    (setq TeX-output-extension "pdf"))   ;; for the last 200 years now, +/-.
+
+  (if process (TeX-format-mode-line process))
+
+  (if (catch 'found
+        (while (re-search-forward
+                "^\\(?:.*tex error on line [0-9]+ in file \\(.+?\\):\\)" nil t)
+          (if (or (not (match-beginning 1))
+                  ;; Ignore non-error warning. (bug#55065)
+                  (file-exists-p (TeX-match-buffer 1)))
+              (throw 'found t))))
+      (progn
+        (if TeX-error-overview-open-after-TeX-run
+            ;; Don't leave inconsistent message.
+            (message nil)
+          (message "%s errors in `%s'. Use %s to display."
+                   name (buffer-name)
+                   (substitute-command-keys
+                    "\\<TeX-mode-map>\\[TeX-next-error]")))
+        (setq TeX-command-next TeX-command-default)
+        ;; error reported to TeX-error-report-switches
+        (setq TeX-error-report-switches
+              (plist-put TeX-error-report-switches
+                         (intern (plist-get TeX-error-report-switches
+                                            'TeX-current-master))
+                         t))
+        t)
+    ;; In case that there were only non-error warnings of type
+    ;; bug#55065, restore point to the initial position.
+    (goto-char (point-min))
+    (setq TeX-command-next TeX-command-Show)
+    nil))
+
+
 (defun TeX-ConTeXt-sentinel (process name)
-  "Cleanup TeX output buffer after running ConTeXt."
-  (cond
-   ;; Mark IV
-   ((with-current-buffer TeX-command-buffer
-      (string= ConTeXt-Mark-version "IV"))
-    (cond ((TeX-TeX-sentinel-check process name))
-          ((re-search-forward "fatal error: " nil t)
-           (message (concat name ": problems after "
-                            (TeX-current-pages)))
-           (setq TeX-command-next TeX-command-default))
-          (t
-           (message (concat name ": successfully formatted "
-                            (TeX-current-pages)))
-           (setq TeX-command-next TeX-command-Show))))
-   ;; Mark II
-   (t
-    (cond ((TeX-TeX-sentinel-check process name))
-          ((save-excursion
-             ;; in a full ConTeXt run there will multiple texutil
-             ;; outputs.  Just looking for "another run needed" would
-             ;; find the first occurence
-             (goto-char (point-max))
-             (re-search-backward "TeXUtil " nil t)
-             (re-search-forward "another run needed" nil t))
-           (message (concat "You should run ConTeXt again "
-                            "to get references right, "
-                            (TeX-current-pages)))
-           (setq TeX-command-next TeX-command-default))
-          ((re-search-forward "removed files :" nil t)
-           (message "sucessfully cleaned up"))
-          ((re-search-forward "^ ?TeX\\(Exec\\|Util\\)" nil t) ;; strange 
regexp --pg
-           (message (concat name ": successfully formatted "
-                            (TeX-current-pages)))
-           (setq TeX-command-next TeX-command-Show))
-          (t
-           (message (concat name ": problems after "
-                            (TeX-current-pages)))
-           (setq TeX-command-next TeX-command-default)))))
+  "Examine the TeX output buffer after running ConTeXt.
+
+Parse the output buffer to collect errors and warnings if the
+variable `TeX-parse-all-errors' is non-nil.
+
+Open the error overview if
+`TeX-error-overview-open-after-TeX-run' is non-nil and there are
+errors or warnings to show."
+
+  (if (TeX-ConTeXt-sentinel-check process name)
+      (progn
+        ;; ConTeXt LMTX stops after 1 error (unless "heroic" efforts are
+        ;; made by the user to do otherwise) and if such efforts are made
+        ;; the error messages in the log file are not complete (at least
+        ;; as of ConTeXt Version 2026.02.12).  Arguably it might make
+        ;; sense to just call (TeX-parse-error) once (and set the other
+        ;; variables as seen in (TeX-parse-all-errors)).  But for now, ...
+        (if TeX-parse-all-errors
+            (TeX-parse-all-errors))
+        (if (and (with-current-buffer TeX-command-buffer
+                   TeX-error-overview-open-after-TeX-run)
+                 (TeX-error-overview-make-entries
+                  (TeX-master-directory) (TeX-active-buffer)))
+            (TeX-error-overview)))
+
+    (message (concat name ": formatted " (TeX-current-pages)))
+    (setq TeX-command-next TeX-command-Show))
   (unless TeX-error-list
     (run-hook-with-args 'TeX-after-compilation-finished-functions
                         (with-current-buffer TeX-command-buffer
diff --git a/tex.el b/tex.el
index b34ab258..8a5c047a 100644
--- a/tex.el
+++ b/tex.el
@@ -8574,7 +8574,7 @@ errors or warnings to show."
     (run-hook-with-args 'TeX-after-compilation-finished-functions
                         (with-current-buffer TeX-command-buffer
                           (expand-file-name
-                          (TeX-active-master (TeX-output-extension)))))))
+                           (TeX-active-master (TeX-output-extension)))))))
 
 (defun TeX-current-pages ()
   "Return string indicating the number of pages formatted."
@@ -9652,24 +9652,28 @@ displaying the issue.
 Return non-nil if an error or warning is found."
   (let ((regexp
          (concat
-          ;; TeX error
+          ;; TeX error: grab (1) filename:line-number and (2) filename:
           "^\\(!\\|\\(.+?\\):[0-9]+:\\) \\|"
-          ;; New file
+          ;; New file (or parenthesized comment): match 3
           "(\n?\\([^\n()]+\\)\\|"
-          ;; End of file.
+          ;; End of file (or comment): "match" 4
           "\\()\\)\\|"
-          ;; Hook to change line numbers
+          ;; Hook to change line numbers: match 5
           " !\\(?:offset(\\([---0-9]+\\))\\|"
-          ;; Hook to change file name
+          ;; Hook to change file name: match 6
           "name(\\([^)]+\\))\\)\\|"
-          ;; Start of LaTeX bad box
+          ;; Start of LaTeX bad box: match 7
           "^\\(\\(?:Overfull\\|Underfull\\|Tight\\|Loose\\) "
           ;;   Horizontal bad box
           "\\(?:\\\\hbox.* at lines? [0-9]+\\(?:--[0-9]+\\)?$\\|"
           ;;   Vertical bad box.  See also `TeX-warning'.
           "\\\\vbox ([ a-z0-9]+) has occurred while \\\\output is active 
\\[[^]]+\\]\\)\\)\\|"
-          ;; LaTeX warning
-          "^\\(" LaTeX-warnings-regexp ".*\\)"))
+          ;; LaTeX warning: match 8
+          "^\\(" LaTeX-warnings-regexp ".*\\)"
+          ;; ConTeXt LMTX error; sample output line:
+          ;; tex error       > tex error on line 5 in file ./bbb.tex: ! 
Undefined control sequence
+          ;; Grab (9) entire line and (10) filename
+          "\\|^\\(tex error .* in file \\([^:]*\\): \\)"))
         (error-found nil))
     (while
         (cond
@@ -9681,18 +9685,21 @@ Return non-nil if an error or warning is found."
             (beep)
             (TeX-pop-to-buffer old))
           nil)
-         ;; TeX error
-         ((match-beginning 1)
-          (if (or (not (match-beginning 2))
-                  ;; Ignore non-error warning. (bug#55065)
-                  (file-exists-p (TeX-match-buffer 2)))
+         ;; TeX/LaTeX (1) or ConTeXt LMTX (9) error:
+         ((or (match-beginning 1) (match-beginning 9))
+          (if (or ;; Ignore non-error warning. (bug#55065)
+                  (file-exists-p (TeX-match-buffer 2))
+                  (file-exists-p (TeX-match-buffer 10)))
               (progn
-                (when (match-beginning 2)
-                  (unless TeX-error-file
-                    (push nil TeX-error-file)
-                    (push nil TeX-error-offset))
-                  (unless (car TeX-error-offset)
-                    (rplaca TeX-error-file (TeX-match-buffer 2))))
+                (unless TeX-error-file
+                  (push nil TeX-error-file)
+                  (push nil TeX-error-offset))
+                (unless (car TeX-error-offset)
+                  ;; match 2 or 10 is the .tex file name.
+                  (rplaca TeX-error-file
+                    (if (match-beginning 2)
+                      (TeX-match-buffer 2)
+                      (TeX-match-buffer 10))))
                 (setq error-found t)
                 (if (looking-at "Preview ")
                     t
@@ -9813,6 +9820,7 @@ value is not used here."
           (setq-local TeX-command-buffer command-buffer)
 
           ;; Find the location of the error or warning.
+          ;; Note: we are searching in the TeX/ConTeXt *source file*.
           (let ((narrowed (buffer-narrowed-p))
                 (visible-min (point-min))
                 (visible-max (point-max))
@@ -9866,6 +9874,21 @@ value is not used here."
           (t
            (message "! %s" TeX-translate-location-error)))))
 
+
+;; TeX and ConTeXt LMTX error messages are formatted differently (and thus
+;; some tweakings are necessary for ConTeXt error messages to be parsed).
+;; E.g., in TeX:
+;; ./file.tex:9: Undefined control sequence.
+;; l.9 blah blah \undefinedINplainTEX
+;;                                       <<< line with many initial spaces
+;; and in ConTeXt:
+;; tex error       > tex error on line 9 in file ./file.tex: Undefined control 
sequence
+;;                                       <<<--- empty line here
+;; <line 3.9> 
+;;    aardvark \undefinedINcontext
+;;                                       <<<--- empty line here
+;; Because of how the parsing is done below, these formatting differences
+;; must be handled.
 (defun TeX-error (&optional store)
   "Display an error.
 
@@ -9892,16 +9915,48 @@ information in `TeX-error-list' instead of displaying 
the error."
                    (re-search-backward ":\\([0-9]+\\): "
                                        (line-beginning-position) t))
                  (string-to-number (TeX-match-buffer 1)))
+                ;; ConTeXt: ^<line n.[linenum]>\n +[error message]'
+                ((re-search-forward "^<line [^.]+[.]\\([0-9]+\\)>" nil t)
+                 ;; Need this in the ConTeXt case for the 'string' search
+                 ;; (just below here) to work correctly (FWIW):
+                 (forward-line)
+                 (setq context-available t)
+                 ;; ConTeXt has a blank line where pdftex does not; adjust:
+                 (setq context-start (1+ context-start))
+                 (string-to-number (TeX-match-buffer 1)))
                 ;; nothing found
                 (t 1)))
 
-         ;; And a string of the context to search for.
+         ;; Save a string of the error token, used to position the cursor
+         ;; in the source file.
+         ;; plain TeX example of what we are looking at:
+         ;; ((point) is before ' aard...')
+         ;; l.9 aardvark \undefinedINplainTEX
+         ;;                                  \n
+         ;; ConTeXt:
+         ;; ((point) is before '    aard...')
+         ;;     aardvark \undefinedINcontext
+         ;; \n   
+         ;; The pdftex error message *always* has a line starting with
+         ;; spaces after the error line.
+         ;; ConTeXt LMTX (V 2026.02.12 anyway) does not have such a thing
+         ;; when the error token is at the end of a line.  Because of the
+         ;; space chars on the line following the pdftex error message, the
+         ;; (following) regexp in the previous version of this function 
+         ;; didn't include the \n at the end of the line(s).
+         ;; However, since ConTeXt may have no space chars on the next
+         ;; line, the match includes the \n, which causes TeX-next-error to
+         ;; position the cursor incorrectly.
+         ;; This regexp deals with this problem.
          (string (progn
                    (beginning-of-line)
-                   (re-search-forward " \\(\\([^ \t]*$\\)\\|\\($\\)\\)")
+                   (re-search-forward " \\(\\([^ \t\n\r]*$\\)\\|\\($\\)\\)")
                    (TeX-match-buffer 1)))
 
-         ;; And we have now found to the end of the context.
+         ;; (point) is now positioned at the end of the input line
+         ;; which caused this error (TeX) or the beginning of the next 
+         ;; line (ConTeXt).  To find the error context, rather than searching 
+         ;; just use (point) and locations we saved above.
          (context (if context-available
                       (buffer-substring context-start (progn (forward-line 1)
                                                              (end-of-line)
@@ -9915,7 +9970,7 @@ information in `TeX-error-list' instead of displaying the 
error."
          (file (car TeX-error-file))
          info-list)
 
-    ;; Remember where we was.
+    ;; Remember where we were.
     (setq TeX-error-point (point)
           info-list (list 'error file line error offset context string nil nil
                           TeX-error-point nil))
@@ -10202,15 +10257,28 @@ a bad box."
                         (insert-file-contents log-file nil nil nil 'replace)
                         (setq TeX--log-file-readin-modtime modtime)))
                     (goto-char (point-min))
-                    (when (and (search-forward error nil t 1)
+                    (if (and (search-forward error nil t 1)
                                (re-search-forward "^l\\." nil t)
                                (re-search-forward "^ [^\n]+$" nil t))
                       (let ((start (1+ (point))))
                         (forward-char 1)
                         (re-search-forward "^$")
                         (concat "From the .log file...\n\n"
-                                (buffer-substring start (point)))))))
-             help))))
+                                (buffer-substring start (point))))
+                      ;; ConTeXt case: assume just one error per run,
+                      ;; since it requires some ConTeXt wizardry to not
+                      ;; stop on the first error, and, if the run
+                      ;; doesn't stop on the first error, getting
+                      ;; meaningful info from the log file is very
+                      ;; difficult.
+                      (goto-char (point-max))
+                      (when (re-search-backward "^[0-9]+ ")
+                          (end-of-line)
+                          (let ((start (1+ (point))))
+                            (goto-char (point-max))
+                            (concat "From the .log file...\n\n"
+                              (buffer-substring start (point))))))))
+           help))))
     (goto-char (point-min))
     (TeX-special-mode)
     (TeX-pop-to-buffer old-buffer nil t)))
-- 
2.46.4

_______________________________________________
bug-auctex mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/bug-auctex

Reply via email to