From 34836e33cc7ff08e66443c6bc10a142c950f35b4 Mon Sep 17 00:00:00 2001 From: Justin Date: Mon, 4 Nov 2024 18:24:45 -0800 Subject: [PATCH] Add Flycheck and Flymake for error reporting (#109) * feat: define a flycheck checker * feat: add flymake support * feat: only report message if other backends aren't running * chore: update DS_Store * chore: add documentation on error reporting with flycheck and flymake --- .gitignore | 3 +- parinfer-rust-flycheck.el | 72 +++++++++++++++++++++++++++++++++++++++ parinfer-rust-flymake.el | 53 ++++++++++++++++++++++++++++ parinfer-rust-mode.el | 16 +++++++-- readme.org | 15 ++++++++ 5 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 parinfer-rust-flycheck.el create mode 100644 parinfer-rust-flymake.el diff --git a/.gitignore b/.gitignore index dccb2aa..760ce71 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ elpa-emacs .cask/* -.node_modules/ \ No newline at end of file +.node_modules/ +.DS_Store \ No newline at end of file diff --git a/parinfer-rust-flycheck.el b/parinfer-rust-flycheck.el new file mode 100644 index 0000000..7daceed --- /dev/null +++ b/parinfer-rust-flycheck.el @@ -0,0 +1,72 @@ +;;; parinfer-rust-flycheck.el --- Flycheck integration for parinfer-rust-mode -*- lexical-binding: t; -*- + +;; Copyright (C) 2024 Justin Barclay + +;; Author: Justin Barclay + +;; This program 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 of the License, or +;; (at your option) any later version. + +;; This program 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 this program. If not, see . + +;; This file is not part of GNU Emacs. + +;;; Commentary: +;; An assortment of helper functions and ports of functions from Emacs + +;;; Code: +(eval-when-compile + (declare-function flycheck-error-new-at "flycheck") + (declare-function flycheck-define-generic-checker "flycheck") + (defvar parinfer-rust--error nil)) + +(require 'flycheck nil t) + +(defun parinfer-rust--flycheck-start (checker callback) + (funcall callback 'finished + (when-let ((error parinfer-rust--error)) + (list + (flycheck-error-new-at + (+ 1 (plist-get error :line_no)) + (+ 1 (plist-get error :x)) + 'error + (plist-get error :message) + :id (plist-get error :name) + :checker checker))))) + +(flycheck-define-generic-checker 'parinfer-rust + "A checker for parinfer-rust." + :start 'parinfer-rust--flycheck-start + :verify (lambda (&rest args) + (list (flycheck-verification-result-new + :label "parinfer-rust-mode" + :message (if parinfer-rust-mode + "enabled" + "not enabled")))) + :modes '(clojure-mode + clojurec-mode + clojurescript-mode + clojure-ts-mode + clojure-ts-clojurescript-mode + janet-mode + common-lisp-mode + lisp-mode + racket-mode + scheme-mode + lisp-interaction-mode + emacs-lisp-mode)) + +(flycheck-add-next-checker 'emacs-lisp 'parinfer-rust t) + +(add-to-list 'flycheck-checkers 'parinfer-rust t) + +(provide 'parinfer-rust-flycheck) +;;; parinfer-rust-flycheck.el ends here diff --git a/parinfer-rust-flymake.el b/parinfer-rust-flymake.el new file mode 100644 index 0000000..3fb3087 --- /dev/null +++ b/parinfer-rust-flymake.el @@ -0,0 +1,53 @@ +;;; parinfer-rust-flymake.el --- Flymake integration for parinfer-rust-mode -*- lexical-binding: t; -*- + +;; Copyright (C) 2024 Justin Barclay + +;; Author: Justin Barclay + +;; This program 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 of the License, or +;; (at your option) any later version. + +;; This program 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 this program. If not, see . + +;; This file is not part of GNU Emacs. + +;;; Commentary: +;; + +;;; Code: + +(require 'flymake) + +(eval-when-compile + (defvar parinfer-rust--error nil)) + +(defun parinfer-rust-flymake (report-fn &rest _args) + (funcall report-fn + (when-let ((error parinfer-rust--error)) + (list + (let ((loc (flymake-diag-region + (current-buffer) + (+ 1 (plist-get error :line_no)) + (+ 1 (plist-get error :x))))) + (flymake-make-diagnostic + (current-buffer) + (car loc) + (cdr loc) + :error + (plist-get error :message))))))) + +(defun parinfer-rust-setup-flymake () + (add-hook 'flymake-diagnostic-functions 'parinfer-rust-flymake nil t)) + +(add-hook 'parinfer-rust-mode-hook 'parinfer-rust-setup-flymake) + +(provide 'parinfer-rust-flymake) +;;; parinfer-rust-flymake.el ends here diff --git a/parinfer-rust-mode.el b/parinfer-rust-mode.el index 13aed75..a49f623 100644 --- a/parinfer-rust-mode.el +++ b/parinfer-rust-mode.el @@ -407,6 +407,12 @@ See `parinfer-rust--option-type' for a more complete explanation of the options. (require 'subr-x) (require 'font-lock) +(with-eval-after-load 'flycheck + (require 'parinfer-rust-flycheck)) + +(with-eval-after-load 'flymake + (require 'parinfer-rust-flymake)) + (defconst parinfer-rust--mode-types '("indent" "smart" "paren") "The different modes that parinfer can operate on.") @@ -620,10 +626,16 @@ CHANGES." (when (and (local-variable-if-set-p 'parinfer-rust--in-debug) parinfer-rust--in-debug) (parinfer-rust-debug "./parinfer-rust-debug.txt" options answer)) - (if parinfer-error + (setq parinfer-rust--error parinfer-error) + ;; If we have an error and are not being reported by a backend, warn the user + (if (and parinfer-error + (not (and (boundp 'flycheck-mode) + (memq 'parinfer-rust flycheck--automatically-enabled-checkers))) + (not (and (boundp 'flymake-mode) + (memq 'parinfer-rust-flymake (flymake-reporting-backends))))) (message "Problem on line %s: %s" (plist-get parinfer-error :line_no) - (plist-get parinfer-error :message)) ;; TODO - Handler errors + (plist-get parinfer-error :message)) ;; This stops Emacs from flickering when scrolling (if (not (string-equal parinfer-rust--previous-buffer-text replacement-string)) (save-mark-and-excursion diff --git a/readme.org b/readme.org index be6ffa3..09833b9 100644 --- a/readme.org +++ b/readme.org @@ -220,6 +220,21 @@ Options: #+begin_quote default: safe #+end_quote +** Error reporting +parinfer-rust-mode uses flycheck and flymake to report parsing errors. +*** Flymake +There should be no config needed to work in ==flymake-mode== is enabled. +*** Flycheck +parinfer-rust-mode is set-up to be chained with the ==emacs-lisp== checker. + +However, if you want it to work alongside other checkers you'll need to [[https://www.flycheck.org/en/latest/user/syntax-checkers.html#configuring-checker-chains][chain]] it yourself. +#+begin_src emacs-lisp + (use-package parinfer-rust-mode + :config + (flycheck-add-next-checker 'emacs-lisp 'parinfer-rust t)) +#+end_src +*** Message buffer +If neither Flycheck or Flymake are enabled then ==parinfer-rust-mode== will output the error to ==*Messages*== buffer. ** parinfer-mode There is an alternate implementation of Parinfer for Emacs called [[https://github.com/DogLooksGood/parinfer-mode][parinfer-mode]]. It currently has support for Parinfer's "paren" and "indent". Additionally, it has had experimental support for "smart" mode, however, this has remained hidden on a branch and not accessible from MELPA for over a year. parinfer-smart-mode aims to be a simpler adaptation of Parinfer that just offers "smart mode", leveraging the parinfer-rust plugin to do most of the heavy lifting.