(require 'rmail)
;;;###autoload
-(defvar rmail-summary-scroll-between-messages t
- "*Non-nil means Rmail summary scroll commands move between messages.")
+(defcustom rmail-summary-scroll-between-messages t
+ "*Non-nil means Rmail summary scroll commands move between messages."
+ :type 'boolean
+ :group 'rmail-summary)
+
+;;;###autoload
+(defcustom rmail-summary-line-count-flag t
+ "*Non-nil if Rmail summary should show the number of lines in each message."
+ :type 'boolean
+ :group 'rmail-summary)
(defvar rmail-summary-font-lock-keywords
'(("^....D.*" . font-lock-string-face) ; Deleted.
(defun rmail-update-summary (&rest ignore)
(apply (car rmail-summary-redo) (cdr rmail-summary-redo)))
+;;;###autoload
(defun rmail-summary ()
"Display a summary of all messages, one line per message."
(interactive)
(rmail-new-summary "All" '(rmail-summary) nil))
+;;;###autoload
(defun rmail-summary-by-labels (labels)
"Display a summary of all messages with one or more LABELS.
LABELS should be a string containing the desired labels, separated by commas."
'rmail-message-labels-p
(concat ", \\(" (mail-comma-list-regexp labels) "\\),")))
+;;;###autoload
(defun rmail-summary-by-recipients (recipients &optional primary-only)
"Display a summary of all messages with the given RECIPIENTS.
Normally checks the To, From and Cc fields of headers;
'rmail-message-recipients-p
(mail-comma-list-regexp recipients) primary-only))
+;;;###autoload
(defun rmail-summary-by-regexp (regexp)
"Display a summary of all messages according to regexp REGEXP.
If the regular expression is found in the header of the message
;; rmail-summary-by-topic
;; 1989 R.A. Schnitzler
+;;;###autoload
(defun rmail-summary-by-topic (subject &optional whole-message)
"Display a summary of all messages with the given SUBJECT.
Normally checks the Subject field of headers;
(if whole-message (re-search-forward subject nil t)
(string-match subject (or (mail-fetch-field "Subject") "")) )))
+;;;###autoload
(defun rmail-summary-by-senders (senders)
"Display a summary of all messages with the given SENDERS.
SENDERS is a string of names separated by commas."
(setq rmail-summary-buffer nil)
(save-excursion
(let ((rbuf (current-buffer))
+ (vbuf rmail-view-buffer)
(total rmail-total-messages))
(set-buffer sumbuf)
;; Set up the summary buffer's contents.
(make-local-variable 'minor-mode-alist)
(setq minor-mode-alist (list (list t (concat ": " description))))
(setq rmail-buffer rbuf
+ rmail-view-buffer vbuf
rmail-summary-redo redo-form
rmail-total-messages total))))
(setq rmail-summary-buffer sumbuf))
?\- ?\ )))
line))
+;;;###autoload
+(defcustom rmail-summary-line-decoder (function identity)
+ "*Function to decode summary-line.
+
+By default, `identity' is set."
+ :type 'function
+ :group 'rmail-summary)
+
(defun rmail-make-summary-line-1 (msg)
(goto-char (rmail-msgbeg msg))
(let* ((lim (save-excursion (forward-line 2) (point)))
(insert "Summary-line: " line)))
(setq pos (string-match "#" line))
(aset rmail-summary-vector (1- msg)
- (concat (format "%4d " msg)
- (substring line 0 pos)
- labels
- (substring line (1+ pos))))))
+ (funcall rmail-summary-line-decoder
+ (concat (format "%4d " msg)
+ (substring line 0 pos)
+ labels
+ (substring line (1+ pos)))))
+ ))
(defun rmail-make-basic-summary-line ()
(goto-char (point-min))
(- len 25))
(t (- mch 14))))
(min len (+ lo 25))))))))
- (save-excursion
- (save-restriction
- (widen)
- (let ((beg (rmail-msgbeg msgnum))
- (end (rmail-msgend msgnum))
- lines)
- (save-excursion
- (goto-char beg)
- ;; Count only lines in the reformatted header,
- ;; if we have reformatted it.
- (search-forward "\n*** EOOH ***\n" end t)
- (setq lines (count-lines (point) end)))
- (format (cond
- ((<= lines 9) " [%d]")
- ((<= lines 99) " [%d]")
- ((<= lines 999) " [%3d]")
- (t "[%d]"))
- lines))))
+ (if rmail-summary-line-count-flag
+ (save-excursion
+ (save-restriction
+ (widen)
+ (let ((beg (rmail-msgbeg msgnum))
+ (end (rmail-msgend msgnum))
+ lines)
+ (save-excursion
+ (goto-char beg)
+ ;; Count only lines in the reformatted header,
+ ;; if we have reformatted it.
+ (search-forward "\n*** EOOH ***\n" end t)
+ (setq lines (count-lines (point) end)))
+ (format (cond
+ ((<= lines 9) " [%d]")
+ ((<= lines 99) " [%d]")
+ ((<= lines 999) " [%3d]")
+ (t "[%d]"))
+ lines))))
+ " ")
" #" ;The # is part of the format.
(if (re-search-forward "^Subject:" nil t)
(progn (skip-chars-forward " \t")
non-del-msg-found)))
(setq count (1- count))))
(beginning-of-line)
- (display-buffer rmail-buffer))
+ (display-buffer rmail-view-buffer)
+ )
(defun rmail-summary-previous-msg (&optional number)
(interactive "p")
(save-excursion
(set-buffer rmail-buffer)
(setq subject (mail-fetch-field "Subject"))
- (setq search-regexp (concat "^Subject: *\\(Re: *\\)?"
- (regexp-quote subject)
- "\n"))
(setq i rmail-current-message))
(if (string-match "Re:[ \t]*" subject)
(setq subject (substring subject (match-end 0))))
+ (setq search-regexp (concat "^Subject: *\\(Re: *\\)?"
+ (regexp-quote subject)
+ "\n"))
(save-excursion
(while (and (/= n 0)
(if forward
\f
;; Delete and undelete summary commands.
-(defun rmail-summary-delete-forward (&optional backward)
+(defun rmail-summary-delete-forward (&optional count)
"Delete this message and move to next nondeleted one.
Deleted messages stay in the file until the \\[rmail-expunge] command is given.
-With prefix argument, delete and move backward."
- (interactive "P")
- (let (end)
- (rmail-summary-goto-msg)
- (pop-to-buffer rmail-buffer)
- (rmail-delete-message)
- (let ((del-msg rmail-current-message))
- (pop-to-buffer rmail-summary-buffer)
+A prefix argument serves as a repeat count;
+a negative argument means to delete and move backward."
+ (interactive "p")
+ (unless (numberp count) (setq count 1))
+ (let (end del-msg
+ (backward (< count 0)))
+ (while (/= count 0)
+ (rmail-summary-goto-msg)
+ (with-current-buffer rmail-buffer
+ (rmail-delete-message)
+ (setq del-msg rmail-current-message))
(rmail-summary-mark-deleted del-msg)
(while (and (not (if backward (bobp) (eobp)))
(save-excursion (beginning-of-line)
(forward-line (if backward -1 1)))
;; It looks ugly to move to the empty line at end of buffer.
(and (eobp) (not backward)
- (forward-line -1)))))
+ (forward-line -1))
+ (setq count
+ (if (> count 0) (1- count) (1+ count))))))
-(defun rmail-summary-delete-backward ()
+(defun rmail-summary-delete-backward (&optional count)
"Delete this message and move to previous nondeleted one.
-Deleted messages stay in the file until the \\[rmail-expunge] command is given."
- (interactive)
- (rmail-summary-delete-forward t))
+Deleted messages stay in the file until the \\[rmail-expunge] command is given.
+A prefix argument serves as a repeat count;
+a negative argument means to delete and move forward."
+ (interactive "p")
+ (rmail-summary-delete-forward (- count)))
(defun rmail-summary-mark-deleted (&optional n undel)
;; Since third arg is t, this only alters the summary, not the Rmail buf.
(setq buffer-read-only t)
(set-syntax-table text-mode-syntax-table)
(make-local-variable 'rmail-buffer)
+ (make-local-variable 'rmail-view-buffer)
(make-local-variable 'rmail-total-messages)
(make-local-variable 'rmail-current-message)
(setq rmail-current-message nil)
(add-hook 'post-command-hook 'rmail-summary-rmail-update nil t)
(setq revert-buffer-function 'rmail-update-summary))
+(defvar rmail-summary-put-back-unseen nil
+ "Used for communicating between calls to `rmail-summary-rmail-update'.
+If it moves to a message within an Incremental Search, and removes
+the `unseen' attribute from that message, it sets this flag
+so that if the next motion between messages is in the same Incremental
+Search, the `unseen' attribute is restored.")
+
;; Show in Rmail the message described by the summary line that point is on,
;; but only if the Rmail buffer is already visible.
;; This is a post-command-hook in summary buffers.
(point)
(progn (skip-chars-forward "0-9")
(point))))))
+ ;; Always leave `unseen' removed
+ ;; if we get out of isearch mode.
+ ;; Don't let a subsequent isearch restore that `unseen'.
+ (if (not isearch-mode)
+ (setq rmail-summary-put-back-unseen nil))
+
(or (eq rmail-current-message msg-num)
- (let ((window (get-buffer-window rmail-buffer))
+ (let ((window (get-buffer-window rmail-view-buffer t))
(owin (selected-window)))
+ (if isearch-mode
+ (save-excursion
+ (set-buffer rmail-buffer)
+ ;; If we first saw the previous message in this search,
+ ;; and we have gone to a different message while searching,
+ ;; put back `unseen' on the former one.
+ (rmail-set-attribute "unseen" t
+ rmail-current-message)
+ ;; Arrange to do that later, for the new current message,
+ ;; if it still has `unseen'.
+ (setq rmail-summary-put-back-unseen
+ (rmail-message-labels-p msg-num ", ?\\(unseen\\),")))
+ (setq rmail-summary-put-back-unseen nil))
+
+ ;; Go to the desired message.
(setq rmail-current-message msg-num)
+
+ ;; Update the summary to show the message has been seen.
(if (= (following-char) ?-)
(progn
(delete-char 1)
(insert " ")))
+
(if window
;; Using save-window-excursion would cause the new value
;; of point to get lost.
nil
(setq rmail-summary-mode-map (make-keymap))
(suppress-keymap rmail-summary-mode-map)
+
+ (define-key rmail-summary-mode-map [mouse-2] 'rmail-summary-mouse-goto-message)
(define-key rmail-summary-mode-map "a" 'rmail-summary-add-label)
(define-key rmail-summary-mode-map "b" 'rmail-summary-bury)
(define-key rmail-summary-mode-map "c" 'rmail-summary-continue)
(defvar rmail-summary-overlay nil)
(put 'rmail-summary-overlay 'permanent-local t)
-;; Go to message N in the summary buffer which is current,
-;; and in the corresponding Rmail buffer.
-;; If N is nil, use the message corresponding to point in the summary
-;; and move to that message in the Rmail buffer.
-
-;; If NOWARN, don't say anything if N is out of range.
-;; If SKIP-RMAIL, don't do anything to the Rmail buffer.
+(defun rmail-summary-mouse-goto-message (event)
+ "Select the message whose summary line you click on."
+ (interactive "@e")
+ (goto-char (posn-point (event-end event)))
+ (rmail-summary-goto-msg))
(defun rmail-summary-goto-msg (&optional n nowarn skip-rmail)
+ "Go to message N in the summary buffer and the Rmail buffer.
+If N is nil, use the message corresponding to point in the summary
+and move to that message in the Rmail buffer.
+
+If NOWARN, don't say anything if N is out of range.
+If SKIP-RMAIL, don't do anything to the Rmail buffer."
(interactive "P")
(if (consp n) (setq n (prefix-numeric-value n)))
(if (eobp) (forward-line -1))
(interactive "P")
(if (eq dist '-)
(rmail-summary-scroll-msg-down nil)
- (let ((rmail-buffer-window (get-buffer-window rmail-buffer)))
+ (let ((rmail-buffer-window (get-buffer-window rmail-view-buffer)))
(if rmail-buffer-window
(if (let ((rmail-summary-window (selected-window)))
(select-window rmail-buffer-window)
(if (not rmail-summary-scroll-between-messages)
(error "End of buffer")
(rmail-summary-next-msg (or dist 1)))
- (let ((other-window-scroll-buffer rmail-buffer))
+ (let ((other-window-scroll-buffer rmail-view-buffer))
(scroll-other-window dist)))
- ;; This forces rmail-buffer to be sized correctly later.
- (display-buffer rmail-buffer)
- (setq rmail-current-message nil)))))
+ ;; If it isn't visible at all, show the beginning.
+ (rmail-summary-beginning-of-message)))))
(defun rmail-summary-scroll-msg-down (&optional dist)
"Scroll the Rmail window backward.
-If the Rmail window is displaying the beginning of a message,
-advance to the previous message."
+If the Rmail window is now displaying the beginning of a message,
+move to the previous message."
(interactive "P")
(if (eq dist '-)
(rmail-summary-scroll-msg-up nil)
(rmail-summary-previous-msg (or dist 1)))
(let ((other-window-scroll-buffer rmail-buffer))
(scroll-other-window-down dist)))
- ;; This forces rmail-buffer to be sized correctly later.
- (display-buffer rmail-buffer)
- (setq rmail-current-message nil)))))
+ ;; If it isn't visible at all, show the beginning.
+ (rmail-summary-beginning-of-message)))))
(defun rmail-summary-beginning-of-message ()
"Show current message from the beginning."
(interactive)
- (pop-to-buffer rmail-buffer)
+ (if (and (one-window-p) (not pop-up-frames))
+ ;; If there is just one window, put the summary on the top.
+ (let ((buffer rmail-buffer))
+ (split-window (selected-window) rmail-summary-window-size)
+ (select-window (frame-first-window))
+ (pop-to-buffer rmail-buffer)
+ ;; If pop-to-buffer did not use that window, delete that
+ ;; window. (This can happen if it uses another frame.)
+ (or (eq buffer (window-buffer (next-window (frame-first-window))))
+ (delete-other-windows)))
+ (pop-to-buffer rmail-buffer))
(beginning-of-buffer)
(pop-to-buffer rmail-summary-buffer))
(save-buffer))
(set-buffer-modified-p nil))
-(defun rmail-summary-get-new-mail ()
- "Get new mail and recompute summary headers."
- (interactive)
+(defun rmail-summary-get-new-mail (&optional file-name)
+ "Get new mail and recompute summary headers.
+
+Optionally you can specify the file to get new mail from. In this case,
+the file of new mail is not changed or deleted. Noninteractively, you can
+pass the inbox file name as an argument. Interactively, a prefix
+argument says to read a file name and use that file as the inbox."
+ (interactive
+ (list (if current-prefix-arg
+ (read-file-name "Get new mail from file: "))))
(let (msg)
(save-excursion
(set-buffer rmail-buffer)
- (rmail-get-new-mail)
+ (rmail-get-new-mail file-name)
;; Get the proper new message number.
(setq msg rmail-current-message))
;; Make sure that message is displayed.