diff --git a/emacs/mu-common.el b/emacs/mu-common.el index 8073c95e..1f8d9269 100644 --- a/emacs/mu-common.el +++ b/emacs/mu-common.el @@ -42,7 +42,6 @@ notation) e.g. for mail headers") (defvar mu-date-format-long "%c" "date format (in strftime(2) notation) for the mail view and in replied/forwarded message quotations") - (defvar mu-folder-draft "/home/djcb/Maildir/") (defface mu-date-face '((t (:foreground "#8c5353"))) "") @@ -64,6 +63,13 @@ notation) for the mail view and in replied/forwarded message quotations") (defvar mu-own-address "djcb" "regexp matching my own address") + +;;; internal stuff +(defvar mu-parent-buf nil "the parent buffer for a +buffer (buffer-local), i.e., the buffer we'll return to when this +buffer is killed") + + (defun mu-binary-version () "get the version of the mu binary" (let ((cmd (concat mu-binary @@ -157,8 +163,8 @@ Lisp data as a plist. Returns nil in case of error" (let* ((cmd (concat mu-binary " view --format=sexp " path)) (str (shell-command-to-string cmd)) (msglst (read-from-string str))) - (if (msglst) - (car msglist) + (if msglst + (car msglst) (progn (message "Failed to parse message") nil))))) @@ -167,17 +173,105 @@ Lisp data as a plist. Returns nil in case of error" ;; TODO ) - -;; todo: check for unhandled marks (defun mu-quit-buffer () - "kill this find or view buffer" + "kill this buffer, and switch to it's parentbuf if it is alive" (interactive) - (if (or (equalp major-mode 'mu-find-mode) - (equalp major-mode 'mu-view-mode)) - (kill-buffer))) + (let ((parentbuf (mu-parent-buf))) + (kill-buffer) + (when (buffer-live-p parentbuf) + (switch-to-buffer parentbuf)))) + +(defun mu-get-marked () + "get all marked messages as a list; each element is a cell; +with 'action', 'source' , 'target'). ie one of three: + ('delete ) + ('trash ) + ('move )" + (let ((lst)) + (with-current-buffer mu-find-buffer-name + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "^." nil t) + (let* ((char0 (match-string 0)) + (action (get-text-property 0 'action char0)) + (path (get-text-property 0 'path char0)) + (target (get-text-property 0 'target char0))) + (cond + ((eq action 'trash) + (setq lst (cons (list 'trash path target) lst))) + ((eq action 'delete) + (setq lst (cons (list 'delete path) lst))) + ((eq action 'move) + (setq lst (cons (list 'move path target) lst)))))))) + lst)) + +(defun mu-execute () + "execute marked actions on messages" + (interactive) + (let* ((markedcount (mu-count-marked)) + (movenum (nth 0 markedcount)) (trashnum (nth 1 markedcount)) + (deletenum (nth 2 markedcount))) + (if (= 0 (apply '+ markedcount)) + (message "No messages are marked") + (if (and (< 0 movenum) + (y-or-n-p (format "Do you want to move %d message(s)?" movenum))) + (message "Moving message(s)")) + (if (and (< 0 trashnum) + (y-or-n-p (format "Do you want to move %d message(s) to trash?" trashnum))) + (message "Trashing message(s)")) + (if (and (< 0 deletenum) + (yes-or-no-p (format "Do you want to permanently delete %d message(s)?" + deletenum))) + (message "Deleting message(s)")) + (mu-find-refresh)))) +(defun mu-foreach-marked (func) + "call FUNC for each marked message; the argument to FUNC is a list, either: +with 'action', 'source' , 'target'). ie one of three: + ('delete ) + ('trash ) + ('move )" + (with-current-buffer mu-find-buffer-name + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "^." nil t) + (move-beginning-of-line 1) + (let* ((char0 (match-string 0)) + (action (get-text-property 0 'action char0)) + (path (get-text-property 0 'path char0)) + (target (get-text-property 0 'target char0))) + (cond + ((eq action 'trash) (funcall func (list 'trash path target))) + ((eq action 'delete) (funcall func (list 'delete path))) + ((eq action 'move) (funcall func (list 'move path target))))) + (move-end-of-line 1))))) +(defun mu-count-marked () + "return a vector with three items (marked-move marked-trash +marked-delete) which are the number of messages marked for each +of those" + (let ((result (make-vector 3 0))) + (mu-foreach-marked + (lambda (cell) + (case (car cell) + ('move (aset result 0 (+ 1 (aref result 0)))) + ('trash (aset result 1 (+ 1 (aref result 1)))) + ('delete (aset result 2 (+ 1 (aref result 2))))))) + (append result nil))) ;; convert to list +(defun mu-unmark-all () + "unmark all messages" + (interactive) + (let ((marked 0)) + (mu-foreach-marked (lambda(cell) (setq marked (+ 1 marked)))) + (if (= 0 marked) + (message "No messages are marked") + (when (y-or-n-p (format "Unmark %d message(s)?" marked)) + (mu-foreach-marked + (lambda(cell) + (let ((inhibit-read-only t)) + (delete-char 1) + (insert-and-inherit " ")))))))) (provide 'mu-common) diff --git a/emacs/mu-find.el b/emacs/mu-find.el index 2dddf89e..5fc533c1 100644 --- a/emacs/mu-find.el +++ b/emacs/mu-find.el @@ -315,11 +315,11 @@ the mu find output") (delete-char 1) (case what ('trash (insert-and-inherit - (mu-str (propertize "d" 'action what)))) + (mu-str (propertize "d" 'action what 'target "/foo/bar")))) ('delete (insert-and-inherit - (mu-str (propertize "D" 'action what)))) + (mu-str (propertize "D" 'action what 'target "/foo/bar")))) ('move (insert-and-inherit - (mu-str (propertize "m" 'action what)))) + (mu-str (propertize "m" 'action what 'target "/foo/bar")))) ('none (insert-and-inherit " "))) (forward-line)))))) diff --git a/emacs/mu-message.el b/emacs/mu-message.el index 87815ce6..75d588a8 100644 --- a/emacs/mu-message.el +++ b/emacs/mu-message.el @@ -46,7 +46,7 @@ (format "On %s, %s wrote:\n" (format-time-string mu-date-format-long (plist-get msg :date)) (cdr (car (plist-get msg :from))))) - + (defun mu-message-cite (msg) "cite an existing message" (let ((body @@ -120,14 +120,10 @@ create a forwarded message. After creation, switch to the message editor" "create a reply to the message at point; After creation, switch to the message editor" (let ((path (mu-get-path))) - (when path - (let ()) + (when path + (mu-ask-key "Reply to [s]ender only or to [a]ll?") + (mu-message-reply-or-forward path)))) - - - (mu-ask-key "Reply to [s]ender only or to [a]ll?") - (mu-message-reply-or-forward path)) - (defun mu-message-forward (path) "create a forward-message to the message at PATH; After creation, switch to the message editor" diff --git a/emacs/mu-view.el b/emacs/mu-view.el index beac3113..a788a9ed 100644 --- a/emacs/mu-view.el +++ b/emacs/mu-view.el @@ -114,7 +114,7 @@ function returns the resulting name" (defvar mu-view-mode-map (let ((map (make-sparse-keymap))) - (define-key map "q" 'mu-view-quit-buffer) + (define-key map "q" 'mu-quit-buffer) (define-key map "s" 'mu-find) (define-key map "f" 'mu-forward) (define-key map "r" 'mu-reply) @@ -144,10 +144,4 @@ function returns the resulting name" (when (mu-find-prev) (mu-view (mu-get-path))))) -(defun mu-view-quit-buffer () - "quit this buffer and return to the find buffer" - (interactive) - (mu-quit-buffer) - (switch-to-buffer mu-find-buffer-name)) - (provide 'mu-view) diff --git a/emacs/mu.el b/emacs/mu.el index 89b6b6a7..423bdfc7 100644 --- a/emacs/mu.el +++ b/emacs/mu.el @@ -38,19 +38,22 @@ (define-key mu-find-mode-map "o" 'mu-find-change-sort) (define-key mu-find-mode-map "g" 'mu-find-refresh) (define-key mu-find-mode-map "m" 'mu-find-mark-for-move) -(define-key mu-find-mode-map "d" 'mu-find-mark-for-thrash) +(define-key mu-find-mode-map "d" 'mu-find-mark-for-trash) (define-key mu-find-mode-map "D" 'mu-find-mark-for-deletion) (define-key mu-find-mode-map "u" 'mu-find-unmark) +(define-key mu-find-mode-map "U" 'mu-unmark-all) (define-key mu-find-mode-map "r" 'mu-reply) -(define-key mu-view-mode-map "f" 'mu-forward) +(define-key mu-find-mode-map "f" 'mu-forward) +(define-key mu-find-mode-map "x" 'mu-execute) -(define-key mu-view-mode-map "q" 'mu-view-quit-buffer) + +(define-key mu-view-mode-map "q" 'mu-quit-buffer) (define-key mu-view-mode-map "f" 'mu-view-find) (define-key mu-view-mode-map "n" 'mu-view-next) (define-key mu-view-mode-map "p" 'mu-view-prev) (define-key mu-view-mode-map "r" 'mu-reply) (define-key mu-view-mode-map "f" 'mu-forward) - +(define-key mu-view-mode-map "x" 'mu-execute) (provide 'mu)