NeoMutt  2025-12-11-872-g385a04
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
lib.h File Reference

Match patterns to emails. More...

#include <stdbool.h>
#include <stdint.h>
#include "mutt/lib.h"
#include "mutt.h"
#include "search_state.h"
+ Include dependency graph for lib.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  Pattern
 A simple (non-regex) pattern. More...
 
struct  PatternCache
 Cache commonly-used patterns. More...
 

Macros

#define MUTT_ALIAS_SIMPLESEARCH   "~f %s | ~t %s | ~c %s"
 Simple search pattern for aliases (from/to/cc fields)
 

Typedefs

typedef uint8_t PatternCompFlags
 
typedef uint8_t PatternExecFlags
 

Enumerations

enum  PatternCompFlag { MUTT_PC_NONE = 0 , MUTT_PC_FULL_MSG = 1U << 0 , MUTT_PC_PATTERN_DYNAMIC = 1U << 1 , MUTT_PC_SEND_MODE_SEARCH = 1U << 2 }
 Flags for mutt_pattern_comp(), e.g. More...
 
enum  PatternExecFlag { MUTT_PAT_EXEC_NONE = 0 , MUTT_MATCH_FULL_ADDRESS = 1U << 0 }
 Flags for mutt_pattern_exec(), e.g. More...
 
enum  PatternType {
  MUTT_PAT_AND = MUTT_MT_MAX , MUTT_PAT_OR , MUTT_PAT_THREAD , MUTT_PAT_PARENT ,
  MUTT_PAT_CHILDREN , MUTT_PAT_TO , MUTT_PAT_CC , MUTT_PAT_BCC ,
  MUTT_PAT_COLLAPSED , MUTT_PAT_SUBJECT , MUTT_PAT_FROM , MUTT_PAT_DATE ,
  MUTT_PAT_DATE_RECEIVED , MUTT_PAT_DUPLICATED , MUTT_PAT_UNREFERENCED , MUTT_PAT_BROKEN ,
  MUTT_PAT_ID , MUTT_PAT_ID_EXTERNAL , MUTT_PAT_BODY , MUTT_PAT_HEADER ,
  MUTT_PAT_HORMEL , MUTT_PAT_WHOLE_MSG , MUTT_PAT_SENDER , MUTT_PAT_MESSAGE ,
  MUTT_PAT_SCORE , MUTT_PAT_SIZE , MUTT_PAT_REFERENCE , MUTT_PAT_RECIPIENT ,
  MUTT_PAT_LIST , MUTT_PAT_SUBSCRIBED_LIST , MUTT_PAT_PERSONAL_RECIP , MUTT_PAT_PERSONAL_FROM ,
  MUTT_PAT_ADDRESS , MUTT_PAT_CRYPT_SIGN , MUTT_PAT_CRYPT_VERIFIED , MUTT_PAT_CRYPT_ENCRYPT ,
  MUTT_PAT_PGP_KEY , MUTT_PAT_XLABEL , MUTT_PAT_SERVERSEARCH , MUTT_PAT_DRIVER_TAGS ,
  MUTT_PAT_MIMEATTACH , MUTT_PAT_MIMETYPE , MUTT_PAT_NEWSGROUPS , MUTT_PAT_MAX
}
 Types of pattern to match. More...
 
enum  PatternAlias { PAA_TAG , PAA_UNTAG , PAA_VISIBLE }
 What to do with the matching Aliases. More...
 

Functions

 SLIST_HEAD (PatternList, Pattern)
 
bool mutt_pattern_exec (struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
 Match a pattern against an email header.
 
bool mutt_pattern_alias_exec (struct Pattern *pat, PatternExecFlags flags, struct AliasView *av, struct PatternCache *cache)
 Match a pattern against an alias.
 
struct PatternList * mutt_pattern_comp (struct MailboxView *mv, const char *s, PatternCompFlags flags, struct Buffer *err)
 Create a Pattern.
 
void mutt_check_simple (struct Buffer *s, const char *simple)
 Convert a simple search into a real request.
 
void mutt_pattern_free (struct PatternList **pat)
 Free a Pattern.
 
bool dlg_pattern (struct Buffer *buf)
 Show menu to select a Pattern -.
 
bool mutt_is_list_recipient (bool all_addr, struct Envelope *env)
 Matches known mailing lists.
 
bool mutt_is_subscribed_list_recipient (bool all_addr, struct Envelope *env)
 Matches subscribed mailing lists.
 
int mutt_pattern_func (struct MailboxView *mv, int op, char *prompt)
 Perform some Pattern matching.
 
int mutt_pattern_alias_func (char *prompt, struct AliasMenuData *mdata, enum PatternAlias action, struct Menu *menu)
 Perform some Pattern matching for Alias.
 
int mutt_search_command (struct MailboxView *mv, struct Menu *menu, int cur, struct SearchState *state, SearchFlags flags)
 Perform a search.
 
int mutt_search_alias_command (struct Menu *menu, int cur, struct SearchState *state, SearchFlags flags)
 Perform a search.
 

Variables

const struct CompleteOps CompletePatternOps
 Auto-Completion of Patterns.
 

Detailed Description

Match patterns to emails.

Authors
  • Richard Russon
  • Pietro Cerutti

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file lib.h.

Macro Definition Documentation

◆ MUTT_ALIAS_SIMPLESEARCH

#define MUTT_ALIAS_SIMPLESEARCH   "~f %s | ~t %s | ~c %s"

Simple search pattern for aliases (from/to/cc fields)

Definition at line 64 of file lib.h.

Typedef Documentation

◆ PatternCompFlags

typedef uint8_t PatternCompFlags

Definition at line 78 of file lib.h.

◆ PatternExecFlags

typedef uint8_t PatternExecFlags

Definition at line 119 of file lib.h.

Enumeration Type Documentation

◆ PatternCompFlag

Flags for mutt_pattern_comp(), e.g.

MUTT_PC_FULL_MSG

Enumerator
MUTT_PC_NONE 

No flags are set.

MUTT_PC_FULL_MSG 

Enable body and header matching.

MUTT_PC_PATTERN_DYNAMIC 

Enable runtime date range evaluation.

MUTT_PC_SEND_MODE_SEARCH 

Allow send-mode body searching.

Definition at line 71 of file lib.h.

72{
73 MUTT_PC_NONE = 0,
74 MUTT_PC_FULL_MSG = 1U << 0,
75 MUTT_PC_PATTERN_DYNAMIC = 1U << 1,
76 MUTT_PC_SEND_MODE_SEARCH = 1U << 2,
77};
@ MUTT_PC_PATTERN_DYNAMIC
Enable runtime date range evaluation.
Definition lib.h:75
@ MUTT_PC_NONE
No flags are set.
Definition lib.h:73
@ MUTT_PC_SEND_MODE_SEARCH
Allow send-mode body searching.
Definition lib.h:76
@ MUTT_PC_FULL_MSG
Enable body and header matching.
Definition lib.h:74

◆ PatternExecFlag

Flags for mutt_pattern_exec(), e.g.

MUTT_MATCH_FULL_ADDRESS

Enumerator
MUTT_PAT_EXEC_NONE 

No flags are set.

MUTT_MATCH_FULL_ADDRESS 

Match the full address.

Definition at line 114 of file lib.h.

115{
117 MUTT_MATCH_FULL_ADDRESS = 1U << 0,
118};
@ MUTT_PAT_EXEC_NONE
No flags are set.
Definition lib.h:116
@ MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition lib.h:117

◆ PatternType

Types of pattern to match.

Note
This enum piggy-backs on top of MessageType
See also
mutt_pattern_comp(), mutt_pattern_exec()
Enumerator
MUTT_PAT_AND 

Both patterns must match.

MUTT_PAT_OR 

Either pattern can match.

MUTT_PAT_THREAD 

Pattern matches email thread.

MUTT_PAT_PARENT 

Pattern matches parent.

MUTT_PAT_CHILDREN 

Pattern matches a child email.

MUTT_PAT_TO 

Pattern matches 'To:' field.

MUTT_PAT_CC 

Pattern matches 'Cc:' field.

MUTT_PAT_BCC 

Pattern matches 'Bcc:' field.

MUTT_PAT_COLLAPSED 

Thread is collapsed.

MUTT_PAT_SUBJECT 

Pattern matches 'Subject:' field.

MUTT_PAT_FROM 

Pattern matches 'From:' field.

MUTT_PAT_DATE 

Pattern matches 'Date:' field.

MUTT_PAT_DATE_RECEIVED 

Pattern matches date received.

MUTT_PAT_DUPLICATED 

Duplicate message.

MUTT_PAT_UNREFERENCED 

Message is unreferenced in the thread.

MUTT_PAT_BROKEN 

Message is part of a broken thread.

MUTT_PAT_ID 

Pattern matches email's Message-ID.

MUTT_PAT_ID_EXTERNAL 

Message-ID is among results from an external query.

MUTT_PAT_BODY 

Pattern matches email's body.

MUTT_PAT_HEADER 

Pattern matches email's header.

MUTT_PAT_HORMEL 

Pattern matches email's spam score.

MUTT_PAT_WHOLE_MSG 

Pattern matches raw email text.

MUTT_PAT_SENDER 

Pattern matches sender.

MUTT_PAT_MESSAGE 

Pattern matches message number.

MUTT_PAT_SCORE 

Pattern matches email's score.

MUTT_PAT_SIZE 

Pattern matches email's size.

MUTT_PAT_REFERENCE 

Pattern matches 'References:' or 'In-Reply-To:' field.

MUTT_PAT_RECIPIENT 

User is a recipient of the email.

MUTT_PAT_LIST 

Email is on mailing list.

MUTT_PAT_SUBSCRIBED_LIST 

Email is on subscribed mailing list.

MUTT_PAT_PERSONAL_RECIP 

Email is addressed to the user.

MUTT_PAT_PERSONAL_FROM 

Email is from the user.

MUTT_PAT_ADDRESS 

Pattern matches any address field.

MUTT_PAT_CRYPT_SIGN 

Message is signed.

MUTT_PAT_CRYPT_VERIFIED 

Message is crypographically verified.

MUTT_PAT_CRYPT_ENCRYPT 

Message is encrypted.

MUTT_PAT_PGP_KEY 

Message has PGP key.

MUTT_PAT_XLABEL 

Pattern matches keyword/label.

MUTT_PAT_SERVERSEARCH 

Server-side pattern matches.

MUTT_PAT_DRIVER_TAGS 

Pattern matches message tags.

MUTT_PAT_MIMEATTACH 

Pattern matches number of attachments.

MUTT_PAT_MIMETYPE 

Pattern matches MIME type.

MUTT_PAT_NEWSGROUPS 

Pattern matches newsgroup.

MUTT_PAT_MAX 

Definition at line 148 of file lib.h.

149{
194};
@ MUTT_MT_MAX
Definition mutt.h:106
@ MUTT_PAT_HEADER
Pattern matches email's header.
Definition lib.h:169
@ MUTT_PAT_WHOLE_MSG
Pattern matches raw email text.
Definition lib.h:171
@ MUTT_PAT_BROKEN
Message is part of a broken thread.
Definition lib.h:165
@ MUTT_PAT_ID_EXTERNAL
Message-ID is among results from an external query.
Definition lib.h:167
@ MUTT_PAT_OR
Either pattern can match.
Definition lib.h:151
@ MUTT_PAT_CHILDREN
Pattern matches a child email.
Definition lib.h:154
@ MUTT_PAT_PARENT
Pattern matches parent.
Definition lib.h:153
@ MUTT_PAT_REFERENCE
Pattern matches 'References:' or 'In-Reply-To:' field.
Definition lib.h:176
@ MUTT_PAT_FROM
Pattern matches 'From:' field.
Definition lib.h:160
@ MUTT_PAT_DRIVER_TAGS
Pattern matches message tags.
Definition lib.h:189
@ MUTT_PAT_COLLAPSED
Thread is collapsed.
Definition lib.h:158
@ MUTT_PAT_CRYPT_VERIFIED
Message is crypographically verified.
Definition lib.h:184
@ MUTT_PAT_HORMEL
Pattern matches email's spam score.
Definition lib.h:170
@ MUTT_PAT_SUBJECT
Pattern matches 'Subject:' field.
Definition lib.h:159
@ MUTT_PAT_LIST
Email is on mailing list.
Definition lib.h:178
@ MUTT_PAT_NEWSGROUPS
Pattern matches newsgroup.
Definition lib.h:192
@ MUTT_PAT_PERSONAL_RECIP
Email is addressed to the user.
Definition lib.h:180
@ MUTT_PAT_CC
Pattern matches 'Cc:' field.
Definition lib.h:156
@ MUTT_PAT_SUBSCRIBED_LIST
Email is on subscribed mailing list.
Definition lib.h:179
@ MUTT_PAT_SERVERSEARCH
Server-side pattern matches.
Definition lib.h:188
@ MUTT_PAT_RECIPIENT
User is a recipient of the email.
Definition lib.h:177
@ MUTT_PAT_CRYPT_ENCRYPT
Message is encrypted.
Definition lib.h:185
@ MUTT_PAT_UNREFERENCED
Message is unreferenced in the thread.
Definition lib.h:164
@ MUTT_PAT_CRYPT_SIGN
Message is signed.
Definition lib.h:183
@ MUTT_PAT_MESSAGE
Pattern matches message number.
Definition lib.h:173
@ MUTT_PAT_AND
Both patterns must match.
Definition lib.h:150
@ MUTT_PAT_DATE
Pattern matches 'Date:' field.
Definition lib.h:161
@ MUTT_PAT_XLABEL
Pattern matches keyword/label.
Definition lib.h:187
@ MUTT_PAT_SCORE
Pattern matches email's score.
Definition lib.h:174
@ MUTT_PAT_MIMEATTACH
Pattern matches number of attachments.
Definition lib.h:190
@ MUTT_PAT_DUPLICATED
Duplicate message.
Definition lib.h:163
@ MUTT_PAT_PERSONAL_FROM
Email is from the user.
Definition lib.h:181
@ MUTT_PAT_TO
Pattern matches 'To:' field.
Definition lib.h:155
@ MUTT_PAT_BCC
Pattern matches 'Bcc:' field.
Definition lib.h:157
@ MUTT_PAT_SENDER
Pattern matches sender.
Definition lib.h:172
@ MUTT_PAT_DATE_RECEIVED
Pattern matches date received.
Definition lib.h:162
@ MUTT_PAT_ADDRESS
Pattern matches any address field.
Definition lib.h:182
@ MUTT_PAT_MAX
Definition lib.h:193
@ MUTT_PAT_MIMETYPE
Pattern matches MIME type.
Definition lib.h:191
@ MUTT_PAT_PGP_KEY
Message has PGP key.
Definition lib.h:186
@ MUTT_PAT_ID
Pattern matches email's Message-ID.
Definition lib.h:166
@ MUTT_PAT_THREAD
Pattern matches email thread.
Definition lib.h:152
@ MUTT_PAT_SIZE
Pattern matches email's size.
Definition lib.h:175
@ MUTT_PAT_BODY
Pattern matches email's body.
Definition lib.h:168

◆ PatternAlias

What to do with the matching Aliases.

Enumerator
PAA_TAG 

Set AliasView.is_tagged, but don't touch the others.

PAA_UNTAG 

Unset AliasView.is_tagged, but don't touch the others.

PAA_VISIBLE 

Set AliasView.is_visible and hide the rest.

Definition at line 199 of file lib.h.

200{
201 PAA_TAG,
202 PAA_UNTAG,
204};
@ PAA_VISIBLE
Set AliasView.is_visible and hide the rest.
Definition lib.h:203
@ PAA_TAG
Set AliasView.is_tagged, but don't touch the others.
Definition lib.h:201
@ PAA_UNTAG
Unset AliasView.is_tagged, but don't touch the others.
Definition lib.h:202

Function Documentation

◆ SLIST_HEAD()

SLIST_HEAD ( PatternList ,
Pattern  )

◆ mutt_pattern_exec()

bool mutt_pattern_exec ( struct Pattern * pat,
PatternExecFlags flags,
struct Mailbox * m,
struct Email * e,
struct PatternCache * cache )

Match a pattern against an email header.

Parameters
patPattern to match
flagsFlags, e.g. MUTT_MATCH_FULL_ADDRESS
mMailbox
eEmail
cacheCache for common Patterns
Return values
trueSuccess, pattern matched
falsePattern did not match

flags: MUTT_MATCH_FULL_ADDRESS: match both personal and machine address cache: For repeated matches against the same Header, passing in non-NULL will store some of the cacheable pattern matches in this structure.

Definition at line 1151 of file exec.c.

1153{
1154 const bool needs_msg = pattern_needs_msg(m, pat);
1155 struct Message *msg = needs_msg ? mx_msg_open(m, e) : NULL;
1156 if (needs_msg && !msg)
1157 {
1158 return false;
1159 }
1160 const bool matched = pattern_exec(pat, flags, m, e, msg, cache);
1161 mx_msg_close(m, &msg);
1162 return matched;
1163}
int mx_msg_close(struct Mailbox *m, struct Message **ptr)
Close a message.
Definition mx.c:1182
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition mx.c:1136
static bool pattern_needs_msg(const struct Mailbox *m, const struct Pattern *pat)
Check whether a pattern needs a full message.
Definition exec.c:796
static bool pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct Message *msg, struct PatternCache *cache)
Match a pattern against an email header.
Definition exec.c:843
A local copy of an email.
Definition message.h:34
struct Message::@264267271004327071125374067057142037276212342100 flags
Flags for the Message.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_pattern_alias_exec()

bool mutt_pattern_alias_exec ( struct Pattern * pat,
PatternExecFlags flags,
struct AliasView * av,
struct PatternCache * cache )

Match a pattern against an alias.

Parameters
patPattern to match
flagsFlags, e.g. MUTT_MATCH_FULL_ADDRESS
avAliasView
cacheCache for common Patterns
Return values
trueSuccess, pattern matched
falsePattern did not match

flags: MUTT_MATCH_FULL_ADDRESS: match both personal and machine address cache: For repeated matches against the same Alias, passing in non-NULL will store some of the cacheable pattern matches in this structure.

Definition at line 1178 of file exec.c.

1180{
1181 switch (pat->op)
1182 {
1183 case MUTT_PAT_FROM: /* alias */
1184 if (!av->alias)
1185 return false;
1186 return pat->pat_not ^ (av->alias->name && patmatch(pat, av->alias->name));
1187 case MUTT_PAT_CC: /* comment */
1188 if (!av->alias)
1189 return false;
1190 return pat->pat_not ^ (av->alias->comment && patmatch(pat, av->alias->comment));
1191 case MUTT_PAT_TO: /* alias address list */
1192 if (!av->alias)
1193 return false;
1194 return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
1195 1, &av->alias->addr);
1197 if (!av->alias)
1198 return false;
1199 return match_tags(pat, &av->alias->tags);
1200 case MUTT_PAT_AND:
1201 return pat->pat_not ^ (perform_alias_and(pat->child, flags, av, cache) > 0);
1202 case MUTT_PAT_OR:
1203 return pat->pat_not ^ (perform_alias_or(pat->child, flags, av, cache) > 0);
1204 }
1205
1206 return false;
1207}
static bool perform_alias_and(struct PatternList *pat, PatternExecFlags flags, struct AliasView *av, struct PatternCache *cache)
Perform a logical AND on a set of Patterns.
Definition exec.c:326
static int match_addrlist(struct Pattern *pat, bool match_personal, int n,...)
match a pattern against an address list
Definition exec.c:417
static bool patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition exec.c:70
static int perform_alias_or(struct PatternList *pat, PatternExecFlags flags, struct AliasView *av, struct PatternCache *cache)
Perform a logical OR on a set of Patterns.
Definition exec.c:375
static bool match_tags(struct Pattern *pat, struct TagList *tags)
match a pattern against a tags list
Definition exec.c:396
struct Alias * alias
Alias.
Definition gui.h:46
struct TagList tags
Tags.
Definition alias.h:39
char * comment
Free-form comment string.
Definition alias.h:38
char * name
Short name.
Definition alias.h:36
struct AddressList addr
List of Addresses the Alias expands to.
Definition alias.h:37
struct PatternList * child
Arguments to logical operation.
Definition lib.h:97
short op
Operation, e.g. MUTT_PAT_SCORE.
Definition lib.h:85
bool pat_not
Pattern should be inverted (not)
Definition lib.h:86
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_pattern_comp()

struct PatternList * mutt_pattern_comp ( struct MailboxView * mv,
const char * s,
PatternCompFlags flags,
struct Buffer * err )

Create a Pattern.

Parameters
mvMailbox view
sPattern string
flagsFlags, e.g. MUTT_PC_FULL_MSG
errBuffer for error messages
Return values
ptrNewly allocated Pattern

Definition at line 964 of file compile.c.

966{
967 /* curlist when assigned will always point to a list containing at least one node
968 * with a Pattern value. */
969 struct PatternList *curlist = NULL;
970 bool pat_not = false;
971 bool all_addr = false;
972 bool pat_or = false;
973 bool implicit = true; /* used to detect logical AND operator */
974 bool is_alias = false;
975 const struct PatternFlags *entry = NULL;
976 char *p = NULL;
977 char *buf = NULL;
978 struct Mailbox *m = mv ? mv->mailbox : NULL;
979
980 if (!s || (s[0] == '\0'))
981 {
982 buf_strcpy(err, _("empty pattern"));
983 return NULL;
984 }
985
986 struct Buffer *ps = buf_pool_get();
987 buf_strcpy(ps, s);
988 buf_seek(ps, 0);
989
990 SKIPWS(ps->dptr);
991 while (*ps->dptr)
992 {
993 switch (*ps->dptr)
994 {
995 case '^':
996 ps->dptr++;
997 all_addr = !all_addr;
998 break;
999 case '!':
1000 ps->dptr++;
1001 pat_not = !pat_not;
1002 break;
1003 case '@':
1004 ps->dptr++;
1005 is_alias = !is_alias;
1006 break;
1007 case '|':
1008 if (!pat_or)
1009 {
1010 if (!curlist)
1011 {
1012 buf_printf(err, _("error in pattern at: %s"), ps->dptr);
1013 buf_pool_release(&ps);
1014 return NULL;
1015 }
1016
1017 struct Pattern *pat = SLIST_FIRST(curlist);
1018 if (SLIST_NEXT(pat, entries))
1019 {
1020 /* A & B | C == (A & B) | C */
1021 struct Pattern *root = attach_new_root(&curlist);
1022 root->op = MUTT_PAT_AND;
1023 }
1024
1025 pat_or = true;
1026 }
1027 ps->dptr++;
1028 implicit = false;
1029 pat_not = false;
1030 all_addr = false;
1031 is_alias = false;
1032 break;
1033 case '%':
1034 case '=':
1035 case '~':
1036 {
1037 if (ps->dptr[1] == '\0')
1038 {
1039 buf_printf(err, _("missing pattern: %s"), ps->dptr);
1040 goto cleanup;
1041 }
1042 short thread_op = 0;
1043 if (ps->dptr[1] == '(')
1044 thread_op = MUTT_PAT_THREAD;
1045 else if ((ps->dptr[1] == '<') && (ps->dptr[2] == '('))
1046 thread_op = MUTT_PAT_PARENT;
1047 else if ((ps->dptr[1] == '>') && (ps->dptr[2] == '('))
1048 thread_op = MUTT_PAT_CHILDREN;
1049 if (thread_op != 0)
1050 {
1051 ps->dptr++; /* skip ~ */
1052 if ((thread_op == MUTT_PAT_PARENT) || (thread_op == MUTT_PAT_CHILDREN))
1053 ps->dptr++;
1054 p = find_matching_paren(ps->dptr + 1);
1055 if (p[0] != ')')
1056 {
1057 buf_printf(err, _("mismatched parentheses: %s"), ps->dptr);
1058 goto cleanup;
1059 }
1060 struct Pattern *leaf = attach_new_leaf(&curlist);
1061 leaf->op = thread_op;
1062 leaf->pat_not = pat_not;
1063 leaf->all_addr = all_addr;
1064 leaf->is_alias = is_alias;
1065 pat_not = false;
1066 all_addr = false;
1067 is_alias = false;
1068 /* compile the sub-expression */
1069 buf = mutt_strn_dup(ps->dptr + 1, p - (ps->dptr + 1));
1070 leaf->child = mutt_pattern_comp(mv, buf, flags, err);
1071 if (!leaf->child)
1072 {
1073 FREE(&buf);
1074 goto cleanup;
1075 }
1076 FREE(&buf);
1077 ps->dptr = p + 1; /* restore location */
1078 break;
1079 }
1080 if (implicit && pat_or)
1081 {
1082 /* A | B & C == (A | B) & C */
1083 struct Pattern *root = attach_new_root(&curlist);
1084 root->op = MUTT_PAT_OR;
1085 pat_or = false;
1086 }
1087
1088 char prefix = ps->dptr[0];
1089 entry = lookup_tag(prefix, ps->dptr[1]);
1090 if (!entry)
1091 {
1092 buf_printf(err, _("%c%c: invalid pattern"), prefix, ps->dptr[1]);
1093 goto cleanup;
1094 }
1095 if (entry->flags && ((flags & entry->flags) == 0))
1096 {
1097 buf_printf(err, _("%c%c: not supported in this mode"), prefix, ps->dptr[1]);
1098 goto cleanup;
1099 }
1100
1101 struct Pattern *leaf = attach_new_leaf(&curlist);
1102 leaf->pat_not = pat_not;
1103 leaf->all_addr = all_addr;
1104 leaf->is_alias = is_alias;
1105 leaf->sendmode = (flags & MUTT_PC_SEND_MODE_SEARCH);
1106 leaf->op = entry->op;
1107 pat_not = false;
1108 all_addr = false;
1109 is_alias = false;
1110
1111 // Determine the actual eat_arg to use.
1112 // If the entry was found via fallback (entry->prefix is '~' but we used '=' or '%'),
1113 // override the eat_arg to use string or group parsing respectively.
1114 enum PatternEat eat_arg = entry->eat_arg;
1115 if ((entry->prefix == '~') && (prefix == '=') && (eat_arg == EAT_REGEX))
1116 eat_arg = EAT_STRING;
1117 else if ((entry->prefix == '~') && (prefix == '%') && (eat_arg == EAT_REGEX))
1118 eat_arg = EAT_GROUP;
1119
1120 ps->dptr++; /* move past the prefix (~, %, =) */
1121 ps->dptr++; /* eat the operator and any optional whitespace */
1122 SKIPWS(ps->dptr);
1123 if (eat_arg)
1124 {
1125 if (ps->dptr[0] == '\0')
1126 {
1127 buf_addstr(err, _("missing parameter"));
1128 goto cleanup;
1129 }
1130 switch (eat_arg)
1131 {
1132 case EAT_REGEX:
1133 if (!eat_regex(leaf, flags, ps, err))
1134 goto cleanup;
1135 break;
1136 case EAT_STRING:
1137 if (!eat_string(leaf, flags, ps, err))
1138 goto cleanup;
1139 break;
1140 case EAT_GROUP:
1141 if (!eat_group(leaf, flags, ps, err))
1142 goto cleanup;
1143 break;
1144 case EAT_DATE:
1145 if (!eat_date(leaf, flags, ps, err))
1146 goto cleanup;
1147 break;
1148 case EAT_RANGE:
1149 if (!eat_range(leaf, flags, ps, err))
1150 goto cleanup;
1151 break;
1152 case EAT_MESSAGE_RANGE:
1153 if (!eat_message_range(leaf, flags, ps, err, mv))
1154 goto cleanup;
1155 break;
1156 case EAT_QUERY:
1157 if (!eat_query(leaf, flags, ps, err, m))
1158 goto cleanup;
1159 break;
1160 default:
1161 break;
1162 }
1163 }
1164 implicit = true;
1165 break;
1166 }
1167
1168 case '(':
1169 {
1170 p = find_matching_paren(ps->dptr + 1);
1171 if (p[0] != ')')
1172 {
1173 buf_printf(err, _("mismatched parentheses: %s"), ps->dptr);
1174 goto cleanup;
1175 }
1176 /* compile the sub-expression */
1177 buf = mutt_strn_dup(ps->dptr + 1, p - (ps->dptr + 1));
1178 struct PatternList *sub = mutt_pattern_comp(mv, buf, flags, err);
1179 FREE(&buf);
1180 if (!sub)
1181 goto cleanup;
1182 struct Pattern *leaf = SLIST_FIRST(sub);
1183 if (curlist)
1184 {
1185 attach_leaf(curlist, leaf);
1186 FREE(&sub);
1187 }
1188 else
1189 {
1190 curlist = sub;
1191 }
1192 leaf->pat_not ^= pat_not;
1193 leaf->all_addr |= all_addr;
1194 leaf->is_alias |= is_alias;
1195 pat_not = false;
1196 all_addr = false;
1197 is_alias = false;
1198 ps->dptr = p + 1; /* restore location */
1199 break;
1200 }
1201
1202 default:
1203 buf_printf(err, _("error in pattern at: %s"), ps->dptr);
1204 goto cleanup;
1205 }
1206 SKIPWS(ps->dptr);
1207 }
1208 buf_pool_release(&ps);
1209
1210 if (!curlist)
1211 {
1212 buf_strcpy(err, _("empty pattern"));
1213 return NULL;
1214 }
1215
1216 if (SLIST_NEXT(SLIST_FIRST(curlist), entries))
1217 {
1218 struct Pattern *root = attach_new_root(&curlist);
1219 root->op = pat_or ? MUTT_PAT_OR : MUTT_PAT_AND;
1220 }
1221
1222 return curlist;
1223
1224cleanup:
1225 mutt_pattern_free(&curlist);
1226 buf_pool_release(&ps);
1227 return NULL;
1228}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
void buf_seek(struct Buffer *buf, size_t offset)
Set current read/write position to offset from beginning.
Definition buffer.c:622
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:226
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
static struct Pattern * attach_new_root(struct PatternList **curlist)
Create a new Pattern as a parent for a List.
Definition compile.c:928
static struct Pattern * attach_new_leaf(struct PatternList **curlist)
Attach a new Pattern to a List.
Definition compile.c:944
struct PatternList * mutt_pattern_comp(struct MailboxView *mv, const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition compile.c:964
static struct Pattern * attach_leaf(struct PatternList *list, struct Pattern *leaf)
Attach a Pattern to a Pattern List.
Definition compile.c:906
static char * find_matching_paren(char *s)
Find the matching parenthesis.
Definition compile.c:812
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition compile.c:836
static bool eat_group(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
Parse a group name - Implements eat_arg_t -.
Definition compile.c:147
static bool eat_string(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
Parse a plain string - Implements eat_arg_t -.
Definition compile.c:115
static bool eat_query(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err, struct Mailbox *m)
Parse a query for an external search program - Implements eat_arg_t -.
Definition compile.c:202
bool eat_message_range(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err, struct MailboxView *mv)
Parse a range of message numbers - Implements eat_arg_t -.
Definition message.c:283
static bool eat_range(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
Parse a number range - Implements eat_arg_t -.
Definition compile.c:682
static bool eat_date(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
Parse a date pattern - Implements eat_arg_t -.
Definition compile.c:773
static bool eat_regex(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
Parse a regex - Implements eat_arg_t -.
Definition compile.c:72
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define _(a)
Definition message.h:28
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition string.c:384
const struct PatternFlags * lookup_tag(char prefix, char tag)
Lookup a pattern modifier.
Definition flags.c:235
PatternEat
Function to process pattern arguments.
Definition private.h:51
@ EAT_STRING
Process a plain string.
Definition private.h:59
@ EAT_RANGE
Process a number (range)
Definition private.h:57
@ EAT_GROUP
Process a group name.
Definition private.h:54
@ EAT_MESSAGE_RANGE
Process a message number (range)
Definition private.h:55
@ EAT_DATE
Process a date (range)
Definition private.h:53
@ EAT_QUERY
Process a query string.
Definition private.h:56
@ EAT_REGEX
Process a regex.
Definition private.h:58
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
#define SLIST_NEXT(elm, field)
Definition queue.h:268
#define SLIST_FIRST(head)
Definition queue.h:227
#define SKIPWS(ch)
Definition string2.h:52
String manipulation buffer.
Definition buffer.h:36
char * dptr
Current read/write position.
Definition buffer.h:38
struct Mailbox * mailbox
Current Mailbox.
Definition mview.h:51
A mailbox.
Definition mailbox.h:81
Mapping between user character and internal constant.
Definition private.h:66
enum PatternEat eat_arg
Type of function needed to parse flag, e.g. EAT_DATE.
Definition private.h:72
PatternCompFlags flags
Pattern flags, e.g. MUTT_PC_FULL_MSG.
Definition private.h:70
int op
Operation to perform, e.g. MUTT_PAT_SCORE.
Definition private.h:69
char prefix
Prefix for this pattern, e.g. '~', '', or '='.
Definition private.h:67
A simple (non-regex) pattern.
Definition lib.h:84
union Pattern::@006112053024257132210207314205210350156165326341 p
bool all_addr
All Addresses in the list must match.
Definition lib.h:87
bool is_alias
Is there an alias for this Address?
Definition lib.h:91
bool sendmode
Evaluate searches in send-mode.
Definition lib.h:93
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_check_simple()

void mutt_check_simple ( struct Buffer * buf,
const char * simple )

Convert a simple search into a real request.

Parameters
bufBuffer for the result
simpleSearch string to convert

Definition at line 91 of file pattern.c.

92{
93 bool do_simple = true;
94
95 for (const char *p = buf_string(buf); p && (p[0] != '\0'); p++)
96 {
97 if ((p[0] == '\\') && (p[1] != '\0'))
98 {
99 p++;
100 }
101 else if ((p[0] == '~') || (p[0] == '=') || (p[0] == '%'))
102 {
103 do_simple = false;
104 break;
105 }
106 }
107
108 /* XXX - is mutt_istr_cmp() right here, or should we use locale's
109 * equivalences? */
110
111 if (do_simple) /* yup, so spoof a real request */
112 {
113 /* convert old tokens into the new format */
114 if (mutt_istr_equal("all", buf_string(buf)) || mutt_str_equal("^", buf_string(buf)) ||
115 mutt_str_equal(".", buf_string(buf))) /* ~A is more efficient */
116 {
117 buf_strcpy(buf, "~A");
118 }
119 else if (mutt_istr_equal("del", buf_string(buf)))
120 {
121 buf_strcpy(buf, "~D");
122 }
123 else if (mutt_istr_equal("flag", buf_string(buf)))
124 {
125 buf_strcpy(buf, "~F");
126 }
127 else if (mutt_istr_equal("new", buf_string(buf)))
128 {
129 buf_strcpy(buf, "~N");
130 }
131 else if (mutt_istr_equal("old", buf_string(buf)))
132 {
133 buf_strcpy(buf, "~O");
134 }
135 else if (mutt_istr_equal("repl", buf_string(buf)))
136 {
137 buf_strcpy(buf, "~Q");
138 }
139 else if (mutt_istr_equal("read", buf_string(buf)))
140 {
141 buf_strcpy(buf, "~R");
142 }
143 else if (mutt_istr_equal("tag", buf_string(buf)))
144 {
145 buf_strcpy(buf, "~T");
146 }
147 else if (mutt_istr_equal("unread", buf_string(buf)))
148 {
149 buf_strcpy(buf, "~U");
150 }
151 else
152 {
153 struct Buffer *tmp = buf_pool_get();
154 quote_simple(buf_string(buf), tmp);
155 mutt_file_expand_fmt(buf, simple, buf_string(tmp));
156 buf_pool_release(&tmp);
157 }
158 }
159}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
void mutt_file_expand_fmt(struct Buffer *dest, const char *fmt, const char *src)
Replace s in a string with a filename.
Definition file.c:1366
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:677
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:665
static void quote_simple(const char *str, struct Buffer *buf)
Apply simple quoting to a string.
Definition pattern.c:73
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_pattern_free()

void mutt_pattern_free ( struct PatternList ** pat)

Free a Pattern.

Parameters
[out]patPattern to free

Definition at line 836 of file compile.c.

837{
838 if (!pat || !*pat)
839 return;
840
841 struct Pattern *np = SLIST_FIRST(*pat);
842 struct Pattern *next = NULL;
843
844 while (np)
845 {
846 next = SLIST_NEXT(np, entries);
847
848 if (np->is_multi)
849 {
851 }
852 else if (np->string_match || np->dynamic)
853 {
854 FREE(&np->p.str);
855 }
856 else if (np->group_match)
857 {
858 np->p.group = NULL;
859 }
860 else if (np->p.regex)
861 {
862 regfree(np->p.regex);
863 FREE(&np->p.regex);
864 }
865
866#ifdef USE_DEBUG_GRAPHVIZ
867 FREE(&np->raw_pattern);
868#endif
870 FREE(&np);
871
872 np = next;
873 }
874
875 FREE(pat);
876}
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition list.c:123
bool group_match
Check a group of Addresses.
Definition lib.h:89
struct Group * group
Address group if group_match is set.
Definition lib.h:100
bool string_match
Check a string for a match.
Definition lib.h:88
regex_t * regex
Compiled regex, for non-pattern matching.
Definition lib.h:99
struct ListHead multi_cases
Multiple strings for ~I pattern.
Definition lib.h:102
char * str
String, if string_match is set.
Definition lib.h:101
bool dynamic
Evaluate date ranges at run time.
Definition lib.h:92
bool is_multi
Multiple case (only for ~I pattern now)
Definition lib.h:94
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_is_list_recipient()

bool mutt_is_list_recipient ( bool all_addr,
struct Envelope * env )

Matches known mailing lists.

Parameters
all_addrIf true, ALL Addresses must be mailing lists
envEnvelope
Return values
true
  • One Address is a mailing list (all_addr is false)
  • All the Addresses are mailing lists (all_addr is true)

Definition at line 507 of file exec.c.

508{
509 return mutt_is_predicate_recipient(all_addr, env, &mutt_is_mail_list);
510}
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list?
Definition maillist.c:46
static bool mutt_is_predicate_recipient(bool all_addr, struct Envelope *env, addr_predicate_t p)
Test an Envelopes Addresses using a predicate function.
Definition exec.c:470
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_is_subscribed_list_recipient()

bool mutt_is_subscribed_list_recipient ( bool all_addr,
struct Envelope * env )

Matches subscribed mailing lists.

Parameters
all_addrIf true, ALL Addresses must be on the subscribed list
envEnvelope
Return values
true
  • One Address is subscribed (all_addr is false)
  • All the Addresses are subscribed (all_addr is true)

Definition at line 494 of file exec.c.

495{
497}
bool mutt_is_subscribed_list(const struct Address *addr)
Is this the email address of a user-subscribed mailing list?
Definition maillist.c:61
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_pattern_func()

int mutt_pattern_func ( struct MailboxView * mv,
int op,
char * prompt )

Perform some Pattern matching.

Parameters
mvMailbox View
opOperation to perform, e.g. MUTT_LIMIT
promptPrompt to show the user
Return values
0Success
-1Failure

Definition at line 295 of file pattern.c.

296{
297 if (!mv || !mv->mailbox)
298 return -1;
299
300 struct Mailbox *m = mv->mailbox;
301
302 struct Buffer *err = NULL;
303 int rc = -1;
304 struct Progress *progress = NULL;
305 struct Buffer *buf = buf_pool_get();
306 bool interrupted = false;
307
308 buf_strcpy(buf, mv->pattern);
309 if (prompt || (op != MUTT_LIMIT))
310 {
311 if ((mw_get_field(prompt, buf, MUTT_COMP_CLEAR, HC_PATTERN, &CompletePatternOps, NULL) != 0) ||
312 buf_is_empty(buf))
313 {
314 buf_pool_release(&buf);
315 return -1;
316 }
317 }
318
319 mutt_message(_("Compiling search pattern..."));
320
321 char *simple = buf_strdup(buf);
322 const char *const c_simple_search = cs_subset_string(NeoMutt->sub, "simple_search");
323 mutt_check_simple(buf, NONULL(c_simple_search));
324 const char *pbuf = buf->data;
325 while (*pbuf == ' ')
326 pbuf++;
327 const bool match_all = mutt_str_equal(pbuf, "~A");
328
329 err = buf_pool_get();
330 struct PatternList *pat = mutt_pattern_comp(mv, buf->data, MUTT_PC_FULL_MSG, err);
331 if (!pat)
332 {
333 mutt_error("%s", buf_string(err));
334 goto bail;
335 }
336
337 if ((m->type == MUTT_IMAP) && (!imap_search(m, pat)))
338 goto bail;
339
340 progress = progress_new(MUTT_PROGRESS_READ, (op == MUTT_LIMIT) ? m->msg_count : m->vcount);
341 progress_set_message(progress, _("Executing command on matching messages..."));
342
343 if (op == MUTT_LIMIT)
344 {
345 m->vcount = 0;
346 mv->vsize = 0;
347 mv->collapsed = false;
348 int padding = mx_msg_padding_size(m);
349
350 for (int i = 0; i < m->msg_count; i++)
351 {
352 struct Email *e = m->emails[i];
353 if (!e)
354 break;
355
356 if (SigInt)
357 {
358 interrupted = true;
359 SigInt = false;
360 break;
361 }
362 progress_update(progress, i, -1);
363 /* new limit pattern implicitly uncollapses all threads */
364 e->vnum = -1;
365 e->visible = false;
366 e->limit_visited = true;
367 e->collapsed = false;
368 e->num_hidden = 0;
369
370 if (match_all ||
372 {
373 e->vnum = m->vcount;
374 e->visible = true;
375 m->v2r[m->vcount] = i;
376 m->vcount++;
377 struct Body *b = e->body;
378 mv->vsize += b->length + b->offset - b->hdr_offset + padding;
379 }
380 }
381 }
382 else
383 {
384 for (int i = 0; i < m->vcount; i++)
385 {
386 struct Email *e = mutt_get_virt_email(m, i);
387 if (!e)
388 continue;
389
390 if (SigInt)
391 {
392 interrupted = true;
393 SigInt = false;
394 break;
395 }
396 progress_update(progress, i, -1);
398 {
399 switch (op)
400 {
401 case MUTT_UNDELETE:
402 mutt_set_flag(m, e, MUTT_PURGE, false, true);
404
405 case MUTT_DELETE:
406 mutt_set_flag(m, e, MUTT_DELETE, (op == MUTT_DELETE), true);
407 break;
408 case MUTT_TAG:
409 case MUTT_UNTAG:
410 mutt_set_flag(m, e, MUTT_TAG, (op == MUTT_TAG), true);
411 break;
412 }
413 }
414 }
415 }
416 progress_free(&progress);
417
419
420 if (op == MUTT_LIMIT)
421 {
422 /* drop previous limit pattern */
423 FREE(&mv->pattern);
425
426 if (m->msg_count && !m->vcount)
427 mutt_error(_("No messages matched criteria"));
428
429 /* record new limit pattern, unless match all */
430 if (!match_all)
431 {
432 mv->pattern = simple;
433 simple = NULL; /* don't clobber it */
435 }
436 }
437
438 if (interrupted)
439 mutt_error(_("Search interrupted"));
440
441 rc = 0;
442
443bail:
444 buf_pool_release(&buf);
445 buf_pool_release(&err);
446 FREE(&simple);
447 mutt_pattern_free(&pat);
448
449 return rc;
450}
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:571
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
@ MUTT_IMAP
'IMAP' Mailbox type
Definition mailbox.h:49
@ MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition wdata.h:47
void mutt_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
Definition flags.c:54
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition window.c:467
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
@ HC_PATTERN
Patterns.
Definition lib.h:60
bool imap_search(struct Mailbox *m, const struct PatternList *pat)
Find messages in mailbox matching a pattern.
Definition search.c:227
#define FALLTHROUGH
Definition lib.h:117
@ MUTT_UNDELETE
Messages to be un-deleted.
Definition mutt.h:95
@ MUTT_LIMIT
Messages in limited view.
Definition mutt.h:101
@ MUTT_UNTAG
Messages to be un-tagged.
Definition mutt.h:100
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition mutt.h:96
@ MUTT_TAG
Tagged messages.
Definition mutt.h:99
@ MUTT_DELETE
Messages to be deleted.
Definition mutt.h:94
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
struct Email * mutt_get_virt_email(struct Mailbox *m, int vnum)
Get a virtual Email.
Definition mview.c:376
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size()
Definition mx.c:1507
const struct CompleteOps CompletePatternOps
Auto-Completion of Patterns.
Definition complete.c:98
bool mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition exec.c:1151
void mutt_check_simple(struct Buffer *buf, const char *simple)
Convert a simple search into a real request.
Definition pattern.c:91
@ MUTT_PROGRESS_READ
Progress tracks elements, according to $read_inc
Definition lib.h:84
struct Progress * progress_new(enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition progress.c:139
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition progress.c:110
void progress_set_message(struct Progress *progress, const char *fmt,...) __attribute__((__format__(__printf__
bool progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition progress.c:80
volatile sig_atomic_t SigInt
true after SIGINT is received
Definition signal.c:68
#define NONULL(x)
Definition string2.h:44
The body of an email.
Definition body.h:36
LOFF_T offset
offset where the actual data begins
Definition body.h:52
LOFF_T length
length (in bytes) of attachment
Definition body.h:53
long hdr_offset
Offset in stream where the headers begin.
Definition body.h:81
char * data
Pointer to data.
Definition buffer.h:37
The envelope/body of an email.
Definition email.h:39
bool visible
Is this message part of the view?
Definition email.h:121
bool limit_visited
Has the limit pattern been applied to this message?
Definition email.h:122
bool collapsed
Is this message part of a collapsed thread?
Definition email.h:120
struct Body * body
List of MIME parts.
Definition email.h:69
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
Definition email.h:123
int vnum
Virtual message number.
Definition email.h:114
bool collapsed
Are all threads collapsed?
Definition mview.h:49
off_t vsize
Size (in bytes) of the messages shown.
Definition mview.h:41
struct PatternList * limit_pattern
Compiled limit pattern.
Definition mview.h:43
char * pattern
Limit pattern string.
Definition mview.h:42
int vcount
The number of virtual messages.
Definition mailbox.h:101
int * v2r
Mapping from virtual to real msgno.
Definition mailbox.h:100
int msg_count
Total number of messages.
Definition mailbox.h:90
enum MailboxType type
Mailbox type.
Definition mailbox.h:104
struct Email ** emails
Array of Emails.
Definition mailbox.h:98
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_pattern_alias_func()

int mutt_pattern_alias_func ( char * prompt,
struct AliasMenuData * mdata,
enum PatternAlias action,
struct Menu * menu )

Perform some Pattern matching for Alias.

Parameters
promptPrompt to show the user
mdataMenu data holding Aliases
actionWhat to do with the results, e.g. PAA_TAG
menuCurrent menu
Return values
0Success
-1Failure

Definition at line 170 of file pattern.c.

172{
173 int rc = -1;
174 struct Progress *progress = NULL;
175 struct Buffer *buf = buf_pool_get();
176
177 buf_strcpy(buf, mdata->limit);
178 if (prompt)
179 {
180 if ((mw_get_field(prompt, buf, MUTT_COMP_CLEAR, HC_PATTERN, &CompletePatternOps, NULL) != 0) ||
181 buf_is_empty(buf))
182 {
183 buf_pool_release(&buf);
184 return -1;
185 }
186 }
187
188 mutt_message(_("Compiling search pattern..."));
189
190 /* Compile the pattern string; "~A" means match-all. If the simple string
191 * was expanded into a pattern, compile it for evaluation. */
192 bool match_all = false;
193 struct PatternList *pat = NULL;
194 char *simple = buf_strdup(buf);
195 if (simple)
196 {
198 const char *pbuf = buf->data;
199 while (*pbuf == ' ')
200 pbuf++;
201 match_all = mutt_str_equal(pbuf, "~A");
202
203 struct Buffer *err = buf_pool_get();
204 pat = mutt_pattern_comp(NULL, buf->data, MUTT_PC_FULL_MSG, err);
205 if (!pat)
206 {
207 mutt_error("%s", buf_string(err));
208 buf_pool_release(&err);
209 goto bail;
210 }
211 buf_pool_release(&err);
212 }
213 else
214 {
215 match_all = true;
216 }
217
218 progress = progress_new(MUTT_PROGRESS_READ, ARRAY_SIZE(&mdata->ava));
219 progress_set_message(progress, _("Executing command on matching messages..."));
220
221 /* Apply the action (tag, untag, or filter visibility) to each alias
222 * that matches the compiled pattern */
223 int vcounter = 0;
224 struct AliasView *avp = NULL;
225 ARRAY_FOREACH(avp, &mdata->ava)
226 {
227 progress_update(progress, ARRAY_FOREACH_IDX_avp, -1);
228
229 if (match_all ||
231 {
232 switch (action)
233 {
234 case PAA_TAG:
235 avp->is_tagged = true;
236 break;
237 case PAA_UNTAG:
238 avp->is_tagged = false;
239 break;
240 case PAA_VISIBLE:
241 avp->is_visible = true;
242 vcounter++;
243 break;
244 }
245 }
246 else
247 {
248 switch (action)
249 {
250 case PAA_TAG:
251 case PAA_UNTAG:
252 // Do nothing
253 break;
254 case PAA_VISIBLE:
255 avp->is_visible = false;
256 break;
257 }
258 }
259 }
260 progress_free(&progress);
261
262 FREE(&mdata->limit);
263 if (!match_all)
264 {
265 mdata->limit = simple;
266 simple = NULL;
267 }
268
269 if (menu && (action == PAA_VISIBLE))
270 {
271 menu->max = vcounter;
272 menu_set_index(menu, 0);
273 }
274
276
277 rc = 0;
278
279bail:
280 buf_pool_release(&buf);
281 FREE(&simple);
282 mutt_pattern_free(&pat);
283
284 return rc;
285}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#define ARRAY_SIZE(head)
The number of elements stored.
Definition array.h:87
MenuRedrawFlags menu_set_index(struct Menu *menu, int index)
Set the current selection in the Menu.
Definition menu.c:169
bool mutt_pattern_alias_exec(struct Pattern *pat, PatternExecFlags flags, struct AliasView *av, struct PatternCache *cache)
Match a pattern against an alias.
Definition exec.c:1178
#define MUTT_ALIAS_SIMPLESEARCH
Simple search pattern for aliases (from/to/cc fields)
Definition lib.h:64
char * limit
Limit being used.
Definition gui.h:61
struct AliasViewArray ava
All Aliases/Queries.
Definition gui.h:56
GUI data wrapping an Alias.
Definition gui.h:38
bool is_visible
Is visible?
Definition gui.h:45
bool is_tagged
Is it tagged?
Definition gui.h:43
int max
Number of entries in the menu.
Definition lib.h:88
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_search_command()

int mutt_search_command ( struct MailboxView * mv,
struct Menu * menu,
int cur,
struct SearchState * state,
SearchFlags flags )

Perform a search.

Parameters
mvMailbox view to search through
menuCurrent Menu
curIndex number of current email
stateCurrent search state
flagsSearch flags, e.g. SEARCH_PROMPT
Return values
>=0Index of matching email
-1No match, or error

Definition at line 462 of file pattern.c.

464{
465 struct Progress *progress = NULL;
466 int rc = -1;
467 struct Mailbox *m = mv ? mv->mailbox : NULL;
468 if (!m)
469 return -1;
470 bool pattern_changed = false;
471
472 if (buf_is_empty(state->string) || (flags & SEARCH_PROMPT))
473 {
474 if ((mw_get_field((state->reverse) ? _("Reverse search for: ") : _("Search for: "),
476 &CompletePatternOps, NULL) != 0) ||
477 buf_is_empty(state->string))
478 {
479 goto done;
480 }
481
482 /* compare the *expanded* version of the search pattern in case
483 * $simple_search has changed while we were searching */
484 struct Buffer *tmp = buf_pool_get();
485 buf_copy(tmp, state->string);
486 const char *const c_simple_search = cs_subset_string(NeoMutt->sub, "simple_search");
487 mutt_check_simple(tmp, NONULL(c_simple_search));
488 if (!buf_str_equal(tmp, state->string_expn))
489 {
490 mutt_pattern_free(&state->pattern);
491 buf_copy(state->string_expn, tmp);
492 buf_pool_release(&tmp);
493 }
494 }
495
496 if (!state->pattern)
497 {
498 mutt_message(_("Compiling search pattern..."));
499 mutt_pattern_free(&state->pattern);
500 struct Buffer *err = buf_pool_get();
501 state->pattern = mutt_pattern_comp(mv, state->string_expn->data, MUTT_PC_FULL_MSG, err);
502 pattern_changed = true;
503 if (!state->pattern)
504 {
505 mutt_error("%s", buf_string(err));
506 buf_free(&err);
507 buf_reset(state->string);
508 buf_reset(state->string_expn);
509 return -1;
510 }
511 buf_free(&err);
513 }
514
515 if (pattern_changed)
516 {
517 for (int i = 0; i < m->msg_count; i++)
518 m->emails[i]->searched = false;
519 if ((m->type == MUTT_IMAP) && (!imap_search(m, state->pattern)))
520 return -1;
521 }
522
523 int incr = state->reverse ? -1 : 1;
524 if (flags & SEARCH_OPPOSITE)
525 incr = -incr;
526
527 progress = progress_new(MUTT_PROGRESS_READ, m->vcount);
528 progress_set_message(progress, _("Searching..."));
529
530 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
531 for (int i = cur + incr, j = 0; j != m->vcount; j++)
532 {
533 const char *msg = NULL;
534 progress_update(progress, j, -1);
535 if (i > m->vcount - 1)
536 {
537 i = 0;
538 if (c_wrap_search)
539 {
540 msg = _("Search wrapped to top");
541 }
542 else
543 {
544 mutt_message(_("Search hit bottom without finding match"));
545 goto done;
546 }
547 }
548 else if (i < 0)
549 {
550 i = m->vcount - 1;
551 if (c_wrap_search)
552 {
553 msg = _("Search wrapped to bottom");
554 }
555 else
556 {
557 mutt_message(_("Search hit top without finding match"));
558 goto done;
559 }
560 }
561
562 struct Email *e = mutt_get_virt_email(m, i);
563 if (!e)
564 goto done;
565
566 if (e->searched)
567 {
568 /* if we've already evaluated this message, use the cached value */
569 if (e->matched)
570 {
572 if (msg && *msg)
573 mutt_message("%s", msg);
574 rc = i;
575 goto done;
576 }
577 }
578 else
579 {
580 /* remember that we've already searched this message */
581 e->searched = true;
583 MUTT_MATCH_FULL_ADDRESS, m, e, NULL);
584 if (e->matched)
585 {
587 if (msg && *msg)
588 mutt_message("%s", msg);
589 rc = i;
590 goto done;
591 }
592 }
593
594 if (SigInt)
595 {
596 mutt_error(_("Search interrupted"));
597 SigInt = false;
598 goto done;
599 }
600
601 i += incr;
602 }
603
604 mutt_error(_("Not found"));
605done:
606 progress_free(&progress);
607 return rc;
608}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
void buf_free(struct Buffer **ptr)
Deallocates a buffer.
Definition buffer.c:319
bool buf_str_equal(const struct Buffer *a, const struct Buffer *b)
Return if two buffers are equal.
Definition buffer.c:683
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition buffer.c:601
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
@ SEARCH_PROMPT
Ask for search input.
@ SEARCH_OPPOSITE
Search in the opposite direction.
bool searched
Email has been searched.
Definition email.h:105
bool matched
Search matches this Email.
Definition email.h:102
struct Buffer * string
search string
struct Buffer * string_expn
expanded search string
bool reverse
search backwards
struct PatternList * pattern
compiled search pattern
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_search_alias_command()

int mutt_search_alias_command ( struct Menu * menu,
int cur,
struct SearchState * state,
SearchFlags flags )

Perform a search.

Parameters
menuMenu to search through
curIndex number of current email
stateCurrent search state
flagsSearch flags, e.g. SEARCH_PROMPT
Return values
>=0Index of matching alias
-1No match, or error

Definition at line 619 of file pattern.c.

621{
622 struct Progress *progress = NULL;
623 const struct AliasMenuData *mdata = menu->mdata;
624 const struct AliasViewArray *ava = &mdata->ava;
625 int rc = -1;
626 bool pattern_changed = false;
627
628 if (buf_is_empty(state->string) || flags & SEARCH_PROMPT)
629 {
630 if ((mw_get_field(state->reverse ? _("Reverse search for: ") : _("Search for: "),
632 &CompletePatternOps, NULL) != 0) ||
633 buf_is_empty(state->string))
634 {
635 goto done;
636 }
637
638 /* compare the *expanded* version of the search pattern in case
639 * $simple_search has changed while we were searching */
640 struct Buffer *tmp = buf_pool_get();
641 buf_copy(tmp, state->string);
643 if (!buf_str_equal(tmp, state->string_expn))
644 {
645 mutt_pattern_free(&state->pattern);
646 buf_copy(state->string_expn, tmp);
647 buf_pool_release(&tmp);
648 }
649 }
650
651 if (!state->pattern)
652 {
653 mutt_message(_("Compiling search pattern..."));
654 struct Buffer *err = buf_pool_get();
655 state->pattern = mutt_pattern_comp(NULL, state->string_expn->data, MUTT_PC_FULL_MSG, err);
656 pattern_changed = true;
657 if (!state->pattern)
658 {
659 mutt_error("%s", buf_string(err));
660 buf_free(&err);
661 buf_reset(state->string);
662 buf_reset(state->string_expn);
663 return -1;
664 }
665 buf_free(&err);
667 }
668
669 if (pattern_changed)
670 {
671 struct AliasView *av = NULL;
672 ARRAY_FOREACH(av, ava)
673 {
674 av->is_searched = false;
675 }
676 }
677
678 int incr = state->reverse ? -1 : 1;
679 if (flags & SEARCH_OPPOSITE)
680 incr = -incr;
681
683 progress_set_message(progress, _("Searching..."));
684
685 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
686 for (int i = cur + incr, j = 0; j != ARRAY_SIZE(ava); j++)
687 {
688 const char *msg = NULL;
689 progress_update(progress, j, -1);
690 if (i > ARRAY_SIZE(ava) - 1)
691 {
692 i = 0;
693 if (c_wrap_search)
694 {
695 msg = _("Search wrapped to top");
696 }
697 else
698 {
699 mutt_message(_("Search hit bottom without finding match"));
700 goto done;
701 }
702 }
703 else if (i < 0)
704 {
705 i = ARRAY_SIZE(ava) - 1;
706 if (c_wrap_search)
707 {
708 msg = _("Search wrapped to bottom");
709 }
710 else
711 {
712 mutt_message(_("Search hit top without finding match"));
713 goto done;
714 }
715 }
716
717 struct AliasView *av = ARRAY_GET(ava, i);
718 if (av->is_searched)
719 {
720 /* if we've already evaluated this message, use the cached value */
721 if (av->is_matched)
722 {
724 if (msg && *msg)
725 mutt_message("%s", msg);
726 rc = i;
727 goto done;
728 }
729 }
730 else
731 {
732 /* remember that we've already searched this message */
733 av->is_searched = true;
735 MUTT_MATCH_FULL_ADDRESS, av, NULL);
736 if (av->is_matched)
737 {
739 if (msg && *msg)
740 mutt_message("%s", msg);
741 rc = i;
742 goto done;
743 }
744 }
745
746 if (SigInt)
747 {
748 mutt_error(_("Search interrupted"));
749 SigInt = false;
750 goto done;
751 }
752
753 i += incr;
754 }
755
756 mutt_error(_("Not found"));
757done:
758 progress_free(&progress);
759 return rc;
760}
#define ARRAY_GET(head, idx)
Return the element at index.
Definition array.h:109
AliasView array wrapper with Pattern information -.
Definition gui.h:55
struct Menu * menu
Menu.
Definition gui.h:59
bool is_matched
Search matches this Alias.
Definition gui.h:42
bool is_searched
Alias has been searched.
Definition gui.h:41
void * mdata
Private data.
Definition lib.h:155
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ CompletePatternOps

const struct CompleteOps CompletePatternOps
extern

Auto-Completion of Patterns.

Definition at line 98 of file complete.c.

98 {
99 .complete = complete_pattern,
100};
static enum FunctionRetval complete_pattern(struct EnterWindowData *wdata, int op)
Complete a NeoMutt Pattern - Implements CompleteOps::complete() -.
Definition complete.c:53