From: joaotavora@gmail.com (João Távora)
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: "John Wiegley" <jwiegley@gmail.com>,
emacs-devel@gnu.org, "Mark Oteiza" <mvoteiza@udel.edu>,
"Simen Heggestøyl" <simenheg@gmail.com>,
dgutov@yandex.ru, "Steve Purcell" <steve@sanityinc.com>,
sdl.web@gmail.com
Subject: Re: Flymake refactored
Date: Fri, 06 Oct 2017 00:01:56 +0100 [thread overview]
Message-ID: <87bmll19nf.fsf@gmail.com> (raw)
In-Reply-To: <CALDnm50v6ELytUKLEnFVb86MP7YJ6X4eQ0Ug2-Rr_BQCqua2zQ@mail.gmail.com> ("João Távora"'s message of "Thu, 5 Oct 2017 15:45:38 +0100")
João Távora <joaotavora@gmail.com> writes:
> We should come up with a canonic way to launch flymake processes
> and then either hide that behind an abstraction or document it.
Attached is a possible such function: it's just like make-process, but
does all those boring checks and has some good defaults. I didn't give
it much testing, but it seems to work and backends become easier to read.
Of course, some macrology can probably get us further, but I wouldn't
want to straitjacket backend writers.
Here's what the Ruby backend looks like after using the diff below my
sig. Notice how no separate variable is needed.
(defun ruby-flymake (report-fn &rest _args)
(unless (executable-find
(car ruby-flymake-command)) (error "Cannot find a suitable ruby"))
(let ((source (current-buffer)))
(save-restriction
(widen)
(let ((proc
(flymake-easy-make-process
:name "ruby-flymake"
:command '("ruby" "-w" "-c")
:sentinel
(lambda (proc _event)
(with-current-buffer (process-buffer proc)
(goto-char (point-min))
(cl-loop
while (search-forward-regexp
"^\\(?:.*.rb\\|-\\):\\([0-9]+\\): \\(.*\\)$" nil t)
for msg = (match-string 2)
for (beg . end) = (flymake-diag-region
source
(string-to-number (match-string 1)))
for type = (if (string-match "^warning" msg) :warning :error)
collect (flymake-make-diagnostic source beg end type msg)
into diags
finally (funcall report-fn diags)))))))
(process-send-region proc (point-min) (point-max))
(process-send-eof proc)))))
João
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el
index e747f1a12d..5277e48bc6 100644
--- a/lisp/progmodes/flymake.el
+++ b/lisp/progmodes/flymake.el
@@ -617,6 +617,82 @@ flymake-make-report-fn
(with-current-buffer buffer
(apply #'flymake--handle-report backend token args))))))
+(defvar-local flymake-easy-make-process--processes
+ nil)
+
+;;;###autoload
+(defun flymake-easy-make-process (&rest args)
+ "Like `make-process', but suitable for writing Flymake backends.
+Use this function when writing Flymake backends based on invoking
+external processes as it preserves the semantics explained
+
+ARGS is a plist of keyword-value pairs. The same keywords are
+accepted as in `make-process', but with slightly different
+semantics:
+
+* `:name' is mandatory and `:backend' is a synonym for it. Can
+ be a string or a symbol and must be constant for the backend,
+ i.e. you mustn't generate a different name every time.
+
+* `:buffer' defaults to a temporary buffer, which is always
+ killed after the process exits.
+
+* `:noquery' defaults to t.
+
+* `:connection-type' defaults to 'pipe'
+
+* `:filter', if provided, is only executed if the process is the
+ most recent process created with `flymake-easy-make-process'
+ for a given buffer and `:name'. If these conditions aren't met,
+ the process is killed immediately.
+
+* `:sentinel', if provided, is only executed if the process has
+ exited cleanly and is the most recent process created with
+ `flymake-easy-make-process' for a given buffer and `:name'."
+ (let* ((backend (or (plist-get args :name)
+ (plist-get args :backend)
+ (error "`:name' or `:backend' are mandatory")))
+ (backend (if (symbolp backend) (symbol-name backend) backend))
+ (existing (gethash backend
+ (or flymake-easy-make-process--processes
+ (setq flymake-easy-make-process--processes
+ (make-hash-table :test #'equal))))))
+ (if (process-live-p existing) (kill-process existing))
+ (setq existing
+ (make-process
+ :name backend
+ :command (plist-get args :command)
+ :buffer (if (plist-member args :buffer)
+ (plist-get args :buffer)
+ (generate-new-buffer
+ (concat " *flymake-easy-make-process-"
+ backend
+ "*")))
+ :coding (plist-get args :coding)
+ :noquery (if (plist-member args :noquery)
+ (plist-get args :noquery)
+ t)
+ :connection-type (if (plist-member args :connection-type)
+ (plist-get args :connection-type)
+ 'pipe)
+ :filter (lambda (proc string)
+ (when (eq proc existing)
+ (if (plist-member args :filter)
+ (funcall (plist-get args :filter)
+ proc string)
+ (internal-default-process-filter proc
+ string))))
+ :sentinel (lambda (proc event)
+ (unwind-protect
+ (when (and (plist-member args :sentinel)
+ (eq proc existing)
+ (eq 'exit (process-status proc)))
+ (funcall (plist-get args :sentinel)
+ proc event))
+ (let ((buf (process-buffer proc)))
+ (when buf (kill-buffer buf)))))))
+ (puthash backend existing flymake-easy-make-process--processes)))
+
(defun flymake--collect (fn)
(let (retval)
(maphash (lambda (backend state)
next prev parent reply other threads:[~2017-10-05 23:01 UTC|newest]
Thread overview: 79+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-09-28 14:27 Flymake refactored João Távora
2017-09-28 19:52 ` Stefan Monnier
2017-09-29 0:22 ` João Távora
2017-09-29 3:11 ` Stefan Monnier
2017-10-01 16:52 ` João Távora
2017-10-01 20:50 ` Stefan Monnier
2017-10-02 1:01 ` João Távora
2017-10-02 3:12 ` Stefan Monnier
2017-10-03 0:33 ` João Távora
2017-10-03 1:09 ` Stefan Monnier
2017-09-29 12:51 ` Dmitry Gutov
2017-09-29 14:55 ` Ted Zlatanov
2017-09-29 15:03 ` Dmitry Gutov
2017-09-29 16:26 ` Ted Zlatanov
2017-09-29 17:35 ` Dmitry Gutov
2017-09-29 17:56 ` Ted Zlatanov
2017-09-30 15:07 ` Dmitry Gutov
2017-09-30 7:55 ` Marcin Borkowski
2017-09-30 23:43 ` João Távora
2017-10-01 8:53 ` Marcin Borkowski
2017-10-01 11:54 ` Mark Oteiza
2017-10-04 17:37 ` Simen Heggestøyl
2017-10-05 2:08 ` João Távora
2017-10-05 3:52 ` Mark Oteiza
2017-10-05 10:57 ` João Távora
2017-10-05 13:11 ` Stefan Monnier
2017-10-05 14:45 ` João Távora
2017-10-05 23:01 ` João Távora [this message]
2017-10-05 21:22 ` Mark Oteiza
2017-10-05 23:05 ` João Távora
2017-10-06 3:35 ` Stefan Monnier
2017-10-06 7:09 ` Lele Gaifax
2017-10-06 8:14 ` Eli Zaretskii
2017-10-06 8:19 ` Lele Gaifax
2017-10-06 9:48 ` Eli Zaretskii
2017-10-06 9:54 ` Lele Gaifax
2017-10-06 13:04 ` Mark Oteiza
2017-10-06 14:47 ` Lele Gaifax
2017-10-06 15:21 ` Mark Oteiza
2017-10-06 15:26 ` Mark Oteiza
2017-10-06 15:28 ` Lele Gaifax
2017-10-06 16:28 ` João Távora
2017-10-06 19:24 ` Lele Gaifax
2017-10-06 15:13 ` João Távora
2017-10-07 13:28 ` Stefan Monnier
2017-10-07 13:44 ` Eli Zaretskii
2017-10-07 14:40 ` Lele Gaifax
2017-10-07 14:52 ` Eli Zaretskii
2017-10-08 2:06 ` Stefan Monnier
2017-10-08 9:32 ` João Távora
2017-10-08 11:24 ` Lele Gaifax
2017-10-08 14:17 ` Stefan Monnier
2017-10-08 23:33 ` João Távora
2017-10-09 3:01 ` Stefan Monnier
2017-10-09 10:19 ` João Távora
2017-10-09 15:50 ` [SUSPECTED SPAM] " Stefan Monnier
2017-10-09 16:33 ` [PATCH] " Lele Gaifax
2017-10-07 6:31 ` Marcin Borkowski
2017-10-07 13:37 ` Stefan Monnier
2017-10-07 16:48 ` Marcin Borkowski
2017-10-06 12:54 ` John Wiegley
2017-10-06 15:17 ` Mark Oteiza
2017-10-06 16:04 ` João Távora
2017-10-06 21:22 ` Mark Oteiza
2017-10-06 22:03 ` João Távora
2017-10-07 13:31 ` Stefan Monnier
2017-10-07 16:02 ` João Távora
2017-10-07 16:07 ` João Távora
2017-10-07 18:18 ` Mark Oteiza
2017-10-08 9:06 ` João Távora
2017-10-08 12:51 ` Mark Oteiza
2017-10-08 23:21 ` João Távora
2017-10-10 14:27 ` Mark Oteiza
2017-10-10 15:20 ` João Távora
2017-10-10 16:10 ` Mark Oteiza
2017-10-05 11:28 ` Lele Gaifax
2017-10-05 15:12 ` Lele Gaifax
2017-10-10 10:40 ` Lele Gaifax
2017-10-10 12:27 ` João Távora
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=87bmll19nf.fsf@gmail.com \
--to=joaotavora@gmail.com \
--cc=dgutov@yandex.ru \
--cc=emacs-devel@gnu.org \
--cc=jwiegley@gmail.com \
--cc=monnier@iro.umontreal.ca \
--cc=mvoteiza@udel.edu \
--cc=sdl.web@gmail.com \
--cc=simenheg@gmail.com \
--cc=steve@sanityinc.com \
/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.