mu4e: support message-action when marking 'deferred'

When marking headers as 'deferred' (with '*'), and executing them ('x'),
you can now also apply arbitrary header actions to them.
This commit is contained in:
djcb
2015-04-26 17:09:06 +03:00
parent 7eb244b3b0
commit 976711c16c
3 changed files with 107 additions and 91 deletions

View File

@ -563,6 +563,7 @@ after the end of the search results."
(mu4e~headers-defun-mark-for untrash) (mu4e~headers-defun-mark-for untrash)
(mu4e~headers-defun-mark-for unmark) (mu4e~headers-defun-mark-for unmark)
(mu4e~headers-defun-mark-for unread) (mu4e~headers-defun-mark-for unread)
(mu4e~headers-defun-mark-for action)
;;; headers-mode and mode-map ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; headers-mode and mode-map ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -636,6 +637,7 @@ after the end of the search results."
(define-key map (kbd "?") 'mu4e-headers-mark-for-unread) (define-key map (kbd "?") 'mu4e-headers-mark-for-unread)
(define-key map (kbd "!") 'mu4e-headers-mark-for-read) (define-key map (kbd "!") 'mu4e-headers-mark-for-read)
(define-key map (kbd "A") 'mu4e-headers-mark-for-action)
(define-key map (kbd "u") 'mu4e-headers-mark-for-unmark) (define-key map (kbd "u") 'mu4e-headers-mark-for-unmark)
(define-key map (kbd "+") 'mu4e-headers-mark-for-flag) (define-key map (kbd "+") 'mu4e-headers-mark-for-flag)
@ -1514,13 +1516,15 @@ do nothing."
(interactive "P") (interactive "P")
(mu4e-headers-split-view-grow (- (or n 1)))) (mu4e-headers-split-view-grow (- (or n 1))))
(defun mu4e-headers-action () (defun mu4e-headers-action (&optional actionfunc)
"Ask user what to do with message-at-point, then do it. "Ask user what to do with message-at-point, then do it.
The actions are specified in `mu4e-headers-actions'." The actions are specified in `mu4e-headers-actions'. Optionally,
pass ACTIONFUNC, which is a function that takes a msg-plist
argument."
(interactive) (interactive)
(let ((msg (mu4e-message-at-point)) (let ((msg (mu4e-message-at-point))
(actionfunc (mu4e-read-option "Action: " mu4e-headers-actions))) (afunc (or actionfunc (mu4e-read-option "Action: " mu4e-headers-actions))))
(funcall actionfunc msg))) (funcall afunc msg)))
(defun mu4e-headers-mark-and-next (mark) (defun mu4e-headers-mark-and-next (mark)
"Set mark MARK on the message at point or on all messages in the "Set mark MARK on the message at point or on all messages in the

View File

@ -141,7 +141,7 @@ properties are:
(unless mu4e-marks (unless mu4e-marks
(setq mu4e-marks (setq mu4e-marks
'((refile '((refile
:char "r" :char "r"
:prompt "refile" :prompt "refile"
:dyn-target (lambda (target msg) (mu4e-get-refile-folder msg)) :dyn-target (lambda (target msg) (mu4e-get-refile-folder msg))
@ -190,6 +190,14 @@ properties are:
:char " " :char " "
:prompt "unmark" :prompt "unmark"
:action (mu4e-error "No action for unmarking")) :action (mu4e-error "No action for unmarking"))
(action
:char "a"
:prompt "action"
:ask-target (lambda () (mu4e-read-option "Action: " mu4e-headers-actions))
:action (lambda (docid msg actionfunc)
(save-excursion
(when (mu4e~headers-goto-docid docid)
(mu4e-headers-action actionfunc)))))
(something (something
:char "*" :char "*"
:prompt "*something" :prompt "*something"
@ -218,7 +226,8 @@ The following marks are available, and the corresponding props:
`unflag' n mark this message for unflagging `unflag' n mark this message for unflagging
`untrash' n remove the 'trashed' flag from a message `untrash' n remove the 'trashed' flag from a message
`unmark' n unmark this message `unmark' n unmark this message
`unread' n mark the message as unread" `unread' n mark the message as unread
`action' y mark the message for some action."
(interactive) (interactive)
(let* ((msg (mu4e-message-at-point)) (let* ((msg (mu4e-message-at-point))
(docid (mu4e-message-field msg :docid)) (docid (mu4e-message-field msg :docid))
@ -231,7 +240,7 @@ The following marks are available, and the corresponding props:
(show-fct (plist-get markdesc :show-target)) (show-fct (plist-get markdesc :show-target))
(shown-target (if show-fct (shown-target (if show-fct
(funcall show-fct target) (funcall show-fct target)
target))) (if target (format "%S" target)))))
(unless docid (mu4e-warn "No message on this line")) (unless docid (mu4e-warn "No message on this line"))
(unless (eq major-mode 'mu4e-headers-mode) (mu4e-error "Not in headers-mode")) (unless (eq major-mode 'mu4e-headers-mode) (mu4e-error "Not in headers-mode"))
(save-excursion (save-excursion
@ -261,7 +270,7 @@ The following marks are available, and the corresponding props:
(defun mu4e~mark-get-move-target () (defun mu4e~mark-get-move-target ()
"Ask for a move target, and propose to create it if it does not exist." "Ask for a move target, and propose to create it if it does not exist."
(interactive) (interactive)
;; (mu4e-message-at-point) ;; raises error if there is none ;; (mu4e-message-at-point) ;; raises error if there is none
(let* ((target (mu4e-ask-maildir "Move message to: ")) (let* ((target (mu4e-ask-maildir "Move message to: "))
(target (if (string= (substring target 0 1) "/") (target (if (string= (substring target 0 1) "/")
target target
@ -315,11 +324,13 @@ headers in the region. Optionally, provide TARGET (for moves)."
"Ask user for a mark; return (MARK . TARGET). "Ask user for a mark; return (MARK . TARGET).
If ALLOW-SOMETHING is non-nil, allow the 'something' pseudo mark If ALLOW-SOMETHING is non-nil, allow the 'something' pseudo mark
as well." as well."
(let* ((marks (mapcar (lambda (markdescr) (cons (plist-get (cdr markdescr) :prompt) (car markdescr))) mu4e-marks)) (let* ((marks (mapcar (lambda (markdescr)
(cons (plist-get (cdr markdescr) :prompt)
(car markdescr)))
mu4e-marks))
(marks (marks
(if allow-something (if allow-something
marks marks (remove-if (lambda (m) (eq 'something (cdr m))) marks)))
(assq-delete-all 'something marks)))
(mark (mu4e-read-option prompt marks)) (mark (mu4e-read-option prompt marks))
(target (mu4e~mark-ask-target mark))) (target (mu4e~mark-ask-target mark)))
(cons mark target))) (cons mark target)))
@ -351,7 +362,6 @@ user which one)."
(mu4e-error "Target dir %s does not exist " fulltarget) (mu4e-error "Target dir %s does not exist " fulltarget)
target))) target)))
(defun mu4e-mark-execute-all (&optional no-confirmation) (defun mu4e-mark-execute-all (&optional no-confirmation)
"Execute the actions for all marked messages in this buffer. "Execute the actions for all marked messages in this buffer.
After the actions have been executed succesfully, the affected After the actions have been executed succesfully, the affected

View File

@ -2050,7 +2050,7 @@ mu4e-headers-mark-subthread}, respectively
@cartouche @cartouche
@verbatim @verbatim
mark for/as | keybinding | description mark for/as | keybinding | description
--------------+-------------+-------------------------- --------------+-------------+------------------------------
'something' | *, <insert> | mark now, decide later 'something' | *, <insert> | mark now, decide later
delete | D, <delete> | delete delete | D, <delete> | delete
flag | + | mark as 'flagged' ('starred') flag | + | mark as 'flagged' ('starred')
@ -2063,6 +2063,7 @@ mu4e-headers-mark-subthread}, respectively
unmark | u | remove mark at point unmark | u | remove mark at point
unmark all | U | remove all marks unmark all | U | remove all marks
unread | ? | marks as unread unread | ? | marks as unread
action | a | apply some action
@end verbatim @end verbatim
@end cartouche @end cartouche
@ -2073,14 +2074,15 @@ messages, this slows things down significantly@footnote{this uses an
in a buffer}. For this reason, you can disable this by setting in a buffer}. For this reason, you can disable this by setting
@code{mu4e-headers-show-target} to @code{nil}. @code{mu4e-headers-show-target} to @code{nil}.
@t{something} is a special kind of mark; you can use it to mark messages for @t{something} is a special kind of mark; you can use it to mark messages
'something', and then decide later what the 'something' should for 'something', and then decide later what the 'something' should
be@footnote{This kind of 'deferred marking' is similar to the facility in be@footnote{This kind of 'deferred marking' is similar to the facility
@t{midnight commander} (@url{http://www.midnight-commander.org/}) and the in @t{dired}, @t{midnight commander}
like, and uses the same key binding (@key{insert}).} Later, you can set the (@url{http://www.midnight-commander.org/}) and the like, and uses the
actual mark using @kbd{M-x mu4e-mark-resolve-deferred-marks} same key binding (@key{insert}).} Later, you can set the actual mark
(@key{#}). Alternatively, @t{mu4e} will ask you when you try to execute the using @kbd{M-x mu4e-mark-resolve-deferred-marks}
marks (@key{x}). (@key{#}). Alternatively, @t{mu4e} will ask you when you try to execute
the marks (@key{x}).
@node Executing the marks @node Executing the marks
@section Executing the marks @section Executing the marks