;;; mh-folder.el --- MH-Folder mode
-;; Copyright (C) 2002-2003, 2005-2011 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2003, 2005-2013 Free Software Foundation, Inc.
;; Author: Bill Wohler <wohler@newt.com>
;; Maintainer: Bill Wohler <wohler@newt.com>
["Go to Last Message" mh-last-msg t]
["Go to Message by Number..." mh-goto-msg t]
["Modify Message" mh-modify t]
- ["Delete Message" mh-delete-msg (mh-get-msg-num nil)]
["Refile Message" mh-refile-msg (mh-get-msg-num nil)]
- ["Undo Delete/Refile" mh-undo (mh-outstanding-commands-p)]
+ ["Delete Message" mh-delete-msg (mh-get-msg-num nil)]
+ ["Undo Delete/Refile/Junk" mh-undo (mh-outstanding-commands-p)]
["Execute Delete/Refile" mh-execute-commands
(mh-outstanding-commands-p)]
"--"
;; Folders when displaying index buffer
(list "^\\+.*"
'(0 'mh-search-folder))
- ;; Marked for deletion
- (list (concat mh-scan-deleted-msg-regexp ".*")
- '(0 'mh-folder-deleted))
;; Marked for refile
(list (concat mh-scan-refiled-msg-regexp ".*")
'(0 'mh-folder-refiled))
+ ;; Marked for deletion
+ (list (concat mh-scan-deleted-msg-regexp ".*")
+ '(0 'mh-folder-deleted))
+ ;; Marked for blacklisting
+ (list (concat mh-scan-blacklisted-msg-regexp ".*")
+ '(0 'mh-folder-blacklisted))
+ ;; Marked for whitelisting
+ (list (concat mh-scan-whitelisted-msg-regexp ".*")
+ '(0 'mh-folder-whitelisted))
;; After subject
(list mh-scan-body-regexp
'(1 'mh-folder-body nil t))
;; Register mh-folder-mode as supporting which-function-mode...
(mh-require 'which-func nil t)
-(when (boundp 'which-func-modes)
+(when (and (boundp 'which-func-modes) (listp which-func-modes))
(add-to-list 'which-func-modes 'mh-folder-mode))
;; Shush compiler.
'overlay-arrow-position nil ; Allow for simultaneous display in
'overlay-arrow-string ">" ; different MH-E buffers.
'mh-showing-mode nil ; Show message also?
- 'mh-delete-list nil ; List of msgs nums to delete
'mh-refile-list nil ; List of folder names in mh-seq-list
+ 'mh-delete-list nil ; List of msgs nums to delete
+ 'mh-blacklist nil ; List of messages to process as spam
+ 'mh-whitelist nil ; List of messages to process as ham
'mh-seq-list nil ; Alist of (seq . msgs) nums
'mh-seen-list nil ; List of displayed messages
'mh-next-direction 'forward ; Direction to move to next message
;;;###mh-autoload
(defun mh-execute-commands ()
- "Process outstanding delete and refile requests\\<mh-folder-mode-map>.
+ "Perform outstanding operations\\<mh-folder-mode-map>.
-If you've marked messages to be deleted or refiled and you want
-to go ahead and delete or refile the messages, use this command.
-Many MH-E commands that may affect the numbering of the
-messages (such as \\[mh-rescan-folder] or \\[mh-pack-folder])
-will ask if you want to process refiles or deletes first and then
-either run this command for you or undo the pending refiles and
-deletes.
+If you've marked messages to be refiled, deleted, blacklisted, or
+whitelisted and you want to go ahead and perform these operations
+on these messages, use this command. Many MH-E commands that may
+affect the numbering of the messages (such as
+\\[mh-rescan-folder] or \\[mh-pack-folder]) will ask if you want
+to perform these operations first and then either run this
+command for you or undo the pending operations.
This function runs `mh-before-commands-processed-hook' before the
commands are processed and `mh-after-commands-processed-hook'
nil))))
(mh-toggle-threads))
(beginning-of-line)
+ (when (mh-outstanding-commands-p)
+ (mh-notate-deleted-and-refiled))
(if (and mh-showing-mode (looking-at mh-scan-valid-regexp)) (mh-show))
(run-hooks 'mh-inc-folder-hook)))
(cond ((numberp range)
(let ((original-position (point)))
(beginning-of-line)
- (while (not (or (looking-at mh-scan-deleted-msg-regexp)
- (looking-at mh-scan-refiled-msg-regexp)
+ (while (not (or (looking-at mh-scan-refiled-msg-regexp)
+ (looking-at mh-scan-deleted-msg-regexp)
+ (looking-at mh-scan-blacklisted-msg-regexp)
+ (looking-at mh-scan-whitelisted-msg-regexp)
(and (eq mh-next-direction 'forward) (bobp))
(and (eq mh-next-direction 'backward)
(save-excursion (forward-line) (eobp)))))
(forward-line (if (eq mh-next-direction 'forward) -1 1)))
- (if (or (looking-at mh-scan-deleted-msg-regexp)
- (looking-at mh-scan-refiled-msg-regexp))
+ (if (or (looking-at mh-scan-refiled-msg-regexp)
+ (looking-at mh-scan-deleted-msg-regexp)
+ (looking-at mh-scan-blacklisted-msg-regexp)
+ (looking-at mh-scan-whitelisted-msg-regexp))
(progn
(mh-undo-msg (mh-get-msg-num t))
(mh-maybe-show))
(save-excursion
(when (eq major-mode 'mh-show-mode)
(set-buffer mh-show-folder-buffer))
- (or mh-delete-list mh-refile-list)))
+ (or mh-delete-list mh-refile-list mh-blacklist mh-whitelist)))
;;;###mh-autoload
(defun mh-set-folder-modified-p (flag)
(let ((redraw-needed-flag mh-index-data)
(folders-changed (list mh-current-folder))
- (seq-map (and mh-refile-list mh-refile-preserves-sequences-flag
- (mh-create-sequence-map mh-seq-list)))
+ (seq-map (and
+ (or (and mh-refile-list mh-refile-preserves-sequences-flag)
+ (and mh-whitelist
+ mh-whitelist-preserves-sequences-flag))
+ (mh-create-sequence-map mh-seq-list)))
(dest-map (and mh-refile-list mh-refile-preserves-sequences-flag
- (make-hash-table))))
+ (make-hash-table)))
+ (white-map (and mh-whitelist mh-whitelist-preserves-sequences-flag
+ (make-hash-table))))
;; Remove invalid scan lines if we are in an index folder and then remove
;; the real messages
(when mh-index-data
(mh-delete-scan-msgs mh-delete-list)
(setq mh-delete-list nil)))
+ ;; Blacklist messages.
+ (when mh-blacklist
+ (let ((msg-list (mh-coalesce-msg-list mh-blacklist))
+ (dest (mh-junk-blacklist-disposition)))
+ (mh-junk-process-blacklist mh-blacklist)
+ ;; TODO I wonder why mh-exec-cmd is used instead of the following:
+ ;; (mh-refile-a-msg nil (intern dest))
+ ;; (mh-delete-a-msg nil)))
+ (if (null dest)
+ (apply 'mh-exec-cmd "rmm" folder msg-list)
+ (apply 'mh-exec-cmd "refile" "-src" folder dest msg-list)
+ (push dest folders-changed))
+ (setq redraw-needed-flag t)
+ (mh-delete-scan-msgs mh-blacklist)
+ (setq mh-blacklist nil)))
+
+ ;; Whitelist messages.
+ (when mh-whitelist
+ (let ((msg-list (mh-coalesce-msg-list mh-whitelist))
+ (last (car (mh-translate-range mh-inbox "last"))))
+ (mh-junk-process-whitelist mh-whitelist)
+ (apply #'mh-exec-cmd "refile" "-src" folder mh-inbox msg-list)
+ (push mh-inbox folders-changed)
+ (setq redraw-needed-flag t)
+ (mh-delete-scan-msgs mh-whitelist)
+ (when mh-whitelist-preserves-sequences-flag
+ (clrhash white-map)
+ (loop for i from (1+ (or last 0))
+ for msg in (sort (copy-sequence mh-whitelist) #'<)
+ do (loop for seq-name in (gethash msg seq-map)
+ do (push i (gethash seq-name white-map))))
+ (maphash
+ #'(lambda (seq msgs)
+ ;; Can't be run in background, since the current
+ ;; folder is changed by mark this could lead to a
+ ;; race condition with the next refile/whitelist.
+ (apply #'mh-exec-cmd "mark"
+ "-sequence" (symbol-name seq) mh-inbox
+ "-add" (mapcar #'(lambda(x) (format "%s" x))
+ (mh-coalesce-msg-list msgs))))
+ white-map))
+ (setq mh-whitelist nil)))
+
;; Don't need to remove sequences since delete and refile do so.
;; Mark cur message
(if (> (buffer-size) 0)
(setq message (mh-get-msg-num t)))
(if (looking-at mh-scan-refiled-msg-regexp)
(error "Message %d is refiled; undo refile before deleting" message))
+ (if (looking-at mh-scan-blacklisted-msg-regexp)
+ (error "Message %d is blacklisted; undo before deleting" message))
+ (if (looking-at mh-scan-whitelisted-msg-regexp)
+ (error "Message %d is whitelisted; undo before deleting" message))
(if (looking-at mh-scan-deleted-msg-regexp)
nil
(mh-set-folder-modified-p t)
(setq message (mh-get-msg-num t)))
(cond ((looking-at mh-scan-deleted-msg-regexp)
(error "Message %d is deleted; undo delete before moving" message))
+ ((looking-at mh-scan-blacklisted-msg-regexp)
+ (error "Message %d is blacklisted; undo before moving" message))
+ ((looking-at mh-scan-whitelisted-msg-regexp)
+ (error "Message %d is whitelisted; undo before moving" message))
((looking-at mh-scan-refiled-msg-regexp)
(if (y-or-n-p
(format "Message %d already refiled; copy to %s as well? "
(run-hooks 'mh-refile-msg-hook)))))
(defun mh-undo-msg (msg)
- "Undo the deletion or refile of one MSG.
+ "Undo the deletion, refile, black- or whitelisting of one MSG.
If MSG is nil then act on the message at point"
(save-excursion
(if (numberp msg)
(setq msg (mh-get-msg-num t)))
(cond ((memq msg mh-delete-list)
(setq mh-delete-list (delq msg mh-delete-list)))
+ ((memq msg mh-blacklist)
+ (setq mh-blacklist (delq msg mh-blacklist)))
+ ((memq msg mh-whitelist)
+ (setq mh-whitelist (delq msg mh-whitelist)))
(t
(dolist (folder-msg-list mh-refile-list)
(setf (cdr folder-msg-list) (remove msg (cdr folder-msg-list))))