* mu4e: check marks in headers context (fixes issue #200)

This commit is contained in:
djcb
2013-06-08 17:32:10 +03:00
parent 7180b30a21
commit 74feeded3b

View File

@ -1,6 +1,6 @@
;; mu4e-mark.el -- part of mu4e, the mu mail user agent ;; mu4e-mark.el -- part of mu4e, the mu mail user agent
;; ;;
;; Copyright (C) 2011-2012 Dirk-Jan C. Binnema ;; Copyright (C) 2011-2013 Dirk-Jan C. Binnema
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
@ -82,6 +82,24 @@ where
"Clear the marks subsystem." "Clear the marks subsystem."
(clrhash mu4e~mark-map)) (clrhash mu4e~mark-map))
(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, and "
`(cond
((eq major-mode 'mu4e-headers-mode) ,@body)
((eq major-mode 'mu4e-view-mode)
(if (buffer-live-p mu4e~view-headers-buffer)
(let* ((msg (mu4e-message-at-point))
(docid (mu4e-message-field msg :docid)))
(with-current-buffer mu4e~view-headers-buffer
(if (mu4e~headers-goto-docid docid)
,@body
(mu4e-error "cannot find message in headers buffer."))))
(mu4e-error "no headers buffer connected to view")))
(t (progn (mu4e-message "%S" major-mode) ,@body))))
(defun mu4e-mark-at-point (mark &optional target) (defun mu4e-mark-at-point (mark &optional target)
"Mark (or unmark) message at point. "Mark (or unmark) message at point.
MARK specifies the mark-type. For `move'-marks and `trash'-marks MARK specifies the mark-type. For `move'-marks and `trash'-marks
@ -229,18 +247,19 @@ as well."
If there are such marks, replace them with a _real_ mark (ask the If there are such marks, replace them with a _real_ mark (ask the
user which one)." user which one)."
(interactive) (interactive)
(let ((markpair)) (mu4e~mark-in-context
(maphash (let ((markpair))
(lambda (docid val) (maphash
(let ((mark (car val)) (target (cdr val))) (lambda (docid val)
(when (eql mark 'something) (let ((mark (car val)) (target (cdr val)))
(unless markpair (when (eql mark 'something)
(setq markpair (unless markpair
(mu4e~mark-get-markpair "Set deferred mark to: " nil))) (setq markpair
(save-excursion (mu4e~mark-get-markpair "Set deferred mark to: " nil)))
(when (mu4e~headers-goto-docid docid) (save-excursion
(mu4e-mark-set (car markpair) (cdr markpair))))))) (when (mu4e~headers-goto-docid docid)
mu4e~mark-map))) (mu4e-mark-set (car markpair) (cdr markpair)))))))
mu4e~mark-map))))
(defun mu4e~mark-check-target (target) (defun mu4e~mark-check-target (target)
@ -264,46 +283,48 @@ work well.
If NO-CONFIRMATION is non-nil, don't ask user for confirmation." If NO-CONFIRMATION is non-nil, don't ask user for confirmation."
(interactive) (interactive)
(let ((marknum (hash-table-count mu4e~mark-map))) (mu4e~mark-in-context
(if (zerop marknum) (let ((marknum (hash-table-count mu4e~mark-map)))
(message "Nothing is marked") (if (zerop marknum)
(mu4e-mark-resolve-deferred-marks) (message "Nothing is marked")
(when (or no-confirmation (mu4e-mark-resolve-deferred-marks)
(y-or-n-p (when (or no-confirmation
(format "Are you sure you want to execute %d mark%s?" (y-or-n-p
marknum (if (> marknum 1) "s" "")))) (format "Are you sure you want to execute %d mark%s?"
(maphash marknum (if (> marknum 1) "s" ""))))
(lambda (docid val) (maphash
(let ((mark (car val)) (target (cdr val))) (lambda (docid val)
;; note: whenever you do something with the message, (let ((mark (car val)) (target (cdr val)))
;; it looses its N (new) flag ;; note: whenever you do something with the message,
(case mark ;; it looses its N (new) flag
(refile (mu4e~proc-move docid (mu4e~mark-check-target target) "-N")) (case mark
(delete (mu4e~proc-remove docid)) (refile (mu4e~proc-move docid (mu4e~mark-check-target target) "-N"))
(flag (mu4e~proc-move docid nil "+F-u-N")) (delete (mu4e~proc-remove docid))
(move (mu4e~proc-move docid (mu4e~mark-check-target target) "-N")) (flag (mu4e~proc-move docid nil "+F-u-N"))
(read (mu4e~proc-move docid nil "+S-u-N")) (move (mu4e~proc-move docid (mu4e~mark-check-target target) "-N"))
(trash (mu4e~proc-move docid (mu4e~mark-check-target target) "+T-N")) (read (mu4e~proc-move docid nil "+S-u-N"))
(unflag (mu4e~proc-move docid nil "-F-N")) (trash (mu4e~proc-move docid (mu4e~mark-check-target target) "+T-N"))
(unread (mu4e~proc-move docid nil "-S+u-N")) (unflag (mu4e~proc-move docid nil "-F-N"))
(otherwise (mu4e-error "Unrecognized mark %S" mark))))) (unread (mu4e~proc-move docid nil "-S+u-N"))
mu4e~mark-map)) (otherwise (mu4e-error "Unrecognized mark %S" mark)))))
(mu4e-mark-unmark-all) mu4e~mark-map))
(message nil)))) (mu4e-mark-unmark-all)
(message nil)))))
(defun mu4e-mark-unmark-all () (defun mu4e-mark-unmark-all ()
"Unmark all marked messages." "Unmark all marked messages."
(interactive) (interactive)
(when (or (null mu4e~mark-map) (zerop (hash-table-count mu4e~mark-map))) (mu4e~mark-in-context
(mu4e-warn "Nothing is marked")) (when (or (null mu4e~mark-map) (zerop (hash-table-count mu4e~mark-map)))
(maphash (mu4e-warn "Nothing is marked"))
(lambda (docid val) (maphash
(save-excursion (lambda (docid val)
(when (mu4e~headers-goto-docid docid) (save-excursion
(mu4e-mark-set 'unmark)))) (when (mu4e~headers-goto-docid docid)
mu4e~mark-map) (mu4e-mark-set 'unmark))))
;; in any case, clear the marks map mu4e~mark-map)
(mu4e~mark-clear)) ;; in any case, clear the marks map
(mu4e~mark-clear)))
(defun mu4e-mark-docid-marked-p (docid) (defun mu4e-mark-docid-marked-p (docid)
"Is the given docid marked?" "Is the given docid marked?"
@ -314,23 +335,25 @@ If NO-CONFIRMATION is non-nil, don't ask user for confirmation."
"Return the number of marks in the current buffer." "Return the number of marks in the current buffer."
(if mu4e~mark-map (hash-table-count mu4e~mark-map) 0)) (if mu4e~mark-map (hash-table-count mu4e~mark-map) 0))
(defun mu4e-mark-handle-when-leaving () (defun mu4e-mark-handle-when-leaving ()
"If there are any marks in the current buffer, handle those "If there are any marks in the current buffer, handle those
according to the value of `mu4e-headers-leave-behavior'. This according to the value of `mu4e-headers-leave-behavior'. This
function is to be called before any further action (like searching, function is to be called before any further action (like searching,
quiting the buffer) is taken; returning t means 'take the following quiting the buffer) is taken; returning t means 'take the following
action', return nil means 'don't do anything'" action', return nil means 'don't do anything'."
(let ((marknum (mu4e-mark-marks-num)) (mu4e~mark-in-context
(what mu4e-headers-leave-behavior)) (let ((marknum (mu4e-mark-marks-num))
(unless (zerop marknum) ;; nothing to do? (what mu4e-headers-leave-behavior))
(when (eq what 'ask) (unless (zerop marknum) ;; nothing to do?
(setq what (mu4e-read-option (when (eq what 'ask)
(format "There are %d existing mark(s); should we: " marknum) (setq what (mu4e-read-option
'( ("apply marks" . apply) (format "There are %d existing mark(s); should we: " marknum)
("ignore marks?" . ignore))))) '( ("apply marks" . apply)
;; we determined what to do... now do it ("ignore marks?" . ignore)))))
(when (eq what 'apply) ;; we determined what to do... now do it
(mu4e-mark-execute-all t))))) (when (eq what 'apply)
(mu4e-mark-execute-all t))))))
(provide 'mu4e-mark) (provide 'mu4e-mark)