[PATCH] latex-mode flymake backend

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] latex-mode flymake backend

Mark Oteiza
Hi,

Here is a patch for a flymake backend using chktex.

diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el
index 948743e8e5..5e778ec526 100644
--- a/lisp/textmodes/tex-mode.el
+++ b/lisp/textmodes/tex-mode.el
@@ -55,6 +55,11 @@ tex-view
   :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 @@ tex-font-script-display
                (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 @@ latex-mode
   (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 @@ tex--prettify-symbols-compose-p
            ;; 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)))
+    (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)
+               (unwind-protect
+                   (when (eq process tex-chktex--process)
+                     (with-current-buffer (process-buffer process)
+                       (goto-char (point-min))
+                       (cl-loop
+                        while (search-forward-regexp
+                               "^stdin:\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\):\\(.*\\)$"
+                               nil t)
+                        for msg = (match-string 4)
+                        for (beg . end) = (flymake-diag-region source
+                                                               (string-to-number (match-string 1))
+                                                               (string-to-number (match-string 2)))
+                        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)

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] latex-mode flymake backend

João Távora
Mark Oteiza <[hidden email]> writes:

> Here is a patch for a flymake backend using chktex.

Hi Mark, just a couple of comments below the sig.

João

> +            (make-process
> +             :name "tex-chktex"
> +             :buffer (generate-new-buffer "*tex-chktex*")
> +             :command (tex-chktex-command)
> +             :noquery t :connection-type 'pipe
> +             :sentinel
> +             (lambda (process _event)

Before proceeding to the unwind-protect form, I think you have to check
that 'process' has indeed exited by using

(when (eq (process-status process) 'exit)
  (unwind-protect ...))

According to Stefan, the sentinel also runs when the process is merely
suspended.

> +               (unwind-protect
> +                   (when (eq process tex-chktex--process)

Are you sure you don't want to additionally check process-exit-status
for 0 here? (it's OK if you know you don't, GCC for example exits non-0
with suitable output)

> +                     (with-current-buffer (process-buffer process)
> +                       (goto-char (point-min))
> +                       (cl-loop
> +                        while (search-forward-regexp
> +                               "^stdin:\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\):\\(.*\\)$"
> +                               nil t)
> +                        for msg = (match-string 4)
> +                        for (beg . end) = (flymake-diag-region source
> +                                                               (string-to-number (match-string 1))
> +                                                               (string-to-number (match-string 2)))

Someone else will nitpick you on the 80 cols :-)