branch: elpa/flymake-collection
commit 013a53a10632f0f498697030354abd31ca74d5ce
Author: Mohsin Kaleem <mohk...@kisara.moe>
Commit: Mohsin Kaleem <mohk...@kisara.moe>

    (flymake-rest): Add several checkers
---
 checkers/flymake-rest-awk-gawk.el     | 29 +++++++++++++++++++++
 checkers/flymake-rest-clang.el        | 48 ++++++++++++++++++++++++++++++++++
 checkers/flymake-rest-eslint.el       | 46 ++++++++++++++++++++++++++++++++
 checkers/flymake-rest-gcc.el          | 49 +++++++++++++++++++++++++++++++++++
 checkers/flymake-rest-html-tidy.el    | 26 +++++++++++++++++++
 checkers/flymake-rest-jq.el           | 29 +++++++++++++++++++++
 checkers/flymake-rest-jsonlint.el     | 26 +++++++++++++++++++
 checkers/flymake-rest-less.el         | 28 ++++++++++++++++++++
 checkers/flymake-rest-markdownlint.el | 31 ++++++++++++++++++++++
 checkers/flymake-rest-mypy.el         | 34 ++++++++++++++++++++++++
 checkers/flymake-rest-proselint.el    | 41 +++++++++++++++++++++++++++++
 checkers/flymake-rest-pycodestyle.el  | 26 +++++++++++++++++++
 checkers/flymake-rest-pylint.el       | 46 ++++++++++++++++++++++++++++++++
 checkers/flymake-rest-rubocop.el      | 49 +++++++++++++++++++++++++++++++++++
 checkers/flymake-rest-shellcheck.el   | 44 +++++++++++++++++++++++++++++++
 checkers/flymake-rest-yamllint.el     | 25 ++++++++++++++++++
 16 files changed, 577 insertions(+)

diff --git a/checkers/flymake-rest-awk-gawk.el 
b/checkers/flymake-rest-awk-gawk.el
new file mode 100644
index 0000000000..09fb6cf814
--- /dev/null
+++ b/checkers/flymake-rest-awk-gawk.el
@@ -0,0 +1,29 @@
+;;; flymake-rest-awk-gawk.el --- awk/gawk diagnostic function -*- 
lexical-binding: t -*-
+
+;;; Code:
+
+(require 'flymake)
+(require 'flymake-rest-define)
+
+(eval-when-compile
+  (require 'flymake-rest-rx))
+
+(flymake-backend! flymake-rest-awk-gawk
+  "GNU awk's built-in --lint checker."
+  :title "gawk-awk"
+  :pre-let ((gawk-exec (executable-find "gawk")))
+  :pre-check (unless gawk-exec
+               (error "Cannot find gawk executable"))
+  :write-type 'pipe
+  :command (list gawk-exec
+                 ;; Avoid code execution.  See 
https://github.com/w0rp/ale/pull/1411
+                 "--source" "'BEGIN{exit} END{exit 1}'"
+                 "-f" "-"
+                 "--lint"
+                 null-device)
+  :error-parser
+  (flymake-rest-parse-rx
+   ((error   bol (? "g") "awk: -:" line ": " (or "fatal" "error") ": " 
(message) eol)
+    (warning bol (? "g") "awk: -:" line ": " "warning"            ": " 
(message) eol))))
+
+(provide 'flymake-rest-awk-gawk)
diff --git a/checkers/flymake-rest-clang.el b/checkers/flymake-rest-clang.el
new file mode 100644
index 0000000000..2c1a4dedb9
--- /dev/null
+++ b/checkers/flymake-rest-clang.el
@@ -0,0 +1,48 @@
+;;; flymake-rest-clang.el --- Clang diagnostic function -*- lexical-binding: t 
-*-
+
+;;; Code:
+
+(require 'flymake)
+(require 'flymake-rest-define)
+
+(eval-when-compile
+  (require 'flymake-rest-rx))
+
+(defvar flymake-rest-clang-args
+  '("-pedantic" "-pedantic-errors")
+  "Command line arguments always passed to `flymake-rest-clang'.")
+
+(defvar flymake-rest-clang-include-path nil
+  "Default include path for gcc in `flymake-rest-clang'.")
+
+(flymake-rest-define flymake-clang
+  "A C/C++ syntax checker using Clang.
+
+See URL `http://clang.llvm.org/'."
+  :title "clang"
+  :pre-let ((clang-exec (executable-find "clang")))
+  :pre-check (unless clang-exec
+               (error "Cannot find clang executable"))
+  :write-type 'pipe
+  :command `(,clang-exec
+             "-fsyntax-only"
+             "-fno-color-diagnostics"                                 ; Do not 
include color codes in output
+             "-fno-caret-diagnostics"                                 ; Do not 
visually indicate the source
+             "-fno-diagnostics-show-option"                           ; Do not 
show the corresponding
+             "-iquote" ,(if-let ((file (buffer-file-name)))
+                            (file-name-directory file)
+                          default-directory)
+             ,@(cl-loop for it in flymake-rest-clang-include-path
+                        collect (concat "-I" it))
+             ,@flymake-rest-clang-args
+             "-x" ,(pcase major-mode
+                     ('c-mode "c")
+                     ((or 'c++-mode _) "c++"))
+             "-")
+  :error-parser
+  (flymake-backend-parse-rx!
+   ((error   bol "<stdin>:" line ":" column ": " (or "fatal" "error") ": " 
(message) eol)
+    (warning bol "<stdin>:" line ":" column ": " "warning"            ": " 
(message) eol)
+    (note    bol "<stdin>:" line ":" column ": " "note"               ": " 
(message) eol))))
+
+(provide 'flymake-rest-gcc)
diff --git a/checkers/flymake-rest-eslint.el b/checkers/flymake-rest-eslint.el
new file mode 100644
index 0000000000..54c43351ed
--- /dev/null
+++ b/checkers/flymake-rest-eslint.el
@@ -0,0 +1,46 @@
+;;; flymake-rest-eslint.el --- ESLint diagnostic function -*- lexical-binding: 
t -*-
+
+;;; Code:
+
+(require 'flymake)
+(require 'flymake-rest-define)
+
+(eval-when-compile
+  (require 'flymake-rest-enumerate))
+
+(flymake-rest-define flymake-rest-eslint
+  "A Javascript syntax and style checker using eslint.
+
+See URL `https://eslint.org/'."
+  :title "eslint"
+  :pre-let ((eslint-exec (executable-find "eslint")))
+  :pre-check (unless eslint-exec
+               (error "Cannot find eslint executable"))
+  :write-type 'pipe
+  :command
+  `(,eslint-exec
+    "--format=json"
+    "--stdin"
+    ,@(when-let ((file (buffer-file-name)))
+        (list "--stdin-filename" file)))
+  :error-parser
+  (flymake-rest-parse-enumerate
+      (alist-get
+       'messages
+       (caar
+        (flymake-backend-parse-json!
+         (buffer-substring-no-properties
+          (point-min) (point-max)))))
+    (let-alist it
+      (let ((loc (cons (car (flymake-diag-region fmqd-source .line .column))
+                       (cdr (flymake-diag-region fmqd-source .endLine 
.endColumn)))))
+        (list fmqd-source
+              (car loc)
+              (cdr loc)
+              (pcase .severity
+                (2 :error)
+                (1 :warning)
+                (_ :note))
+              (concat "[" .ruleId "] " .message))))))
+
+(provide 'flymake-rest-eslint)
diff --git a/checkers/flymake-rest-gcc.el b/checkers/flymake-rest-gcc.el
new file mode 100644
index 0000000000..1a5e3446a3
--- /dev/null
+++ b/checkers/flymake-rest-gcc.el
@@ -0,0 +1,49 @@
+;;; flymake-rest-gcc.el --- GCC diagnostic function -*- lexical-binding: t -*-
+
+;;; Code:
+
+(require 'flymake)
+(require 'flymake-rest-define)
+
+(eval-when-compile
+  (require 'flymake-rest-rx))
+
+(defcustom flymake-rest-gcc-args
+  '("-pedantic" "-pedantic-errors")
+  "Command line arguments always passed to `flymake-rest-gcc'.")
+
+(defcustom flymake-rest-gcc-include-path nil
+  "Default include path for gcc in `flymake-rest-gcc'.")
+
+(flymake-rest-define flymake-rest-gcc
+  "A C/C++ syntax checker using GCC.
+
+Requires GCC 4.4 or newer.  See URL `https://gcc.gnu.org/'."
+  :title "gcc"
+  :pre-let ((gcc-exec (executable-find "gcc")))
+  :pre-check (unless gcc-exec
+               (error "Cannot find gcc executable"))
+  :write-type 'pipe
+  :command `(,gcc-exec
+             "-fshow-column"
+             "-iquote" ,(if-let ((file (buffer-file-name)))
+                            (file-name-directory file)
+                          default-directory)
+             ,@(cl-loop for it in flymake-rest-gcc-include-path
+                        collect (concat "-I" it))
+             ,@flymake-rest-gcc-args
+             "-x" ,(pcase major-mode
+                     ('c-mode "c")
+                     ((or 'c++-mode _) "c++"))
+             ;; GCC performs full checking only when actually compiling, so
+             ;; `-fsyntax-only' is not enough. Just let it generate assembly
+             ;; code.
+             "-S" "-o" ,null-device
+             "-")
+  :error-parser
+  (flymake-rest-parse-rx
+   ((error   bol "<stdin>:" line ":" column ": " (or "fatal" "error") ": " 
(message) eol)
+    (warning bol "<stdin>:" line ":" column ": " "warning"            ": " 
(message) eol)
+    (note    bol "<stdin>:" line ":" column ": " "note"               ": " 
(message) eol))))
+
+(provide 'flymake-rest-gcc)
diff --git a/checkers/flymake-rest-html-tidy.el 
b/checkers/flymake-rest-html-tidy.el
new file mode 100644
index 0000000000..ba9fe38707
--- /dev/null
+++ b/checkers/flymake-rest-html-tidy.el
@@ -0,0 +1,26 @@
+;;; flymake-rest-html-tidy.el --- Tidy-HTML5 diagnostic function -*- 
lexical-binding: t -*-
+
+;;; Code:
+
+(require 'flymake)
+(require 'flymake-rest-define)
+
+(eval-when-compile
+  (require 'flymake-rest-rx))
+
+(flymake-rest-define flymake-rest-html-tidy
+  "A HTML syntax and style checker using Tidy.
+
+See URL `https://github.com/htacg/tidy-html5'."
+  :title "tidy"
+  :pre-let ((tidy-exec (executable-find "tidy")))
+  :pre-check (unless tidy-exec
+               (error "Cannot find tidy executable"))
+  :write-type 'pipe
+  :command `(,tidy-exec "-lang" "en" "-e" "-q")
+  :error-parser
+  (flymake-rest-parse-rx
+   ((error   bol "line " line " column " column " - Error: "   (message) eol)
+    (warning bol "line " line " column " column " - Warning: " (message) 
eol))))
+
+(provide 'flymake-rest-html-tidy)
diff --git a/checkers/flymake-rest-jq.el b/checkers/flymake-rest-jq.el
new file mode 100644
index 0000000000..3ca92f9410
--- /dev/null
+++ b/checkers/flymake-rest-jq.el
@@ -0,0 +1,29 @@
+;;; flymake-rest-jq.el --- jq diagnostic function -*- lexical-binding: t -*-
+
+;;; Code:
+
+(require 'flymake)
+(require 'flymake-rest-define)
+
+(eval-when-compile
+  (require 'flymake-rest-rx))
+
+(flymake-rest-define flymake-rest-jq
+  "JSON checker using the jq tool.
+
+This checker accepts multiple consecutive JSON values in a
+single input, which is useful for jsonlines data.
+
+See URL `https://stedolan.github.io/jq/'."
+  :title "jq"
+  :pre-let ((jq-exec (executable-find "jq")))
+  :pre-check (unless jq-exec
+               (error "Cannot find jq executable"))
+  :write-type 'pipe
+  :command (list jq-exec "." "-" null-device)
+  :error-parser
+  (flymake-rest-parse-rx
+   ((error bol "parse error: " (message) " at line " line ", column " column 
eol))))
+
+(provide 'flymake-rest-jq)
+
diff --git a/checkers/flymake-rest-jsonlint.el 
b/checkers/flymake-rest-jsonlint.el
new file mode 100644
index 0000000000..ffb6495555
--- /dev/null
+++ b/checkers/flymake-rest-jsonlint.el
@@ -0,0 +1,26 @@
+;;; flymake-rest-jsonlint.el --- JSONLint diagnostic function -*- 
lexical-binding: t -*-
+
+;;; Code:
+
+(require 'flymake)
+(require 'flymake-rest-define)
+
+(eval-when-compile
+  (require 'flymake-rest-rx))
+
+(flymake-rest-define flymake-rest-jsonlint
+  "A JSON syntax and style checker using jsonlint.
+
+See URL `https://github.com/zaach/jsonlint'."
+  :title "jsonlint"
+  :pre-let ((jsonlint-exec (executable-find "jsonlint")))
+  :pre-check (unless jsonlint-exec
+               (error "Cannot find jsonlint executable"))
+  :write-type 'file
+  :command (list jsonlint-exec "-c" "-q" fmqd-temp-file)
+  :error-parser
+  (flymake-rest-parse-rx
+   ((error bol (file-name) ": line " line ", col " column ", " (message) 
eol))))
+
+(provide 'flymake-rest-jsonlint)
+
diff --git a/checkers/flymake-rest-less.el b/checkers/flymake-rest-less.el
new file mode 100644
index 0000000000..c4c9ba565a
--- /dev/null
+++ b/checkers/flymake-rest-less.el
@@ -0,0 +1,28 @@
+;;; flymake-rest-less.el --- Less diagnostic function -*- lexical-binding: t 
-*-
+
+;;; Code:
+
+(require 'flymake)
+(require 'flymake-rest-define)
+
+(eval-when-compile
+  (require 'flymake-rest-rx))
+
+(flymake-rest-define flymake-rest-less
+  "A LESS syntax checker using lessc.
+
+Requires lessc 1.4 or newer.
+
+See URL `http://lesscss.org'."
+  :title "lessc"
+  :pre-let ((lessc-exec (executable-find "lessc")))
+  :pre-check (unless lessc-exec
+               (error "Cannot find lessc executable"))
+  :write-type 'pipe
+  :command (list lessc-exec  "--lint" "--no-color" "-")
+  :error-parser
+  (flymake-rest-parse-rx
+   ((error bol (+ not-newline) ": " (message) " in - on line " line ", column 
" column ":" eol))))
+
+(provide 'flymake-rest-less)
+
diff --git a/checkers/flymake-rest-markdownlint.el 
b/checkers/flymake-rest-markdownlint.el
new file mode 100644
index 0000000000..5fa8bdcee0
--- /dev/null
+++ b/checkers/flymake-rest-markdownlint.el
@@ -0,0 +1,31 @@
+;;; flymake-rest-markdownlint.el --- Markdownlint diagnostic function -*- 
lexical-binding: t -*-
+
+;;; Code:
+
+(require 'flymake)
+(require 'flymake-rest-define)
+
+(eval-when-compile
+  (require 'flymake-rest-rx))
+
+(defcustom flymake-rest-markdownlint-style nil
+  "Path to the style config for markdownlint."
+  :type 'string)
+
+(flymake-rest-define flymake-rest-markdownlint
+  "Markdown checker using mdl.
+
+See URL `https://github.com/markdownlint/markdownlint'."
+  :title "markdownlint"
+  :pre-let ((mdl-exec (executable-find "mdl")))
+  :pre-check (unless mdl-exec
+               (error "Cannot find mdl executable"))
+  :write-type 'pipe
+  :command `(,mdl-exec
+             ,@(and flymake-rest-markdownlint-style
+                    `("--style" ,flymake-rest-markdownlint-style)))
+  :error-parser
+  (flymake-rest-parse-rx
+   ((error bol "(stdin):" line ": " (id "MD" (+ digit)) " " (message) eol))))
+
+(provide 'flymake-rest-markdownlint)
diff --git a/checkers/flymake-rest-mypy.el b/checkers/flymake-rest-mypy.el
new file mode 100644
index 0000000000..0ccb3cc979
--- /dev/null
+++ b/checkers/flymake-rest-mypy.el
@@ -0,0 +1,34 @@
+;;; flymake-rest-mypy.el --- MyPy diagnostic function -*- lexical-binding: t 
-*-
+
+;;; Code:
+
+(require 'flymake)
+(require 'flymake-rest-define)
+
+(eval-when-compile
+  (require 'flymake-rest-rx))
+
+(flymake-rest-define flymake-rest-mypy
+  "Mypy syntax and type checker.  Requires mypy>=0.580.
+
+See URL `http://mypy-lang.org/'."
+  :title "mypy"
+  :pre-let ((mypy-exec (executable-find "mypy")))
+  :pre-check (unless mypy-exec
+               (error "Cannot find mypy executable"))
+  :write-type 'file
+  :source-inplace t
+  :command (list mypy-exec
+                 "--show-column-numbers"
+                 "--no-error-summary"
+                 "--no-color-output"
+                 "--show-absolute-path"
+                 "--show-error-codes"
+                 fmqd-temp-file)
+  :error-parser
+  (flymake-rest-parse-rx
+   ((error   bol (file-name) ":" line ":" column ": error: "   (message) eol)
+    (warning bol (file-name) ":" line ":" column ": warning: " (message) eol)
+    (note    bol (file-name) ":" line ":" column ": note: "    (message) 
eol))))
+
+(provide 'flymake-rest-mypy)
diff --git a/checkers/flymake-rest-proselint.el 
b/checkers/flymake-rest-proselint.el
new file mode 100644
index 0000000000..f307fc50bb
--- /dev/null
+++ b/checkers/flymake-rest-proselint.el
@@ -0,0 +1,41 @@
+;;; flymake-rest-proselint.el --- Proselint diagnostic function -*- 
lexical-binding: t -*-
+
+;;; Code:
+
+(require 'flymake)
+(require 'flymake-rest-define)
+
+(eval-when-compile
+  (require 'flymake-rest-enumerate))
+
+(flymake-rest-define flymake-rest-proselint
+  "Flymake checker using Proselint.
+
+See URL `http://proselint.com/'."
+  :title "proselint"
+  :pre-let ((proselint-exec (executable-find "proselint")))
+  :pre-check (unless proselint-exec
+               (error "Cannot find proselint executable"))
+  :write-type 'pipe
+  :command `(,proselint-exec "--json" "-")
+  :error-parser
+  (flymake-rest-parse-enumerate
+      (alist-get 'errors
+       (alist-get 'data
+        (car
+         (flymake-backend-parse-json!
+          (buffer-substring-no-properties
+           (point-min) (point-max))))))
+    (let-alist it
+      (let ((loc (cons (car (flymake-diag-region fmqd-source .line .column))
+                       (cdr (flymake-diag-region fmqd-source .endLine 
.endColumn)))))
+        (list fmqd-source
+              .start
+              .end
+              (pcase .severity
+                ("suggestion" :note)
+                ("warning" :warning)
+                ((or "error" _) :error))
+              (concat (propertize .check 'face 'flymake-diag-id!) " " 
.message))))))
+
+(provide 'flymake-rest-proselint)
diff --git a/checkers/flymake-rest-pycodestyle.el 
b/checkers/flymake-rest-pycodestyle.el
new file mode 100644
index 0000000000..8d2ace203c
--- /dev/null
+++ b/checkers/flymake-rest-pycodestyle.el
@@ -0,0 +1,26 @@
+;;; flymake-rest-pycodestyle.el --- Pycodestyle diagnostic function -*- 
lexical-binding: t -*-
+
+;;; Code:
+
+(require 'flymake)
+(require 'flymake-rest-define)
+
+(eval-when-compile
+  (require 'flymake-rest-rx))
+
+(flymake-rest-define flymake-rest-pycodestyle
+  :title "pycodestyle"
+  :pre-let ((pycodestyle-exec (executable-find "pycodestyle")))
+  :pre-check
+  (unless pycodestyle-exec
+    (error "Cannot find pycodestyle executable"))
+  :write-type 'file
+  :source-inplace t
+  :command (list pycodestyle-exec fmqd-temp-file)
+  :error-parser
+  (flymake-rest-parse-rx
+   ((error bol
+           (file-name) ":" line ":" column ": " (id (or "E" "W") (one-or-more 
digit)) " " (message)
+           eol))))
+
+(provide 'flymake-rest-pycodestyle)
diff --git a/checkers/flymake-rest-pylint.el b/checkers/flymake-rest-pylint.el
new file mode 100644
index 0000000000..8a1ff8808f
--- /dev/null
+++ b/checkers/flymake-rest-pylint.el
@@ -0,0 +1,46 @@
+;;; flymake-rest-pylint.el --- Pylint diagnostic function -*- lexical-binding: 
t -*-
+
+;;; Code:
+
+(require 'flymake)
+(require 'flymake-rest-define)
+
+(eval-when-compile
+  (require 'flymake-rest-enumerate))
+
+(flymake-rest-define flymake-rest-pylint
+  :title "pylint"
+  :pre-let ((python-exec (executable-find "python3"))
+            (pylint-exec (executable-find "pylint")))
+  :pre-check
+  (progn
+    (unless python-exec
+      (error "Cannot find python executable"))
+    (unless pylint-exec
+      (error "Cannot find pylint executable")))
+  :write-type 'file
+  :source-inplace t
+  :command (list python-exec
+                 "-m" "pylint"
+                 "--reports=n"
+                 "--output-format=json"
+                 fmqd-temp-file)
+  :error-parser
+  (flymake-rest-parse-enumerate
+      (car
+       (flymake-rest-parse-json
+        (buffer-substring-no-properties
+         (point-min) (point-max))))
+    (let-alist it
+      (let ((loc (flymake-diag-region fmqd-source .line .column)))
+        (list fmqd-source
+              (car loc)
+              (cdr loc)
+              (pcase .type
+                ;; See "pylint/utils.py"
+                ((or "fatal" "error") :error)
+                ((or "warning" "refactor" "convention") :warning)
+                ((or "info" _) :note))
+              (concat (propertize .message-id 'face 'flymake-rest-diag-id) " " 
.message))))))
+
+(provide 'flymake-rest-pylint)
diff --git a/checkers/flymake-rest-rubocop.el b/checkers/flymake-rest-rubocop.el
new file mode 100644
index 0000000000..0bfd9bb7ee
--- /dev/null
+++ b/checkers/flymake-rest-rubocop.el
@@ -0,0 +1,49 @@
+;;; flymake-rest-rubocop.el --- Rubocop diagnostic function -*- 
lexical-binding: t -*-
+
+;;; Code:
+
+(require 'flymake)
+(require 'flymake-rest-define)
+
+(eval-when-compile
+  (require 'flymake-rest-rx))
+
+(defcustom flymake-rest-rubocop-use-bundler t
+  :type 'boolean)
+
+(flymake-rest-define flymake-rest-rubocop
+  "A Ruby syntax checker using rubocop.
+
+See URL `https://github.com/rubocop/rubocop'."
+  :title "rubocop"
+  :pre-let ((rubocop-exec (executable-find "rubocop"))
+            (file-name (or (buffer-file-name)
+                           "-")))
+  :pre-check (unless rubocop-exec
+               (error "Cannot find rubocop executable"))
+  :write-type 'pipe
+  :command `(,@(or (and flymake-rest-rubocop-use-bundler
+                        (locate-dominating-file (buffer-file-name) "Gemfile")
+                        (if-let ((bundler-exec (executable-find "bundler")))
+                            (list bundler-exec "exec" "rubocop")
+                          (flymake-log :warning "In bundler controlled project 
but bundler not installed")))
+                   (list rubocop-exec))
+             "--display-cop-names"
+             "--force-exclusion"
+             "--format" "emacs"
+             ;; Explicitly disable caching to prevent Rubocop 0.35.1 and 
earlier
+             ;; from caching standard input.  Later versions of Rubocop
+             ;; automatically disable caching with --stdin, see
+             ;; https://github.com/flycheck/flycheck/issues/844 and
+             ;; https://github.com/bbatsov/rubocop/issues/2576
+             "--cache" "false"
+             ;; Rubocop takes the original file name as argument when reading
+             ;; from standard input
+             "--stdin" ,file-name)
+  :error-parser
+  (flymake-rest-parse-rx
+   ((error   bol (file-name) ":" line ":" column ": " (or "E" "F") ": " (? 
"[Correctable] ") (message) eol)
+    (warning bol (file-name) ":" line ":" column ": " "C"          ": " (? 
"[Correctable] ") (message) eol)
+    (note    bol (file-name) ":" line ":" column ": " "W"          ": " (? 
"[Correctable] ") (message) eol))))
+
+(provide 'flymake-rest-rubocop)
diff --git a/checkers/flymake-rest-shellcheck.el 
b/checkers/flymake-rest-shellcheck.el
new file mode 100644
index 0000000000..a0f1b6ae04
--- /dev/null
+++ b/checkers/flymake-rest-shellcheck.el
@@ -0,0 +1,44 @@
+;;; flymake-rest-shellcheck.el --- Shellcheck diagnostic function -*- 
lexical-binding: t -*-
+
+;;; Code:
+
+(require 'flymake)
+(require 'flymake-rest-define)
+
+(eval-when-compile
+  (require 'flymake-rest-enumerate))
+
+(flymake-rest-define flymake-rest-shellcheck
+  "A shell script syntax and style checker using Shellcheck.
+
+See URL `https://github.com/koalaman/shellcheck/'."
+  :title "shellcheck"
+  :pre-let ((sh-exec (executable-find "shellcheck")))
+  :pre-check (unless sh-exec
+               (error "Cannot find shellcheck executable"))
+  :write-type 'pipe
+  :command `(,sh-exec
+             "--format" "json"
+             ,@(when-let ((sh (bound-and-true-p sh-shell)))
+                 `("--shell" ,(symbol-name sh)))
+             "--external-sources"
+             "-")
+  :error-parser
+  (flymake-rest-parse-enumerate
+      (car
+       (flymake-backend-parse-json!
+        (buffer-substring-no-properties
+         (point-min) (point-max))))
+    (let-alist it
+      (let ((loc (cons (car (flymake-diag-region fmqd-source .line .column))
+                       (cdr (flymake-diag-region fmqd-source .endLine 
.endColumn)))))
+        (list fmqd-source
+              (car loc)
+              (cdr loc)
+              (pcase .level
+                ("error" :error)
+                ("warning" :warning)
+                ((or "info" "style" _) :note))
+              (concat (propertize (format "SC%s" .code) 'face 
'flymake-diag-id!) " " .message))))))
+
+(provide 'flymake-rest-shellcheck)
diff --git a/checkers/flymake-rest-yamllint.el 
b/checkers/flymake-rest-yamllint.el
new file mode 100644
index 0000000000..cf94d15b23
--- /dev/null
+++ b/checkers/flymake-rest-yamllint.el
@@ -0,0 +1,25 @@
+;;; flymake-rest-yamllint.el --- Yamllint diagnostic function -*- 
lexical-binding: t -*-
+
+;;; Code:
+
+(require 'flymake)
+(require 'flymake-rest-define)
+
+(eval-when-compile
+  (require 'flymake-rest-rx))
+
+(flymake-rest-define flymake-rest-yamllint
+  "A YAML syntax checker using YAMLLint.
+See URL `https://github.com/adrienverge/yamllint'."
+  :title "yamllint"
+  :pre-let ((yamllint-exec (executable-find "yamllint")))
+  :pre-check (unless yamllint-exec
+               (error "Cannot find yamllint executable"))
+  :write-type 'pipe
+  :command (list yamllint-exec "-f" "parsable" "-")
+  :error-parser
+  (flymake-rest-parse-rx
+   ((error   bol "stdin:" line ":" column ": " "[error] "   (message) eol)
+    (warning bol "stdin:" line ":" column ": " "[warning] " (message) eol))))
+
+(provide 'flymake-rest-yamllint)

Reply via email to