Hi Jim,

Jim Diamond <[email protected]> writes:

> 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.

Many thanks for working on this.  Please find my comments below.

> 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-fin*d*-...?

> TeX-help-error): many changes to these functions to handle error
> messages output by ConTeXt LMTX.

Can you be more specific about the changes?  We usually describe briefly
those changes.

> 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."
    ^       ^ ^

Do you have an extra space at the beginning of the second line of the
docstring?  If so, please remove it.  Are the extra spaces around t on
purpose?

> +  ;; 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))

I think you have Tabs in your change, e.g., in the line above.  AUCTeX
repo has this in its .dir-locals.el:

  (emacs-lisp-mode . ((mode . bug-reference-prog)
                      (electric-quote-comment . nil)
                      (electric-quote-string . nil)
                      (indent-tabs-mode . nil)))

I wonder where those Tabs are coming?

> +      (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))))))

  (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]"))
> +       )

No sole parenthesis in a line, please.

> +        (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."

Again, the docstring seems to be intended.

> +
> +  (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*.

Another TAB.

>            (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)))))))))

You could also do:

  (when (re-search-backward "^[0-9]+ ")
    (end-of-line)
    ...

and get rid of that `progn'.

> +           help))))
>      (goto-char (point-min))
>      (TeX-special-mode)
>      (TeX-pop-to-buffer old-buffer nil t)))

Can you please consider my comments and send a new patch?  I will try to
read the code more carefully during the next round.

TIA.  Best, Arash



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

Reply via email to