mirror of
https://git.FreeBSD.org/ports.git
synced 2024-12-26 05:02:18 +00:00
bb040dde3e
Move mail/mutt-lite to mail/mutt14-lite Move mail/mutt-devel to mail/mutt Moving mail/mutt-devel-lite to mail/mutt-lite will follow next to avoid breaking the cvs exporter PR: ports/169546 Suggested by: obrien Approved by: maintainer
170 lines
4.8 KiB
Plaintext
170 lines
4.8 KiB
Plaintext
--- mutt-1.5.20/doc/manual.xml.head 2009-05-30 19:20:08.000000000 +0200
|
|
+++ mutt-1.5.20-parentchildmatch/doc/manual.xml.head 2009-07-18 01:09:23.000000000 +0200
|
|
@@ -3947,6 +3947,22 @@ With the <command>reset</command> comman
|
|
which allows you to reset all variables to their system defaults.
|
|
</para>
|
|
|
|
+<para>
|
|
+<emphasis role="bold">Parent and child match</emphasis>.
|
|
+You can tell mutt that the following pattern has to be matched against
|
|
+the parent message with < or one of its childs with >.
|
|
+This example matches all mails which have at least an unread duplicate
|
|
+message:
|
|
+</para>
|
|
+
|
|
+<para>
|
|
+
|
|
+<screen>
|
|
+>(~= ~N)
|
|
+</screen>
|
|
+
|
|
+</para>
|
|
+
|
|
</sect2>
|
|
|
|
<sect2 id="set-myvar">
|
|
diff -urNp mutt-1.5.20/mutt.h mutt-1.5.20-parentchildmatch/mutt.h
|
|
--- mutt-1.5.20/mutt.h 2009-06-13 00:15:42.000000000 +0200
|
|
+++ mutt-1.5.20-parentchildmatch/mutt.h 2009-07-18 01:14:21.000000000 +0200
|
|
@@ -819,6 +819,8 @@ typedef struct pattern_t
|
|
unsigned int alladdr : 1;
|
|
unsigned int stringmatch : 1;
|
|
unsigned int groupmatch : 1;
|
|
+ unsigned int parentmatch : 1;
|
|
+ unsigned int childsmatch : 1;
|
|
unsigned int ign_case : 1; /* ignore case for local stringmatch searches */
|
|
int min;
|
|
int max;
|
|
diff -urNp mutt-1.5.20/pattern.c mutt-1.5.20-parentchildmatch/pattern.c
|
|
--- mutt-1.5.20/pattern.c 2009-06-03 22:48:31.000000000 +0200
|
|
+++ 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_range (pattern_t *pat, BUFFER *, BUFFER *);
|
|
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 struct pattern_flags
|
|
{
|
|
@@ -769,6 +770,8 @@ pattern_t *mutt_pattern_comp (/* const *
|
|
pattern_t *last = NULL;
|
|
int not = 0;
|
|
int alladdr = 0;
|
|
+ int parentmatch = 0;
|
|
+ int childsmatch = 0;
|
|
int or = 0;
|
|
int implicit = 1; /* used to detect logical AND operator */
|
|
struct pattern_flags *entry;
|
|
@@ -793,6 +796,24 @@ pattern_t *mutt_pattern_comp (/* const *
|
|
ps.dptr++;
|
|
not = !not;
|
|
break;
|
|
+ case '<':
|
|
+ ps.dptr++;
|
|
+ if (childsmatch) {
|
|
+ snprintf (err->data, err->dsize, _("cannot use both < and > as a pattern modifier"));
|
|
+ mutt_pattern_free (&curlist);
|
|
+ return NULL;
|
|
+ }
|
|
+ parentmatch = 1;
|
|
+ break;
|
|
+ case '>':
|
|
+ ps.dptr++;
|
|
+ if (parentmatch) {
|
|
+ snprintf (err->data, err->dsize, _("cannot use both < and > as a pattern modifier"));
|
|
+ mutt_pattern_free (&curlist);
|
|
+ return NULL;
|
|
+ }
|
|
+ childsmatch = 1;
|
|
+ break;
|
|
case '|':
|
|
if (!or)
|
|
{
|
|
@@ -818,6 +839,8 @@ pattern_t *mutt_pattern_comp (/* const *
|
|
implicit = 0;
|
|
not = 0;
|
|
alladdr = 0;
|
|
+ parentmatch = 0;
|
|
+ childsmatch = 0;
|
|
break;
|
|
case '%':
|
|
case '=':
|
|
@@ -841,8 +864,12 @@ pattern_t *mutt_pattern_comp (/* const *
|
|
last = tmp;
|
|
tmp->not ^= not;
|
|
tmp->alladdr |= alladdr;
|
|
+ tmp->parentmatch |= parentmatch;
|
|
+ tmp->childsmatch |= childsmatch;
|
|
not = 0;
|
|
alladdr = 0;
|
|
+ parentmatch = 0;
|
|
+ childsmatch = 0;
|
|
/* compile the sub-expression */
|
|
buf = mutt_substrdup (ps.dptr + 1, p);
|
|
if ((tmp2 = mutt_pattern_comp (buf, flags, err)) == NULL)
|
|
@@ -870,10 +897,14 @@ pattern_t *mutt_pattern_comp (/* const *
|
|
tmp = new_pattern ();
|
|
tmp->not = not;
|
|
tmp->alladdr = alladdr;
|
|
+ tmp->parentmatch = parentmatch;
|
|
+ tmp->childsmatch = childsmatch;
|
|
tmp->stringmatch = (*ps.dptr == '=') ? 1 : 0;
|
|
tmp->groupmatch = (*ps.dptr == '%') ? 1 : 0;
|
|
not = 0;
|
|
alladdr = 0;
|
|
+ parentmatch = 0;
|
|
+ childsmatch = 0;
|
|
|
|
if (last)
|
|
last->next = tmp;
|
|
@@ -939,8 +970,12 @@ pattern_t *mutt_pattern_comp (/* const *
|
|
last = tmp;
|
|
tmp->not ^= not;
|
|
tmp->alladdr |= alladdr;
|
|
+ tmp->parentmatch |= parentmatch;
|
|
+ tmp->childsmatch |= childsmatch;
|
|
not = 0;
|
|
alladdr = 0;
|
|
+ parentmatch = 0;
|
|
+ childsmatch = 0;
|
|
ps.dptr = p + 1; /* restore location */
|
|
break;
|
|
default:
|
|
@@ -1081,6 +1116,36 @@ static int match_threadcomplete(struct p
|
|
int
|
|
mutt_pattern_exec (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, HEADER *h)
|
|
{
|
|
+ THREAD *t;
|
|
+
|
|
+ if (pat->parentmatch) {
|
|
+ if (h->thread && h->thread->parent && h->thread->parent->message)
|
|
+ return pattern_exec (pat, flags, ctx, h->thread->parent->message);
|
|
+ else
|
|
+ return pat->not;
|
|
+ }
|
|
+ if (pat->childsmatch) {
|
|
+ if (!h->thread)
|
|
+ return pat->not;
|
|
+ if (!h->thread->child)
|
|
+ return pat->not;
|
|
+ t = h->thread->child;
|
|
+ while (t->prev)
|
|
+ t = t->prev;
|
|
+ for (; t; t = t->next) {
|
|
+ if (!t->message)
|
|
+ continue;
|
|
+ if (pattern_exec (pat, flags, ctx, t->message))
|
|
+ return !pat->not;
|
|
+ }
|
|
+ return pat->not;
|
|
+ }
|
|
+ return pattern_exec (pat, flags, ctx, h);
|
|
+}
|
|
+
|
|
+static int
|
|
+pattern_exec (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, HEADER *h)
|
|
+{
|
|
switch (pat->op)
|
|
{
|
|
case M_AND:
|