]> granicus.if.org Git - mutt/commitdiff
Mutt-thread patch. Use ~(PATTERN) to match any threads that
authorThomas Glanzmann <sithglan@stud.uni-erlangen.de>
Fri, 11 Aug 2006 09:32:29 +0000 (09:32 +0000)
committerThomas Glanzmann <sithglan@stud.uni-erlangen.de>
Fri, 11 Aug 2006 09:32:29 +0000 (09:32 +0000)
contain messages that match PATTERN.

doc/manual.xml.head
mutt.h
pattern.c

index 23dcd13952325c3db1f74955df1586bbedeebd7f..51645eed1c6de5b1565ed5022fa7aef793c26147 100644 (file)
@@ -3556,6 +3556,9 @@ messages:
 <row><entry>~z &lsqb;MIN&rsqb;-&lsqb;MAX&rsqb;</entry><entry>messages with a size in the range MIN to MAX *)</entry></row>
 <row><entry>~=</entry><entry>duplicated messages (see $duplicate_threads)</entry></row>
 <row><entry>~$</entry><entry>unreferenced messages (requires threaded view)</entry></row>
+<row><entry>~(PATTERN)</entry><entry>messages in threads
+containing messages matching a certain pattern, e.g. all
+threads containing messages from you: ~(~P)</entry></row>
 </tbody>
 </tgroup>
 </table>
diff --git a/mutt.h b/mutt.h
index c72573c92df67eea6768207701f93682418c8139..bb2a404863dc62f6dae7c992d1a299f52f98ffed 100644 (file)
--- a/mutt.h
+++ b/mutt.h
@@ -208,6 +208,7 @@ enum
   /* actions for mutt_pattern_comp/mutt_pattern_exec */
   M_AND,
   M_OR,
+  M_THREAD,
   M_TO,
   M_CC,
   M_COLLAPSED,
index 6e6d3ff96d455a9e4658b9f1aead6e5718a909c4..03b8ff37e45939455b4af5c705f37c24918f2259 100644 (file)
--- a/pattern.c
+++ b/pattern.c
@@ -765,7 +765,7 @@ void mutt_pattern_free (pattern_t **pat)
 pattern_t *mutt_pattern_comp (/* const */ char *s, int flags, BUFFER *err)
 {
   pattern_t *curlist = NULL;
-  pattern_t *tmp;
+  pattern_t *tmp, *tmp2;
   pattern_t *last = NULL;
   int not = 0;
   int alladdr = 0;
@@ -822,7 +822,41 @@ pattern_t *mutt_pattern_comp (/* const */ char *s, int flags, BUFFER *err)
       case '%':
       case '=':
       case '~':
-       if (implicit && or)
+       if (*(ps.dptr + 1) == '(') 
+        {
+         ps.dptr ++; /* skip ~ */
+         p = find_matching_paren (ps.dptr + 1);
+         if (*p != ')')
+         {
+           snprintf (err->data, err->dsize, _("mismatched brackets: %s"), ps.dptr);
+           mutt_pattern_free (&curlist);
+           return NULL;
+         }
+         tmp = new_pattern ();
+         tmp->op = M_THREAD;
+         if (last)
+           last->next = tmp;
+         else
+           curlist = tmp;
+         last = tmp;
+         tmp->not ^= not;
+         tmp->alladdr |= alladdr;
+         not = 0;
+         alladdr = 0;
+         /* compile the sub-expression */
+         buf = mutt_substrdup (ps.dptr + 1, p);
+         if ((tmp2 = mutt_pattern_comp (buf, flags, err)) == NULL)
+         {
+           FREE (&buf);
+           mutt_pattern_free (&curlist);
+           return NULL;
+         }
+         FREE (&buf);
+         tmp->child = tmp2;
+         ps.dptr = p + 1; /* restore location */
+         break;
+       }
+        if (implicit && or)
        {
          /* A | B & C == (A | B) & C */
          tmp = new_pattern ();
@@ -1019,6 +1053,29 @@ static int match_user (int alladdr, ADDRESS *a1, ADDRESS *a2)
   return alladdr;
 }
 
+static int match_threadcomplete(struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, THREAD *t,int left,int up,int right,int down)
+{
+  int a;
+  HEADER *h;
+
+  if(!t)
+    return 0;
+  h = t->message;
+  if(h)
+    if(mutt_pattern_exec(pat, flags, ctx, h))
+      return 1;
+
+  if(up && (a=match_threadcomplete(pat, flags, ctx, t->parent,1,1,1,0)))
+    return a;
+  if(right && t->parent && (a=match_threadcomplete(pat, flags, ctx, t->next,0,0,1,1)))
+    return a;
+  if(left && t->parent && (a=match_threadcomplete(pat, flags, ctx, t->prev,1,0,0,1)))
+    return a;
+  if(down && (a=match_threadcomplete(pat, flags, ctx, t->child,1,0,1,1)))
+    return a;
+  return 0;
+}
+
 /* flags
        M_MATCH_FULL_ADDRESS    match both personal and machine address */
 int
@@ -1030,6 +1087,8 @@ mutt_pattern_exec (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx,
       return (pat->not ^ (perform_and (pat->child, flags, ctx, h) > 0));
     case M_OR:
       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_ALL:
       return (!pat->not);
     case M_EXPIRED: