diff --git a/mu4e/mu4e-headers.el b/mu4e/mu4e-headers.el index c5f3316a..e700cb88 100644 --- a/mu4e/mu4e-headers.el +++ b/mu4e/mu4e-headers.el @@ -563,6 +563,7 @@ after the end of the search results." (mu4e~headers-defun-mark-for untrash) (mu4e~headers-defun-mark-for unmark) (mu4e~headers-defun-mark-for unread) +(mu4e~headers-defun-mark-for action) ;;; 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-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 "+") 'mu4e-headers-mark-for-flag) @@ -1514,13 +1516,15 @@ do nothing." (interactive "P") (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. -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) (let ((msg (mu4e-message-at-point)) - (actionfunc (mu4e-read-option "Action: " mu4e-headers-actions))) - (funcall actionfunc msg))) + (afunc (or actionfunc (mu4e-read-option "Action: " mu4e-headers-actions)))) + (funcall afunc msg))) (defun mu4e-headers-mark-and-next (mark) "Set mark MARK on the message at point or on all messages in the diff --git a/mu4e/mu4e-mark.el b/mu4e/mu4e-mark.el index e380024c..0b21ef09 100644 --- a/mu4e/mu4e-mark.el +++ b/mu4e/mu4e-mark.el @@ -46,8 +46,8 @@ Value is one of the following symbols: - `apply' automatically apply the marks before doing anything else - `ignore' automatically ignore the marks without asking" :type '(choice (const ask :tag "ask user whether to ignore marks") - (const apply :tag "apply marks without asking") - (const ignore :tag "ignore marks without asking")) + (const apply :tag "apply marks without asking") + (const ignore :tag "ignore marks without asking")) :group 'mu4e-headers) (defvar mu4e-headers-show-target t @@ -97,7 +97,7 @@ where (with-current-buffer b (eq major-mode 'mu4e-headers-mode))) (buffer-list))) - + (defmacro mu4e~mark-in-context (&rest body) "Evaluate BODY in the context of the headers buffer in case this is either a headers or view buffer." @@ -141,59 +141,67 @@ properties are: (unless mu4e-marks (setq mu4e-marks -'((refile - :char "r" - :prompt "refile" - :dyn-target (lambda (target msg) (mu4e-get-refile-folder msg)) - :action (lambda (docid msg target) (mu4e~proc-move docid (mu4e~mark-check-target target) "-N"))) - (delete - :char "D" - :prompt "Delete" - :show-target (lambda (target) "delete") - :action (lambda (docid msg target) (mu4e~proc-remove docid))) - (flag - :char "+" - :prompt "+flag" - :show-target (lambda (target) "flag") - :action (lambda (docid msg target) (mu4e~proc-move docid nil "+F-u-N"))) - (move - :char "m" - :prompt "move" - :ask-target mu4e~mark-get-move-target - :action (lambda (docid msg target) (mu4e~proc-move docid (mu4e~mark-check-target target) "-N"))) - (read - :char "!" - :prompt "!read" - :show-target (lambda (target) "read") - :action (lambda (docid msg target) (mu4e~proc-move docid nil "+S-u-N"))) - (trash - :char "d" - :prompt "dtrash" - :dyn-target (lambda (target msg) (mu4e-get-trash-folder msg)) - :action (lambda (docid msg target) (mu4e~proc-move docid (mu4e~mark-check-target target) "+T-N"))) - (unflag - :char "-" - :prompt "-unflag" - :show-target (lambda (target) "unflag") - :action (lambda (docid msg target) (mu4e~proc-move docid nil "-F-N"))) - (untrash - :char "=" - :prompt "=untrash" - :show-target (lambda (target) "untrash") - :action (lambda (docid msg target) (mu4e~proc-move docid nil "-T"))) - (unread - :char "?" - :prompt "?unread" - :show-target (lambda (target) "unread") - :action (lambda (docid msg target) (mu4e~proc-move docid nil "-S+u-N"))) - (unmark - :char " " - :prompt "unmark" - :action (mu4e-error "No action for unmarking")) - (something - :char "*" - :prompt "*something" - :action (mu4e-error "No action for deferred mark")) + '((refile + :char "r" + :prompt "refile" + :dyn-target (lambda (target msg) (mu4e-get-refile-folder msg)) + :action (lambda (docid msg target) (mu4e~proc-move docid (mu4e~mark-check-target target) "-N"))) + (delete + :char "D" + :prompt "Delete" + :show-target (lambda (target) "delete") + :action (lambda (docid msg target) (mu4e~proc-remove docid))) + (flag + :char "+" + :prompt "+flag" + :show-target (lambda (target) "flag") + :action (lambda (docid msg target) (mu4e~proc-move docid nil "+F-u-N"))) + (move + :char "m" + :prompt "move" + :ask-target mu4e~mark-get-move-target + :action (lambda (docid msg target) (mu4e~proc-move docid (mu4e~mark-check-target target) "-N"))) + (read + :char "!" + :prompt "!read" + :show-target (lambda (target) "read") + :action (lambda (docid msg target) (mu4e~proc-move docid nil "+S-u-N"))) + (trash + :char "d" + :prompt "dtrash" + :dyn-target (lambda (target msg) (mu4e-get-trash-folder msg)) + :action (lambda (docid msg target) (mu4e~proc-move docid (mu4e~mark-check-target target) "+T-N"))) + (unflag + :char "-" + :prompt "-unflag" + :show-target (lambda (target) "unflag") + :action (lambda (docid msg target) (mu4e~proc-move docid nil "-F-N"))) + (untrash + :char "=" + :prompt "=untrash" + :show-target (lambda (target) "untrash") + :action (lambda (docid msg target) (mu4e~proc-move docid nil "-T"))) + (unread + :char "?" + :prompt "?unread" + :show-target (lambda (target) "unread") + :action (lambda (docid msg target) (mu4e~proc-move docid nil "-S+u-N"))) + (unmark + :char " " + :prompt "unmark" + :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 + :char "*" + :prompt "*something" + :action (mu4e-error "No action for deferred mark")) ))) @@ -218,7 +226,8 @@ The following marks are available, and the corresponding props: `unflag' n mark this message for unflagging `untrash' n remove the 'trashed' flag from a 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) (let* ((msg (mu4e-message-at-point)) (docid (mu4e-message-field msg :docid)) @@ -230,8 +239,8 @@ The following marks are available, and the corresponding props: (target (mu4e~mark-get-dyn-target mark target)) (show-fct (plist-get markdesc :show-target)) (shown-target (if show-fct - (funcall show-fct target) - target))) + (funcall show-fct target) + (if target (format "%S" 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 @@ -261,9 +270,9 @@ The following marks are available, and the corresponding props: (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 + ;; (mu4e-message-at-point) ;; raises error if there is none (let* ((target (mu4e-ask-maildir "Move message to: ")) - (target (if (string= (substring target 0 1) "/") + (target (if (string= (substring target 0 1) "/") target (concat "/" target))) (fulltarget (concat mu4e-maildir target))) @@ -283,7 +292,7 @@ The following marks are available, and the corresponding props: message at point." (let ((getter (plist-get (cdr (assq mark mu4e-marks)) :dyn-target))) (if getter - (funcall getter target (mu4e-message-at-point)) + (funcall getter target (mu4e-message-at-point)) target))) @@ -315,11 +324,13 @@ headers in the region. Optionally, provide TARGET (for moves)." "Ask user for a mark; return (MARK . TARGET). If ALLOW-SOMETHING is non-nil, allow the 'something' pseudo mark as well." - (let* ((marks (mapcar (lambda (markdescr) (cons (plist-get (cdr markdescr) :prompt) (car markdescr))) mu4e-marks)) - (marks - (if allow-something - marks - (assq-delete-all 'something marks))) + (let* ((marks (mapcar (lambda (markdescr) + (cons (plist-get (cdr markdescr) :prompt) + (car markdescr))) + mu4e-marks)) + (marks + (if allow-something + marks (remove-if (lambda (m) (eq 'something (cdr m))) marks))) (mark (mu4e-read-option prompt marks)) (target (mu4e~mark-ask-target mark))) (cons mark target))) @@ -351,7 +362,6 @@ user which one)." (mu4e-error "Target dir %s does not exist " fulltarget) target))) - (defun mu4e-mark-execute-all (&optional no-confirmation) "Execute the actions for all marked messages in this buffer. After the actions have been executed succesfully, the affected @@ -377,15 +387,15 @@ If NO-CONFIRMATION is non-nil, don't ask user for confirmation." (maphash (lambda (docid val) (let* ((mark (car val)) (target (cdr val)) - (markdescr (assq mark mu4e-marks)) - (msg (save-excursion - (mu4e~headers-goto-docid docid) - (mu4e-message-at-point)))) + (markdescr (assq mark mu4e-marks)) + (msg (save-excursion + (mu4e~headers-goto-docid docid) + (mu4e-message-at-point)))) ;; note: whenever you do something with the message, ;; it looses its N (new) flag (if markdescr - (funcall (plist-get (cdr markdescr) :action) docid msg target) - (mu4e-error "Unrecognized mark %S" mark)))) + (funcall (plist-get (cdr markdescr) :action) docid msg target) + (mu4e-error "Unrecognized mark %S" mark)))) mu4e~mark-map)) (mu4e-mark-unmark-all) (message nil))))) @@ -413,7 +423,7 @@ If NO-CONFIRMATION is non-nil, don't ask user for confirmation." (defun mu4e-mark-marks-num () "Return the number of marks in the current buffer." (if mu4e~mark-map (hash-table-count mu4e~mark-map) 0)) - + (defun mu4e-mark-handle-when-leaving () "If there are any marks in the current buffer, handle those @@ -431,9 +441,9 @@ action', return nil means 'don't do anything'." '( ("apply marks" . apply) ("ignore marks?" . ignore))))) ;; we determined what to do... now do it - (when (eq what 'apply) - (mu4e-mark-execute-all t)))))) - + (when (eq what 'apply) + (mu4e-mark-execute-all t)))))) + (provide 'mu4e-mark) ;; End of mu4e-mark.el diff --git a/mu4e/mu4e.texi b/mu4e/mu4e.texi index 239df84b..445b8ce2 100644 --- a/mu4e/mu4e.texi +++ b/mu4e/mu4e.texi @@ -2050,7 +2050,7 @@ mu4e-headers-mark-subthread}, respectively @cartouche @verbatim mark for/as | keybinding | description - --------------+-------------+-------------------------- + --------------+-------------+------------------------------ 'something' | *, | mark now, decide later delete | D, | delete flag | + | mark as 'flagged' ('starred') @@ -2063,6 +2063,7 @@ mu4e-headers-mark-subthread}, respectively unmark | u | remove mark at point unmark all | U | remove all marks unread | ? | marks as unread + action | a | apply some action @end verbatim @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 @code{mu4e-headers-show-target} to @code{nil}. -@t{something} is a special kind of mark; you can use it to mark messages for -'something', and then decide later what the 'something' should -be@footnote{This kind of 'deferred marking' is similar to the facility in -@t{midnight commander} (@url{http://www.midnight-commander.org/}) and the -like, and uses the same key binding (@key{insert}).} Later, you can set the -actual mark using @kbd{M-x mu4e-mark-resolve-deferred-marks} -(@key{#}). Alternatively, @t{mu4e} will ask you when you try to execute the -marks (@key{x}). +@t{something} is a special kind of mark; you can use it to mark messages +for 'something', and then decide later what the 'something' should +be@footnote{This kind of 'deferred marking' is similar to the facility +in @t{dired}, @t{midnight commander} +(@url{http://www.midnight-commander.org/}) and the like, and uses the +same key binding (@key{insert}).} Later, you can set the actual mark +using @kbd{M-x mu4e-mark-resolve-deferred-marks} +(@key{#}). Alternatively, @t{mu4e} will ask you when you try to execute +the marks (@key{x}). @node Executing the marks @section Executing the marks