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