summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormgmarlow <graham@mgmarlow.com>2023-06-12 19:59:44 -0700
committermgmarlow <graham@mgmarlow.com>2023-06-12 19:59:44 -0700
commit217ff0ca6e4d4f9e1290d830456a82312cd2b008 (patch)
tree747f7cdc042b87434b1c24a6572851431d99d8eb
parent3b136e9ce8905740d076e5222599dc59decba32c (diff)
parent8f735f72bd109745fa7032502aa253759c661850 (diff)
downloadflymake-clippy-217ff0ca6e4d4f9e1290d830456a82312cd2b008.tar.gz
Merge branch 'clippy-flymake'
-rw-r--r--Makefile7
-rw-r--r--README.md22
-rw-r--r--clippy-flymake.el58
3 files changed, 85 insertions, 2 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..3acc1df
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,7 @@
+.PHONY: build clean
+
+build: clean
+ emacs -batch -L . -f batch-byte-compile clippy-flymake.el
+
+clean:
+ rm -f clippy-flymake.elc
diff --git a/README.md b/README.md
index b799486..504c795 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,23 @@
# flymake-clippy
-A Flymake backend for Clippy.
+A Flymake backend for [Clippy](https://doc.rust-lang.org/stable/clippy/index.html), the Rust linter.
+
+## Instructions
+
+Use with [rust-mode](https://elpa.nongnu.org/nongnu/rust-mode.html):
+
+```elisp
+(add-hook 'rust-mode-hook #'clippy-flymake-setup-backend)
+```
+
+## Eglot users
+
+Eglot [fully manages Flymake](https://github.com/joaotavora/eglot/issues/268) so you'll need some extra code to make it cooperate:
+
+```elisp
+(add-to-list 'eglot-stay-out-of 'flymake)
+
+(add-hook 'eglot--managed-mode-hook
+ (lambda ()
+ (add-hook 'flymake-diagnostic-functions #'eglot-flymake-backend nil t)))
+```
diff --git a/clippy-flymake.el b/clippy-flymake.el
index df5624a..e268c63 100644
--- a/clippy-flymake.el
+++ b/clippy-flymake.el
@@ -1,4 +1,8 @@
+<<<<<<< HEAD
;;; flymake-clippy.el --- Flymake backend for Clippy -*- lexical-binding: t; -*-
+=======
+;;; flymake-clippy.el --- Flymake backend for cargo clippy -*- lexical-binding: t; -*-
+>>>>>>> @{-1}
;; Copyright (C) 2023 Graham Marlow
@@ -20,9 +24,61 @@
;;; Commentary:
-;; Flymake backend for Clippy.
+;; Flymake backend for Clippy, the Rust linter.
+;; https://doc.rust-lang.org/stable/clippy/index.html
;;; Code:
+(defun clippy-flymake (report-fn &rest _args)
+ "Flymake backend for cargo clippy."
+ (unless (executable-find "cargo")
+ (error "Cannot find cargo"))
+
+ (let* ((source (current-buffer))
+ (filename (file-name-nondirectory (buffer-file-name source))))
+ (save-restriction
+ (widen)
+ (setq clippy--flymake-proc
+ (make-process
+ :name "clippy-flymake" :noquery t :connection-type 'pipe
+ :buffer (generate-new-buffer "*clippy-flymake*")
+ :command '("cargo" "clippy")
+ :sentinel
+ (lambda (proc _event)
+ (when (memq (process-status proc) '(exit signal))
+ (unwind-protect
+ (if (with-current-buffer source (eq proc clippy--flymake-proc))
+ (with-current-buffer (process-buffer proc)
+ (goto-char (point-min))
+ ;; Collect output buffer into diagnostic messages/locations,
+ ;; exposing them via `report-fn'.
+ (cl-loop
+ while (search-forward-regexp
+ ;; Capture group source example:
+ ;; "warning: ..."
+ ;; --> src/filename.rs
+ ;; 98 | ...
+ (concat "^\\(warning:.*\\)\n\\(.*" filename "\\):\\([0-9]+\\):\\([0-9]+\\)$")
+ nil t)
+ for msg = (match-string 1)
+ for (beg . end) = (flymake-diag-region
+ source
+ (string-to-number (match-string 3)))
+ for type = (if (string-match "^warning" msg)
+ :warning
+ :error)
+ collect (flymake-make-diagnostic source beg end type msg)
+ into diags
+ finally (funcall report-fn diags)))
+ (flymake-log :warning "Canceling obsolete check %s" proc))
+ ;; Cleanup temp buffer.
+ (kill-buffer (process-buffer proc)))))))
+ (process-send-region clippy--flymake-proc (point-min) (point-max))
+ (process-send-eof clippy--flymake-proc))))
+
+(defun clippy-flymake-setup-backend ()
+ "Add `clippy-flymake' to `flymake-diagnostic-functions' hook."
+ (add-hook 'flymake-diagnostic-functions #'clippy-flymake nil t))
+
(provide 'flymake-clippy)
;;; flymake-clippy.el ends here