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 6A797431FAF for ; Sun, 15 Jan 2012 04:16:12 -0800 (PST) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org X-Spam-Flag: NO X-Spam-Score: 0.201 X-Spam-Level: X-Spam-Status: No, score=0.201 tagged_above=-999 required=5 tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, FREEMAIL_ENVFROM_END_DIGIT=1, FREEMAIL_FROM=0.001, 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 H+p61UoJ6UdC for ; Sun, 15 Jan 2012 04:16:11 -0800 (PST) Received: from mail-we0-f181.google.com (mail-we0-f181.google.com [74.125.82.181]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) (No client certificate requested) by olra.theworths.org (Postfix) with ESMTPS id 7139B431FAE for ; Sun, 15 Jan 2012 04:16:11 -0800 (PST) Received: by werh12 with SMTP id h12so667281wer.26 for ; Sun, 15 Jan 2012 04:16:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=zOn2V4o6eiZgnjmfbphBMFOEn/C+j5/YvUzenhJt0Rw=; b=g6g56O4d8eDvTWOqaqeYt3eaWBGPGHM5CqkH8XdM2EIAlNh72WvRVqAyretwsCgWAL MhEMw2oKPIrAJbnZegapSa+fu1iu0YuIQJekW8nwmxr+gDZ03FlxOEX1UjfPYskvnQ5m Mh3bdMPqFlxD/WaREo2YerX6iiSQjLmdSnRRY= Received: by 10.216.133.234 with SMTP id q84mr3296415wei.30.1326629770246; Sun, 15 Jan 2012 04:16:10 -0800 (PST) Received: from localhost (94-192-233-223.zone6.bethere.co.uk. [94.192.233.223]) by mx.google.com with ESMTPS id di5sm27566485wib.3.2012.01.15.04.16.08 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 15 Jan 2012 04:16:09 -0800 (PST) From: Mark Walters To: notmuch@notmuchmail.org Subject: [PATCH 1/1] Make buttons for attachments allow viewing as well as saving Date: Sun, 15 Jan 2012 12:16:36 +0000 Message-Id: <1326629796-11436-2-git-send-email-markwalters1009@gmail.com> X-Mailer: git-send-email 1.7.2.3 In-Reply-To: <1326629796-11436-1-git-send-email-markwalters1009@gmail.com> References: <1326629796-11436-1-git-send-email-markwalters1009@gmail.com> 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: Sun, 15 Jan 2012 12:16:12 -0000 Define a keymap for attachment buttons to allow multiple actions. Define 3 possible actions: save attachment: exactly as currently, view attachment: uses mailcap entry, view attachment with user chosen program Keymap on a button is: s for save, v for view and o for view with other program. Default (i.e. enter or mouse button) is save but is easily configurable e.g. set to view with (setq notmuch-show-part-button-default-action 'notmuch-show-part-view-action) One implementation detail: the view attachment function forces all attachments to be "displayed" using mailcap even if emacs could display them itself. Thus, for example, text/html appears in a browser and text/plain asks whether to save (on a standard debian setup) --- emacs/notmuch-show.el | 81 ++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 64 insertions(+), 17 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 03c1f6b..a1c0e63 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -281,10 +281,21 @@ message at DEPTH in the current thread." (run-hooks 'notmuch-show-markup-headers-hook))))) (define-button-type 'notmuch-show-part-button-type - 'action 'notmuch-show-part-button-action + 'action 'notmuch-show-part-button-default + 'keymap 'notmuch-show-part-button-map 'follow-link t 'face 'message-mml) +(defvar notmuch-show-part-button-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map button-map) + (define-key map "s" 'notmuch-show-part-button-save) + (define-key map "v" 'notmuch-show-part-button-view) + (define-key map "o" 'notmuch-show-part-button-interactively-view) + map) + "Submap for button commands") +(fset 'notmuch-show-part-button-map notmuch-show-part-button-map) + (defun notmuch-show-insert-part-header (nth content-type declared-type &optional name comment) (let ((button)) (setq button @@ -299,29 +310,43 @@ message at DEPTH in the current thread." " ]") :type 'notmuch-show-part-button-type :notmuch-part nth - :notmuch-filename name)) + :notmuch-filename name + :notmuch-content-type content-type)) (insert "\n") ;; return button button)) ;; Functions handling particular MIME parts. +;; this function is kept for the tests and any external users (defun notmuch-show-save-part (message-id nth &optional filename) + (notmuch-show-part-action 'notmuch-show-part-save-action message-id nth nil filename)) + +(defun notmuch-show-part-action (action message-id nth content-type &optional filename) (let ((process-crypto notmuch-show-process-crypto)) (with-temp-buffer (setq notmuch-show-process-crypto process-crypto) ;; Always acquires the part via `notmuch part', even if it is ;; available in the JSON output. (insert (notmuch-show-get-bodypart-internal message-id nth)) - (let ((file (read-file-name - "Filename to save as: " - (or mailcap-download-directory "~/") - nil nil - filename))) - ;; Don't re-compress .gz & al. Arguably we should make - ;; `file-name-handler-alist' nil, but that would chop - ;; ange-ftp, which is reasonable to use here. - (mm-write-region (point-min) (point-max) file nil nil nil 'no-conversion t))))) + (cond ((eq action 'notmuch-show-part-save-action) + (let ((file (read-file-name + "Filename to save as: " + (or mailcap-download-directory "~/") + nil nil + filename))) + ;; Don't re-compress .gz & al. Arguably we should make + ;; `file-name-handler-alist' nil, but that would chop + ;; ange-ftp, which is reasonable to use here. + (mm-write-region (point-min) (point-max) file nil nil nil 'no-conversion t))) + ((eq action 'notmuch-show-part-view-action) + ;; set mm-inlined-types to nil to force an external viewer + (let ((handle (mm-make-handle (current-buffer) (list content-type))) + (mm-inlined-types nil)) + (mm-display-part handle))) + ((eq action 'notmuch-show-part-interactively-view-action) + (let ((handle (mm-make-handle (current-buffer) (list content-type)))) + (mm-interactively-view-part handle))))))) (defun notmuch-show-mm-display-part-inline (msg part nth content-type) "Use the mm-decode/mm-view functions to display a part in the @@ -1502,12 +1527,34 @@ buffer." ;; Commands typically bound to buttons. -(defun notmuch-show-part-button-action (button) - (let ((nth (button-get button :notmuch-part))) - (if nth - (notmuch-show-save-part (notmuch-show-get-message-id) nth - (button-get button :notmuch-filename)) - (message "Not a valid part (is it a fake part?).")))) +(defvar notmuch-show-part-button-default-action 'notmuch-show-part-save-action) + +(defun notmuch-show-part-button-default (&optional button) + (interactive) + (notmuch-show-part-button notmuch-show-part-button-default-action button)) + +(defun notmuch-show-part-button-save (&optional button) + (interactive) + (notmuch-show-part-button 'notmuch-show-part-save-action button)) + +(defun notmuch-show-part-button-view (&optional button) + (interactive) + (notmuch-show-part-button 'notmuch-show-part-view-action button)) + +(defun notmuch-show-part-button-interactively-view (&optional button) + (interactive) + (notmuch-show-part-button 'notmuch-show-part-interactively-view-action button)) + +(defun notmuch-show-part-button (action &optional button) + (interactive) + (let ((button (or button (button-at (point))))) + (if button + (let ((nth (button-get button :notmuch-part))) + (if nth + (notmuch-show-part-action action (notmuch-show-get-message-id) nth + (button-get button :notmuch-content-type) + (button-get button :notmuch-filename)) + (message "Not a valid part (is it a fake part?).")))))) ;; -- 1.7.2.3