mu4e: marks: clarify the way targets are obtained.

:get-target is split into:
- :ask-target (run once per bulk operation)
- :dyn-target (run once per message)

A side benefit is that the existence of the target of a move is not
checked for every message when doing bulk moves.
This commit is contained in:
Jean-Philippe Bernardy 2014-11-27 11:10:51 +01:00
parent 3981f5412f
commit 818eedf59f
1 changed files with 35 additions and 27 deletions

View File

@ -127,22 +127,24 @@ properties are:
:char The character to display in the headers view
:prompt The prompt to use when asking for marks (used for
example when marking a whole thread)
:get-target The function to obtain the target for the mark
action, or nil if the action requires no target.
:ask-target Get the target. This function run once per
bulk-operation, and thus is suitable for user-interaction.
If nil, the target is nil.
:dyn-target Compute the dynamic target. This is run once per
message, which is passed as an argument. If nil, the target
is not touched.
:show-target How to display the target.
:action The action to apply on the message.
")
;; TODO: the arguments taken by the various functions should probably
;; be different. 1. It appears that the TARGET argument of
;; :get-target is always nil. 2. The actions should probably get the
;; TODO: The actions should probably get the
;; message: it contains more info than the docid.
(unless mu4e-marks
(setq mu4e-marks
`((refile
'((refile
:char "r"
:prompt "refile"
:get-target (lambda (target msg) (mu4e-get-refile-folder msg))
:dyn-target (lambda (target msg) (mu4e-get-refile-folder msg))
:show-target (lambda (target) target)
:action (lambda (docid target) (mu4e~proc-move docid (mu4e~mark-check-target target) "-N")))
(delete
@ -158,7 +160,7 @@ properties are:
(move
:char "m"
:prompt "move"
:get-target (lambda (target msg) (mu4e~mark-get-move-target target))
:ask-target mu4e~mark-get-move-target
:show-target (lambda (target) target)
:action (lambda (docid target) (mu4e~proc-move docid (mu4e~mark-check-target target) "-N")))
(read
@ -169,7 +171,7 @@ properties are:
(trash
:char "d"
:prompt "dtrash"
:get-target (lambda (target msg) (mu4e-get-trash-folder msg))
:dyn-target (lambda (target msg) (mu4e-get-trash-folder msg))
:show-target (lambda (target) target)
:action (lambda (docid target) (mu4e~proc-move docid (mu4e~mark-check-target target) "+T-N")))
(unflag
@ -200,10 +202,10 @@ properties are:
)))
(defun mu4e-mark-at-point (mark &optional target)
(defun mu4e-mark-at-point (mark target)
"Mark (or unmark) message at point.
MARK specifies the mark-type. For `move'-marks and `trash'-marks
there is also the TARGET argument, which specifies to which
the TARGET argument is non-nil and specifies to which
maildir the message is to be moved/trashed. The function works in
both headers buffers and message buffers.
@ -230,7 +232,8 @@ The following marks are available, and the corresponding props:
;; info for the user.
(markdesc (cdr (or (assq mark mu4e-marks) (mu4e-error "Invalid mark %S" mark))))
(markkar (plist-get markdesc :char))
(target (funcall (plist-get markdesc :show-target) target)))
(target (mu4e~mark-get-dyn-target mark target))
(shown-target (funcall (plist-get markdesc :show-target) target)))
(unless docid (mu4e-warn "No message on this line"))
(unless (eq major-mode 'mu4e-headers-mode) (mu4e-error "Not in headers-mode"))
(save-excursion
@ -246,7 +249,7 @@ The following marks are available, and the corresponding props:
;; when we have a target (ie., when moving), show the target folder in
;; an overlay
(when (and target mu4e-headers-show-target)
(let* ((targetstr (propertize (concat "-> " target " ")
(let* ((targetstr (propertize (concat "-> " shown-target " ")
'face 'mu4e-system-face))
;; mu4e~headers-goto-docid docid t \will take us just after the
;; docid cookie and then we skip the mu4e~mark-fringe
@ -257,34 +260,40 @@ The following marks are available, and the corresponding props:
docid)))))))
(defun mu4e~mark-get-move-target (&optional target)
"Ask for a move target, and propose to create it if it does not exist. If TARGET is provided,
this function merely checks the validity of the move."
(defun mu4e~mark-get-move-target ()
"Ask for a move target, and propose to create it if it does not exist."
(interactive)
;; (mu4e-message-at-point) ;; raises error if there is none
(let* ((target (or target (mu4e-ask-maildir "Move message to: ")))
(target (if (string= (substring target 0 1) "/")
(let* ((target (mu4e-ask-maildir "Move message to: "))
(target (if (string= (substring target 0 1) "/")
target
(concat "/" target)))
(fulltarget (concat mu4e-maildir target)))
(when (or (file-directory-p fulltarget)
(and (yes-or-no-p
(format "%s does not exist. Create now?" fulltarget))
(format "%s does not exist. Create now?" fulltarget))
(mu4e~proc-mkdir fulltarget)))
target)))
(defun mu4e~mark-get-target (mark &optional target)
"Get the target for MARK, if it is a mark that has a target;
otherwise return nil."
(let ((getter (plist-get (cdr (assq mark mu4e-marks)) :get-target)))
(and getter (funcall getter target (mu4e-message-at-point)))))
(defun mu4e~mark-ask-target (mark)
"Ask the target for MARK, if the user should be asked the target."
(let ((getter (plist-get (cdr (assq mark mu4e-marks)) :ask-target)))
(and getter (funcall getter))))
(defun mu4e~mark-get-dyn-target (mark target)
"Get the dynamic target for MARK. The result may depend on the
message at point."
(let ((getter (plist-get (cdr (assq mark mu4e-marks)) :dyn-target)))
(if getter
(funcall getter target (mu4e-message-at-point))
target)))
(defun mu4e-mark-set (mark &optional target)
"Mark the header at point, or, if region is active, mark all
headers in the region. Optionally, provide TARGET (for moves)."
(unless target
(setq target (mu4e~mark-get-target mark target)))
(setq target (mu4e~mark-ask-target mark)))
(if (not (use-region-p))
;; single message
(mu4e-mark-at-point mark target)
@ -293,7 +302,6 @@ headers in the region. Optionally, provide TARGET (for moves)."
(let ((cant-go-further) (eor (region-end)))
(goto-char (region-beginning))
(while (and (<= (point) eor) (not cant-go-further))
(setq target (mu4e~mark-get-target mark target))
(mu4e-mark-at-point mark target)
(setq cant-go-further (not (mu4e-headers-next))))))))
@ -315,7 +323,7 @@ as well."
marks
(assq-delete-all 'something marks)))
(mark (mu4e-read-option prompt marks))
(target (mu4e~mark-get-target mark)))
(target (mu4e~mark-ask-target mark)))
(cons mark target)))