-
Notifications
You must be signed in to change notification settings - Fork 1
/
flymake-yamllint.el
114 lines (99 loc) · 4.92 KB
/
flymake-yamllint.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
;;; flymake-yamllint.el --- YAML linter with yamllint -*- lexical-binding: t; -*-
;; Copyright (C) 2021 Martin Kjær Jørgensen (shaohme) <[email protected]>
;;
;; Author: Martin Kjær Jørgensen <[email protected]>
;; Created: 26 November 2021
;; Version: 0.1.4
;; Package-Requires: ((emacs "26.1"))
;; URL: https://github.com/shaohme/flymake-yamllint
;;; Commentary:
;; This package adds YAML syntax checker yamllint.
;; Make sure 'yamllint' binary is on your path.
;; Installation instructions https://github.com/adrienverge/yamllint#installation
;; flymake-yamllint expect `yamllint' to produce stdout like:
;; test.yml:2:4: [error] wrong indentation: expected 2 but found 3 (indentation)
;; Example above should be matched by regex used in code like this:
;; 0: stdin:79:81: [warning] line too long (117 > 80 characters) (line-length)
;; 1: 79
;; 2: 81
;; 3: [warning]
;; 4: line too long (117 > 80 characters) (line-length)
;; SPDX-License-Identifier: GPL-3.0-or-later
;; flymake-yamllint 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, or (at your option)
;; any later version.
;;
;; flymake-yamllint 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 flymake-yamllint. If not, see http://www.gnu.org/licenses.
;;; Code:
(require 'flymake)
(defgroup flymake-yamllint nil
"Yamllint backend for Flymake."
:prefix "flymake-yamllint-"
:group 'tools)
(defcustom flymake-yamllint-program
"yamllint"
"Name of `yamllint' executable."
:type 'string)
(defcustom flymake-yamllint-arguments
nil
"A list of strings to pass to the yamllint program as arguments."
:type '(repeat (string :tag "Argument")))
(defvar-local flymake-yamllint--proc nil)
(defun flymake-yamllint (report-fn &rest _args)
"Flymake backend for yamllint report using REPORT-FN."
(if (not flymake-yamllint-program)
(error "No yamllint program name set"))
(let ((flymake-yamllint--executable-path (executable-find flymake-yamllint-program)))
(if (or (null flymake-yamllint--executable-path)
(not (file-executable-p flymake-yamllint--executable-path)))
(error "Could not find '%s' executable" flymake-yamllint-program))
(when (process-live-p flymake-yamllint--proc)
(kill-process flymake-yamllint--proc)
(setq flymake-yamllint--proc nil))
(let ((source (current-buffer)))
(save-restriction
(widen)
(setq
flymake-yamllint--proc
(make-process
:name "flymake-yamllint" :noquery t :connection-type 'pipe
:buffer (generate-new-buffer " *flymake-yamllint*")
:command `(,flymake-yamllint--executable-path ,@flymake-yamllint-arguments "-f" "parsable" "-")
:sentinel
(lambda (proc _event)
(when (eq 'exit (process-status proc))
(unwind-protect
(if (with-current-buffer source (eq proc flymake-yamllint--proc))
(with-current-buffer (process-buffer proc)
(goto-char (point-min))
(let ((diags))
(while (search-forward-regexp "^.+?:\\([0-9]+\\):\\([0-9]+\\): \\(\\[.*\\]\\) \\(.*\\)$" nil t)
(let ((region (flymake-diag-region source (string-to-number (match-string 1)) (string-to-number (match-string 2))))
(error-type (match-string 3)))
;; expect `region' to only have 2 values (start . end)
(push (flymake-make-diagnostic source
(car region)
(cdr region)
(cond ((equal error-type "[error]") :error)
((equal error-type "[warning]") :warning)
((equal error-type "[info]") :note))
(match-string 4)) diags)))
(funcall report-fn (reverse diags))))
(flymake-log :warning "Canceling obsolete check %s"
proc))
(kill-buffer (process-buffer proc)))))))
(process-send-region flymake-yamllint--proc (point-min) (point-max))
(process-send-eof flymake-yamllint--proc)))))
;;;###autoload
(defun flymake-yamllint-setup ()
"Enable yamllint flymake backend."
(add-hook 'flymake-diagnostic-functions #'flymake-yamllint nil t))
(provide 'flymake-yamllint)
;;; flymake-yamllint.el ends here