From 0834dd59742eb0035c3109a1405b90487dd5a31a Mon Sep 17 00:00:00 2001 From: djcb Date: Sun, 13 May 2012 13:10:56 +0300 Subject: [PATCH] * mu4e: get information about all mime parts, not just attachments --- emacs/mu4e-view.el | 71 ++++++++++++++++++++++++++++++---------------- src/mu-msg-sexp.c | 18 ++++++------ 2 files changed, 56 insertions(+), 33 deletions(-) diff --git a/emacs/mu4e-view.el b/emacs/mu4e-view.el index b0173bc0..f7004481 100644 --- a/emacs/mu4e-view.el +++ b/emacs/mu4e-view.el @@ -112,12 +112,26 @@ where: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; some buffer-local variables +;; some buffer-local variables / constants (defvar mu4e~view-headers-buffer nil - "*internal* Headers buffer connected to this view.") + "The headers buffer connected to this view.") + +(defvar mu4e~view-lines-wrapped nil "Whether lines are wrapped.") +(defvar mu4e~view-cited-hidden nil "Whether cited lines are hidden.") + +(defvar mu4e~view-link-map nil + "A map of some number->url so we can jump to url by number.") + +(defconst mu4e~view-url-regexp + "\\(https?://[-+a-zA-Z0-9.?_$%/+&#@!~,:;=/()]+\\)" + "Regexp that matches URLs; match-string 1 will contain + the matched URL, if any.") + +(defvar mu4e~view-attach-map nil + "A mapping of user-visible attachment number to the actual part index.") +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + -(defvar mu4e~view-lines-wrapped nil "*internal* Whether lines are wrapped.") -(defvar mu4e~view-cited-hidden nil "*internal* Whether cited lines are hidden.") (defun mu4e-view-message-with-msgid (msgid) @@ -261,21 +275,32 @@ is nil, and otherwise open it." (mu4e-view-open-attachment msg attachnum) (mu4e-view-save-attachment msg attachnum))))) -;; note -- attachments have an index which is needed for the backend, which does -;; not necessarily follow 1,2,3,4 etc. (defun mu4e~view-construct-attachments (msg) "Display attachment information; the field looks like something like: - :attachments ((:index 4 :name \"test123.doc\" - :mime-type \"application/msword\" :size 1234))." + :parts ((:index 1 :name \"test123.doc\" + :mime-type \"application/msword\" :attachment t :size 1234) + (:index 2 :name \"test456.pdf\" + :mime-type \"application/pdf\" :attachment t :size 12234))." + (setq mu4e~view-attach-map ;; buffer local + (make-hash-table :size 16 :rehash-size 2 :weakness nil)) (let* ((id 0) + (attachments + ;; we only list parts that look like attachments, ie. that have a + ;; non-nil :attachment property; we record a mapping between user-visible + ;; numbers and the part indices + (remove-if-not + (lambda (part) + (plist-get part :attachment)) + (plist-get msg :parts))) (attstr (mapconcat - (lambda (att) - (let ( (index (plist-get att :index)) - (name (plist-get att :name)) - (size (plist-get att :size)) + (lambda (part) + (let ((index (plist-get part :index)) + (name (plist-get part :name)) + (size (plist-get part :size)) (map (make-sparse-keymap))) (incf id) + (puthash id index mu4e~view-attach-map) (define-key map [mouse-2] (mu4e~view-open-save-attach-func msg id nil)) (define-key map [?\r] @@ -292,7 +317,7 @@ is nil, and otherwise open it." (concat (format "(%s)" (propertize (mu4e-display-size size) 'face 'mu4e-view-header-key-face))))))) - (plist-get msg :attachments) ", "))) + attachments ", "))) (unless (zerop id) (mu4e~view-construct-header (format "Attachments(%d)" id) attstr t)))) @@ -457,6 +482,7 @@ is nil, and otherwise open it." (make-local-variable 'mu4e~view-headers-buffer) (make-local-variable 'mu4e~view-msg) (make-local-variable 'mu4e~view-link-map) + (make-local-variable 'mu4e~view-attach-map) (make-local-variable 'mu4e~view-lines-wrapped) (make-local-variable 'mu4e~view-cited-hidden) @@ -528,14 +554,6 @@ Seen; if the message is not New/Unread, do nothing." (when p (add-text-properties p (point-max) '(face mu4e-footer-face))))))) -(defvar mu4e~view-link-map nil - "*internal* A map of some number->url so we can jump to url by number.") - -(defconst mu4e~view-url-regexp - "\\(https?://[-+a-zA-Z0-9.?_$%/+&#@!~,:;=/()]+\\)" - "*internal* regexp that matches URLs; match-string 1 will contain - the matched URL, if any.") - (defun mu4e~view-browse-url-func (url) "Return a function that executes `browse-url' with URL." (lexical-let ((url url)) @@ -705,8 +723,7 @@ all messages in the thread at point in the headers view." "Ask the user with PROMPT for an attachment number for MSG, and ensure it is valid. The number is [1..n] for attachments [0..(n-1)] in the message." - (let* ((attlist (plist-get msg :attachments)) - (count (length attlist))) + (let* ((count (hash-table-count mu4e~view-attach-map))) (when (zerop count) (error "No attachments for this message")) (if (= count 1) (read-number (mu4e-format "%s: " prompt) 1) @@ -715,8 +732,12 @@ all messages in the thread at point in the headers view." (defun mu4e~view-get-attach (msg attnum) "Return the attachment plist in MSG corresponding to attachment number ATTNUM." - (let ((attlist (plist-get msg :attachments))) - (nth (- attnum 1) attlist))) + (let ((partid (gethash attnum mu4e~view-attach-map))) + (find-if + (lambda (part) + (eq (plist-get part :index) partid)) + (plist-get msg :parts)))) + (defun mu4e-view-save-attachment (&optional msg attnum) "Save attachment number ATTNUM (or ask if nil) from MSG (or diff --git a/src/mu-msg-sexp.c b/src/mu-msg-sexp.c index 0440154c..f552d9a4 100644 --- a/src/mu-msg-sexp.c +++ b/src/mu-msg-sexp.c @@ -208,9 +208,6 @@ each_part (MuMsg *msg, MuMsgPart *part, gchar **parts) const char *fname; char *name, *tmp; - if (!mu_msg_part_looks_like_attachment (part, TRUE)) - return; - fname = mu_msg_part_file_name (part); if (!fname) fname = mu_msg_part_description (part); @@ -218,13 +215,18 @@ each_part (MuMsg *msg, MuMsgPart *part, gchar **parts) if (fname) name = mu_str_escape_c_literal (fname, TRUE); else - name = g_strdup_printf ("\"part-%d\"", part->index); + name = g_strdup_printf + ("\"%s-%s-%d\"", + part->type ? part->type : "application", + part->subtype ? part->subtype : "octet-stream", + part->index); tmp = g_strdup_printf - ("%s(:index %d :name %s :mime-type \"%s/%s\" :size %i)", + ("%s(:index %d :name %s :mime-type \"%s/%s\" :attachment %s :size %i)", *parts ? *parts : "", part->index, name, part->type ? part->type : "application", part->subtype ? part->subtype : "octet-stream", + mu_msg_part_looks_like_attachment (part, TRUE) ? "t" : "nil", (int)part->size); g_free (*parts); @@ -233,7 +235,7 @@ each_part (MuMsg *msg, MuMsgPart *part, gchar **parts) static void -append_sexp_attachments (GString *gstr, MuMsg *msg) +append_sexp_parts (GString *gstr, MuMsg *msg) { char *parts; @@ -242,7 +244,7 @@ append_sexp_attachments (GString *gstr, MuMsg *msg) (MuMsgPartForeachFunc)each_part, &parts); if (parts) { - g_string_append_printf (gstr, "\t:attachments (%s)\n", parts); + g_string_append_printf (gstr, "\t:parts (%s)\n", parts); g_free (parts); } } @@ -252,7 +254,7 @@ append_sexp_attachments (GString *gstr, MuMsg *msg) static void append_sexp_message_file_attr (GString *gstr, MuMsg *msg) { - append_sexp_attachments (gstr, msg); + append_sexp_parts (gstr, msg); append_sexp_attr_list (gstr, "references", mu_msg_get_references (msg)); append_sexp_attr (gstr, "in-reply-to",