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

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

[elpa] externals/flymake-proselint 47b7618b35 3/6: Allow for file local


From: ELPA Syncer
Subject: [elpa] externals/flymake-proselint 47b7618b35 3/6: Allow for file local Proselint configurations
Date: Sat, 17 Sep 2022 16:57:42 -0400 (EDT)

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

    Allow for file local Proselint configurations
    
    * flymake-proselint.el:
    (flymake-proselint-max-errors): Add new option.
    (flymake-proselint-enable): Add new option.
    (flymake-proselint-disable): Add new option.
    (flymake-proselint-config-directory): Add new option.
    (flymake-proselint-generate-configuration): Add new function.
    (flymake-proselint-backend): Use 'flymake-proselint-generate-configuration'.
---
 flymake-proselint.el | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 196 insertions(+), 1 deletion(-)

diff --git a/flymake-proselint.el b/flymake-proselint.el
index c8e7d83608..2b2b2c965d 100644
--- a/flymake-proselint.el
+++ b/flymake-proselint.el
@@ -34,6 +34,7 @@
   (require 'subr-x)
   (require 'pcase))
 (require 'flymake)
+(require 'xdg)
 
 (defgroup flymake-proselint ()
   "Flymake backend for proselint."
@@ -50,6 +51,197 @@ The following %-sequences are replaced:
   %c - the error code"
   :type 'string)
 
+(defconst flymake-proselint--options
+  ;; Regenerate using:
+  ;;
+  ;; (with-temp-buffer
+  ;;   (call-process "proselint" nil t nil "--dump-config")
+  ;;   (goto-char (point-min))
+  ;;   (let ((config (json-parse-buffer :object-type 'alist)))
+  ;;     (mapcar #'car (alist-get 'checks config))))
+  '(airlinese.misc
+    annotations.misc
+    archaism.misc
+    cliches.hell
+    cliches.misc
+    consistency.spacing
+    consistency.spelling
+    corporate_speak.misc
+    cursing.filth
+    cursing.nfl
+    cursing.nword
+    dates_times.am_pm
+    dates_times.dates
+    hedging.misc
+    hyperbole.misc
+    jargon.misc
+    lexical_illusions.misc
+    lgbtq.offensive_terms
+    lgbtq.terms
+    links.broken
+    malapropisms.misc
+    misc.apologizing
+    misc.back_formations
+    misc.bureaucratese
+    misc.but
+    misc.capitalization
+    misc.chatspeak
+    misc.commercialese
+    misc.composition
+    misc.currency
+    misc.debased
+    misc.false_plurals
+    misc.illogic
+    misc.inferior_superior
+    misc.institution_name
+    misc.latin
+    misc.many_a
+    misc.metaconcepts
+    misc.metadiscourse
+    misc.narcissism
+    misc.not_guilty
+    misc.phrasal_adjectives
+    misc.preferred_forms
+    misc.pretension
+    misc.professions
+    misc.punctuation
+    misc.scare_quotes
+    misc.suddenly
+    misc.tense_present
+    misc.waxed
+    misc.whence
+    mixed_metaphors.misc
+    mondegreens.misc
+    needless_variants.misc
+    nonwords.misc
+    oxymorons.misc
+    psychology.misc
+    redundancy.misc
+    redundancy.ras_syndrome
+    security.credit_card
+    security.password
+    sexism.misc
+    skunked_terms.misc
+    spelling.able_atable
+    spelling.able_ible
+    spelling.athletes
+    spelling.em_im_en_in
+    spelling.er_or
+    spelling.in_un
+    spelling.misc
+    terms.animal_adjectives
+    terms.denizen_labels
+    terms.eponymous_adjectives
+    terms.venery
+    typography.diacritical_marks
+    typography.exclamation
+    typography.symbols
+    uncomparables.misc
+    weasel_words.misc
+    weasel_words.very)
+  "List of Proselint options.")
+
+(defconst flymake-proselint--custom-type
+  `(set :greedy t
+       ,@(mapcar
+          (lambda (opt)
+            ;; TODO: Add a :tag
+            `(const ,opt))
+          flymake-proselint--options))
+  "Custom option type for proselint configurations.")
+
+(defun flymake-proselint-safe-option-p (val)
+  "Check if VAL is a safe (and valid) local value."
+  (and (listp val)
+       (catch 'fail
+        (dolist (elem val)
+          (unless (memq elem flymake-proselint--options)
+            (throw 'fail nil)))
+        t)))
+
+(defcustom flymake-proselint-max-errors 1000
+  "After how many errors should Proselint give up?
+For this option to work, the user option
+`flymake-proselint-config-directory' must be non-nil."
+  :safe #'natnump
+  :type 'natnum)
+
+(defcustom flymake-proselint-enable '()
+  "List of Proselint options to enable.
+See `flymake-proselint--options' for a list of possible options.
+For this option to work, the user option
+`flymake-proselint-config-directory' must be non-nil."
+  :safe #'flymake-proselint-safe-option-p
+  :type flymake-proselint--custom-type)
+
+(defcustom flymake-proselint-disable '()
+  "List of Proselint options to disable.
+See `flymake-proselint--options' for a list of possible options.
+For this option to work, the user option
+`flymake-proselint-config-directory' must be non-nil."
+  :safe #'flymake-proselint-safe-option-p
+  :type flymake-proselint--custom-type)
+
+(defcustom flymake-proselint-config-directory
+  (when-let* ((parent (or (xdg-cache-home) (temporary-file-directory)))
+              (dir (expand-file-name "flymake-proselint" parent)))
+    (condition-case nil
+        (progn
+          (unless (file-exists-p dir)
+            (make-directory dir))
+          dir)
+      ;; In case there was an issue while creating the directory, this
+      ;; option will just be disabled.
+      (permission-denied nil)))
+  "Directory to use for temporary configuration files.
+If nil, `flymake-proselint' will not generate temporary
+configuration files.  This means that the user options
+`flymake-proselint-max-errors', `flymake-proselint-enable' and
+`flymake-proselint-disable' will have no effect.."
+  :type 'boolean)
+
+(defun flymake-proselint-generate-configuration ()
+  "Generate a configuration and return path.
+This function uses the buffer local values of
+`flymake-proselint-max-errors', `flymake-proselint-enable' and
+`flymake-proselint-disable'.  If no configuration was
+generated (either because it wasn't necessary or because disabled
+by `flymake-proselint-inhibit-configuration'), the return value
+will be nil."
+  (unless (and flymake-proselint-config-directory
+               (= flymake-proselint-max-errors 1000) ;default
+               (null flymake-proselint-enable)
+               (null flymake-proselint-disable))
+    (let ((output (expand-file-name
+                   ;; As done by `make-backup-file-name-1'
+                   (secure-hash
+                    'sha256
+                    (prin1-to-string
+                     (list (file-truename (buffer-file-name))
+                           flymake-proselint-max-errors
+                           flymake-proselint-enable
+                           flymake-proselint-disable)))
+                   flymake-proselint-config-directory)))
+      (unless (file-exists-p output)
+        (let* ((config (with-temp-buffer
+                         (call-process "proselint" nil t nil "--dump-config")
+                         (goto-char (point-min))
+                         (json-parse-buffer :object-type 'alist)))
+               (checks (alist-get 'checks config)))
+          (setf (alist-get 'checks config)
+                (mapcar
+                 (lambda (opt)
+                   (cons opt
+                         (cond
+                          ((memq opt flymake-proselint-disable) :false)
+                          ((memq opt flymake-proselint-enable)  t)
+                          ((alist-get opt checks)))))
+                 flymake-proselint--options)
+                (alist-get 'max_errors config)
+                flymake-proselint-max-errors)
+          (with-temp-file output (json-insert config))))
+      output)))
+
 (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
@@ -133,7 +325,10 @@ node (flymake) Backend functions for more details."
   (let ((proc (make-process
                :name "proselint-flymake" :noquery t :connection-type 'pipe
                :buffer (generate-new-buffer " *proselint-flymake*")
-               :command '("proselint" "--json" "-")
+               :command
+               (if-let* ((conf (flymake-proselint-generate-configuration)))
+                   (list "proselint" "--config" conf "--json" "-")
+                 '("proselint" "--json" "-"))
                :sentinel #'flymake-proselint-sentinel)))
     (process-put proc 'source (current-buffer))
     (process-put proc 'report-fn report-fn)



reply via email to

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