emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/flymake-proselint 30c4baa08d 1/6: Generate and parse JS


From: ELPA Syncer
Subject: [elpa] externals/flymake-proselint 30c4baa08d 1/6: Generate and parse JSON output
Date: Sat, 17 Sep 2022 16:57:42 -0400 (EDT)

branch: externals/flymake-proselint
commit 30c4baa08db32e73d956c978c81a9f79062c2e1d
Author: Philip Kaludercic <philipk@posteo.net>
Commit: Manuel Uberti <manuel.uberti@inventati.org>

    Generate and parse JSON output
    
    * flymake-proselint.el
    (flymake-proselint-sentinel-1): Add new function for translating JSON
    objects to Flymake diagnostics.
    (flymake-proselint-sentinel): Extract sentinel into a separate function.
    (flymake-proselint-backend): Use 'flymake-proselint-sentinel'.
---
 flymake-proselint.el | 118 ++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 83 insertions(+), 35 deletions(-)

diff --git a/flymake-proselint.el b/flymake-proselint.el
index 91d1fec92b..4908197720 100644
--- a/flymake-proselint.el
+++ b/flymake-proselint.el
@@ -30,54 +30,102 @@
 
 ;;; Code:
 
+(eval-when-compile
+  (require 'subr-x)
+  (require 'pcase))
 (require 'flymake)
 
+(defun flymake-proselint-sentinel-1 (source data)
+  "Handle a successfully parsed DATA from SOURCE.
+DATA is a list of error diagnostics that are converted into
+Flymake diagnostic objects."
+  (let (diags)
+    (dolist (err (plist-get data :errors))
+      (push (flymake-make-diagnostic
+             source
+             (plist-get err :start)
+             (plist-get err :end)
+             (pcase (plist-get err :severity)
+               ("warning"      :warning)
+               ("suggestion"   :note)
+               (_              :error))
+             (with-temp-buffer         ;create a message
+               (insert (plist-get err :message))
+               (let ((replacements (plist-get err :replacements)))
+                 (cond
+                  ((or (eq replacements :null) (null replacements))
+                   ;; There are no replacements.
+                   )
+                  ((stringp replacements)
+                   (insert " (Replacement: " replacements ")"))
+                  ((listp replacements)
+                   (insert " (Replacements: "
+                           (mapconcat
+                            (lambda (r)
+                              (plist-get r :unique))
+                            replacements ", ")
+                           ")"))))
+               (buffer-string)))
+            diags))
+    diags))
+
 (defvar-local flymake-proselint--flymake-proc nil)
 
+(defun flymake-proselint-sentinel (proc _event)
+  "Sentinel on PROC for handling Proselint response.
+A successfully parsed message is passed onto the function
+`flymake-proselint-sentinel-1' for further handling."
+  (pcase (process-status proc)
+    ('exit
+     (let ((report-fn (process-get proc 'report-fn))
+           (source (process-get proc 'source)))
+       (unwind-protect
+           (with-current-buffer (process-buffer proc)
+             (goto-char (point-min))
+             (cond
+              ((with-current-buffer source
+                 (not (eq proc flymake-proselint--flymake-proc)))
+               (flymake-log :warning "Canceling obsolete check %s" proc))
+              ((= (point-max) (point-min))
+               (flymake-log :debug "Empty response"))
+              ((condition-case err
+                   (let ((response (json-parse-buffer :object-type 'plist
+                                                      :array-type 'list)))
+                     (if (string= (plist-get response :status) "success")
+                         (thread-last
+                           (plist-get response :data)
+                           (flymake-proselint-sentinel-1 source)
+                           (funcall report-fn))
+                       (flymake-log :error "Check failed")))
+                 (json-parse-error
+                  (flymake-log :error "Invalid response: %S" err))))))
+         (with-current-buffer source
+           (setq flymake-proselint--flymake-proc nil))
+         (kill-buffer (process-buffer proc)))))
+    ('signal (kill-buffer (process-buffer proc)))))
+
 (defun flymake-proselint-backend (report-fn &rest _args)
+  "Flymake backend for Proselint.
+REPORT-FN is the flymake reporter function.  See the Info
+node (flymake) Backend functions for more details."
   (unless (executable-find "proselint")
     (user-error "Executable proselint not found on PATH"))
 
   (when (process-live-p flymake-proselint--flymake-proc)
     (kill-process flymake-proselint--flymake-proc))
 
-  (let ((source (current-buffer)))
+  (let ((proc (make-process
+               :name "proselint-flymake" :noquery t :connection-type 'pipe
+               :buffer (generate-new-buffer " *proselint-flymake*")
+               :command '("proselint" "--json" "-")
+               :sentinel #'flymake-proselint-sentinel)))
+    (process-put proc 'source (current-buffer))
+    (process-put proc 'report-fn report-fn)
+    (setq flymake-proselint--flymake-proc proc)
     (save-restriction
       (widen)
-      (setq
-       flymake-proselint--flymake-proc
-       (make-process
-        :name "proselint-flymake" :noquery t :connection-type 'pipe
-        :buffer (generate-new-buffer " *proselint-flymake*")
-        :command '("proselint" "-")
-        :sentinel
-        (lambda (proc _event)
-          (when (memq (process-status proc) '(exit signal))
-            (unwind-protect
-                (if (with-current-buffer source (eq proc 
flymake-proselint--flymake-proc))
-                    (with-current-buffer (process-buffer proc)
-                      (goto-char (point-min))
-                      (cl-loop
-                       while (search-forward-regexp
-                              "^.+:\\([[:digit:]]+\\):\\([[:digit:]]+\\): 
\\(.+\\)$"
-                              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)))
-                       collect (flymake-make-diagnostic source
-                                                        beg
-                                                        end
-                                                        :warning
-                                                        msg)
-                       into diags
-                       finally (funcall report-fn diags)))
-                  (flymake-log :warning "Canceling obsolete check %s"
-                               proc))
-              (kill-buffer (process-buffer proc)))))))
-      (process-send-region flymake-proselint--flymake-proc (point-min) 
(point-max))
-      (process-send-eof flymake-proselint--flymake-proc))))
+      (process-send-region proc (point-min) (point-max))
+      (process-send-eof proc))))
 
 ;;;###autoload
 (defun flymake-proselint-setup ()



reply via email to

[Prev in Thread] Current Thread [Next in Thread]