]> granicus.if.org Git - neomutt/commitdiff
Add ~<() and ~>() immediate parent/children patterns. (closes #3144)
authorKevin McCarthy <kevin@8t8.us>
Thu, 6 Jul 2017 02:09:51 +0000 (19:09 -0700)
committerRichard Russon <rich@flatcap.org>
Thu, 6 Jul 2017 14:14:48 +0000 (15:14 +0100)
Thanks to Jeremie Le Hen for the original patch, and for his
persistence in getting this feature merged.

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

index 0a49a76ada27824125123c2d87204ab698d1bd41..cc092c0e5128e30a2898aa8ddaa229ead6a81f9a 100755 (executable)
@@ -6601,6 +6601,20 @@ mailboxes $my_mx +mailbox3</screen>
                 <emphasis>PATTERN</emphasis>, e.g. all threads containing
                 messages from you: ~(~P)</entry>
               </row>
+              <row>
+                <entry>~&lt;(
+                <emphasis>PATTERN</emphasis>)</entry>
+                <entry>messages whose immediate parent matches
+                <emphasis>PATTERN</emphasis>, e.g. replies to your messages:
+                ~&lt;(~P)</entry>
+              </row>
+              <row>
+                <entry>~&gt;(
+                <emphasis>PATTERN</emphasis>)</entry>
+                <entry>messages having an immediate child matching
+                <emphasis>PATTERN</emphasis>, e.g. messages you replied to:
+                ~&gt;(~P)</entry>
+              </row>
             </tbody>
           </tgroup>
         </table>
index 1cd2fafa33669479844a04e8ffe1ea52c2c9519d..487d0bf29f25dfee95098848e3e067f665aec18a 100644 (file)
@@ -636,6 +636,12 @@ unreferenced message (requires threaded view)
 .TP
 ~(PATTERN)
 messages in threads containing messages matching a certain pattern, e.g. all threads containing messages from you: ~(~P)
+.TP
+~<(PATTERN)
+messages whose immediate parent matches PATTERN, e.g. replies to your messages: ~<(~P)
+.TP
+~>(PATTERN)
+messages having an immediate child matching PATTERN, e.g. messages you replied to: ~>(~P)
 .PD 1
 .DT
 .PP
diff --git a/mutt.h b/mutt.h
index 57dc6c47f38d22d3f6948abdb03e2bad0acfef4d..04840ae7caca94855422069d02783de0af4f04d7 100644 (file)
--- a/mutt.h
+++ b/mutt.h
@@ -154,6 +154,8 @@ enum
   MUTT_AND,
   MUTT_OR,
   MUTT_THREAD,
+  MUTT_PARENT,
+  MUTT_CHILDREN,
   MUTT_TO,
   MUTT_CC,
   MUTT_COLLAPSED,
index 77f8b5ed2607aae5012e997e6c4665da9482c4e4..40dacaab9a3e77e846b7b91fab34dc7bf5f9f055 100644 (file)
--- a/pattern.c
+++ b/pattern.c
@@ -1113,6 +1113,7 @@ struct Pattern *mutt_pattern_comp(/* const */ char *s, int flags, struct Buffer
   bool or = false;
   bool implicit = true; /* used to detect logical AND operator */
   bool isalias = false;
+  short thread_op;
   const struct PatternFlags *entry = NULL;
   char *p = NULL;
   char *buf = NULL;
@@ -1175,9 +1176,18 @@ struct Pattern *mutt_pattern_comp(/* const */ char *s, int flags, struct Buffer
           mutt_pattern_free(&curlist);
           return NULL;
         }
+        thread_op = 0;
         if (*(ps.dptr + 1) == '(')
+          thread_op = MUTT_THREAD;
+        else if ((*(ps.dptr + 1) == '<') && (*(ps.dptr + 2) == '('))
+          thread_op = MUTT_PARENT;
+        else if ((*(ps.dptr + 1) == '>') && (*(ps.dptr + 2) == '('))
+          thread_op = MUTT_CHILDREN;
+        if (thread_op)
         {
           ps.dptr++; /* skip ~ */
+          if (thread_op == MUTT_PARENT || thread_op == MUTT_CHILDREN)
+            ps.dptr++;
           p = find_matching_paren(ps.dptr + 1);
           if (*p != ')')
           {
@@ -1186,7 +1196,7 @@ struct Pattern *mutt_pattern_comp(/* const */ char *s, int flags, struct Buffer
             return NULL;
           }
           tmp = new_pattern();
-          tmp->op = MUTT_THREAD;
+          tmp->op = thread_op;
           if (last)
             last->next = tmp;
           else
@@ -1440,6 +1450,28 @@ static int match_threadcomplete(struct Pattern *pat, pattern_exec_flag flags,
   return 0;
 }
 
+static int match_threadparent(struct Pattern *pat, pattern_exec_flag flags,
+                              struct Context *ctx, struct MuttThread *t)
+{
+  if (!t || !t->parent || !t->parent->message)
+    return 0;
+
+  return mutt_pattern_exec(pat, flags, ctx, t->parent->message, NULL);
+}
+
+static int match_threadchildren(struct Pattern *pat, pattern_exec_flag flags,
+                                struct Context *ctx, struct MuttThread *t)
+{
+  if (!t || !t->child)
+    return 0;
+
+  for (t = t->child; t; t = t->next)
+    if (t->message && mutt_pattern_exec(pat, flags, ctx, t->message, NULL))
+      return 1;
+
+  return 0;
+}
+
 
 /* Sets a value in the PatternCache cache entry.
  * Normalizes the "true" value to 2. */
@@ -1480,6 +1512,10 @@ int mutt_pattern_exec(struct Pattern *pat, pattern_exec_flag flags,
     case MUTT_THREAD:
       return (pat->not ^
               match_threadcomplete(pat->child, flags, ctx, h->thread, 1, 1, 1, 1));
+    case MUTT_PARENT:
+      return (pat->not ^ match_threadparent(pat->child, flags, ctx, h->thread));
+    case MUTT_CHILDREN:
+      return (pat->not ^ match_threadchildren(pat->child, flags, ctx, h->thread));
     case MUTT_ALL:
       return !pat->not;
     case MUTT_EXPIRED: