From 2ebdde6e9cfe5bba337cad0a8be695f1e2bce7f8 Mon Sep 17 00:00:00 2001 From: Mark Oteiza Date: Sat, 28 Oct 2017 20:32:50 -0400 Subject: [PATCH] Add ChkTeX flymake backend for latex-mode * lisp/textmodes/tex-mode.el (tex-flymake): New custom group. (tex-chktex-program, tex-chktex-extra-flags): New custom variables. (latex-mode): Add backend to flymake-diagnostic-functions. (tex-chktex--process): New variable. (tex-chktex-command, tex-chktex): New functions. --- lisp/textmodes/tex-mode.el | 63 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el index 948743e8e5b..3da6e4e1124 100644 --- a/lisp/textmodes/tex-mode.el +++ b/lisp/textmodes/tex-mode.el @@ -55,6 +55,11 @@ :prefix "tex-" :group 'tex) +(defgroup tex-flymake nil + "Flymake backend for linting TeX files." + :prefix "tex-" + :group 'tex) + ;;;###autoload (defcustom tex-shell-file-name nil "If non-nil, the shell file name to run in the subshell used to run TeX." @@ -259,6 +264,17 @@ measured relative to that of the normal text." (float :tag "Superscript")) :version "23.1") +(defcustom tex-chktex-program "chktex" + "ChkTeX executable to use for linting TeX files." + :type 'string + :link '(url-link "man:chktex(1)") + :group 'tex-flymake) + +(defcustom tex-chktex-extra-flags nil + "Extra command line flags for `tex-chktex-program'." + :type '(repeat string) + :group 'tex-flymake) + (defvar tex-last-temp-file nil "Latest temporary file generated by \\[tex-region] and \\[tex-buffer]. Deleted when the \\[tex-region] or \\[tex-buffer] is next run, or when the @@ -1154,6 +1170,7 @@ subshell is initiated, `tex-shell-hook' is run." (setq-local fill-indent-according-to-mode t) (add-hook 'completion-at-point-functions #'latex-complete-data nil 'local) + (add-hook 'flymake-diagnostic-functions 'tex-chktex nil t) (setq-local outline-regexp latex-outline-regexp) (setq-local outline-level #'latex-outline-level) (setq-local forward-sexp-function #'latex-forward-sexp) @@ -3465,6 +3482,52 @@ There might be text before point." ;; Don't compose inside verbatim blocks. (eq 2 (nth 7 (syntax-ppss)))))))) + +;;; Flymake support + +(defvar-local tex-chktex--process nil) + +(defun tex-chktex-command () + "Return a list of command arguments for invoking ChkTeX." + `(,tex-chktex-program ,@tex-chktex-extra-flags + "--quiet" "--verbosity=0" "--inputfiles")) + +(defun tex-chktex (report-fn &rest _args) + "Flymake backend for linting TeX buffers with ChkTeX." + (unless (executable-find tex-chktex-program) + (error "Cannot find a suitable TeX checker")) + (when (process-live-p tex-chktex--process) + (kill-process tex-chktex--process)) + (let ((source (current-buffer)) + (re "^stdin:\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\):\\(.*\\)$")) + (save-restriction + (widen) + (setq tex-chktex--process + (make-process + :name "tex-chktex" + :buffer (generate-new-buffer "*tex-chktex*") + :command (tex-chktex-command) + :noquery t :connection-type 'pipe + :sentinel + (lambda (process _event) + (when (eq (process-status process) 'exit) + (unwind-protect + (when (eq process tex-chktex--process) + (with-current-buffer (process-buffer process) + (goto-char (point-min)) + (cl-loop + while (search-forward-regexp re nil t) + for msg = (match-string 4) + for line = (string-to-number (match-string 1)) + for col = (string-to-number (match-string 2)) + for (beg . end) = (flymake-diag-region source line col) + collect (flymake-make-diagnostic source beg end :warning msg) + into diags + finally (funcall report-fn diags)))) + (kill-buffer (process-buffer process))))))) + (process-send-region tex-chktex--process (point-min) (point-max)) + (process-send-eof tex-chktex--process)))) + (run-hooks 'tex-mode-load-hook) (provide 'tex-mode) -- 2.39.2