[WIP PATCH] emacs: postpone/resume support
authorMark Walters <markwalters1009@gmail.com>
Fri, 3 Jun 2016 00:57:52 +0000 (01:57 +0100)
committerW. Trevor King <wking@tremily.us>
Sat, 20 Aug 2016 23:21:56 +0000 (16:21 -0700)
ea/93210a93e10f25e6ececf530bbd93828b31125 [new file with mode: 0644]

diff --git a/ea/93210a93e10f25e6ececf530bbd93828b31125 b/ea/93210a93e10f25e6ececf530bbd93828b31125
new file mode 100644 (file)
index 0000000..247b9e8
--- /dev/null
@@ -0,0 +1,257 @@
+Return-Path: <markwalters1009@gmail.com>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by arlo.cworth.org (Postfix) with ESMTP id 1117F6DE01D0\r
+ for <notmuch@notmuchmail.org>; Thu,  2 Jun 2016 17:58:09 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at cworth.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.323\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.323 tagged_above=-999 required=5 tests=[AWL=0.247,\r
+  DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1,\r
+ FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7,\r
+ RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_PASS=-0.001]\r
+ autolearn=disabled\r
+Received: from arlo.cworth.org ([127.0.0.1])\r
+ by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id mN0wW-DIWM9u for <notmuch@notmuchmail.org>;\r
+ Thu,  2 Jun 2016 17:58:01 -0700 (PDT)\r
+Received: from mail-wm0-f68.google.com (mail-wm0-f68.google.com\r
+ [74.125.82.68]) by arlo.cworth.org (Postfix) with ESMTPS id 8E31C6DE00DB for\r
+ <notmuch@notmuchmail.org>; Thu,  2 Jun 2016 17:58:00 -0700 (PDT)\r
+Received: by mail-wm0-f68.google.com with SMTP id a20so8343045wma.3\r
+ for <notmuch@notmuchmail.org>; Thu, 02 Jun 2016 17:58:00 -0700 (PDT)\r
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;\r
+ h=from:to:cc:subject:date:message-id:in-reply-to:references;\r
+ bh=+uaVGQFH7IB3pkUFxo2nEl4IaRrZJdSb3Sfs0Nt70S8=;\r
+ b=xb/W0uSbMvuEE+Go1fmibUKWwS4TCVPEEz41SHy/RyZMPdPgGd3IyzliuyFu7gQrVT\r
+ juG0VxmcpaqENd+Z2O3hCNjfR/xMLTcDiHYCOx8TDZaFjbe/y2HG+pnw7+TUNZ6byYQO\r
+ mRU3jbiwpnLBijswbvUqQL9/+joIYTaoczZLyFCrLqR8WwM/qKs4Ft+QwDK3YWLKNb0M\r
+ c+DIeT2aduEJQOADJMtJW1+iWXBUGIdalWIr9wyT+lxHVXAiHQV1sJGGWo6XjiJioCk5\r
+ a/wgAXXucGoBs0CjMw5CHnarjUF0KtGsbTMXbWkkbFT2QwA5HsgqH8UTuG5EMWrmtfB3\r
+ z0Pg==\r
+X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;\r
+ d=1e100.net; s=20130820;\r
+ h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\r
+ :references;\r
+ bh=+uaVGQFH7IB3pkUFxo2nEl4IaRrZJdSb3Sfs0Nt70S8=;\r
+ b=GxTtC72+t8zWmg4vTkAwZYx5keaXFFq9fa0IlKD8ZPjg+6jpQkjaZHt/8xBRf1cG/z\r
+ XC59hy0/keLBIx0pGZKCchHax9qkFmHfxe6L/KI5EEmU5u4hP4QeAkMFScJ4hO3V+C1f\r
+ CpbGEB3xWA7EHIRqHq2WMj9N3E8YtJjTFOMv7tHhJ9ARqqgKmsfFM0s+6D0aiQVeu/Ls\r
+ U1u1EeXocKwAho4ji1ufxeYRX+DtKA5hR194ELLJgmDF/LR6gS58ZEID0XDlIkfDev+y\r
+ G1QHqAnydstjvGR8Cm97w3eKLn3+IbdbfArBCpVIIdbXEi13OwwVvIsqAOWfhZ3YU0it\r
+ N6Iw==\r
+X-Gm-Message-State:\r
+ ALyK8tKt61/2M9L5a7MZMr3pLImfThA1YcOyp1bbO0bX3ODISa1ayaQyGKvO/iZcxbbwww==\r
+X-Received: by 10.194.235.193 with SMTP id uo1mr714133wjc.1.1464915478853;\r
+ Thu, 02 Jun 2016 17:57:58 -0700 (PDT)\r
+Received: from localhost (5751dfa2.skybroadband.com. [87.81.223.162])\r
+ by smtp.gmail.com with ESMTPSA id kc2sm3095384wjb.5.2016.06.02.17.57.57\r
+ (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\r
+ Thu, 02 Jun 2016 17:57:58 -0700 (PDT)\r
+From: Mark Walters <markwalters1009@gmail.com>\r
+To: notmuch@notmuchmail.org\r
+Subject: [WIP PATCH] emacs:  postpone/resume support\r
+Date: Fri,  3 Jun 2016 01:57:52 +0100\r
+Message-Id: <1464915472-5669-1-git-send-email-markwalters1009@gmail.com>\r
+X-Mailer: git-send-email 2.1.4\r
+In-Reply-To: <87mvn330zr.fsf@qmul.ac.uk>\r
+References: <87mvn330zr.fsf@qmul.ac.uk>\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.20\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <https://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: <https://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Fri, 03 Jun 2016 00:58:09 -0000\r
+\r
+This provides preliminary support for postponing and resuming in the\r
+emacs frontend. On postponing it uses notmuch insert to put the\r
+message in the notmuch database; resume gets the raw file from notmuch\r
+and using the emacs function mime-to-mml reconstructs the message\r
+(including attachments).\r
+---\r
+\r
+This is a WIP patch enabling postpone/resume. On very light testing so\r
+far it seems to work surprisingly well.\r
+\r
+Please note that it is an early version, so it may eat your draft\r
+message, mangle (or mysteriously corrupt) your draft message etc; and\r
+it each draft will remain in your message store unless you manually\r
+delete it.\r
+\r
+To use: to postpone just do M-x notmuch-message-postpone in your\r
+compose buffer. To resume fo M-x notmuch-message-resume while on the\r
+correct message in a show buffer. You may want to add "draft" to your\r
+exclude tags in .notmuch-config so that drafts only show up if you\r
+search for them explicitly.\r
+\r
+CAVEATS:\r
+\r
+Attachments work, but the attachment that is sent is the attachment\r
+that was there when the message was postponed. (Attachments added\r
+after resume are obviously not added until the message is sent.)\r
+\r
+If the database is locked when you try and postpone it will\r
+mysteriously fail. I think this is actually caused by a bug elsewhere\r
+in notmuch. But in any case the compose buffer should not be killed in\r
+this case.\r
+\r
+It would probably be nice to delete the messages on resume. Since we\r
+don't really have that functionality, we just add a deleted tag. This\r
+will hide them in search buffers but, if you postpone a reply, it ill\r
+still show up (collapsed) in the show buffer for the thread.\r
+\r
+If you resume a postponed message and then postpone again without\r
+editting then the deleted tag will not be removed so the message may\r
+be hard to find. (see below for possible fixed for this)\r
+\r
+Messages don't get a date header as emacs adds that when it sends it\r
+so notmuch will list all postponed message as 1 Jan 1970. \r
+\r
+If you use signing or encryption then I don't know what will happen --\r
+I have not tested at all.  You might sign a partial message that you\r
+didn't mean too; you might expose plain text to someone.\r
+\r
+WHAT NEEDS DOING\r
+\r
+Trivially we would want some keybindings for the two commands (any\r
+suggested keybindings gratefully received). More significantly, I\r
+would either like a flag to notmuch insert to say "make these tag\r
+changes even if the message already exists"; or perhaps a notmuch\r
+delete command that (genuinely) deletes a single message.\r
+\r
+Best wishes\r
+\r
+Mark\r
+\r
+\r
+\r
+emacs/notmuch-message.el | 90 ++++++++++++++++++++++++++++++++++++++++++++++++\r
+ 1 file changed, 90 insertions(+)\r
+\r
+diff --git a/emacs/notmuch-message.el b/emacs/notmuch-message.el\r
+index d437b85..fdd91c0 100644\r
+--- a/emacs/notmuch-message.el\r
++++ b/emacs/notmuch-message.el\r
+@@ -25,6 +25,8 @@\r
+ (require 'notmuch-tag)\r
+ (require 'notmuch-mua)\r
\r
++(declare-function notmuch-show-get-message-id "notmuch-show" (&optional bare))\r
++\r
+ (defcustom notmuch-message-replied-tags '("+replied")\r
+   "List of tag changes to apply to a message when it has been replied to.\r
\r
+@@ -38,6 +40,28 @@ the \"inbox\" and \"todo\" tags, you would set:\r
+   :type '(repeat string)\r
+   :group 'notmuch-send)\r
\r
++(defcustom notmuch-message-draft-tags '("+draft")\r
++  "List of tags changes to apply to a draft message when it is saved in the database.\r
++\r
++Tags starting with \"+\" (or not starting with either \"+\" or\r
++\"-\") in the list will be added, and tags starting with \"-\"\r
++will be removed from the message being stored.\r
++\r
++For example, if you wanted to give the message a \"draft\" tag\r
++but not the (normally added by default) \"inbox\" tag, you would\r
++set:\r
++    (\"+draft\" \"-inbox\")"\r
++  :type '(repeat string)\r
++  :group 'notmuch-send)\r
++\r
++(defcustom notmuch-message-draft-folder "drafts"\r
++  "Folder to save draft messages in.\r
++\r
++This should be specified relative to the root of the notmuch\r
++database. It will be created if necessary."\r
++  :type 'string\r
++  :group 'notmuch-send)\r
++\r
+ (defun notmuch-message-mark-replied ()\r
+   ;; get the in-reply-to header and parse it for the message id.\r
+   (let ((rep (mail-header-parse-addresses (message-field-value "In-Reply-To"))))\r
+@@ -45,6 +69,72 @@ the \"inbox\" and \"todo\" tags, you would set:\r
+       (notmuch-tag (notmuch-id-to-query (car (car rep)))\r
+              (notmuch-tag-change-list notmuch-message-replied-tags)))))\r
\r
++(defun notmuch-message-postpone ()\r
++  "Save the current draft message in the notmuch database.\r
++\r
++This saves the current message in the database with tags\r
++`notmuch-message-draft-tags` (in addition to any default tags\r
++applied to newly inserted messages)."\r
++  ;; This is taken from message-do-fcc but modified for our needs.  In\r
++  ;; particular we don't want to process other fcc lines, nor remove\r
++  ;; them. Note some of the following may not be needed -- I tried to\r
++  ;; stay close to the original function.\r
++  (interactive)\r
++  (let ((case-fold-search t)\r
++      (buf (current-buffer))\r
++      (mml-externalize-attachments nil))\r
++    (with-current-buffer (get-buffer-create " *message temp*")\r
++      (erase-buffer)\r
++      (insert-buffer-substring buf)\r
++      (message-encode-message-body)\r
++      (save-restriction\r
++      (message-narrow-to-headers)\r
++      (let ((mail-parse-charset message-default-charset)\r
++            (rfc2047-header-encoding-alist\r
++             (cons '("Newsgroups" . default)\r
++                   rfc2047-header-encoding-alist)))\r
++        (mail-encode-encoded-word-buffer)))\r
++      (goto-char (point-min))\r
++      (when (re-search-forward\r
++           (concat "^" (regexp-quote mail-header-separator) "$")\r
++           nil t)\r
++      (replace-match "" t t ))\r
++\r
++      ;; Unless the user has entered a message-id manually the message\r
++      ;; does not have one -- thus notmuch will use the sha1 of the\r
++      ;; message. Hence we should only get a collision if the message\r
++      ;; is identical to a previous draft. In this case we should\r
++      ;; remove the deleted tag, but it is not clear howto.\r
++      (apply 'notmuch-call-notmuch-process :stdin-string (buffer-string)\r
++           "insert" "--create-folder"\r
++           (concat "--folder=" notmuch-message-draft-folder)\r
++           notmuch-message-draft-tags)))\r
++  ;; The function notmuch-call-notmuch-process signals an error on failure, so\r
++  ;; to get to this point it must have succeeded.\r
++  (set-buffer-modified-p nil)\r
++  (kill-buffer))\r
++\r
++(defun notmuch-message-resume (&optional id)\r
++  "View the original source of the current message."\r
++  (interactive)\r
++  (let* ((id (or id (notmuch-show-get-message-id)))\r
++       (buf (get-buffer-create (concat "*notmuch-draft-" id "*")))\r
++       (inhibit-read-only t))\r
++    (switch-to-buffer buf)\r
++    (setq buffer-read-only nil)\r
++    (erase-buffer)\r
++    (let ((coding-system-for-read 'no-conversion))\r
++      (call-process notmuch-command nil t nil "show" "--format=raw" id))\r
++    (mime-to-mml)\r
++    (goto-char (point-min))\r
++    (when (re-search-forward "^$" nil t)\r
++      (replace-match mail-header-separator t t))\r
++    (notmuch-message-mode)\r
++    (set-buffer-modified-p t)\r
++    ;; Delete the message (since we can't do this yet just tag it deleted).\r
++    (notmuch-tag id '("+deleted"))))\r
++\r
++\r
+ (add-hook 'message-send-hook 'notmuch-message-mark-replied)\r
\r
+ (provide 'notmuch-message)\r
+-- \r
+2.1.4\r
+\r