[gnu.emacs] Displaying recipient in summary and grouping by recipients in VM

montnaro@sprite.crd.ge.com (Skip Montanaro) (08/21/89)

I FCC all my mail, and occasionally need to browse that file, either to
delete unwanted messages, or to resend a message. VM allows the user to
group by a number of attributes, but not (any of) the receipient(s). Neither
does it allow you to format the summary line to show the recipient. The
context diffs against 4.39 at the end of this message do that. The "%t"
string in vm-summary-format will cause VM to find the primary recipient of
the message and place it in the summary line, instead of the author. The
primary recipient is defined as the first address in either the To,
Apparently-To, or CC fields (searched in that order). You can group by the
primary recipient as well, by giving "recipient" as field to group by when
prompted.

I use the changes by executing the small piece of code in ~/.emacs:

    (setq vm-mode-hooks '(hack-vm-summary-format))

    (defun hack-vm-summary-format ()
      (if (string= (expand-file-name mail-archive-file-name)
		   buffer-file-name)
	  (progn
	    (make-variable-buffer-local 'vm-summary-format)
	    (setq vm-summary-format "%3n %a %-17.17t %3m %2d %3l/%-5c \"%s\"\n")
	    (make-variable-buffer-local 'vm-group-by)
	    (setq vm-group-by "recipient"))
	(progn
	  (setq vm-summary-format "%3n %a %-17.17f %3m %2d %3l/%-5c \"%s\"\n")
	  (setq vm-group-by "author"))))

(Setting vm-group-by doesn't have an immediate effect when displaying
summaries. I'm still debating whether to add a (vm-group-messages
vm-group-by) to the end of vm-summarize.)

One note of caution. I made the changes to 4.37, then discovered I didn't
have the original files anywhere. So I used diff to diff my modified VM 4.37
with the latest version (4.39), edited the output to remove any 4.37-4.39
diffs, then used patch to splice in my changes.  I then remade diffs and
checked them to make sure no 4.37-4.39 changes were undone. I don't think I
botched it, but one never knows...

*** vm-group.el.orig	Mon Jul 24 10:51:56 1989
--- vm-group.el	Sun Aug 20 19:07:29 1989
***************
*** 57,60 ****
--- 57,63 ----
    (string= (vm-full-name-of m1) (vm-full-name-of m2)))
  
+ (defun vm-group-by-recipient (m1 m2)
+   (string= (vm-to-of m1) (vm-to-of m2)))
+ 
  (defun vm-group-by-date-sent (m1 m2)
    (and (string= (vm-monthday-of m1) (vm-monthday-of m2))
*** vm-summary.el.orig	Mon Jul 24 10:51:57 1989
--- vm-summary.el	Sun Aug 20 19:07:31 1989
***************
*** 160,167 ****
      (store-match-data nil)
      (while (string-match
! "%\\(-\\)?\\([0-9]\\)*\\(\\.\\([0-9]+\\)\\)?\\([acdfFhilmnswyz%]\\)"
  	    format (match-end 0))
        (setq conv-spec (aref format (match-beginning 5)))
!       (if (memq conv-spec '(?a ?c ?d ?f ?F ?h ?i ?l ?m ?n ?s ?w ?y ?z))
  	  (progn
  	    (cond ((= conv-spec ?a)
--- 160,167 ----
      (store-match-data nil)
      (while (string-match
! "%\\(-\\)?\\([0-9]\\)*\\(\\.\\([0-9]+\\)\\)?\\([acdfFhilmnstwyz%]\\)"
  	    format (match-end 0))
        (setq conv-spec (aref format (match-beginning 5)))
!       (if (memq conv-spec '(?a ?c ?d ?f ?F ?h ?i ?l ?m ?n ?s ?t ?w ?y ?z))
  	  (progn
  	    (cond ((= conv-spec ?a)
***************
*** 198,201 ****
--- 198,204 ----
  		   (setq sexp (cons (list 'vm-su-subject
  					  'vm-su-message) sexp)))
+ 		  ((= conv-spec ?t)
+ 		   (setq sexp (cons (list 'vm-su-to
+ 					  'vm-su-message) sexp)))
  		  ((= conv-spec ?w)
  		   (setq sexp (cons (list 'vm-su-weekday
***************
*** 388,391 ****
--- 391,435 ----
    (or (vm-from-of m)
        (progn (vm-su-do-author m) (vm-from-of m))))
+ 
+ (defun vm-su-to (m)
+   (or (vm-to-of m)
+       (progn (vm-su-do-recipient m) (vm-to-of m))))
+ 
+ ;; Just pick off the first recipient - useful for browsing outgoing archives
+ ;; (e.g., FCC'd mail).
+ (defun vm-su-do-recipient (message)
+   (let (to pat1 pat2 pat3)
+     (setq to (or (vm-get-header-contents m "To")
+ 		 (vm-get-header-contents m "Apparently-To")
+ 		 (vm-get-header-contents m "CC")))
+     (if (null to)
+ 	(setq to "???")
+       (progn
+ 	;; pick off first address
+ 	(if (string-match "^[ \t]*\\([^\n,]+\\).*" to)
+ 	    (setq to (substring to (match-beginning 1) (match-end 1))))
+ 
+ 	;; pat1, pat2, and pat3 are tried in order. 
+ 	;; junk < address > junk
+ 	(setq pat1 "^.*<\\([^> \t\n]+\\).*")
+ 	;; addr? ( junk ) addr?
+ 	(setq pat2 "^[ \t]*\\([^( \t\n]*\\)[ \t]*([^)]*)[ \t]*\\([^ \t\n]*\\)[ \t]*")
+ 	;; addr?
+ 	(setq pat3 "^[ \t]*\\([^ \t\n]+\\)[ \t\n]*")
+ 	(if (not (string-match pat1 to))
+ 	    (progn
+ 	      (if (not (string-match pat2 to))
+ 		  (progn
+ 		    (if (not (string-match pat3 to))
+ 			(error "Invalid pattern in vm-su-do-recipient")
+ 		      (setq to (substring to (match-beginning 1)
+ 					  (match-end 1)))))
+ 		(if (not (eq (match-beginning 1) (match-end 1)))
+ 		    (setq to (substring to (match-beginning 1)
+ 					(match-end 1)))
+ 		  (setq to (substring to (match-beginning 2)
+ 				      (match-end 2))))))
+ 	  (setq to (substring to (match-beginning 1) (match-end 1))))))
+     (vm-set-to-of m to)))
  
  ;; Some yogurt-headed delivery agents don't even provide a From: header.
*** vm.el.orig	Mon Jul 24 10:51:57 1989
--- vm.el	Sun Aug 20 19:43:27 1989
***************
*** 175,178 ****
--- 175,179 ----
     n - message number
     s - message subject
+    t - the primary recipient (first recipient from To:, Apparently-To:, CC:)
     w - day of the week message sent
     y - year message sent
***************
*** 229,235 ****
      Re:'s) to be presented together,
    \"author\", which causes messages with the same author to be presented
!     together, and
    \"date-sent\", which causes message sent on the same day to be
!     presented together.
    \"arrival-time\" which appears only for completeness, this is the
      default behavior and is the same as nil.
--- 230,238 ----
      Re:'s) to be presented together,
    \"author\", which causes messages with the same author to be presented
!     together,
!   \"recipient\", which causes message sent to the same primary recipient to
!     be presented together,
    \"date-sent\", which causes message sent on the same day to be
!     presented together, and
    \"arrival-time\" which appears only for completeness, this is the
      default behavior and is the same as nil.
***************
*** 368,372 ****
  (defconst vm-header-regexp-format "^%s:[ \t]*\\(.*\\(\n[ \t]+.*\\)*\\)")
  (defconst vm-supported-groupings-alist
!   '(("arrival-time") ("subject") ("author") ("date-sent")))
  (defconst vm-total-count 0)
  (defconst vm-new-count 0)
--- 371,375 ----
  (defconst vm-header-regexp-format "^%s:[ \t]*\\(.*\\(\n[ \t]+.*\\)*\\)")
  (defconst vm-supported-groupings-alist
!   '(("arrival-time") ("subject") ("author") ("recipient") ("date-sent")))
  (defconst vm-total-count 0)
  (defconst vm-new-count 0)
***************
*** 413,417 ****
  
  ;; macros and functions dealing with accessing messages struct fields
! (defun vm-make-message () (make-vector 20 nil))
  
  ;; where message begins (From_ line)
--- 416,420 ----
  
  ;; macros and functions dealing with accessing messages struct fields
! (defun vm-make-message () (make-vector 21 nil))
  
  ;; where message begins (From_ line)
***************
*** 461,464 ****
--- 464,468 ----
  (defmacro vm-su-start-of (message) (list 'aref message 18))
  (defmacro vm-su-end-of (message) (list 'aref message 19))
+ (defmacro vm-to-of (message) (list 'aref message 20))
  
  (defmacro vm-set-start-of (message start) (list 'aset message 0 start))
***************
*** 482,485 ****
--- 486,490 ----
  (defmacro vm-set-su-start-of (message start) (list 'aset message 18 start))
  (defmacro vm-set-su-end-of (message end) (list 'aset message 19 end))
+ (defmacro vm-set-to-of (message end) (list 'aset message 20 end))
  
  (defun vm-text-end-of (message)
*** vm.texinfo.orig	Mon Jul 24 10:50:23 1989
--- vm.texinfo	Sun Aug 20 19:10:32 1989
***************
*** 713,716 ****
--- 713,720 ----
  @item author
  Messages with the same author are grouped together.
+ @item recipient
+ Messages to the same primary recipient are grouped together. The primary
+ recipient is the first addressee in the To, Apparently-To, or CC fields
+ (in that order of preference).
  @item date-sent
  Messages sent on the same day are grouped together.
***************
*** 778,781 ****
--- 782,786 ----
     n - message number
     s - message subject
+    t - primary recipient's address
     w - day of the week message sent
     y - year message sent

wjc@ho5cad.ATT.COM (Bill Carpenter) (08/21/89)

In article <8908210034.AA01934@sprite.crd.Ge.Com> montnaro@sprite.crd.ge.com (Skip Montanaro) writes:

> Neither does [VM] allow you to format the summary line to show the
> recipient. The context diffs against 4.39 at the end of this message
> do that. The "%t" string in vm-summary-format will cause VM to find
> the primary recipient of the message and place it in the summary line,
> instead of the author.

Quite handy.  What would be even handier would be a % escape that
showed the "from" address unless it was me, in which case it would
show something about the recipient(s).

An even more general sequence would be something like:

	%!some-function-name-returning-a-string

where the named function would get run (delimiting the function name
is a tiny syntax problem).  Arguments for the function could be some
nice list comprised of computed values for the other %-things and
perhaps a few relevant buffer objects or whatever else is handy.
--
   Bill Carpenter         att!ho5cad!wjc  or  attmail!bill

jv@mh.nl (Johan Vromans) (08/21/89)

In article <8908210034.AA01934@sprite.crd.Ge.Com> montnaro@sprite.crd.ge.com (Skip Montanaro) writes:

   I FCC all my mail, and occasionally need to browse that file, either to
   delete unwanted messages, or to resend a message. VM allows the user to
   group by a number of attributes, but not (any of) the receipient(s).
	...

Remarkable how people tend to have the same ideas...

I use a slightly different approach. I also have a
'vm-su-do-recipient' function (very much alike), but I have only
hacked 'vm-su-full-name' to return "To <recipient>" if the message was
sent by me. So in all mailboxes I can save both directions of a
communication, and in all summaries mail originated by me show the
recipient instead of my name.

I have not studied Skip's 'vm-su-do-recipient' function thouroughly,
but I think it will work together with my 'vm-su-full-name':

(defun vm-su-full-name (m)
  (let (sl fl)
    (setq fl
	  (or (vm-full-name-of m)
	      (progn (vm-su-do-author m) (vm-full-name-of m))))
    (if (and (or
	      (equal fl (user-login-name))
	      (equal fl (user-full-name)))
	     (setq sl (vm-su-do-recipient m)))
	(concat "To " sl)
      fl)))


Have fun!

	Johan
--
Johan Vromans				       jv@mh.nl via internet backbones
Multihouse Automatisering bv		       uucp: ..!{mcvax,hp4nl}!mh.nl!jv
Doesburgweg 7, 2803 PL Gouda, The Netherlands  phone/fax: +31 1820 62944/62500
------------------------ "Arms are made for hugging" -------------------------

jr@bbn.com (John Robinson) (08/31/89)

In article <WJC.89Aug21095749@ho5cad.ho5cad.ATT.COM>, wjc@ho5cad (Bill Carpenter) writes:
>Quite handy.  What would be even handier would be a % escape that
>showed the "from" address unless it was me, in which case it would
>show something about the recipient(s).

In fact, this is the default behavior in a number of mail reading
systems.  Maybe it should be just VM's standard behavior.  If the
recipient were always prefixed in the summary with, e.g. "To:", you
could still find all mail from yourself.  There is the tiny problem of
deciding which of a number of possible aliases is you, but a RE could
provide that.

In the MH system, one line of my configuration is:

  Alternate-Mailboxes: jr,jr@*,jr%*,bbn*!jr,*unix-emacs-request@*,bbn*!jr@*

Shell syntax, but you get the idea.
--
/jr, nee John Robinson     Life did not take over the globe by combat,
jr@bbn.com or bbn!jr          but by networking -- Lynn Margulis

aglew@urbana.mcd.mot.com (Andy-Krazy-Glew) (09/03/89)

    To check for paren balancing, go to the end of the file and insert a
    ) .  Emacs ought to complain if parens are unbalanced.  Then delete
    that ) and the one before it.  Emacs ought to show you a matching
    paren (check that it's the right one).  This assume you are in some
    form of lisp mode.

I do this, and also use indent-region, suitably wrapped:

(defun indent-buffer ()
  "Indent the entire buffer (AG)"
  (interactive)
  (save-excursion
    (indent-region (point-min) (point-max) nil)))

--
Andy "Krazy" Glew,  Motorola MCD,    	    	    aglew@urbana.mcd.mot.com
1101 E. University, Urbana, IL 61801, USA.          {uunet!,}uiucuxc!udc!aglew
   
My opinions are my own; I indicate my company only so that the reader
may account for any possible bias I may have towards our products.