[PATCH v3] Make buttons for attachments allow viewing as well as saving
authorMark Walters <markwalters1009@gmail.com>
Tue, 17 Jan 2012 23:44:46 +0000 (23:44 +0000)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:42:31 +0000 (09:42 -0800)
18/c7ce822821031e86b342b70942cdaf998b0fa0 [new file with mode: 0644]

diff --git a/18/c7ce822821031e86b342b70942cdaf998b0fa0 b/18/c7ce822821031e86b342b70942cdaf998b0fa0
new file mode 100644 (file)
index 0000000..6b80d4d
--- /dev/null
@@ -0,0 +1,221 @@
+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 olra.theworths.org (Postfix) with ESMTP id 2052E429E5F\r
+       for <notmuch@notmuchmail.org>; Tue, 17 Jan 2012 15:44:29 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: 0.201\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=0.201 tagged_above=-999 required=5\r
+       tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1,\r
+       FREEMAIL_ENVFROM_END_DIGIT=1, FREEMAIL_FROM=0.001,\r
+       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 42+tg8PM2gTJ for <notmuch@notmuchmail.org>;\r
+       Tue, 17 Jan 2012 15:44:28 -0800 (PST)\r
+Received: from mail-we0-f181.google.com (mail-we0-f181.google.com\r
+       [74.125.82.181]) (using TLSv1 with cipher RC4-SHA (128/128 bits))\r
+       (No client certificate requested)\r
+       by olra.theworths.org (Postfix) with ESMTPS id 25645429E27\r
+       for <notmuch@notmuchmail.org>; Tue, 17 Jan 2012 15:44:28 -0800 (PST)\r
+Received: by werp13 with SMTP id p13so914905wer.26\r
+       for <notmuch@notmuchmail.org>; Tue, 17 Jan 2012 15:44:26 -0800 (PST)\r
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma;\r
+       h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references;\r
+       bh=byucpBqCV9QFDt6VbjaSco5/bHV0/Rhjg1zo4JAI/2Y=;\r
+       b=SHuvFSPsNV0BLvhYgFtBTWhUqIzeDMQNZlxniYSqwIhaL0if+zpV3DsclMKWOkmT+j\r
+       BuJE04ZbqZfhd3W20XN8LgDlveQ0iVn9U+x8GsiEYCWdeCwnQSJGaIJ3frHxny9QfnjA\r
+       eJ94swgRh2gcG8mlzE6qA+5g6y533UXgvWqk8=\r
+Received: by 10.216.133.71 with SMTP id p49mr306824wei.8.1326843866721;\r
+       Tue, 17 Jan 2012 15:44:26 -0800 (PST)\r
+Received: from localhost (94-192-233-223.zone6.bethere.co.uk.\r
+ [94.192.233.223])     by mx.google.com with ESMTPS id\r
+ d9sm19615881wiy.2.2012.01.17.15.44.25 (version=TLSv1/SSLv3 cipher=OTHER);\r
+       Tue, 17 Jan 2012 15:44:25 -0800 (PST)\r
+From: Mark Walters <markwalters1009@gmail.com>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH v3] Make buttons for attachments allow viewing as well as\r
+       saving\r
+Date: Tue, 17 Jan 2012 23:44:46 +0000\r
+Message-Id: <1326843886-18387-1-git-send-email-markwalters1009@gmail.com>\r
+X-Mailer: git-send-email 1.7.2.3\r
+In-Reply-To: <87lip5rj43.fsf@qmul.ac.uk>\r
+References: <87lip5rj43.fsf@qmul.ac.uk>\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: Tue, 17 Jan 2012 23:44:29 -0000\r
+\r
+Define a keymap for attachment buttons to allow multiple actions.\r
+Define 3 possible actions:\r
+    save attachment: exactly as currently,\r
+    view attachment: uses mailcap entry,\r
+    view attachment with user chosen program\r
+\r
+Keymap on a button is: s for save, v for view and o for view with\r
+other program. Default (i.e. enter or mouse button) is save but this\r
+is configurable in notmuch customize.\r
+\r
+One implementation detail: the view attachment function forces all\r
+attachments to be "displayed" using mailcap even if emacs could\r
+display them itself. Thus, for example, text/html appears in a browser\r
+and text/plain asks whether to save (on a standard debian setup)\r
+---\r
+ emacs/notmuch-show.el |  106 ++++++++++++++++++++++++++++++++++++++-----------\r
+ 1 files changed, 82 insertions(+), 24 deletions(-)\r
+\r
+diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el\r
+index 03c1f6b..0aaaf79 100644\r
+--- a/emacs/notmuch-show.el\r
++++ b/emacs/notmuch-show.el\r
+@@ -281,10 +281,21 @@ message at DEPTH in the current thread."\r
+       (run-hooks 'notmuch-show-markup-headers-hook)))))\r
\r
+ (define-button-type 'notmuch-show-part-button-type\r
+-  'action 'notmuch-show-part-button-action\r
++  'action 'notmuch-show-part-button-default\r
++  'keymap 'notmuch-show-part-button-map\r
+   'follow-link t\r
+   'face 'message-mml)\r
\r
++(defvar notmuch-show-part-button-map\r
++  (let ((map (make-sparse-keymap)))\r
++       (set-keymap-parent map button-map)\r
++       (define-key map "s" 'notmuch-show-part-button-save)\r
++       (define-key map "v" 'notmuch-show-part-button-view)\r
++       (define-key map "o" 'notmuch-show-part-button-interactively-view)\r
++    map)\r
++  "Submap for button commands")\r
++(fset 'notmuch-show-part-button-map notmuch-show-part-button-map)\r
++\r
+ (defun notmuch-show-insert-part-header (nth content-type declared-type &optional name comment)\r
+   (let ((button))\r
+     (setq button\r
+@@ -299,29 +310,48 @@ message at DEPTH in the current thread."\r
+                  " ]")\r
+          :type 'notmuch-show-part-button-type\r
+          :notmuch-part nth\r
+-         :notmuch-filename name))\r
++         :notmuch-filename name\r
++         :notmuch-content-type content-type))\r
+     (insert "\n")\r
+     ;; return button\r
+     button))\r
\r
+ ;; Functions handling particular MIME parts.\r
\r
+-(defun notmuch-show-save-part (message-id nth &optional filename)\r
+-  (let ((process-crypto notmuch-show-process-crypto))\r
+-    (with-temp-buffer\r
+-      (setq notmuch-show-process-crypto process-crypto)\r
+-      ;; Always acquires the part via `notmuch part', even if it is\r
+-      ;; available in the JSON output.\r
+-      (insert (notmuch-show-get-bodypart-internal message-id nth))\r
+-      (let ((file (read-file-name\r
+-                 "Filename to save as: "\r
+-                 (or mailcap-download-directory "~/")\r
+-                 nil nil\r
+-                 filename)))\r
+-      ;; Don't re-compress .gz & al.  Arguably we should make\r
+-      ;; `file-name-handler-alist' nil, but that would chop\r
+-      ;; ange-ftp, which is reasonable to use here.\r
+-      (mm-write-region (point-min) (point-max) file nil nil nil 'no-conversion t)))))\r
++(defmacro notmuch-with-temp-part-buffer (message-id nth &rest body)\r
++  (declare (indent 2))\r
++  (let ((process-crypto (make-symbol "process-crypto")))\r
++    `(let ((,process-crypto notmuch-show-process-crypto))\r
++       (with-temp-buffer\r
++       (setq notmuch-show-process-crypto ,process-crypto)\r
++       ;; Always acquires the part via `notmuch part', even if it is\r
++       ;; available in the JSON output.\r
++       (insert (notmuch-show-get-bodypart-internal ,message-id ,nth))\r
++       ,@body))))\r
++\r
++(defun notmuch-show-save-part (message-id nth &optional filename content-type)\r
++  (notmuch-with-temp-part-buffer message-id nth\r
++    (let ((file (read-file-name\r
++               "Filename to save as: "\r
++               (or mailcap-download-directory "~/")\r
++               nil nil\r
++               filename)))\r
++      ;; Don't re-compress .gz & al.  Arguably we should make\r
++      ;; `file-name-handler-alist' nil, but that would chop\r
++      ;; ange-ftp, which is reasonable to use here.\r
++      (mm-write-region (point-min) (point-max) file nil nil nil 'no-conversion t))))\r
++\r
++(defun notmuch-show-view-part (message-id nth &optional filename content-type )\r
++  (notmuch-with-temp-part-buffer message-id nth\r
++    ;; set mm-inlined-types to nil to force an external viewer\r
++    (let ((handle (mm-make-handle (current-buffer) (list content-type)))\r
++        (mm-inlined-types nil))\r
++      (mm-display-part handle t))))\r
++\r
++(defun notmuch-show-interactively-view-part (message-id nth &optional filename content-type)\r
++  (notmuch-with-temp-part-buffer message-id nth\r
++    (let ((handle (mm-make-handle (current-buffer) (list content-type))))\r
++      (mm-interactively-view-part handle))))\r
\r
+ (defun notmuch-show-mm-display-part-inline (msg part nth content-type)\r
+   "Use the mm-decode/mm-view functions to display a part in the\r
+@@ -1502,12 +1532,40 @@ buffer."\r
\r
+ ;; Commands typically bound to buttons.\r
\r
+-(defun notmuch-show-part-button-action (button)\r
+-  (let ((nth (button-get button :notmuch-part)))\r
+-    (if nth\r
+-      (notmuch-show-save-part (notmuch-show-get-message-id) nth\r
+-                              (button-get button :notmuch-filename))\r
+-      (message "Not a valid part (is it a fake part?)."))))\r
++(defcustom notmuch-show-part-button-default-action 'notmuch-show-save-part\r
++  "Default part header button action (on ENTER or mouse click)."\r
++  :group 'notmuch\r
++  :type '(choice (const :tag "Save part"\r
++                      notmuch-show-save-part)\r
++               (const :tag "View part"\r
++                      notmuch-show-view-part)\r
++               (const :tag "View interactively"\r
++                      notmuch-show-interactively-view-part)))\r
++\r
++(defun notmuch-show-part-button-default (&optional button)\r
++  (interactive)\r
++  (notmuch-show-part-button-internal button notmuch-show-part-button-default-action))\r
++\r
++(defun notmuch-show-part-button-save (&optional button)\r
++  (interactive)\r
++  (notmuch-show-part-button-internal button #'notmuch-show-save-part))\r
++\r
++(defun notmuch-show-part-button-view (&optional button)\r
++  (interactive)\r
++  (notmuch-show-part-button-internal button #'notmuch-show-view-part))\r
++\r
++(defun notmuch-show-part-button-interactively-view (&optional button)\r
++  (interactive)\r
++  (notmuch-show-part-button-internal button #'notmuch-show-interactively-view-part))\r
++\r
++(defun notmuch-show-part-button-internal (button handler)\r
++  (let ((button (or button (button-at (point)))))\r
++    (if button\r
++      (let ((nth (button-get button :notmuch-part)))\r
++        (if nth\r
++            (funcall handler (notmuch-show-get-message-id) nth\r
++                     (button-get button :notmuch-filename)\r
++                     (button-get button :notmuch-content-type)))))))\r
\r
+ ;;\r
\r
+-- \r
+1.7.2.3\r
+\r