Changeset View
Changeset View
Standalone View
Standalone View
mail/mutt/files/extra-patch-parent-child-match
--- mutt-1.5.20/doc/manual.xml.head 2009-05-30 19:20:08.000000000 +0200 | --- doc/manual.xml.head.orig 2017-02-24 18:29:36 UTC | ||||
+++ mutt-1.5.20-parentchildmatch/doc/manual.xml.head 2009-07-18 01:09:23.000000000 +0200 | +++ doc/manual.xml.head | ||||
@@ -3947,6 +3947,22 @@ With the <command>reset</command> comman | @@ -4259,6 +4259,22 @@ variable <quote>all</quote>, which allow | ||||
which allows you to reset all variables to their system defaults. | their system defaults. | ||||
</para> | </para> | ||||
+<para> | +<para> | ||||
+<emphasis role="bold">Parent and child match</emphasis>. | +<emphasis role="bold">Parent and child match</emphasis>. | ||||
+You can tell mutt that the following pattern has to be matched against | +You can tell mutt that the following pattern has to be matched against | ||||
+the parent message with < or one of its childs with >. | +the parent message with < or one of its childs with >. | ||||
+This example matches all mails which have at least an unread duplicate | +This example matches all mails which have at least an unread duplicate | ||||
+message: | +message: | ||||
+</para> | +</para> | ||||
+ | + | ||||
+<para> | +<para> | ||||
+ | + | ||||
+<screen> | +<screen> | ||||
+>(~= ~N) | +>(~= ~N) | ||||
+</screen> | +</screen> | ||||
+ | + | ||||
+</para> | +</para> | ||||
+ | + | ||||
</sect2> | </sect2> | ||||
<sect2 id="set-myvar"> | <sect2 id="set-myvar"> | ||||
diff -urNp mutt-1.5.20/mutt.h mutt-1.5.20-parentchildmatch/mutt.h | --- mutt.h.orig 2017-02-24 18:29:36 UTC | ||||
--- mutt-1.5.20/mutt.h 2009-06-13 00:15:42.000000000 +0200 | +++ mutt.h | ||||
+++ mutt-1.5.20-parentchildmatch/mutt.h 2009-07-18 01:14:21.000000000 +0200 | @@ -863,6 +863,8 @@ typedef struct pattern_t | ||||
@@ -819,6 +819,8 @@ typedef struct pattern_t | |||||
unsigned int alladdr : 1; | unsigned int alladdr : 1; | ||||
unsigned int stringmatch : 1; | unsigned int stringmatch : 1; | ||||
unsigned int groupmatch : 1; | unsigned int groupmatch : 1; | ||||
+ unsigned int parentmatch : 1; | + unsigned int parentmatch : 1; | ||||
+ unsigned int childsmatch : 1; | + unsigned int childsmatch : 1; | ||||
unsigned int ign_case : 1; /* ignore case for local stringmatch searches */ | unsigned int ign_case : 1; /* ignore case for local stringmatch searches */ | ||||
unsigned int isalias : 1; | |||||
int min; | int min; | ||||
int max; | --- pattern.c.orig 2017-02-24 18:29:37 UTC | ||||
diff -urNp mutt-1.5.20/pattern.c mutt-1.5.20-parentchildmatch/pattern.c | +++ pattern.c | ||||
--- mutt-1.5.20/pattern.c 2009-06-03 22:48:31.000000000 +0200 | @@ -46,6 +46,7 @@ static int eat_regexp (pattern_t *pat, B | ||||
+++ mutt-1.5.20-parentchildmatch/pattern.c 2009-07-18 01:09:23.000000000 +0200 | |||||
@@ -45,6 +45,7 @@ static int eat_regexp (pattern_t *pat, B | |||||
static int eat_date (pattern_t *pat, BUFFER *, BUFFER *); | static int eat_date (pattern_t *pat, BUFFER *, BUFFER *); | ||||
static int eat_range (pattern_t *pat, BUFFER *, BUFFER *); | static int eat_range (pattern_t *pat, BUFFER *, BUFFER *); | ||||
static int patmatch (const pattern_t *pat, const char *buf); | static int patmatch (const pattern_t *pat, const char *buf); | ||||
+static int pattern_exec (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, HEADER *h); | +static int pattern_exec (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, HEADER *h, pattern_cache_t *cache); | ||||
static struct pattern_flags | static const struct pattern_flags | ||||
{ | { | ||||
@@ -769,6 +770,8 @@ pattern_t *mutt_pattern_comp (/* const * | @@ -781,6 +782,8 @@ pattern_t *mutt_pattern_comp (/* const * | ||||
pattern_t *last = NULL; | pattern_t *last = NULL; | ||||
int not = 0; | int not = 0; | ||||
int alladdr = 0; | int alladdr = 0; | ||||
+ int parentmatch = 0; | + int parentmatch = 0; | ||||
+ int childsmatch = 0; | + int childsmatch = 0; | ||||
int or = 0; | int or = 0; | ||||
int implicit = 1; /* used to detect logical AND operator */ | int implicit = 1; /* used to detect logical AND operator */ | ||||
struct pattern_flags *entry; | int isalias = 0; | ||||
@@ -793,6 +796,24 @@ pattern_t *mutt_pattern_comp (/* const * | @@ -810,6 +813,24 @@ pattern_t *mutt_pattern_comp (/* const * | ||||
ps.dptr++; | ps.dptr++; | ||||
not = !not; | isalias = !isalias; | ||||
break; | break; | ||||
+ case '<': | + case '<': | ||||
+ ps.dptr++; | + ps.dptr++; | ||||
+ if (childsmatch) { | + if (childsmatch) { | ||||
+ snprintf (err->data, err->dsize, _("cannot use both < and > as a pattern modifier")); | + snprintf (err->data, err->dsize, _("cannot use both < and > as a pattern modifier")); | ||||
+ mutt_pattern_free (&curlist); | + mutt_pattern_free (&curlist); | ||||
+ return NULL; | + return NULL; | ||||
+ } | + } | ||||
+ parentmatch = 1; | + parentmatch = 1; | ||||
+ break; | + break; | ||||
+ case '>': | + case '>': | ||||
+ ps.dptr++; | + ps.dptr++; | ||||
+ if (parentmatch) { | + if (parentmatch) { | ||||
+ snprintf (err->data, err->dsize, _("cannot use both < and > as a pattern modifier")); | + snprintf (err->data, err->dsize, _("cannot use both < and > as a pattern modifier")); | ||||
+ mutt_pattern_free (&curlist); | + mutt_pattern_free (&curlist); | ||||
+ return NULL; | + return NULL; | ||||
+ } | + } | ||||
+ childsmatch = 1; | + childsmatch = 1; | ||||
+ break; | + break; | ||||
case '|': | case '|': | ||||
if (!or) | if (!or) | ||||
{ | { | ||||
@@ -818,6 +839,8 @@ pattern_t *mutt_pattern_comp (/* const * | @@ -835,6 +856,8 @@ pattern_t *mutt_pattern_comp (/* const * | ||||
implicit = 0; | implicit = 0; | ||||
not = 0; | not = 0; | ||||
alladdr = 0; | alladdr = 0; | ||||
+ parentmatch = 0; | + parentmatch = 0; | ||||
+ childsmatch = 0; | + childsmatch = 0; | ||||
isalias = 0; | |||||
break; | break; | ||||
case '%': | case '%': | ||||
case '=': | @@ -865,9 +888,13 @@ pattern_t *mutt_pattern_comp (/* const * | ||||
@@ -841,8 +864,12 @@ pattern_t *mutt_pattern_comp (/* const * | |||||
last = tmp; | last = tmp; | ||||
tmp->not ^= not; | tmp->not ^= not; | ||||
tmp->alladdr |= alladdr; | tmp->alladdr |= alladdr; | ||||
+ tmp->parentmatch |= parentmatch; | + tmp->parentmatch |= parentmatch; | ||||
+ tmp->childsmatch |= childsmatch; | + tmp->childsmatch |= childsmatch; | ||||
tmp->isalias |= isalias; | |||||
not = 0; | not = 0; | ||||
alladdr = 0; | alladdr = 0; | ||||
+ parentmatch = 0; | + parentmatch = 0; | ||||
+ childsmatch = 0; | + childsmatch = 0; | ||||
isalias = 0; | |||||
/* compile the sub-expression */ | /* compile the sub-expression */ | ||||
buf = mutt_substrdup (ps.dptr + 1, p); | buf = mutt_substrdup (ps.dptr + 1, p); | ||||
if ((tmp2 = mutt_pattern_comp (buf, flags, err)) == NULL) | @@ -896,11 +923,15 @@ pattern_t *mutt_pattern_comp (/* const * | ||||
@@ -870,10 +897,14 @@ pattern_t *mutt_pattern_comp (/* const * | |||||
tmp = new_pattern (); | tmp = new_pattern (); | ||||
tmp->not = not; | tmp->not = not; | ||||
tmp->alladdr = alladdr; | tmp->alladdr = alladdr; | ||||
+ tmp->parentmatch = parentmatch; | + tmp->parentmatch = parentmatch; | ||||
+ tmp->childsmatch = childsmatch; | + tmp->childsmatch = childsmatch; | ||||
tmp->isalias = isalias; | |||||
tmp->stringmatch = (*ps.dptr == '=') ? 1 : 0; | tmp->stringmatch = (*ps.dptr == '=') ? 1 : 0; | ||||
tmp->groupmatch = (*ps.dptr == '%') ? 1 : 0; | tmp->groupmatch = (*ps.dptr == '%') ? 1 : 0; | ||||
not = 0; | not = 0; | ||||
alladdr = 0; | alladdr = 0; | ||||
+ parentmatch = 0; | + parentmatch = 0; | ||||
+ childsmatch = 0; | + childsmatch = 0; | ||||
isalias = 0; | |||||
if (last) | if (last) | ||||
last->next = tmp; | @@ -967,9 +998,13 @@ pattern_t *mutt_pattern_comp (/* const * | ||||
@@ -939,8 +970,12 @@ pattern_t *mutt_pattern_comp (/* const * | |||||
last = tmp; | last = tmp; | ||||
tmp->not ^= not; | tmp->not ^= not; | ||||
tmp->alladdr |= alladdr; | tmp->alladdr |= alladdr; | ||||
+ tmp->parentmatch |= parentmatch; | + tmp->parentmatch |= parentmatch; | ||||
+ tmp->childsmatch |= childsmatch; | + tmp->childsmatch |= childsmatch; | ||||
tmp->isalias |= isalias; | |||||
not = 0; | not = 0; | ||||
alladdr = 0; | alladdr = 0; | ||||
+ parentmatch = 0; | + parentmatch = 0; | ||||
+ childsmatch = 0; | + childsmatch = 0; | ||||
isalias = 0; | |||||
ps.dptr = p + 1; /* restore location */ | ps.dptr = p + 1; /* restore location */ | ||||
break; | break; | ||||
default: | @@ -1137,6 +1172,37 @@ int | ||||
@@ -1081,6 +1116,36 @@ static int match_threadcomplete(struct p | mutt_pattern_exec (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, HEADER *h, | ||||
int | pattern_cache_t *cache) | ||||
mutt_pattern_exec (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, HEADER *h) | |||||
{ | { | ||||
+ THREAD *t; | + THREAD *t; | ||||
+ | + | ||||
+ if (pat->parentmatch) { | + if (pat->parentmatch) { | ||||
+ if (h->thread && h->thread->parent && h->thread->parent->message) | + if (h->thread && h->thread->parent && h->thread->parent->message) | ||||
+ return pattern_exec (pat, flags, ctx, h->thread->parent->message); | + return pattern_exec (pat, flags, ctx, h->thread->parent->message, cache); | ||||
+ else | + else | ||||
+ return pat->not; | + return pat->not; | ||||
+ } | + } | ||||
+ if (pat->childsmatch) { | + if (pat->childsmatch) { | ||||
+ if (!h->thread) | + if (!h->thread) | ||||
+ return pat->not; | + return pat->not; | ||||
+ if (!h->thread->child) | + if (!h->thread->child) | ||||
+ return pat->not; | + return pat->not; | ||||
+ t = h->thread->child; | + t = h->thread->child; | ||||
+ while (t->prev) | + while (t->prev) | ||||
+ t = t->prev; | + t = t->prev; | ||||
+ for (; t; t = t->next) { | + for (; t; t = t->next) { | ||||
+ if (!t->message) | + if (!t->message) | ||||
+ continue; | + continue; | ||||
+ if (pattern_exec (pat, flags, ctx, t->message)) | + if (pattern_exec (pat, flags, ctx, t->message, cache)) | ||||
+ return !pat->not; | + return !pat->not; | ||||
+ } | + } | ||||
+ return pat->not; | + return pat->not; | ||||
+ } | + } | ||||
+ return pattern_exec (pat, flags, ctx, h); | + return pattern_exec (pat, flags, ctx, h, cache); | ||||
+} | +} | ||||
+ | + | ||||
+static int | +static int | ||||
+pattern_exec (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, HEADER *h) | +pattern_exec (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, HEADER *h, | ||||
+ pattern_cache_t *cache) | |||||
+{ | +{ | ||||
switch (pat->op) | int result; | ||||
{ | int *cache_entry; | ||||
case M_AND: |