[PATCH] emacs: Echo the output of notmuch new as it runs
authorAustin Clements <amdragon@MIT.EDU>
Mon, 24 Jun 2013 22:32:25 +0000 (18:32 +2000)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:55:43 +0000 (09:55 -0800)
85/a2d8715e756af5a2a231a633ca06f8147bf72f [new file with mode: 0644]

diff --git a/85/a2d8715e756af5a2a231a633ca06f8147bf72f b/85/a2d8715e756af5a2a231a633ca06f8147bf72f
new file mode 100644 (file)
index 0000000..1baa412
--- /dev/null
@@ -0,0 +1,207 @@
+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