--- /dev/null
+Return-Path: <amdragon@mit.edu>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by olra.theworths.org (Postfix) with ESMTP id 06167431FB6\r
+ for <notmuch@notmuchmail.org>; Mon, 24 Jun 2013 15:32:40 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.7\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
+ tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+ by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id ObtxBzZDDIL1 for <notmuch@notmuchmail.org>;\r
+ Mon, 24 Jun 2013 15:32:33 -0700 (PDT)\r
+Received: from dmz-mailsec-scanner-1.mit.edu (dmz-mailsec-scanner-1.mit.edu\r
+ [18.9.25.12])\r
+ by olra.theworths.org (Postfix) with ESMTP id A9109431FAF\r
+ for <notmuch@notmuchmail.org>; Mon, 24 Jun 2013 15:32:33 -0700 (PDT)\r
+X-AuditID: 1209190c-b7fa48e000000947-37-51c8c900efde\r
+Received: from mailhub-auth-1.mit.edu ( [18.9.21.35])\r
+ by dmz-mailsec-scanner-1.mit.edu (Symantec Messaging Gateway) with SMTP\r
+ id 65.8E.02375.009C8C15; Mon, 24 Jun 2013 18:32:32 -0400 (EDT)\r
+Received: from outgoing.mit.edu (outgoing-auth-1.mit.edu [18.9.28.11])\r
+ by mailhub-auth-1.mit.edu (8.13.8/8.9.2) with ESMTP id r5OMWTXe021271; \r
+ Mon, 24 Jun 2013 18:32:30 -0400\r
+Received: from drake.dyndns.org (26-4-182.dynamic.csail.mit.edu [18.26.4.182])\r
+ (authenticated bits=0)\r
+ (User authenticated as amdragon@ATHENA.MIT.EDU)\r
+ by outgoing.mit.edu (8.13.8/8.12.4) with ESMTP id r5OMWSTf025791\r
+ (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NOT);\r
+ Mon, 24 Jun 2013 18:32:29 -0400\r
+Received: from amthrax by drake.dyndns.org with local (Exim 4.77)\r
+ (envelope-from <amdragon@mit.edu>)\r
+ id 1UrFJE-0000Zw-0g; Mon, 24 Jun 2013 18:32:28 -0400\r
+From: Austin Clements <amdragon@MIT.EDU>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH] emacs: Echo the output of notmuch new as it runs\r
+Date: Mon, 24 Jun 2013 18:32:25 -0400\r
+Message-Id: <1372113145-1944-1-git-send-email-amdragon@mit.edu>\r
+X-Mailer: git-send-email 1.7.10.4\r
+X-Brightmail-Tracker:\r
+ H4sIAAAAAAAAA+NgFlrGIsWRmVeSWpSXmKPExsUixCmqrMtw8kSgwfL9IhbXb85kdmD0eLbq\r
+ FnMAYxSXTUpqTmZZapG+XQJXxtZJi1gKXmhXTH6T18B4TKmLkZNDQsBEYvm7dUwQtpjEhXvr\r
+ 2boYuTiEBPYxSlxb8IcFwtnIKLH53Wco5wiTxKm316CcuYwSn973s4D0swloSGzbv5wRxBYR\r
+ kJbYeXc2axcjBwezgJrEny4VkLCwgKPEt+6FbCA2i4CqxKKmZjCbV8Be4u2HPYwQZyhKdD+b\r
+ wDaBkXcBI8MqRtmU3Crd3MTMnOLUZN3i5MS8vNQiXUO93MwSvdSU0k2M4CCQ5NnB+Oag0iFG\r
+ AQ5GJR7eGTEnAoVYE8uKK3MPMUpyMCmJ8k4+ARTiS8pPqcxILM6ILyrNSS0+xCjBwawkwhsq\r
+ ApTjTUmsrEotyodJSXOwKInzitzaGSgkkJ5YkpqdmlqQWgSTleHgUJLgVQUZKliUmp5akZaZ\r
+ U4KQZuLgBBnOAzT8x3GQ4cUFibnFmekQ+VOMuhyTz255zyjEkpeflyolzvsbpEgApCijNA9u\r
+ Dix6XzGKA70lzHsdpIoHGPlwk14BLWECWjI59TjIkpJEhJRUA+PEtvp5e5tOnLlUM10oIeWM\r
+ ZF7m7FmmNxV/KDgzPlg7MfqnavbcW/rv3U0WHJse0HlS20s3MmGF1tuoJX5609T/rlxuerfT\r
+ S/B0Wo1VdKj653+LvLe8O2kqqNthUilXvdSvYcOuGXtjOKeEnTpU0X6jp8Hk2tW/Lz6eXx6y\r
+ n+OT1c5/cysrFCWVWIozEg21mIuKEwEVeRj+uQIAAA==\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Mon, 24 Jun 2013 22:32:40 -0000\r
+\r
+Previously, when the user pressed "G" to invoke notmuch new, Emacs\r
+would go out to lunch until it finished, giving the user no sense that\r
+the (potentially long-running) notmuch new process was making\r
+progress. This patch fixes this by continuously updating the echo\r
+area to display the last output line of notmuch new as it runs.\r
+---\r
+\r
+This turned out to be a little more complex than I was expecting, but\r
+the effect is really nice, especially if you have a slow computer.\r
+\r
+ emacs/notmuch-lib.el | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++\r
+ emacs/notmuch.el | 5 +--\r
+ 2 files changed, 90 insertions(+), 2 deletions(-)\r
+\r
+diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el\r
+index 534f217..5329146 100644\r
+--- a/emacs/notmuch-lib.el\r
++++ b/emacs/notmuch-lib.el\r
+@@ -372,6 +372,9 @@ returned by FUNC."\r
+ (put-text-property start next prop (funcall func value) object)\r
+ (setq start next))))\r
+ \r
++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
++;; Process helpers\r
++\r
+ (defun notmuch-logged-error (msg &optional extra)\r
+ "Log MSG and EXTRA to *Notmuch errors* and signal MSG.\r
+ \r
+@@ -554,6 +557,90 @@ status."\r
+ (message "%s" (error-message-string err))))\r
+ (ignore-errors (delete-file err-file))))\r
+ \r
++(defun notmuch-call-process-with-progress (msg-prefix program &rest args)\r
++ "Call PROGRAM with ARGS, tailing its last line in the echo area.\r
++\r
++This is useful for potentially long-running commands that print\r
++their progress, since it will continuously display the last line\r
++of the command's output in the echo area as it runs. In other\r
++respects, this is very similar to `call-process': it's\r
++synchronous, handles quits the same way, and its return value is\r
++the same.\r
++\r
++MSG-PREFIX is the string to prefix echo area messages with. If\r
++nil, the message will be constructed from PROGRAM."\r
++\r
++ (unless msg-prefix\r
++ (setq msg-prefix (format "Running %s" program)))\r
++\r
++ (with-temp-buffer\r
++ (let* (;; Inhibit quit until we're ready to handle it properly\r
++ (inhibit-quit t)\r
++ (proc\r
++ (let ((process-environment\r
++ ;; We emulate a (very lame) VT100\r
++ (cons "TERM=vt100" process-environment)))\r
++ (apply #'start-process program (current-buffer) program args)))\r
++ (filter\r
++ (lambda (proc string)\r
++ (when (buffer-live-p (process-buffer proc))\r
++ (with-current-buffer (process-buffer proc)\r
++ (goto-char (point-max))\r
++ ;; Treat both \r and \n as newline\r
++ (insert (replace-regexp-in-string "\r" "\n" string))\r
++ ;; Find the beginning of the last line with content\r
++ ;; (which might be the line we're on)\r
++ (while (and (bolp) (not (bobp)))\r
++ (backward-char))\r
++ (beginning-of-line)\r
++ (delete-region (point-min) (point))\r
++ ;; Strip VT100 control sequences. This isn't\r
++ ;; perfect, but it's simple and it'll handle anything\r
++ ;; we're likely to see.\r
++ (save-excursion\r
++ (while (re-search-forward "\e\\[[0-9;?$]*[@a-zA-Z]" nil t)\r
++ (replace-match "")))\r
++ ;; Update the minibuffer. The text is after the\r
++ ;; "..." so that Emacs will update the line in\r
++ ;; *Messages* rather than flooding the log.\r
++ (message "%s... %s" (process-get proc 'msg-prefix)\r
++ (buffer-substring (point) (line-end-position)))))))\r
++ (sentinel\r
++ (lambda (proc event)\r
++ ;; This is the only way to get signal names\r
++ (process-put proc 'sentinel-event (substring event 0 -1)))))\r
++ (process-put proc 'msg-prefix msg-prefix)\r
++ (set-process-filter proc filter)\r
++ (set-process-sentinel proc sentinel)\r
++ (process-send-eof proc)\r
++ (message "%s..." msg-prefix)\r
++\r
++ ;; Wait for termination, emulating `call-process'\r
++ (unwind-protect\r
++ (while (eq (process-status proc) 'run)\r
++ (let ((inhibit-quit nil))\r
++ (accept-process-output proc nil nil t)))\r
++ (when (eq (process-status proc) 'run)\r
++ (interrupt-process proc t)\r
++ (message "Waiting for process to die...(type C-g again to kill it instantly)")\r
++ (unwind-protect\r
++ (while (eq (process-status proc) 'run)\r
++ (let ((inhibit-quit nil))\r
++ (accept-process-output proc nil nil t)))\r
++ (delete-process proc))\r
++ (message "Waiting for process to die...done")))\r
++\r
++ ;; Print the final status message and return like `call-process'\r
++ (let ((event (process-get proc 'sentinel-event))\r
++ (status (process-status proc))\r
++ (exit-status (process-exit-status proc)))\r
++ (if (eq status 'exit)\r
++ (progn\r
++ (message "%s...%s" msg-prefix (if (= exit-status 0) "done" event))\r
++ exit-status)\r
++ (message "%s...%s" msg-prefix event)\r
++ event)))))\r
++\r
+ ;; This variable is used only buffer local, but it needs to be\r
+ ;; declared globally first to avoid compiler warnings.\r
+ (defvar notmuch-show-process-crypto nil)\r
+diff --git a/emacs/notmuch.el b/emacs/notmuch.el\r
+index a9949a1..9949b6c 100644\r
+--- a/emacs/notmuch.el\r
++++ b/emacs/notmuch.el\r
+@@ -996,8 +996,9 @@ depending on the value of `notmuch-poll-script'."\r
+ (interactive)\r
+ (if (stringp notmuch-poll-script)\r
+ (unless (string= notmuch-poll-script "")\r
+- (call-process notmuch-poll-script nil nil))\r
+- (call-process notmuch-command nil nil nil "new")))\r
++ (notmuch-call-process-with-progress nil notmuch-poll-script))\r
++ (notmuch-call-process-with-progress\r
++ "Checking for mail" notmuch-command "new")))\r
+ \r
+ (defun notmuch-search-poll-and-refresh-view ()\r
+ "Invoke `notmuch-poll' to import mail, then refresh the current view."\r
+-- \r
+1.7.10.4\r
+\r