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

From: Reuben Thomas <[email-masked]>
Date: Mon, 19 Dec 2016 15:48:00 +0000

Attached, a patch for this bug.

It makes hiding the output buffer until there is output the default
behavior; if the user wishes to get the old behavior back, then
display-buffer-alist can be customized to remove the new default element.

If this patch is acceptable, I can add a NEWS item and install it.

As a side effect, the process object is now made available to input and
output filter functions.

-- 
http://rrt.sc3d.org
From c478dad4d4f25980f215c0f99af03520bd2643fa Mon Sep 17 00:00:00 2001
From: Reuben Thomas <[email-masked]>
Date: Mon, 19 Dec 2016 15:38:36 +0000
Subject: [PATCH 2/6] Delay showing Async Shell Command buffer until output
 (Bug#18133)

* lisp/comint.el (comint-input-filter): Add process argument.
(comint-output-filter-functions): Add `comint-make-buffer-visible' to
the list, document the second argument (the process).
(comint-send-input): Call input and output filter functions with
process argument.
(comint-output-filter): Call output filter functions with process
argument.
(comint-make-buffer-visible): New hook function, to make Async Shell
Command buffer visible.
(comint-postoutput-scroll-to-bottom):
(comint-watch-for-password-prompt): Add dummy process argument.
* lisp/window.el (display-buffer-alist): Add a default entry to hide
Async Shell Command output window.
* lisp/ansi-color.el (ansi-color-process-output): Add a dummy process
argument.
---
 lisp/ansi-color.el |  2 +-
 lisp/comint.el     | 31 ++++++++++++++++++++-----------
 lisp/window.el     |  3 ++-
 3 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/lisp/ansi-color.el b/lisp/ansi-color.el
index 788a7bd..ac3a910 100644
--- a/lisp/ansi-color.el
+++ b/lisp/ansi-color.el
@@ -207,7 +207,7 @@ ansi-color-for-comint-mode-filter
   (setq ansi-color-for-comint-mode 'filter))
 
 ;;;###autoload
-(defun ansi-color-process-output (ignored)
+(defun ansi-color-process-output (_string _process)
   "Maybe translate SGR control sequences of comint output into text properties.
 
 Depending on variable `ansi-color-for-comint-mode' the comint output is
diff --git a/lisp/comint.el b/lisp/comint.el
index b9c65b0..23b5d9a 100644
--- a/lisp/comint.el
+++ b/lisp/comint.el
@@ -395,16 +395,17 @@ comint-input-filter
 
 (defvar comint-input-filter-functions '()
   "Abnormal hook run before input is sent to the process.
-These functions get one argument, a string containing the text to send.")
+These functions get two arguments: a string containing the text to send,
+and the process.")
 
 ;;;###autoload
-(defvar comint-output-filter-functions '(ansi-color-process-output comint-postoutput-scroll-to-bottom comint-watch-for-password-prompt)
+(defvar comint-output-filter-functions '(comint-make-buffer-visible ansi-color-process-output comint-postoutput-scroll-to-bottom comint-watch-for-password-prompt)
   "Functions to call after output is inserted into the buffer.
 One possible function is `comint-postoutput-scroll-to-bottom'.
-These functions get one argument, a string containing the text as originally
-inserted.  Note that this might not be the same as the buffer contents between
-`comint-last-output-start' and the buffer's `process-mark', if other filter
-functions have already modified the buffer.
+These functions get two arguments: a string containing the text as originally
+inserted, and the process.  Note that the string might not be the same as the
+buffer contents between `comint-last-output-start' and the buffer's
+`process-mark', if other filter functions have already modified the buffer.
 
 See also `comint-preoutput-filter-functions'.
 
@@ -1834,7 +1835,8 @@ comint-send-input
 
         (run-hook-with-args 'comint-input-filter-functions
                             (if no-newline input
-                              (concat input "\n")))
+                              (concat input "\n"))
+                            proc)
 
         (let ((beg (marker-position pmark))
               (end (if no-newline (point) (1- (point)))))
@@ -1911,7 +1913,7 @@ comint-send-input
 
         ;; This used to call comint-output-filter-functions,
         ;; but that scrolled the buffer in undesirable ways.
-        (run-hook-with-args 'comint-output-filter-functions "")))))
+        (run-hook-with-args 'comint-output-filter-functions "" proc)))))
 
 (defvar comint-preoutput-filter-functions nil
   "List of functions to call before inserting Comint output into the buffer.
@@ -2069,7 +2071,7 @@ comint-output-filter
 
 	    ;; Run these hooks with point where the user had it.
 	    (goto-char saved-point)
-	    (run-hook-with-args 'comint-output-filter-functions string)
+	    (run-hook-with-args 'comint-output-filter-functions string process)
 	    (set-marker saved-point (point))
 
 	    (goto-char (process-mark process)) ; In case a filter moved it.
@@ -2111,6 +2113,13 @@ comint-output-filter
 	      (add-text-properties prompt-start (point) '(rear-nonsticky t)))
 	    (goto-char saved-point)))))))
 
+(defun comint-make-buffer-visible (_string process)
+  "Make the output buffer visible.
+Useful in `comint-output-filter-functions'."
+  (when (and (string-match-p "\\*Async Shell Command\\*"
+                             (buffer-name (process-buffer process))))
+    (display-buffer (process-buffer process))))
+
 (defun comint-preinput-scroll-to-bottom ()
   "Go to the end of buffer in all windows showing it.
 Movement occurs if point in the selected window is not after the process mark,
@@ -2139,7 +2148,7 @@ comint-preinput-scroll-to-bottom
 (defvar follow-mode)
 (declare-function follow-comint-scroll-to-bottom "follow" (&optional window))
 
-(defun comint-postoutput-scroll-to-bottom (_string)
+(defun comint-postoutput-scroll-to-bottom (_string _process)
   "Go to the end of buffer in some or all windows showing it.
 Do not scroll if the current line is the last line in the buffer.
 Depends on the value of `comint-move-point-for-output' and
@@ -2348,7 +2357,7 @@ send-invisible
 	    (message "Warning: text will be echoed")))
       (error "Buffer %s has no process" (current-buffer)))))
 
-(defun comint-watch-for-password-prompt (string)
+(defun comint-watch-for-password-prompt (string _process)
   "Prompt in the minibuffer for password and send without echoing.
 This function uses `send-invisible' to read and send a password to the buffer's
 process if STRING contains a password prompt defined by
diff --git a/lisp/window.el b/lisp/window.el
index fdb67ed..49d9c33 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -6776,7 +6776,8 @@ display-buffer-overriding-action
 See `display-buffer' for details.")
 (put 'display-buffer-overriding-action 'risky-local-variable t)
 
-(defcustom display-buffer-alist nil
+(defcustom display-buffer-alist '(("\\*Async Shell Command\\*"
+                                   display-buffer-no-window))
   "Alist of conditional actions for `display-buffer'.
 This is a list of elements (CONDITION . ACTION), where:
 
-- 
2.7.4