Subject: Re: bug#18133: Suppressing asynchronous command output

From: Reuben Thomas <[email-masked]>
Date: Wed, 28 Jun 2017 22:45:43 +0100

On 31 December 2016 at 08:41, Eli Zaretskii <[email-masked]> wrote:

> > From: Reuben Thomas <[email-masked]>
> > Date: Sat, 31 Dec 2016 00:19:21 +0000
> > Cc: Eli Zaretskii <[email-masked]>, martin rudalics <[email-masked]>,
> [email-masked]
> >
> > Thanks, Juri; can you converge with Eli, and then I'll have a coherent
> proposal I can program?
>
> I'm okay with Juri's approach as well.
>

​Here is a patch that attempts to implement Juri's approach.​

​However, at the moment it doesn't work. I think the problem is to do with
combining process filters. As suggested in the Emacs manual, I use
add-function to combine the new process filter with the default
comint-output-filter. But no matter what I try, the original filter does
not seem to be run any more, even if I pass a trivial function to
add-function. I've studied the documentation, and I can't see what I'm
doing wrong.

-- 
https://rrt.sc3d.org <http://rrt.sc3d.org>
From ee79ead9f2f132e85806c75f30ec861bb094f387 Mon Sep 17 00:00:00 2001
From: Reuben Thomas <[email-masked]>
Date: Wed, 28 Jun 2017 22:40:33 +0100
Subject: [PATCH] Allow async command output buffer to be shown only on output

* lisp/simple.el (async-shell-command-display-buffer): Add
defcustom.
(shell-command): Use the new defcustom to determine whether to show
the buffer immediately, or add a process filter that shows it only
when there is some output.

Thanks to Juri Linkov and Eli Zaretskii for advice and guidance.
---
 lisp/simple.el | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/lisp/simple.el b/lisp/simple.el
index a5565ab..2f2887e 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -3271,6 +3271,17 @@ async-shell-command-buffer
   :group 'shell
   :version "24.3")
 
+(defcustom async-shell-command-display-buffer t
+  "Whether to display the command buffer immediately.
+If t, display the buffer immediately; if nil, wait until there
+is output."
+  :type '(choice (const :tag "Display buffer immediately"
+			t)
+		 (const :tag "Display buffer on output"
+			nil))
+  :group 'shell
+  :version "26.1")
+
 (defun shell-command--save-pos-or-erase ()
   "Store a buffer position or erase the buffer.
 See `shell-command-dont-erase-buffer'."
@@ -3517,7 +3528,6 @@ shell-command
 		    (setq buffer (get-buffer-create
 				  (or output-buffer "*Async Shell Command*"))))))
 		(with-current-buffer buffer
-		  (display-buffer buffer '(nil (allow-no-window . t)))
                   (shell-command--save-pos-or-erase)
 		  (setq default-directory directory)
 		  (setq proc (start-process "Shell" buffer shell-file-name
@@ -3528,7 +3538,16 @@ shell-command
 		  ;; Use the comint filter for proper handling of carriage motion
 		  ;; (see `comint-inhibit-carriage-motion'),.
 		  (set-process-filter proc 'comint-output-filter)
-		  ))
+                  (if async-shell-command-display-buffer
+                      (display-buffer buffer '(nil (allow-no-window . t)))
+                    (add-function :before (process-filter proc)
+                                  `(lambda (process string)
+                                     (when (and (= 0 (buffer-size (process-buffer process)))
+                                                (eq (buffer-name (process-buffer process))
+                                                    ,(or output-buffer "*Async Shell Command*")))
+                                       (display-buffer (process-buffer process))))
+                                  ))
+                  ))
 	    ;; Otherwise, command is executed synchronously.
 	    (shell-command-on-region (point) (point) command
 				     output-buffer nil error-buffer)))))))
-- 
2.7.4