all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Augusto Stoffel <arstoffel@gmail.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: 57884@debbugs.gnu.org
Subject: bug#57884: [PATCH] Flymake backend using the shellcheck program
Date: Sat, 17 Sep 2022 19:32:44 +0200	[thread overview]
Message-ID: <871qs9c3er.fsf@gmail.com> (raw)
In-Reply-To: <83bkre0w4m.fsf@gnu.org> (Eli Zaretskii's message of "Sat, 17 Sep 2022 20:05:29 +0300")

[-- Attachment #1: Type: text/plain, Size: 1665 bytes --]

I've attached a new patch.  See my comments below.

On Sat, 17 Sep 2022 at 20:05, Eli Zaretskii wrote:

>> From: Augusto Stoffel <arstoffel@gmail.com>
>> Date: Sat, 17 Sep 2022 18:48:19 +0200
>> 
>> See https://www.shellcheck.net/ for details on the ShellCheck program.
>> It seems to be the most usual linter for shell scripts.
>
> Thanks.
>
>> * lisp/progmodes/sh-script.el (sh-shellcheck-program,
>> sh--shellcheck-process, sh-shellcheck-flymake): Variables and function
>> defining a Flymake backend.
>> (sh-mode): Add it to 'flymake-diagnostic-functions'.
>
> Please mention the bug number in the log message.

Done.

>> +(defcustom sh-shellcheck-command '("shellcheck")
>> +  "The shellcheck program followed by extra arguments."
>> +  :type 'string)
>
> This lacks the :version tag.

Done (and fixed the :type).

> Also, wouldn't it be better to have separate user options for the
> program and the switches?  That way, there won't be a need to require
> users to provide a list as the value of the option.

I could split this into two defcustoms if you feel strongly about it,
but it seems a bit of overengineering to me.  Not many people will want
to customize the program name, and the switches would have to be
provided as a list anyway, since we're not going to call this through a
shell.

Let me know what you think.

>> +(defun sh-shellcheck-flymake (report-fn &rest _args)
>> +  "Flymake backend using the shellcheck program.
>
> The first line of a function's doc string should mention its
> arguments.

It didn't fit the first line, so as per standard procedure it's in the
body of the docstring.

> And I think this warrants a NEWS entry.

Done.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-New-Flymake-backend-using-the-shellcheck-program.patch --]
[-- Type: text/x-patch, Size: 5107 bytes --]

From 7598653c31bc72a30bc7ed7ba28cc9b6c6b6c843 Mon Sep 17 00:00:00 2001
From: Augusto Stoffel <arstoffel@gmail.com>
Date: Sat, 17 Sep 2022 18:30:04 +0200
Subject: [PATCH] New Flymake backend using the shellcheck program

See bug#57884.

* lisp/progmodes/sh-script.el (sh-shellcheck-program,
sh--shellcheck-process, sh-shellcheck-flymake): Variables and function
defining a Flymake backend.
(sh-mode): Add it to 'flymake-diagnostic-functions'.
---
 etc/NEWS                    |  5 +++
 lisp/progmodes/sh-script.el | 71 +++++++++++++++++++++++++++++++++++++
 2 files changed, 76 insertions(+)

diff --git a/etc/NEWS b/etc/NEWS
index a6a8883593..60e171ad13 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1320,6 +1320,11 @@ This controls how statements like the following are indented:
     foo &&
         bar
 
++++
+*** New Flymake backend using the ShellCheck program
+It is enable by default, only requiring that ShellCheck is installed.
+See https://www.shellcheck.net/ for details.
+
 ** Cperl Mode
 
 ---
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index 517fbbd8e7..9c0f6dabd5 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -31,6 +31,9 @@
 ;; available for filenames, variables known from the script, the shell and
 ;; the environment as well as commands.
 
+;; A Flymake backend using the ShellCheck program is provided.  See
+;; https://www.shellcheck.net/ for installation instructions.
+
 ;;; Known Bugs:
 
 ;; - In Bourne the keyword `in' is not anchored to case, for, select ...
@@ -1580,6 +1583,7 @@ sh-mode
 	 ((equal (file-name-nondirectory buffer-file-name) ".profile") "sh")
          (t sh-shell-file))
    nil nil)
+  (add-hook 'flymake-diagnostic-functions #'sh-shellcheck-flymake nil t)
   (add-hook 'hack-local-variables-hook
     #'sh-after-hack-local-variables nil t))
 
@@ -3103,6 +3107,73 @@ sh-delete-backslash
  	    (delete-region (1+ (point))
  			   (progn (skip-chars-backward " \t") (point)))))))
 
+;;; Flymake backend
+
+(defcustom sh-shellcheck-command '("shellcheck")
+  "The shellcheck program followed by extra arguments."
+  :type '(repeat string)
+  :version "29.1")
+
+(defvar-local sh--shellcheck-process nil)
+
+(defun sh-shellcheck-flymake (report-fn &rest _args)
+  "Flymake backend using the shellcheck program.
+Takes a Flymake callback REPORT-FN as argument, as expected of a
+member of `flymake-diagnostic-functions'."
+  (when (process-live-p sh--shellcheck-process)
+    (kill-process sh--shellcheck-process))
+  (let* ((source (current-buffer))
+         (dialect (named-let dialect ((s sh-shell))
+                    (pcase s
+                      ((or 'bash 'dash 'sh) (symbol-name s))
+                      ('ksh88 "ksh")
+                      ((guard s)
+                       (dialect (alist-get s sh-ancestor-alist))))))
+         (pattern "^-:\\([0-9]+\\):\\([0-9]+\\): \\([^:]+\\): \\(.*\\)$")
+         (sentinel
+          (lambda (proc _event)
+            (when (memq (process-status proc) '(exit signal))
+              (unwind-protect
+                  (if (with-current-buffer source
+                        (not (eq proc sh--shellcheck-process)))
+                      (flymake-log :warning "Canceling obsolete check %s" proc)
+                    (with-current-buffer (process-buffer proc)
+                      (goto-char (point-min))
+                      (cl-loop
+                       while (search-forward-regexp pattern nil t)
+                       for msg = (match-string 4)
+                       for (beg . end) = (flymake-diag-region
+                                          source
+                                          (string-to-number (match-string 1))
+                                          (string-to-number (match-string 2)))
+                       for type = (pcase (match-string 3)
+                                    ("error" :error)
+                                    ("warning" :warning)
+                                    (_ :note))
+                       when (and beg end)
+                       collect (flymake-make-diagnostic source beg end type msg)
+                       into diags
+                       finally (funcall report-fn diags))))
+                (kill-buffer (process-buffer proc)))))))
+    (unless dialect
+      (error "`sh-shellcheck-flymake' is not suitable for shell type `%s'"
+             sh-shell))
+    (setq sh--shellcheck-process
+          (make-process
+           :name "luacheck" :noquery t :connection-type 'pipe
+           :buffer (generate-new-buffer " *flymake-luacheck*")
+           :command `(,(car sh-shellcheck-command)
+                      "--format=gcc"
+                      "--color=never"
+                      "-s" ,dialect
+                      ,@(cdr sh-shellcheck-command)
+                      "-")
+           :sentinel sentinel))
+    (save-restriction
+      (widen)
+      (process-send-region sh--shellcheck-process (point-min) (point-max))
+      (process-send-eof sh--shellcheck-process))))
+
 (provide 'sh-script)
 
 ;;; sh-script.el ends here
-- 
2.37.3


  reply	other threads:[~2022-09-17 17:32 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-17 16:48 bug#57884: [PATCH] Flymake backend using the shellcheck program Augusto Stoffel
2022-09-17 17:05 ` Eli Zaretskii
2022-09-17 17:32   ` Augusto Stoffel [this message]
2022-09-17 17:52     ` Eli Zaretskii
2022-09-17 18:17       ` Stefan Kangas
2022-09-17 17:55     ` Eli Zaretskii
2022-09-17 18:04     ` Stefan Kangas
2022-09-18  7:52       ` Augusto Stoffel
2022-09-18 11:55     ` Philip Kaludercic
2022-09-18 12:38       ` Augusto Stoffel
2022-09-18 12:50         ` Philip Kaludercic
2022-09-18 13:30           ` Augusto Stoffel
2022-09-18 13:46             ` Philip Kaludercic
2022-09-18 19:38               ` Augusto Stoffel
2022-09-18 20:22                 ` Philip Kaludercic
2022-09-18 21:18                   ` Philip Kaludercic
2022-09-19  7:33                     ` Augusto Stoffel
2022-09-19  8:03                       ` Philip Kaludercic
2022-09-24  7:05                     ` Augusto Stoffel
2022-09-24  8:01                       ` Philip Kaludercic
2022-11-04 22:56                         ` Philip Kaludercic
2022-09-18 11:58     ` Philip Kaludercic

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=871qs9c3er.fsf@gmail.com \
    --to=arstoffel@gmail.com \
    --cc=57884@debbugs.gnu.org \
    --cc=eliz@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.