Gnus development mailing list
 help / color / mirror / Atom feed
From: David Moore <dmoore@UCSD.EDU>
Cc: ding@ifi.uio.no
Subject: Re: extensions to nnmail-split-fancy
Date: 05 Nov 1996 13:39:38 -0800	[thread overview]
Message-ID: <rvybggdxwk.fsf@sdnp5.ucsd.edu> (raw)
In-Reply-To: Mark Eichin's message of 04 Nov 1996 15:32:49 -0500

Mark Eichin <eichin@cygnus.com> writes:

> I wanted to be able to do a split of the form:
> 	(any "debian-\\(\\w*\\)@lists.debian.org" "mail.debian.\\1")

> It would seem that a *much* more general extension would be to allow
> arbitrary functions in a split, but lacking functionp it would need to
> use something like eq car lambda/function/byte-foo and that wouldn't
> be fun.  (Or perhaps just grab another special character, like & | are
> now, and have it mean eval? hmm.)  But that wouldn't make the above
> that much easier, just possible...

	The following replacement for nnmail-split-it provides both
arbitrary \N and \& substitutions, as well as supporting calling a
function.  For calling a function, I introduced a new special split
character ':'.

	Note that using \N subs might not always give you the most
desired result.  If someone mails to both "debian-foo" and "debian-bar",
the message will only be posted to one of them.  Namely the match which
comes latest in the message headers.  Getting it to crosspost to all of
the appropriate groups is a bit more work, and is likely to be much
slower.


;;; dmoore@ucsd.edu 5.11.1996
;;; Change nnmail-split-it to support splits of the form:
;;; (any "debian-\(\\w*\\)@lists.debian.org" "mail.debian.\\1")
;;; Also add a new split type :, which specifies a function to
;;; be called to compute the group name:
;;; (: func arg1 arg2 ...)
;;; func is called in a buffer with the message headers, with the
;;; specified arguments.  The function should return nil for no match,
;;; or another split to operate on (this split could just be a group
;;; name string, for example).

(defun nnmail-split-it (split)
  ;; Return a list of groups matching SPLIT.
  (cond
   ;; nil split
   ((null split)
    nil)

   ;; A group name.  Do the \& and \N subs into the string.
   ((stringp split)
    (list (nnmail-expand-newtext split)))

   ;; Junk the message.
   ((eq split 'junk)
    (list 'junk))

   ;; Builtin & operation.
   ((eq (car split) '&)
    (apply 'nconc (mapcar 'nnmail-split-it (cdr split))))

   ;; Builtin | operation.
   ((eq (car split) '|)
    (let (done)
      (while (and (not done) (cdr split))
	(setq split (cdr split)
	      done (nnmail-split-it (car split))))
      done))

   ;; Builtin : operation.
   ((eq (car split) ':)
    (nnmail-split-it (eval (cdr split))))

   ;; Check the cache for the regexp for this split.
   ;; FIX FIX FIX could avoid calling assq twice here
   ((assq split nnmail-split-cache)
    (goto-char (point-max))
    ;; FIX FIX FIX problem with re-search-backward is that if you have
    ;; a split: (from "foo-\\(bar\\|baz\\)@gnus.org "mail.foo.\\1")
    ;; and someone mails a message with 'To: foo-bar@gnus.org' and
    ;; 'CC: foo-baz@gnus.org', we'll pick 'mail.foo.baz' as the group
    ;; if the cc line is a later header, even though the other choice
    ;; is probably better.  Also, this routine won't do a crosspost
    ;; when there are two different matches.
    ;; I guess you could just make this more determined, and it could
    ;; look for still more matches prior to this one, and recurse
    ;; on each of the multiple matches hit.  Of course, then you'd
    ;; want to make sure that nnmail-article-group or nnmail-split-fancy
    ;; removed duplicates, since there might be more of those.
    ;; I guess we could also remove duplicates in the & split case, since
    ;; that's the only thing that can introduce them.
    (when (re-search-backward (cdr (assq split nnmail-split-cache)) nil t)
      ;; Someone might want to do a \N sub on this match, so get the
      ;; correct match positions.
      (goto-char (match-end 0))
      (re-search-backward (nth 1 split) (match-end 1))
      (nnmail-split-it (nth 2 split))))

   ;; Not in cache, compute a regexp for the field/value pair.
   (t
    (let* ((field (nth 0 split))
	   (value (nth 1 split))
	   ;; note this regexp changed from rgnus-0.53
	   (regexp (concat "^\\(\\("
			   (if (symbolp field)
			       (cdr (assq field nnmail-split-abbrev-alist))
			     field)
			   "\\):.*\\)\\<\\("
			   (if (symbolp value)
			       (cdr (assq value nnmail-split-abbrev-alist))
			     value)
			   "\\)\\>")))
      (push (cons split regexp) nnmail-split-cache)
      ;; now that it's in the cache, just call nnmail-split-it again
      ;; on the same split, which will find it immediately in the cache.
      (nnmail-split-it split)))
   ))


;;; based on bbdb-auto-expand-newtext, except for getting the
;;; text from the current buffer, not a string.
;;; FIX FIX FIX, this could be sped up, if it ends up being slow
(defun nnmail-expand-newtext (newtext)
  (let ((pos 0)
	(len (length newtext))
	(expanded-newtext ""))
    (while (< pos len)
      (setq expanded-newtext
	    (concat expanded-newtext
		    (let ((c (aref newtext pos)))
		      (if (= ?\\ c)
			  (cond ((= ?\& (setq c (aref newtext
						      (setq pos (1+ pos)))))
				 (buffer-substring (match-beginning 0)
						   (match-end 0)))
				((and (>= c ?1) 
				      (<= c ?9))
				 ;; return empty string if N'th
				 ;; sub-regexp did not match:
				 (let ((n (- c ?0)))
				   (if (match-beginning n)
				       (buffer-substring (match-beginning n)
							 (match-end n))
				     "")))
				(t (char-to-string c)))
			(char-to-string c)))))
      (setq pos (1+ pos)))
    expanded-newtext))

-- 
David Moore <dmoore@ucsd.edu>       | Computer Systems Lab      __o
UCSD Dept. Computer Science - 0114  | Work: (619) 534-8604    _ \<,_
La Jolla, CA 92093-0114             | Fax:  (619) 534-1445   (_)/ (_)
<URL:http://oj.egbt.org/dmoore/>    | Solo Furnace Creek 508 -- 1996!


  reply	other threads:[~1996-11-05 21:39 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1996-11-04 20:32 Mark Eichin
1996-11-05 21:39 ` David Moore [this message]
1996-11-05 23:11   ` Mark Eichin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=rvybggdxwk.fsf@sdnp5.ucsd.edu \
    --to=dmoore@ucsd.edu \
    --cc=ding@ifi.uio.no \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).