summaryrefslogtreecommitdiff
path: root/lisp/mail/mh-seq.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/mail/mh-seq.el')
-rw-r--r--lisp/mail/mh-seq.el171
1 files changed, 161 insertions, 10 deletions
diff --git a/lisp/mail/mh-seq.el b/lisp/mail/mh-seq.el
index feb5ad11651..30ae6af1720 100644
--- a/lisp/mail/mh-seq.el
+++ b/lisp/mail/mh-seq.el
@@ -1,7 +1,11 @@
;;; mh-seq.el --- mh-e sequences support
-;; Time-stamp: <2001-07-14 13:10:33 pavel>
-;; Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1995, 2001, 2002 Free Software Foundation, Inc.
+
+;; Author: Bill Wohler <wohler@newt.com>
+;; Maintainer: Bill Wohler <wohler@newt.com>
+;; Keywords: mail
+;; See: mh-e.el
;; This file is part of GNU Emacs.
@@ -26,7 +30,7 @@
;;; Change Log:
-;; $Id: mh-seq.el,v 1.6 1996/01/29 23:16:57 kwzh Exp $
+;; $Id: mh-seq.el,v 1.14 2002/04/07 19:20:56 wohler Exp $
;;; Code:
@@ -53,7 +57,7 @@
"List the sequences defined in FOLDER."
(interactive (list (mh-prompt-for-folder "List sequences in"
mh-current-folder t)))
- (let ((temp-buffer mh-temp-buffer)
+ (let ((temp-buffer mh-temp-sequences-buffer)
(seq-list mh-seq-list))
(with-output-to-temp-buffer temp-buffer
(save-excursion
@@ -78,6 +82,8 @@
(insert "\n"))
(setq seq-list (cdr seq-list)))
(goto-char (point-min))
+ (view-mode 1)
+ (setq view-exit-action 'kill-buffer)
(message "Listing sequences...done")))))
@@ -106,13 +112,16 @@ Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
(setq mh-mode-line-annotation (symbol-name sequence))
(mh-make-folder-mode-line)
(mh-recenter nil)
+ (if (and (boundp 'tool-bar-mode) tool-bar-mode)
+ (set (make-local-variable 'tool-bar-map)
+ mh-folder-seq-tool-bar-map))
(setq mh-narrowed-to-seq sequence)))
(t
(error "No messages in sequence `%s'" (symbol-name sequence))))))
(defun mh-put-msg-in-seq (msg-or-seq sequence)
- "Add MESSAGE(s) (default: displayed message) to SEQUENCE.
+ "Add MSG-OR-SEQ (default: displayed message) to SEQUENCE.
If optional prefix argument provided, then prompt for the message sequence."
(interactive (list (if current-prefix-arg
(mh-read-seq-default "Add messages from" t)
@@ -129,14 +138,42 @@ If optional prefix argument provided, then prompt for the message sequence."
(defun mh-widen ()
"Remove restrictions from current folder, thereby showing all messages."
(interactive)
- (if mh-narrowed-to-seq
+ (let ((msg (mh-get-msg-num nil)))
+ (when mh-narrowed-to-seq
(with-mh-folder-updating (t)
- (delete-region (point-min) (point-max))
- (widen)
- (setq mh-mode-line-annotation mh-non-seq-mode-line-annotation)
- (mh-make-folder-mode-line)))
+ (delete-region (point-min) (point-max))
+ (widen)
+ (setq mh-mode-line-annotation mh-non-seq-mode-line-annotation)
+ (mh-make-folder-mode-line))
+ (if msg
+ (mh-goto-msg msg t nil))))
+ (mh-notate-deleted-and-refiled)
+ (if (and (boundp 'tool-bar-mode) tool-bar-mode)
+ (set (make-local-variable 'tool-bar-map) mh-folder-tool-bar-map))
(setq mh-narrowed-to-seq nil))
+
+;; FIXME? We may want to clear all notations and add one for current-message
+;; and process user sequences.
+(defun mh-notate-deleted-and-refiled ()
+ ;; notate the sequence 'deleted as well as all the sequences in
+ ;; mh-refile-list.
+ ;;
+ ;; First, the 'deleted sequence is straightforward
+ (mh-notate-seq 'deleted mh-note-deleted mh-cmd-note)
+ ;; Second, refiles are stored in multiple sequences, one for each folder
+ ;; name to refile to. This list of buffer names is stored in
+ ;; mh-refile-list
+ (mh-mapc
+ (function
+ (lambda (dest)
+ ;; foreach folder name, get the keyed sequence from mh-seq-list
+ (let ((msg-list (cdr (assoc dest mh-seq-list))))
+ (mapcar (lambda (msg)
+ ;; foreach msg in a sequence, do the mh-notate
+ (mh-notate msg mh-note-refiled mh-cmd-note))
+ msg-list))))
+ mh-refile-list))
;;; Commands to manipulate sequences. Sequences are stored in an alist
@@ -235,4 +272,118 @@ If optional prefix argument provided, then prompt for the message sequence."
(goto-char location)
(insert-buffer-substring (current-buffer) beginning-of-line end))))
+(defun mh-region-to-sequence (begin end)
+ "Define sequence 'region as the messages between point and mark.
+When called programmatically, use arguments BEGIN and END to define region."
+ (interactive "r")
+ (mh-delete-seq-locally 'region)
+ (save-excursion
+ (goto-char begin)
+ (while (<= (point) end)
+ (mh-add-msgs-to-seq (mh-get-msg-num t) 'region t)
+ (forward-line 1))))
+
+
+;;; Commands to handle new 'subject sequence.
+;;; Or "Poor man's threading" by psg.
+(defun mh-subject-thread-to-sequence (all)
+ "Put all following messages with same subject in sequence 'subject.
+If arg ALL is t, move to beginning of folder buffer to collect all messages.
+If arg ALL is nil, collect only messages fron current one on forward.
+Return number of messages put in the sequence:
+ nil -> there was no subject line.
+ 0 -> there were no later messages with the same subject (sequence not made)
+ >1 -> the total number of messages including current one."
+ (if (not (eq major-mode 'mh-folder-mode))
+ (error "Not in a folder buffer"))
+ (save-excursion
+ (beginning-of-line)
+ (if (or (not (looking-at mh-scan-subject-regexp))
+ (not (match-string 2))
+ (string-equal "" (match-string 2)))
+ (progn (message "No subject line.")
+ nil)
+ (let ((subject (match-string-no-properties 2))
+ (end (point-max))
+ (list))
+ (if (> (length subject) 41)
+ (setq subject (substring subject 0 41)))
+ (save-excursion
+ (if all
+ (goto-char (point-min)))
+ (while (re-search-forward mh-scan-subject-regexp nil t)
+ (let ((this-subject (match-string-no-properties 2)))
+ (if (> (length this-subject) 41)
+ (setq this-subject (substring this-subject 0 41)))
+ (if (string-equal this-subject subject)
+ (setq list (cons (mh-get-msg-num t) list))))))
+ (cond
+ (list
+ ;; If we created a new sequence, add the initial message to it too.
+ (if (not (member (mh-get-msg-num t) list))
+ (setq list (cons (mh-get-msg-num t) list)))
+ (mh-delete-seq-locally 'subject)
+ ;; sort the result into a sequence
+ (let ((sorted-list (sort (copy-sequence list) 'mh-lessp))
+ (msg))
+ (while sorted-list
+ (mh-add-msgs-to-seq (car sorted-list) 'subject t)
+ (setq sorted-list (cdr sorted-list)))
+ (safe-length list)))
+ (t
+ 0))))))
+
+(defun mh-narrow-to-subject-thread ()
+ "Narrow to a sequence containing all following messages with same subject."
+ (interactive)
+ (let ((num (mh-get-msg-num nil))
+ (count (mh-subject-thread-to-sequence t)))
+ (cond
+ ((not count) ; No subject line, delete msg anyway
+ nil)
+ ((= 0 count) ; No other msgs, delete msg anyway.
+ (message "No other messages with same Subject following this one.")
+ nil)
+ (t ; We have a subject sequence.
+ (message "Found %d messages for subject sequence." count)
+ (mh-narrow-to-seq 'subject)
+ (if (numberp num)
+ (mh-goto-msg num t t))))))
+
+(defun mh-toggle-subject-thread ()
+ "Narrow to or widen from a sequence containing current subject sequence."
+ (interactive)
+ (if (and (stringp mh-mode-line-annotation)
+ (string-equal mh-mode-line-annotation "subject"))
+ (progn
+ (goto-char (point-min))
+ (mh-widen))
+ (mh-narrow-to-subject-thread)))
+
+(defun mh-delete-subject-thread ()
+ "Mark all following messages with same subject to be deleted."
+ (interactive)
+ (let ((count (mh-subject-thread-to-sequence nil)))
+ (cond
+ ((not count) ; No subject line, delete msg anyway
+ (mh-delete-msg (mh-get-msg-num t)))
+ ((= 0 count) ; No other msgs, delete msg anyway.
+ (message "No other messages with same Subject following this one.")
+ (mh-delete-msg (mh-get-msg-num t)))
+ (t ; We have a subject sequence.
+ (message "Marked %d messages for deletion" count)
+ (mh-delete-msg 'subject)))))
+
+(defun mh-next-unseen-subject-thread ()
+ "Get the next unseen subject thread."
+ (interactive)
+ (if (and mh-mode-line-annotation
+ (string-equal mh-mode-line-annotation "subject"))
+ (goto-char (point-min)))
+ (if (or (not mh-mode-line-annotation)
+ (not (string-equal mh-mode-line-annotation "unseen")))
+ (mh-narrow-to-seq 'unseen))
+ (mh-next-undeleted-msg)
+ (mh-narrow-to-subject-thread))
+
;;; mh-seq.el ends here