A 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 7877108bde8e1655678d4ba5ac13c39d806ffb3d Mon Sep 17 00:00:00 2001
From: Jim Diamond <[email protected]>
Date: Mon, 2 Mar 2026 18:33:46 -0400
Subject: [PATCH] Fix parsing of error messages for ConTeXt LMTX.
* tex.el (TeX-parse-error, TeX-fin-display-help, TeX-error)
TeX-help-error): many changes to these functions to handle error
messages output by ConTeXt LMTX. Some illuminating comments added
for the next person who touches this code. (Bug#80350)
* context.el (TeX-ConTeXt-sentinel): rewrite to reflect ConTeXt
LMTX error messages and to use `TeX-ConTeXt-sentinel-check'
instead of `TeX-TeX-sentinel-check'. Add function
`TeX-ConTeXt-sentinel-check' rather than adapting
`TeX-TeX-sentinel-check' since the ConTeXt LMTX error message
syntax is so different from that of pdftex et al. (Bug#80350)
---
context.el | 125 +++++++++++++++++++++++++++++++++++++----------------
tex.el | 121 ++++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 182 insertions(+), 64 deletions(-)
diff --git a/context.el b/context.el
index 84b3efef..3f78d4a8 100644
--- a/context.el
+++ b/context.el
@@ -567,45 +567,94 @@ 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 91d29d63..ce78d47c 100644
--- a/tex.el
+++ b/tex.el
@@ -9654,24 +9654,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
@@ -9683,18 +9687,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
@@ -9815,6 +9822,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))
@@ -9868,6 +9876,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.
@@ -9894,16 +9917,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)
@@ -9917,7 +9972,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))
@@ -10204,15 +10259,29 @@ 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))
+ (if (re-search-backward "^[0-9]+ ")
+ (progn
+ (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