<<< Date Index >>>     <<< Thread Index >>>

Re: [PATCH] Parent match



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: