[PATCH v3 4/5] emacs: Use the new JSON reply format.
authorAdam Wolfe Gordon <awg+notmuch@xvx.ca>
Thu, 19 Jan 2012 17:46:56 +0000 (10:46 +1700)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:42:42 +0000 (09:42 -0800)
e6/b5e3ab823911ffae05ba4e8e551aef1d4b05e0 [new file with mode: 0644]

diff --git a/e6/b5e3ab823911ffae05ba4e8e551aef1d4b05e0 b/e6/b5e3ab823911ffae05ba4e8e551aef1d4b05e0
new file mode 100644 (file)
index 0000000..f22ed86
--- /dev/null
@@ -0,0 +1,218 @@
+Return-Path: <awg@lagos.xvx.ca>\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 594F2431FBD\r
+       for <notmuch@notmuchmail.org>; Thu, 19 Jan 2012 09:47:10 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: 0\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=0 tagged_above=-999 required=5\r
+       tests=[RCVD_IN_DNSWL_NONE=-0.0001] 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 OdPTMt1LaEL4 for <notmuch@notmuchmail.org>;\r
+       Thu, 19 Jan 2012 09:47:08 -0800 (PST)\r
+Received: from idcmail-mo1so.shaw.ca (idcmail-mo1so.shaw.ca [24.71.223.10])\r
+       by olra.theworths.org (Postfix) with ESMTP id EC66B431FBC\r
+       for <notmuch@notmuchmail.org>; Thu, 19 Jan 2012 09:47:06 -0800 (PST)\r
+Received: from pd2ml1so-ssvc.prod.shaw.ca ([10.0.141.139])\r
+       by pd3mo1so-svcs.prod.shaw.ca with ESMTP; 19 Jan 2012 10:47:05 -0700\r
+X-Cloudmark-SP-Filtered: true\r
+X-Cloudmark-SP-Result: v=1.1 cv=2TvZ7eE48NdEYeaL5Xf58dNzJU178UzT+2lxUZ5Mhss=\r
+       c=1 sm=1\r
+       a=P0KT-rxv0FoA:10 a=BLceEmwcHowA:10 a=yQp6g8lIsgqumF79BAsFDg==:17\r
+       a=H4IEW4q-AAAA:8 a=Cau_B0zPb9X8FJSHhfwA:9 a=8b7b0oulBVEiTl3x1mAA:7\r
+       a=Kw4u8EAyA4wA:10 a=HpAAvcLHHh0Zw7uRqdWCyQ==:117\r
+Received: from unknown (HELO lagos.xvx.ca) ([96.52.216.56])\r
+       by pd2ml1so-dmz.prod.shaw.ca with ESMTP; 19 Jan 2012 10:47:05 -0700\r
+Received: by lagos.xvx.ca (Postfix, from userid 1000)\r
+       id 2E0928004C49; Thu, 19 Jan 2012 10:47:04 -0700 (MST)\r
+From: Adam Wolfe Gordon <awg+notmuch@xvx.ca>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH v3 4/5] emacs: Use the new JSON reply format.\r
+Date: Thu, 19 Jan 2012 10:46:56 -0700\r
+Message-Id: <1326995217-27423-5-git-send-email-awg+notmuch@xvx.ca>\r
+X-Mailer: git-send-email 1.7.5.4\r
+In-Reply-To: <1326995217-27423-1-git-send-email-awg+notmuch@xvx.ca>\r
+References: <1326995217-27423-1-git-send-email-awg+notmuch@xvx.ca>\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: Thu, 19 Jan 2012 17:47:10 -0000\r
+\r
+Using the new JSON reply format allows emacs to quote HTML\r
+parts nicely by using mm-display-part to turn them into displayable\r
+text, then quoting them. This is very useful for users who\r
+regularly receive HTML-only email.\r
+\r
+The behavior for messages that contain plain text parts should be\r
+unchanged.\r
+---\r
+ emacs/notmuch-lib.el |    8 ++++\r
+ emacs/notmuch-mua.el |   95 +++++++++++++++++++++++++++++++++-----------------\r
+ 2 files changed, 71 insertions(+), 32 deletions(-)\r
+\r
+diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el\r
+index 9242537..9863d69 100644\r
+--- a/emacs/notmuch-lib.el\r
++++ b/emacs/notmuch-lib.el\r
+@@ -21,6 +21,8 @@\r
\r
+ ;; This is an part of an emacs-based interface to the notmuch mail system.\r
\r
++(eval-when-compile (require 'cl))\r
++\r
+ (defvar notmuch-command "notmuch"\r
+   "Command to run the notmuch binary.")\r
\r
+@@ -160,6 +162,12 @@ the user hasn't set this variable with the old or new value."\r
+   (list 'when (< emacs-major-version 23)\r
+       form))\r
\r
++(defun notmuch-parts-filter-by-type (parts type)\r
++  "Return a list of message parts with the given type"\r
++  (loop for part across parts\r
++      if (string= (cdr (assq 'content-type part)) type)\r
++      collect (cdr (assq 'content part))))\r
++\r
+ ;; Compatibility functions for versions of emacs before emacs 23.\r
+ ;;\r
+ ;; Both functions here were copied from emacs 23 with the following copyright:\r
+diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el\r
+index 023645e..5ae0ccf 100644\r
+--- a/emacs/notmuch-mua.el\r
++++ b/emacs/notmuch-mua.el\r
+@@ -19,6 +19,7 @@\r
+ ;;\r
+ ;; Authors: David Edmondson <dme@dme.org>\r
\r
++(require 'json)\r
+ (require 'message)\r
\r
+ (require 'notmuch-lib)\r
+@@ -72,49 +73,79 @@ list."\r
+           (push header message-hidden-headers)))\r
+       notmuch-mua-hidden-headers))\r
\r
++(defun notmuch-mua-insert-part-quoted (part)\r
++  (let ((start (point))\r
++      limit)\r
++    (insert part)\r
++    (setq limit (point-marker))\r
++    (goto-char start)\r
++    (while (re-search-forward "\\(^\\)[^$]" (marker-position limit) 0)\r
++      (replace-match "> " nil nil nil 1))\r
++    (set-buffer-modified-p nil)))\r
++\r
++(defun notmuch-mua-parse-html-part (part)\r
++  (with-temp-buffer\r
++    (insert part)\r
++    (let ((handle (mm-make-handle (current-buffer) (list "text/html")))\r
++        (end-of-orig (point-max)))\r
++      (mm-display-part handle)\r
++      (delete-region (point-min) end-of-orig)\r
++      (fill-region (point-min) (point-max))\r
++      (buffer-substring (point-min) (point-max)))))\r
++\r
+ (defun notmuch-mua-reply (query-string &optional sender reply-all)\r
+-  (let (headers\r
+-      body\r
+-      (args '("reply")))\r
++  (let ((args '("reply" "--format=json"))\r
++      reply\r
++      body)\r
+     (if notmuch-show-process-crypto\r
+       (setq args (append args '("--decrypt"))))\r
+     (if reply-all\r
+       (setq args (append args '("--reply-to=all")))\r
+       (setq args (append args '("--reply-to=sender"))))\r
+     (setq args (append args (list query-string)))\r
+-    ;; This make assumptions about the output of `notmuch reply', but\r
+-    ;; really only that the headers come first followed by a blank\r
+-    ;; line and then the body.\r
++    ;; Get the reply object as JSON, and parse it into an elisp object.\r
+     (with-temp-buffer\r
+       (apply 'call-process (append (list notmuch-command nil (list t t) nil) args))\r
+       (goto-char (point-min))\r
+-      (if (re-search-forward "^$" nil t)\r
+-        (save-excursion\r
+-          (save-restriction\r
+-            (narrow-to-region (point-min) (point))\r
+-            (goto-char (point-min))\r
+-            (setq headers (mail-header-extract)))))\r
+-      (forward-line 1)\r
+-      (setq body (buffer-substring (point) (point-max))))\r
+-    ;; If sender is non-nil, set the From: header to its value.\r
+-    (when sender\r
+-      (mail-header-set 'from sender headers))\r
+-    (let\r
+-      ;; Overlay the composition window on that being used to read\r
+-      ;; the original message.\r
+-      ((same-window-regexps '("\\*mail .*")))\r
+-      (notmuch-mua-mail (mail-header 'to headers)\r
+-                      (mail-header 'subject headers)\r
+-                      (message-headers-to-generate headers t '(to subject))))\r
+-    ;; insert the message body - but put it in front of the signature\r
+-    ;; if one is present\r
+-    (goto-char (point-max))\r
+-    (if (re-search-backward message-signature-separator nil t)\r
++      (setq reply (aref (json-read) 0)))\r
++\r
++    ;; Start with the prelude, based on the headers of the original message.\r
++    (let* ((original (cdr (assq 'original reply)))\r
++         (headers (cdr (assq 'headers (assq 'reply reply))))\r
++         (original-headers (cdr (assq 'headers original)))\r
++         (body-parts (cdr (assq 'body original)))\r
++         (plain-parts (notmuch-parts-filter-by-type body-parts "text/plain"))\r
++         (html-parts (notmuch-parts-filter-by-type body-parts "text/html")))\r
++\r
++      ;; If sender is non-nil, set the From: header to its value.\r
++      (when sender\r
++      (mail-header-set 'from sender headers))\r
++      (let\r
++        ;; Overlay the composition window on that being used to read\r
++        ;; the original message.\r
++        ((same-window-regexps '("\\*mail .*")))\r
++      (notmuch-mua-mail (mail-header 'to headers)\r
++                        (mail-header 'subject headers)\r
++                        (message-headers-to-generate headers t '(to subject))))\r
++      ;; insert the message body - but put it in front of the signature\r
++      ;; if one is present\r
++      (goto-char (point-max))\r
++      (if (re-search-backward message-signature-separator nil t)\r
+         (forward-line -1)\r
+-      (goto-char (point-max)))\r
+-    (insert body)\r
+-    (push-mark))\r
+-  (set-buffer-modified-p nil)\r
++      (goto-char (point-max)))\r
++\r
++      (insert (format "On %s, %s wrote:\n"\r
++                    (cdr (assq 'date original-headers))\r
++                    (cdr (assq 'from original-headers))))\r
++\r
++      (if plain-parts\r
++        (mapc (lambda (part) (notmuch-mua-insert-part-quoted part)) plain-parts)\r
++      (mapc (lambda (part)\r
++              (notmuch-mua-insert-part-quoted (notmuch-mua-parse-html-part part)))\r
++            html-parts))\r
++\r
++      (push-mark))\r
++    (set-buffer-modified-p nil))\r
\r
+   (message-goto-body))\r
\r
+-- \r
+1.7.5.4\r
+\r