Dear Kyle,

On Thu, Nov 13, 2008 at 10:04:20AM -0600, Kyle Wheeler wrote:
>  On Thursday, November 13 at 12:17 PM, quoth Jeremie Le Hen:
> > Attached you will find a patch introducing a new match pattern: =().
> > Thanks to this pattern you can match the parent message of messages
> > matching the inner pattern.
> 
>  I don't disagree with the idea, but I do disagree with the syntax. All the 
>  other patterns use ~, =, and % to differentiate between different ways of 
>  matching the same information. For example, ~c uses a regex to search the CC 
>  headers, =c performs a string-based match on the CC headers, and %c performs 
>  a group-based match on the CC headers. This is consistent across all of the 
>  various letters that can be used: %c, %C, %e, and %f are all group-based 
>  variants of the ~ versions of those same searches. I don't think it's wise 
>  to create a new pattern that appears to be the same sort of variation but 
>  does not behave in the same way. =() looks like it will be a string-based 
>  version of ~(), even if that doesn't necessarily make any sense. I think it 
>  would be smarter to change the brackets; make the pattern be ~{} or ~[] 
>  instead.

Thanks for this enlightenment.  I didn't grasp this while reading the
manual page.  I've created a new patch following your advices.  I tested
it locally, it works.

I'm a little bit worried about the few number of enclosing character
pairs available.  ~() is already taken, my patch gets its hand on ~[].
~{} and maybe ~`' remain, but it's not much.  I hope there won't be a
too big need of them in the future.

Regards,
-- 
Jeremie Le Hen
< jeremie at le-hen dot org >< ttz at chchile dot org >
diff -urp mutt-1.5.18/doc/muttrc.man.head mutt-1.5.18-parent_match/doc/muttrc.man.head
--- mutt-1.5.18/doc/muttrc.man.head	2008-01-28 03:20:21.000000000 +0100
+++ mutt-1.5.18-parent_match/doc/muttrc.man.head	2008-11-13 18:02:26.000000000 +0100
@@ -577,6 +577,9 @@ unreferenced message (requries threaded 
 .TP
 ~(PATTERN)
 messages in threads containing messages matching a certain pattern, e.g. all threads containing messages from you: ~(~P)
+.TP
+~[PATTERN]
+parent message of messages matching a certain pattern, e.g. all parent messages having duplicates messages: =(~=)
 .PD 1
 .DT
 .PP
diff -urp mutt-1.5.18/mutt.h mutt-1.5.18-parent_match/mutt.h
--- mutt-1.5.18/mutt.h	2008-01-30 05:26:50.000000000 +0100
+++ mutt-1.5.18-parent_match/mutt.h	2008-11-12 14:28:07.000000000 +0100
@@ -212,6 +212,7 @@ enum
   M_AND,
   M_OR,
   M_THREAD,
+  M_PARENT,
   M_TO,
   M_CC,
   M_COLLAPSED,
diff -urp mutt-1.5.18/pattern.c mutt-1.5.18-parent_match/pattern.c
--- mutt-1.5.18/pattern.c	2008-01-30 05:26:51.000000000 +0100
+++ mutt-1.5.18-parent_match/pattern.c	2008-11-13 18:01:40.000000000 +0100
@@ -730,15 +730,15 @@ static struct pattern_flags *lookup_tag 
   return NULL;
 }
 
-static /* const */ char *find_matching_paren (/* const */ char *s)
+static /* const */ char *find_matching_paren (/* const */ char *s, char open, char close)
 {
   int level = 1;
 
   for (; *s; s++)
   {
-    if (*s == '(')
+    if (*s == open)
       level++;
-    else if (*s == ')')
+    else if (*s == close)
     {
       level--;
       if (!level)
@@ -782,6 +782,7 @@ pattern_t *mutt_pattern_comp (/* const *
   int alladdr = 0;
   int or = 0;
   int implicit = 1;	/* used to detect logical AND operator */
+  char opench, closech;
   struct pattern_flags *entry;
   char *p;
   char *buf;
@@ -833,18 +834,20 @@ pattern_t *mutt_pattern_comp (/* const *
       case '%':
       case '=':
       case '~':
-	if (*(ps.dptr + 1) == '(') 
+	if (*(ps.dptr + 1) == '(' || *(ps.dptr + 1) == '[')
         {
 	  ps.dptr ++; /* skip ~ */
-	  p = find_matching_paren (ps.dptr + 1);
-	  if (*p != ')')
+	  opench = *ps.dptr;
+	  closech = opench == '(' ? ')' : ']';
+	  p = find_matching_paren (ps.dptr + 1, opench, closech);
+	  if (*p != closech)
 	  {
 	    snprintf (err->data, err->dsize, _("mismatched brackets: %s"), ps.dptr);
 	    mutt_pattern_free (&curlist);
 	    return NULL;
 	  }
 	  tmp = new_pattern ();
-	  tmp->op = M_THREAD;
+	  tmp->op = opench == '(' ? M_THREAD : M_PARENT;
 	  if (last)
 	    last->next = tmp;
 	  else
@@ -927,7 +930,7 @@ pattern_t *mutt_pattern_comp (/* const *
 	implicit = 1;
 	break;
       case '(':
-	p = find_matching_paren (ps.dptr + 1);
+	p = find_matching_paren (ps.dptr + 1, '(', ')');
 	if (*p != ')')
 	{
 	  snprintf (err->data, err->dsize, _("mismatched parenthesis: %s"), ps.dptr);
@@ -1087,6 +1090,29 @@ static int match_threadcomplete(struct p
   return 0;
 }
 
+static int match_directchilds(struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, THREAD *t)
+{
+  HEADER *h;
+
+  /* Not sure this is needed, but harmless anyway */
+  if (!t)
+    return 0;
+  if (!t->child)
+    return 0;
+  t = t->child;
+  /* Not sure this is needed, but harmless anyway */
+  while (t->prev)
+    t = t->prev;
+  while (t) {
+    h = t->message;
+    if(h)
+      if(mutt_pattern_exec(pat, flags, ctx, h))
+      	return 1;
+    t = t->next;
+  }
+  return 0;
+}
+
 /* flags
    	M_MATCH_FULL_ADDRESS	match both personal and machine address */
 int
@@ -1100,6 +1126,8 @@ mutt_pattern_exec (struct pattern_t *pat
       return (pat->not ^ (perform_or (pat->child, flags, ctx, h) > 0));
     case M_THREAD:
       return (pat->not ^ match_threadcomplete(pat->child, flags, ctx, h->thread, 1, 1, 1, 1));
+    case M_PARENT:
+      return (pat->not ^ match_directchilds(pat->child, flags, ctx, h->thread));
     case M_ALL:
       return (!pat->not);
     case M_EXPIRED:

Reply via email to