3
votes

I use latexmk to compile .tex documents via GNU Emacs + AUCTeX (my setup is described in the solution section here: Emacs + Synctex + Skim: How to correctly set up syncronization? [none of the existing methods worked properly])

By using C-c C-c, the .tex document is compiled (with pdflatex for example). The output of this process can be seen/checked via C-c C-l. Typically, there is a lot of output and it is difficult to read. Is there any way to make this output colored? If I use latexmk from the terminal, I at least get the important parts of the latexmk output highlighted.

1
Maybe you can use bits of the colorizer described in stackoverflow.com/questions/7885853/…N.N.

1 Answers

2
votes

The usual way to do this is to add font lock keywords to the major mode, but the output files are in fundamental mode, so you'll probably want to write a simple major mode with define-derived-mode like below and then advise (say C-c C-l) to turn that mode on (there's surely a better function to advise, but I'm not sure which one).

(define-derived-mode latex-output-mode fundamental-mode "LaTeX Output"
  "Simple mode for colorizing LaTeX output."
  (set (make-local-variable 'font-lock-defaults)
       '((("^!.*" . font-lock-warning-face) ; LaTeX error
          ("^-+$" . font-lock-builtin-face) ; latexmk divider
          ("^\\(?:Overfull\\|Underfull\\|Tight\\|Loose\\).*" . font-lock-string-face)
          ;; ..... 
          ))))
(defadvice TeX-recenter-output-buffer (after colorize-latex-output activate)
  (latex-output-mode))

Alternately, you could (as N.N. suggests) overwrite TeX-parse-error to add text properties or overlays highlighting the portions you are interested. This has the disadvantage that if TeX-parse-error is updated you will have to manually update your version as well, but otherwise it might be less work. Of course it will only work if it is already searching for the things you wish to highlight namely errors, warnings, overfull/underfull boxes, and file information.

An example of the second option might be:

(defun TeX-parse-error (old)
  "Goto next error.  Pop to OLD buffer if no more errors are found.
This version colorizes file name parsing helping to track down annoying bugs"
  (let ((regexp
         (concat
          ;; TeX error
          "^\\(!\\|\\(.*?\\):[0-9]+:\\) \\|"
          ;; New file
          "(\\(\"[^\"]*?\"\\|/*\
\\(?:\\.+[^()\r\n{} \\/]*\\|[^()\r\n{} .\\/]+\
\\(?: [^()\r\n{} .\\/]+\\)*\\(?:\\.[-0-9a-zA-Z_.]*\\)?\\)\
\\(?:[\\/]+\\(?:\\.+[^()\r\n{} \\/]*\\|[^()\r\n{} .\\/]+\
\\(?: [^()\r\n{} .\\/]+\\)*\\(?:\\.[-0-9a-zA-Z_.]*\\)?\\)?\\)*\\)\
)*\\(?: \\|\r?$\\)\\|"
          ;; End of file
          "\\()\\))*\\|"
          ;; Hook to change line numbers
          " !\\(?:offset(\\([---0-9]+\\))\\|"
          ;; Hook to change file name
          "name(\\([^)]+\\))\\)\\|"
          ;; LaTeX bad box
          "^\\(\\(?:Overfull\\|Underfull\\|Tight\\|Loose\\)\
 \\\\.*?[0-9]+--[0-9]+\\)\\|"
          ;; LaTeX warning
          "^\\(LaTeX [A-Za-z]*\\|Package [A-Za-z]+ \\)Warning:.*")))
    (while
        (cond
         ;; Nothing found
         ((null
           (re-search-forward regexp nil t))
          ;; No more errors.
          (message "No more errors.")
          (beep)
          (TeX-pop-to-buffer old)
          nil)

         ;; TeX error
         ((match-beginning 1)
          (put-text-property (match-beginning 2) (match-end 2)
                             'face 'font-lock-warning-face)
          (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))))
          (if (looking-at "Preview ")
              t
            (TeX-error)
            nil))

         ;; LaTeX bad box
         ((match-beginning 7)
          (put-text-property (match-beginning 0) (match-end 0)
                             'face 'font-lock-doc-face)
          (if TeX-debug-bad-boxes
              (progn
                (TeX-warning (TeX-match-buffer 7))
                nil)
            (re-search-forward "\r?\n\
\\(?:.\\{79\\}\r?\n\
\\)*.*\r?$")
            t))

         ;; LaTeX warning
         ((match-beginning 8)
          (put-text-property (match-beginning 0) (match-end 0)
                             'face 'font-lock-string-face)
          (if TeX-debug-warnings
              (progn
                (TeX-warning (TeX-match-buffer 8))
                nil)
            t))

         ;; New file -- Push on stack
         ((match-beginning 3)
          (let ((file (TeX-match-buffer 3))
                (end (match-end 3)))
            (put-text-property (match-beginning 0) (match-end 0)
                               'face 'font-lock-type-face)
            ;; Strip quotation marks and remove newlines if necessary
            (when (or (eq (string-to-char file) ?\")
                      (string-match "\n" file))
              (setq file
                    (mapconcat 'identity (split-string file "[\"\n]+") "")))
            (push file TeX-error-file)
            (push nil TeX-error-offset)
            (goto-char end))
          t)

         ;; End of file -- Pop from stack
         ((match-beginning 4)
          ;; (overlay-put
          ;;  (make-overlay (match-beginning 4) (match-end 4))
          ;;  'face 'font-lock-warning-face)
          (put-text-property (match-beginning 0) (match-end 0)
                             'face 'font-lock-warning-face)
          (when (> (length TeX-error-file) 1)
            (when (string= (pop TeX-error-file) "./auctex-bug.tex")
              (goto-char (match-end 4)))
            (pop TeX-error-offset))
          (goto-char (match-end 4))
          t)

         ;; Hook to change line numbers
         ((match-beginning 5)
          (setq TeX-error-offset
                (list (string-to-number (TeX-match-buffer 5))))
          t)

         ;; Hook to change file name
         ((match-beginning 6)
          (setq TeX-error-file
                (list (TeX-match-buffer 6)))
          t)))))