* mu4e: support extracting ranges of attachments (C-u e); contributed by

Stephen Eglen.
This commit is contained in:
djcb 2012-06-07 16:24:58 +03:00
parent 43785adbf1
commit 76e70185a2
3 changed files with 82 additions and 8 deletions

View File

@ -726,6 +726,42 @@ mu4e logs some of its internal workings to a log-buffer. See
(unless (buffer-live-p buf)
(error "No debug log available"))
(switch-to-buffer buf)))
(defun mu4e-split-ranges-to-numbers (str n)
"Convert STR containing attachment numbers into a list of numbers.
STR is a string; N is the highest possible number in the list.
This includes expanding e.g. 3-5 into 3,4,5. If the letter
\"a\" ('all')) is given, that is expanded to a list with numbers [1..n]."
(let ((str-split (split-string str))
beg end list)
(dolist (elem str-split list)
;; special number "a" converts into all attachments 1-N.
(when (equal elem "a")
(setq elem (concat "1-" (int-to-string n))))
(if (string-match "\\([0-9]+\\)-\\([0-9]+\\)" elem)
;; we have found a range A-B, which needs converting
;; into the numbers A, A+1, A+2, ... B.
(progn
(setq beg (string-to-int (match-string 1 elem))
end (string-to-int (match-string 2 elem)))
(while (<= beg end)
(add-to-list 'list beg 'append)
(setq beg (1+ beg))))
;; else just a number
(add-to-list 'list (string-to-int elem) 'append)))
;; Check that all numbers are valid.
(mapc
'(lambda (x)
(cond
((> x n)
(error "Attachment %d bigger than maximum (%d)" x n))
((< x 1)
(error "Attachment number must be greater than 0 (%d)" x))))
list)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar mu4e-imagemagick-identify "identify"

View File

@ -753,16 +753,23 @@ all messages in the thread at point in the headers view."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; attachment handling
(defun mu4e~view-get-attach-num (prompt msg)
(defun mu4e~view-get-attach-num (prompt msg &optional multi)
"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* ((count (hash-table-count mu4e~view-attach-map)))
[0..(n-1)] in the message. If MULTI is nil, return the number for
the attachment; otherwise (MULTI is non-nil), accept ranges of
attachment numbers, as per `mu4e-split-ranges-to-numbers', and
return the corresponding string."
(let* ((count (hash-table-count mu4e~view-attach-map)) (def))
(when (zerop count) (error "No attachments for this message"))
(if (= count 1)
(read-number (mu4e-format "%s: " prompt) 1)
(read-number (mu4e-format "%s (1-%d): " prompt count)))))
(if (not multi)
(if (= count 1)
(read-number (mu4e-format "%s: " prompt) 1)
(read-number (mu4e-format "%s (1-%d): " prompt count)))
(progn
(setq def (if (= count 1) "1" (format "1-%d" count)))
(read-string (mu4e-format "%s (default %s): " prompt def) nil nil def)))))
(defun mu4e~view-get-attach (msg attnum)
"Return the attachment plist in MSG corresponding to attachment
number ATTNUM."
@ -773,7 +780,7 @@ number ATTNUM."
(plist-get msg :parts))))
(defun mu4e-view-save-attachment (&optional msg attnum)
(defun mu4e-view-save-attachment-single (&optional msg attnum)
"Save attachment number ATTNUM (or ask if nil) from MSG (or
message-at-point if nil) to disk."
(interactive)
@ -795,6 +802,31 @@ message-at-point if nil) to disk."
(mu4e~proc-extract
'save (plist-get msg :docid) index path)))
(defun mu4e-view-save-attachment-multi (&optional msg)
"Offer to save multiple email attachments from the current message.
Default is to save all messages, [1..n], where n is the number of
attachments. You can type multiple values separated by space, e.g.
1 3-6 8
will save attachments 1,3,4,5,6 and 8.
Furthermore, there is a shortcut \"a\" which so means all
attachments, but as this is the default, you may not need it."
(interactive)
(let* ((msg (or msg (mu4e-message-at-point)))
(attachstr (mu4e~view-get-attach-num
"Attachment number range (or 'a' for 'all')" msg t))
(attachnums (mu4e-split-ranges-to-numbers attachstr count)))
(dolist (num attachnums)
(mu4e-view-save-attachment-single msg num))))
(defun mu4e-view-save-attachment (&optional multi)
"Offer to save attachment(s). If MULTI (prefix-argument) is nil,
save a single one, otherwise, offer to save a range of
attachments."
(interactive "P")
(if multi
(mu4e-view-save-attachment-multi)
(mu4e-view-save-attachment-single)))
(defun mu4e-view-open-attachment (&optional msg attnum)
"Open attachment number ATTNUM (or ask if nil) from MSG (or

View File

@ -734,6 +734,7 @@ g go to (visit) numbered URL (using `browse-url')
(or: <mouse-2> or RET with point on url)
e extract (save) attachment (asks for number)
(or: <mouse-2> or RET with point on attachment)
C-u e will extract multiple attachments
o open attachment (asks for number)
(or: <S-mouse-2> or S-RET with point on attachment)
A execute some action on an attachment
@ -761,6 +762,11 @@ variable @code{mu4e-attachment-dir}, for example:
(setq mu4e-attachment-dir (file-name-expand "~/Downloads"))
@end lisp
If you want to extract multiple attachments at once, you can do so by
prefixing the extracting command by @key{C-u}; so @key{C-u e} will ask you for
a range of attachments to extract (for example, 1 3-6 8). Range @t{a} is a
shortcut for @emph{all} attachments.
@subsection Viewing images inline
@anchor{Viewing images inline}