* 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) (unless (buffer-live-p buf)
(error "No debug log available")) (error "No debug log available"))
(switch-to-buffer buf))) (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" (defvar mu4e-imagemagick-identify "identify"

View File

@ -753,16 +753,23 @@ all messages in the thread at point in the headers view."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; attachment handling ;; 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 "Ask the user with PROMPT for an attachment number for MSG, and
ensure it is valid. The number is [1..n] for attachments ensure it is valid. The number is [1..n] for attachments
[0..(n-1)] in the message." [0..(n-1)] in the message. If MULTI is nil, return the number for
(let* ((count (hash-table-count mu4e~view-attach-map))) 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")) (when (zerop count) (error "No attachments for this message"))
(if (= count 1) (if (not multi)
(read-number (mu4e-format "%s: " prompt) 1) (if (= count 1)
(read-number (mu4e-format "%s (1-%d): " prompt count))))) (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) (defun mu4e~view-get-attach (msg attnum)
"Return the attachment plist in MSG corresponding to attachment "Return the attachment plist in MSG corresponding to attachment
number ATTNUM." number ATTNUM."
@ -773,7 +780,7 @@ number ATTNUM."
(plist-get msg :parts)))) (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 "Save attachment number ATTNUM (or ask if nil) from MSG (or
message-at-point if nil) to disk." message-at-point if nil) to disk."
(interactive) (interactive)
@ -795,6 +802,31 @@ message-at-point if nil) to disk."
(mu4e~proc-extract (mu4e~proc-extract
'save (plist-get msg :docid) index path))) '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) (defun mu4e-view-open-attachment (&optional msg attnum)
"Open attachment number ATTNUM (or ask if nil) from MSG (or "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) (or: <mouse-2> or RET with point on url)
e extract (save) attachment (asks for number) e extract (save) attachment (asks for number)
(or: <mouse-2> or RET with point on attachment) (or: <mouse-2> or RET with point on attachment)
C-u e will extract multiple attachments
o open attachment (asks for number) o open attachment (asks for number)
(or: <S-mouse-2> or S-RET with point on attachment) (or: <S-mouse-2> or S-RET with point on attachment)
A execute some action on an 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")) (setq mu4e-attachment-dir (file-name-expand "~/Downloads"))
@end lisp @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 @subsection Viewing images inline
@anchor{Viewing images inline} @anchor{Viewing images inline}