;;; latex-flymake.el --- Flymake integration -*- lexical-binding: t; -*- ;; Copyright (C), 2018--2024 Free Software Foundation, Inc. ;; Author: Alex Branham ;; Maintainer: auctex-devel@gnu.org ;; Created: 2018-02-11 ;; Keywords: tex ;; This file is part of AUCTeX. ;; AUCTeX is free software; you can redistribute it and/or modify it ;; under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; AUCTeX is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with AUCTeX; see the file COPYING. If not, write to the Free ;; Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ;; 02110-1301, USA. ;;; Commentary: ;; This file provides flymake integration for latex documents using ;; "chktex" as a backend. You must be running Emacs 26 or newer. ;; Enable it by adding the following to your init file: ;; (add-hook 'LaTeX-mode-hook #'flymake-mode) ;;; Code: (eval-when-compile (require 'cl-lib)) (require 'flymake) (defvar-local LaTeX--flymake-proc nil) (defcustom LaTeX-flymake-chktex-options nil "A list of strings passed as options to the chktex backend. You can use this to enable or disable specific warnings by setting it to something like: \\='(\"-n12\" \"-w41\") Which would disable warning 12 (\"interword spacing should perhaps be used\") and enable 41 (\"you ought not to use primitive TeX in LaTeX code\"). See the chktex manual for warning numbers and details about how to use flags." :type '(choice (const :tag "Use chktex defaults" nil) (repeat :tag "Custom chktex options" string)) :group 'LaTeX) (defun LaTeX-flymake (report-fn &rest _args) "Setup flymake integration. REPORT-FN is flymake's callback function." (unless (executable-find "chktex") (error "Cannot find chktex")) (when (process-live-p LaTeX--flymake-proc) (kill-process LaTeX--flymake-proc)) (let ((source (current-buffer))) (save-restriction (widen) (setq LaTeX--flymake-proc (make-process :name "LaTeX-flymake" :noquery t :connection-type 'pipe :buffer (generate-new-buffer " *LaTeX-flymake*") :command `("chktex" "--verbosity=0" "--quiet" "--inputfiles" ,@LaTeX-flymake-chktex-options) :sentinel (lambda (proc _event) (when (eq 'exit (process-status proc)) (unwind-protect (if (with-current-buffer source (eq proc LaTeX--flymake-proc)) (with-current-buffer (process-buffer proc) (goto-char (point-min)) (cl-loop while (search-forward-regexp (rx line-start "stdin:" ;; line (group-n 1 (one-or-more num)) ":" ;; column (group-n 2 (one-or-more num)) ":" ;; This is information about the ;; number of the warning, which we ;; probably don't care about: (one-or-more num) ":" ;; Warning message: (group-n 3 (one-or-more not-newline)) line-end) nil t) for msg = (match-string 3) for (beg . end) = (flymake-diag-region source (string-to-number (match-string 1)) (string-to-number (match-string 2))) for type = :warning collect (flymake-make-diagnostic source beg end type msg) into diags finally (funcall report-fn diags))) (flymake-log :warning "Canceling obsolete check %s" proc)) (kill-buffer (process-buffer proc))))))) (process-send-region LaTeX--flymake-proc (point-min) (point-max)) (process-send-eof LaTeX--flymake-proc)))) (provide 'latex-flymake) ;;; latex-flymake.el ends here