[gnu.emacs.bug] mail-plus mode

mlittman@WIND.BELLCORE.COM (Michael S. Littman) (02/18/89)

Hi,

	Someone suggested a fews days ago (in one of these Emacs
lists...) that mail mode allow the possibility of multiple outgoing
mail messages.  I implemented something which does the same thing by
using widening-narrowing in the *mail* buffer.  It changes the
existing package only minimally and actually comes in handy quite
often.

-Michael
------------------
;;;
;;; mail-plus.el: Allows multiple active outgoing mail messages.
;;;

; Use, copy, and alter this program at will but don't blame me if it
;  doesn't work or erase this notice.

(require 'sendmail) ; This allows this file to augment sendmail.el.

; The main idea is that narrowing in on a single mail message allows
;   multiple messages in *mail*.  Extra bindings are used to move
;   around in the narrowed buffer.  Should work as usual for people
;   who don't use it. (Michael S. Littman 11/88)

; C-c C-a (mail+append)
; C-c C-d (mail+delete)
; C-c C-p (mail+previous)
; C-c C-n (mail+next)
; C-c < (mail+first)
; C-c > (mail+last)
; C-c C-c (mail+send-and-exit)

(defvar mail+marker "--new message follows this line--"
  "Separates mail messages within the *mail* buffer.")

(defun mail+narrow ()
  "Narrows the current buffer on a single mail message."
  (interactive)
  (let (top bottom)
    (widen) ; Just in case.
    (save-excursion
      (if (search-backward mail+marker (point-min) 1)
	  (setq top (+ 1 (length mail+marker) (point)))
	(setq top (point))))
    (save-excursion
      (if (search-forward mail+marker (point-max) 1)
	  (setq bottom (+ (- (length mail+marker)) (point)))
	(setq bottom (point))))
    (narrow-to-region top bottom)))

(defun mail+next ()
  "Moves to the next message."
  (interactive)
  (widen)
  (if (not (search-forward mail+marker (point-max) 1))
      (message "No next message."))
  (mail+narrow)
  (goto-char (point-max)))

(defun mail+previous ()
  "Moves to the previous message."
  (interactive)
  (widen)
  (if (not (search-backward mail+marker (point-min) 1))
      (message "No previous message."))
  (mail+narrow)
  (goto-char (point-max)))

(defun mail+append ()
  "Add a new message to the end."
  (interactive)
  (widen)
  (goto-char (point-max))
  (insert-string mail+marker)
  (insert-string "\n")
  (mail+narrow)
  (mail-setup nil nil nil nil nil))

(defun mail+first ()
  "Moves to the first message."
  (interactive)
  (widen)
  (goto-char (point-min))
  (mail+narrow)
  (goto-char (point-max)))

(defun mail+last ()
  "Moves to the last message."
  (interactive)
  (widen)
  (goto-char (point-max))
  (mail+narrow)
  (goto-char (point-max)))

(defun mail+delete (&optional no-message)
  "Delete the current message."
  (interactive)
  (let (top bottom last first)
    (widen)
    (setq first nil)
    (save-excursion
      (if (search-backward mail+marker (point-min) 1)
	  (setq top (+ 1 (length mail+marker) (point)))
	(progn
	  (setq top (point))
	  (setq first t))))
    (setq last nil)
    (save-excursion
      (if (search-forward mail+marker (point-max) 1)
	  (setq bottom (+ 1 (point)))
	(progn
	  (setq bottom (point))
	  (setq last t))))
    (if (and last (not first))
	(setq top (+ top (- (length mail+marker)) -1)))
    (if (and first last)
	(if (not no-message) (message "Last message."))
      (delete-region top bottom))
    (mail+narrow)))

(defun mail+send-and-exit (arg)
  "Send message like mail-send, then, if no errors, exit from mail buffer.
Prefix arg means don't delete this window.  Like mail-send-and-exit
except does a mail+delete."
  (interactive "P")
  (mail-send)
  (mail+delete t)
  (bury-buffer (current-buffer))
  (if (and (not arg)
	   (not (one-window-p))
	   (save-excursion
	     (set-buffer (window-buffer (next-window (selected-window) 'not)))
	     (eq major-mode 'rmail-mode)))
      (delete-window)
    (switch-to-buffer (other-buffer (current-buffer)))))

; Key bindings
(define-key mail-mode-map "\C-c\C-a" 'mail+append)
(define-key mail-mode-map "\C-c\C-d" 'mail+delete)
(define-key mail-mode-map "\C-c\C-p" 'mail+previous)
(define-key mail-mode-map "\C-c\C-n" 'mail+next)
(define-key mail-mode-map "\C-c<" 'mail+first)
(define-key mail-mode-map "\C-c>" 'mail+last)
(define-key mail-mode-map "\C-c\C-c" 'mail+send-and-exit)