NeoMutt  2025-12-11-596-g7cc1dd
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)
 
#define MUTT_PC_NO_FLAGS   0
 No flags are set.
 
#define MUTT_PC_FULL_MSG   (1 << 0)
 Enable body and header matching.
 
#define MUTT_PC_PATTERN_DYNAMIC   (1 << 1)
 Enable runtime date range evaluation.
 
#define MUTT_PC_SEND_MODE_SEARCH   (1 << 2)
 Allow send-mode body searching.
 
#define MUTT_PAT_EXEC_NO_FLAGS   0
 No flags are set.
 
#define MUTT_MATCH_FULL_ADDRESS   (1 << 0)
 Match the full address.
 

Typedefs

typedef uint8_t PatternCompFlags
 Flags for mutt_pattern_comp(), e.g. MUTT_PC_FULL_MSG.
 
typedef uint8_t PatternExecFlags
 Flags for mutt_pattern_exec(), e.g. MUTT_MATCH_FULL_ADDRESS.
 

Enumerations

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.

◆ MUTT_PC_NO_FLAGS

#define MUTT_PC_NO_FLAGS   0

No flags are set.

Definition at line 69 of file lib.h.

◆ MUTT_PC_FULL_MSG

#define MUTT_PC_FULL_MSG   (1 << 0)

Enable body and header matching.

Definition at line 70 of file lib.h.

◆ MUTT_PC_PATTERN_DYNAMIC

#define MUTT_PC_PATTERN_DYNAMIC   (1 << 1)

Enable runtime date range evaluation.

Definition at line 71 of file lib.h.

◆ MUTT_PC_SEND_MODE_SEARCH

#define MUTT_PC_SEND_MODE_SEARCH   (1 << 2)

Allow send-mode body searching.

Definition at line 72 of file lib.h.

◆ MUTT_PAT_EXEC_NO_FLAGS

#define MUTT_PAT_EXEC_NO_FLAGS   0

No flags are set.

Definition at line 106 of file lib.h.

◆ MUTT_MATCH_FULL_ADDRESS

#define MUTT_MATCH_FULL_ADDRESS   (1 << 0)

Match the full address.

Definition at line 107 of file lib.h.

Typedef Documentation

◆ PatternCompFlags

typedef uint8_t PatternCompFlags

Flags for mutt_pattern_comp(), e.g. MUTT_PC_FULL_MSG.

Definition at line 68 of file lib.h.

◆ PatternExecFlags

typedef uint8_t PatternExecFlags

Flags for mutt_pattern_exec(), e.g. MUTT_MATCH_FULL_ADDRESS.

Definition at line 105 of file lib.h.

Enumeration Type Documentation

◆ 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 136 of file lib.h.

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

◆ 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 187 of file lib.h.

188{
189 PAA_TAG,
190 PAA_UNTAG,
192};
@ PAA_VISIBLE
Set AliasView.is_visible and hide the rest.
Definition lib.h:191
@ PAA_TAG
Set AliasView.is_tagged, but don't touch the others.
Definition lib.h:189
@ PAA_UNTAG
Unset AliasView.is_tagged, but don't touch the others.
Definition lib.h:190

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
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition lib.h:107
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:91
short op
Operation, e.g. MUTT_PAT_SCORE.
Definition lib.h:79
bool pat_not
Pattern should be inverted (not)
Definition lib.h:80
+ 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 954 of file compile.c.

956{
957 /* curlist when assigned will always point to a list containing at least one node
958 * with a Pattern value. */
959 struct PatternList *curlist = NULL;
960 bool pat_not = false;
961 bool all_addr = false;
962 bool pat_or = false;
963 bool implicit = true; /* used to detect logical AND operator */
964 bool is_alias = false;
965 const struct PatternFlags *entry = NULL;
966 char *p = NULL;
967 char *buf = NULL;
968 struct Mailbox *m = mv ? mv->mailbox : NULL;
969
970 if (!s || (s[0] == '\0'))
971 {
972 buf_strcpy(err, _("empty pattern"));
973 return NULL;
974 }
975
976 struct Buffer *ps = buf_pool_get();
977 buf_strcpy(ps, s);
978 buf_seek(ps, 0);
979
980 SKIPWS(ps->dptr);
981 while (*ps->dptr)
982 {
983 switch (*ps->dptr)
984 {
985 case '^':
986 ps->dptr++;
987 all_addr = !all_addr;
988 break;
989 case '!':
990 ps->dptr++;
991 pat_not = !pat_not;
992 break;
993 case '@':
994 ps->dptr++;
995 is_alias = !is_alias;
996 break;
997 case '|':
998 if (!pat_or)
999 {
1000 if (!curlist)
1001 {
1002 buf_printf(err, _("error in pattern at: %s"), ps->dptr);
1003 buf_pool_release(&ps);
1004 return NULL;
1005 }
1006
1007 struct Pattern *pat = SLIST_FIRST(curlist);
1008 if (SLIST_NEXT(pat, entries))
1009 {
1010 /* A & B | C == (A & B) | C */
1011 struct Pattern *root = attach_new_root(&curlist);
1012 root->op = MUTT_PAT_AND;
1013 }
1014
1015 pat_or = true;
1016 }
1017 ps->dptr++;
1018 implicit = false;
1019 pat_not = false;
1020 all_addr = false;
1021 is_alias = false;
1022 break;
1023 case '%':
1024 case '=':
1025 case '~':
1026 {
1027 if (ps->dptr[1] == '\0')
1028 {
1029 buf_printf(err, _("missing pattern: %s"), ps->dptr);
1030 goto cleanup;
1031 }
1032 short thread_op = 0;
1033 if (ps->dptr[1] == '(')
1034 thread_op = MUTT_PAT_THREAD;
1035 else if ((ps->dptr[1] == '<') && (ps->dptr[2] == '('))
1036 thread_op = MUTT_PAT_PARENT;
1037 else if ((ps->dptr[1] == '>') && (ps->dptr[2] == '('))
1038 thread_op = MUTT_PAT_CHILDREN;
1039 if (thread_op != 0)
1040 {
1041 ps->dptr++; /* skip ~ */
1042 if ((thread_op == MUTT_PAT_PARENT) || (thread_op == MUTT_PAT_CHILDREN))
1043 ps->dptr++;
1044 p = find_matching_paren(ps->dptr + 1);
1045 if (p[0] != ')')
1046 {
1047 buf_printf(err, _("mismatched parentheses: %s"), ps->dptr);
1048 goto cleanup;
1049 }
1050 struct Pattern *leaf = attach_new_leaf(&curlist);
1051 leaf->op = thread_op;
1052 leaf->pat_not = pat_not;
1053 leaf->all_addr = all_addr;
1054 leaf->is_alias = is_alias;
1055 pat_not = false;
1056 all_addr = false;
1057 is_alias = false;
1058 /* compile the sub-expression */
1059 buf = mutt_strn_dup(ps->dptr + 1, p - (ps->dptr + 1));
1060 leaf->child = mutt_pattern_comp(mv, buf, flags, err);
1061 if (!leaf->child)
1062 {
1063 FREE(&buf);
1064 goto cleanup;
1065 }
1066 FREE(&buf);
1067 ps->dptr = p + 1; /* restore location */
1068 break;
1069 }
1070 if (implicit && pat_or)
1071 {
1072 /* A | B & C == (A | B) & C */
1073 struct Pattern *root = attach_new_root(&curlist);
1074 root->op = MUTT_PAT_OR;
1075 pat_or = false;
1076 }
1077
1078 char prefix = ps->dptr[0];
1079 entry = lookup_tag(prefix, ps->dptr[1]);
1080 if (!entry)
1081 {
1082 buf_printf(err, _("%c%c: invalid pattern"), prefix, ps->dptr[1]);
1083 goto cleanup;
1084 }
1085 if (entry->flags && ((flags & entry->flags) == 0))
1086 {
1087 buf_printf(err, _("%c%c: not supported in this mode"), prefix, ps->dptr[1]);
1088 goto cleanup;
1089 }
1090
1091 struct Pattern *leaf = attach_new_leaf(&curlist);
1092 leaf->pat_not = pat_not;
1093 leaf->all_addr = all_addr;
1094 leaf->is_alias = is_alias;
1095 leaf->sendmode = (flags & MUTT_PC_SEND_MODE_SEARCH);
1096 leaf->op = entry->op;
1097 pat_not = false;
1098 all_addr = false;
1099 is_alias = false;
1100
1101 // Determine the actual eat_arg to use.
1102 // If the entry was found via fallback (entry->prefix is '~' but we used '=' or '%'),
1103 // override the eat_arg to use string or group parsing respectively.
1104 enum PatternEat eat_arg = entry->eat_arg;
1105 if ((entry->prefix == '~') && (prefix == '=') && (eat_arg == EAT_REGEX))
1106 eat_arg = EAT_STRING;
1107 else if ((entry->prefix == '~') && (prefix == '%') && (eat_arg == EAT_REGEX))
1108 eat_arg = EAT_GROUP;
1109
1110 ps->dptr++; /* move past the prefix (~, %, =) */
1111 ps->dptr++; /* eat the operator and any optional whitespace */
1112 SKIPWS(ps->dptr);
1113 if (eat_arg)
1114 {
1115 if (ps->dptr[0] == '\0')
1116 {
1117 buf_addstr(err, _("missing parameter"));
1118 goto cleanup;
1119 }
1120 switch (eat_arg)
1121 {
1122 case EAT_REGEX:
1123 if (!eat_regex(leaf, flags, ps, err))
1124 goto cleanup;
1125 break;
1126 case EAT_STRING:
1127 if (!eat_string(leaf, flags, ps, err))
1128 goto cleanup;
1129 break;
1130 case EAT_GROUP:
1131 if (!eat_group(leaf, flags, ps, err))
1132 goto cleanup;
1133 break;
1134 case EAT_DATE:
1135 if (!eat_date(leaf, flags, ps, err))
1136 goto cleanup;
1137 break;
1138 case EAT_RANGE:
1139 if (!eat_range(leaf, flags, ps, err))
1140 goto cleanup;
1141 break;
1142 case EAT_MESSAGE_RANGE:
1143 if (!eat_message_range(leaf, flags, ps, err, mv))
1144 goto cleanup;
1145 break;
1146 case EAT_QUERY:
1147 if (!eat_query(leaf, flags, ps, err, m))
1148 goto cleanup;
1149 break;
1150 default:
1151 break;
1152 }
1153 }
1154 implicit = true;
1155 break;
1156 }
1157
1158 case '(':
1159 {
1160 p = find_matching_paren(ps->dptr + 1);
1161 if (p[0] != ')')
1162 {
1163 buf_printf(err, _("mismatched parentheses: %s"), ps->dptr);
1164 goto cleanup;
1165 }
1166 /* compile the sub-expression */
1167 buf = mutt_strn_dup(ps->dptr + 1, p - (ps->dptr + 1));
1168 struct PatternList *sub = mutt_pattern_comp(mv, buf, flags, err);
1169 FREE(&buf);
1170 if (!sub)
1171 goto cleanup;
1172 struct Pattern *leaf = SLIST_FIRST(sub);
1173 if (curlist)
1174 {
1175 attach_leaf(curlist, leaf);
1176 FREE(&sub);
1177 }
1178 else
1179 {
1180 curlist = sub;
1181 }
1182 leaf->pat_not ^= pat_not;
1183 leaf->all_addr |= all_addr;
1184 leaf->is_alias |= is_alias;
1185 pat_not = false;
1186 all_addr = false;
1187 is_alias = false;
1188 ps->dptr = p + 1; /* restore location */
1189 break;
1190 }
1191
1192 default:
1193 buf_printf(err, _("error in pattern at: %s"), ps->dptr);
1194 goto cleanup;
1195 }
1196 SKIPWS(ps->dptr);
1197 }
1198 buf_pool_release(&ps);
1199
1200 if (!curlist)
1201 {
1202 buf_strcpy(err, _("empty pattern"));
1203 return NULL;
1204 }
1205
1206 if (SLIST_NEXT(SLIST_FIRST(curlist), entries))
1207 {
1208 struct Pattern *root = attach_new_root(&curlist);
1209 root->op = pat_or ? MUTT_PAT_OR : MUTT_PAT_AND;
1210 }
1211
1212 return curlist;
1213
1214cleanup:
1215 mutt_pattern_free(&curlist);
1216 buf_pool_release(&ps);
1217 return NULL;
1218}
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:918
static struct Pattern * attach_new_leaf(struct PatternList **curlist)
Attach a new Pattern to a List.
Definition compile.c:934
struct PatternList * mutt_pattern_comp(struct MailboxView *mv, const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition compile.c:954
static struct Pattern * attach_leaf(struct PatternList *list, struct Pattern *leaf)
Attach a Pattern to a Pattern List.
Definition compile.c:896
static char * find_matching_paren(char *s)
Find the matching parenthesis.
Definition compile.c:802
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition compile.c:826
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:140
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:108
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:192
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:281
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:672
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:763
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:65
#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
#define MUTT_PC_SEND_MODE_SEARCH
Allow send-mode body searching.
Definition lib.h:72
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:78
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:78
union Pattern::@006112053024257132210207314205210350156165326341 p
bool all_addr
All Addresses in the list must match.
Definition lib.h:81
bool is_alias
Is there an alias for this Address?
Definition lib.h:85
bool sendmode
Evaluate searches in send-mode.
Definition lib.h:87
+ 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 107 of file pattern.c.

108{
109 bool do_simple = true;
110
111 for (const char *p = buf_string(buf); p && (p[0] != '\0'); p++)
112 {
113 if ((p[0] == '\\') && (p[1] != '\0'))
114 {
115 p++;
116 }
117 else if ((p[0] == '~') || (p[0] == '=') || (p[0] == '%'))
118 {
119 do_simple = false;
120 break;
121 }
122 }
123
124 /* XXX - is mutt_istr_cmp() right here, or should we use locale's
125 * equivalences? */
126
127 if (do_simple) /* yup, so spoof a real request */
128 {
129 /* convert old tokens into the new format */
130 if (mutt_istr_equal("all", buf_string(buf)) || mutt_str_equal("^", buf_string(buf)) ||
131 mutt_str_equal(".", buf_string(buf))) /* ~A is more efficient */
132 {
133 buf_strcpy(buf, "~A");
134 }
135 else if (mutt_istr_equal("del", buf_string(buf)))
136 {
137 buf_strcpy(buf, "~D");
138 }
139 else if (mutt_istr_equal("flag", buf_string(buf)))
140 {
141 buf_strcpy(buf, "~F");
142 }
143 else if (mutt_istr_equal("new", buf_string(buf)))
144 {
145 buf_strcpy(buf, "~N");
146 }
147 else if (mutt_istr_equal("old", buf_string(buf)))
148 {
149 buf_strcpy(buf, "~O");
150 }
151 else if (mutt_istr_equal("repl", buf_string(buf)))
152 {
153 buf_strcpy(buf, "~Q");
154 }
155 else if (mutt_istr_equal("read", buf_string(buf)))
156 {
157 buf_strcpy(buf, "~R");
158 }
159 else if (mutt_istr_equal("tag", buf_string(buf)))
160 {
161 buf_strcpy(buf, "~T");
162 }
163 else if (mutt_istr_equal("unread", buf_string(buf)))
164 {
165 buf_strcpy(buf, "~U");
166 }
167 else
168 {
169 struct Buffer *tmp = buf_pool_get();
170 quote_simple(buf_string(buf), tmp);
171 mutt_file_expand_fmt(buf, simple, buf_string(tmp));
172 buf_pool_release(&tmp);
173 }
174 }
175}
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:1361
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:89
+ 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 826 of file compile.c.

827{
828 if (!pat || !*pat)
829 return;
830
831 struct Pattern *np = SLIST_FIRST(*pat);
832 struct Pattern *next = NULL;
833
834 while (np)
835 {
836 next = SLIST_NEXT(np, entries);
837
838 if (np->is_multi)
839 {
841 }
842 else if (np->string_match || np->dynamic)
843 {
844 FREE(&np->p.str);
845 }
846 else if (np->group_match)
847 {
848 np->p.group = NULL;
849 }
850 else if (np->p.regex)
851 {
852 regfree(np->p.regex);
853 FREE(&np->p.regex);
854 }
855
856#ifdef USE_DEBUG_GRAPHVIZ
857 FREE(&np->raw_pattern);
858#endif
860 FREE(&np);
861
862 np = next;
863 }
864
865 FREE(pat);
866}
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:83
struct Group * group
Address group if group_match is set.
Definition lib.h:94
bool string_match
Check a string for a match.
Definition lib.h:82
regex_t * regex
Compiled regex, for non-pattern matching.
Definition lib.h:93
struct ListHead multi_cases
Multiple strings for ~I pattern.
Definition lib.h:96
char * str
String, if string_match is set.
Definition lib.h:95
bool dynamic
Evaluate date ranges at run time.
Definition lib.h:86
bool is_multi
Multiple case (only for ~I pattern now)
Definition lib.h:88
+ 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:45
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:60
+ 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 311 of file pattern.c.

312{
313 if (!mv || !mv->mailbox)
314 return -1;
315
316 struct Mailbox *m = mv->mailbox;
317
318 struct Buffer *err = NULL;
319 int rc = -1;
320 struct Progress *progress = NULL;
321 struct Buffer *buf = buf_pool_get();
322 bool interrupted = false;
323
324 buf_strcpy(buf, mv->pattern);
325 if (prompt || (op != MUTT_LIMIT))
326 {
327 if ((mw_get_field(prompt, buf, MUTT_COMP_CLEAR, HC_PATTERN, &CompletePatternOps, NULL) != 0) ||
328 buf_is_empty(buf))
329 {
330 buf_pool_release(&buf);
331 return -1;
332 }
333 }
334
335 mutt_message(_("Compiling search pattern..."));
336
337 char *simple = buf_strdup(buf);
338 const char *const c_simple_search = cs_subset_string(NeoMutt->sub, "simple_search");
339 mutt_check_simple(buf, NONULL(c_simple_search));
340 const char *pbuf = buf->data;
341 while (*pbuf == ' ')
342 pbuf++;
343 const bool match_all = mutt_str_equal(pbuf, "~A");
344
345 err = buf_pool_get();
346 struct PatternList *pat = mutt_pattern_comp(mv, buf->data, MUTT_PC_FULL_MSG, err);
347 if (!pat)
348 {
349 mutt_error("%s", buf_string(err));
350 goto bail;
351 }
352
353 if ((m->type == MUTT_IMAP) && (!imap_search(m, pat)))
354 goto bail;
355
356 progress = progress_new(MUTT_PROGRESS_READ, (op == MUTT_LIMIT) ? m->msg_count : m->vcount);
357 progress_set_message(progress, _("Executing command on matching messages..."));
358
359 if (op == MUTT_LIMIT)
360 {
361 m->vcount = 0;
362 mv->vsize = 0;
363 mv->collapsed = false;
364 int padding = mx_msg_padding_size(m);
365
366 for (int i = 0; i < m->msg_count; i++)
367 {
368 struct Email *e = m->emails[i];
369 if (!e)
370 break;
371
372 if (SigInt)
373 {
374 interrupted = true;
375 SigInt = false;
376 break;
377 }
378 progress_update(progress, i, -1);
379 /* new limit pattern implicitly uncollapses all threads */
380 e->vnum = -1;
381 e->visible = false;
382 e->limit_visited = true;
383 e->collapsed = false;
384 e->num_hidden = 0;
385
386 if (match_all ||
388 {
389 e->vnum = m->vcount;
390 e->visible = true;
391 m->v2r[m->vcount] = i;
392 m->vcount++;
393 struct Body *b = e->body;
394 mv->vsize += b->length + b->offset - b->hdr_offset + padding;
395 }
396 }
397 }
398 else
399 {
400 for (int i = 0; i < m->vcount; i++)
401 {
402 struct Email *e = mutt_get_virt_email(m, i);
403 if (!e)
404 continue;
405
406 if (SigInt)
407 {
408 interrupted = true;
409 SigInt = false;
410 break;
411 }
412 progress_update(progress, i, -1);
414 {
415 switch (op)
416 {
417 case MUTT_UNDELETE:
418 mutt_set_flag(m, e, MUTT_PURGE, false, true);
420
421 case MUTT_DELETE:
422 mutt_set_flag(m, e, MUTT_DELETE, (op == MUTT_DELETE), true);
423 break;
424 case MUTT_TAG:
425 case MUTT_UNTAG:
426 mutt_set_flag(m, e, MUTT_TAG, (op == MUTT_TAG), true);
427 break;
428 }
429 }
430 }
431 }
432 progress_free(&progress);
433
435
436 if (op == MUTT_LIMIT)
437 {
438 /* drop previous limit pattern */
439 FREE(&mv->pattern);
441
442 if (m->msg_count && !m->vcount)
443 mutt_error(_("No messages matched criteria"));
444
445 /* record new limit pattern, unless match all */
446 if (!match_all)
447 {
448 mv->pattern = simple;
449 simple = NULL; /* don't clobber it */
451 }
452 }
453
454 if (interrupted)
455 mutt_error(_("Search interrupted"));
456
457 rc = 0;
458
459bail:
460 buf_pool_release(&buf);
461 buf_pool_release(&err);
462 FREE(&simple);
463 mutt_pattern_free(&pat);
464
465 return rc;
466}
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
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition wdata.h:43
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:463
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
@ HC_PATTERN
Patterns.
Definition lib.h:59
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:415
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
#define MUTT_PC_FULL_MSG
Enable body and header matching.
Definition lib.h:70
void mutt_check_simple(struct Buffer *buf, const char *simple)
Convert a simple search into a real request.
Definition pattern.c:107
@ 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:98
int * v2r
Mapping from virtual to real msgno.
Definition mailbox.h:97
int msg_count
Total number of messages.
Definition mailbox.h:87
enum MailboxType type
Mailbox type.
Definition mailbox.h:101
struct Email ** emails
Array of Emails.
Definition mailbox.h:95
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 186 of file pattern.c.

188{
189 int rc = -1;
190 struct Progress *progress = NULL;
191 struct Buffer *buf = buf_pool_get();
192
193 buf_strcpy(buf, mdata->limit);
194 if (prompt)
195 {
196 if ((mw_get_field(prompt, buf, MUTT_COMP_CLEAR, HC_PATTERN, &CompletePatternOps, NULL) != 0) ||
197 buf_is_empty(buf))
198 {
199 buf_pool_release(&buf);
200 return -1;
201 }
202 }
203
204 mutt_message(_("Compiling search pattern..."));
205
206 /* Compile the pattern string; "~A" means match-all. If the simple string
207 * was expanded into a pattern, compile it for evaluation. */
208 bool match_all = false;
209 struct PatternList *pat = NULL;
210 char *simple = buf_strdup(buf);
211 if (simple)
212 {
214 const char *pbuf = buf->data;
215 while (*pbuf == ' ')
216 pbuf++;
217 match_all = mutt_str_equal(pbuf, "~A");
218
219 struct Buffer *err = buf_pool_get();
220 pat = mutt_pattern_comp(NULL, buf->data, MUTT_PC_FULL_MSG, err);
221 if (!pat)
222 {
223 mutt_error("%s", buf_string(err));
224 buf_pool_release(&err);
225 goto bail;
226 }
227 buf_pool_release(&err);
228 }
229 else
230 {
231 match_all = true;
232 }
233
234 progress = progress_new(MUTT_PROGRESS_READ, ARRAY_SIZE(&mdata->ava));
235 progress_set_message(progress, _("Executing command on matching messages..."));
236
237 /* Apply the action (tag, untag, or filter visibility) to each alias
238 * that matches the compiled pattern */
239 int vcounter = 0;
240 struct AliasView *avp = NULL;
241 ARRAY_FOREACH(avp, &mdata->ava)
242 {
243 progress_update(progress, ARRAY_FOREACH_IDX_avp, -1);
244
245 if (match_all ||
247 {
248 switch (action)
249 {
250 case PAA_TAG:
251 avp->is_tagged = true;
252 break;
253 case PAA_UNTAG:
254 avp->is_tagged = false;
255 break;
256 case PAA_VISIBLE:
257 avp->is_visible = true;
258 vcounter++;
259 break;
260 }
261 }
262 else
263 {
264 switch (action)
265 {
266 case PAA_TAG:
267 case PAA_UNTAG:
268 // Do nothing
269 break;
270 case PAA_VISIBLE:
271 avp->is_visible = false;
272 break;
273 }
274 }
275 }
276 progress_free(&progress);
277
278 FREE(&mdata->limit);
279 if (!match_all)
280 {
281 mdata->limit = simple;
282 simple = NULL;
283 }
284
285 if (menu && (action == PAA_VISIBLE))
286 {
287 menu->max = vcounter;
288 menu_set_index(menu, 0);
289 }
290
292
293 rc = 0;
294
295bail:
296 buf_pool_release(&buf);
297 FREE(&simple);
298 mutt_pattern_free(&pat);
299
300 return rc;
301}
#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:178
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:60
struct AliasViewArray ava
All Aliases/Queries.
Definition gui.h:55
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:82
+ 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 478 of file pattern.c.

480{
481 struct Progress *progress = NULL;
482 int rc = -1;
483 struct Mailbox *m = mv ? mv->mailbox : NULL;
484 if (!m)
485 return -1;
486 bool pattern_changed = false;
487
488 if (buf_is_empty(state->string) || (flags & SEARCH_PROMPT))
489 {
490 if ((mw_get_field((state->reverse) ? _("Reverse search for: ") : _("Search for: "),
492 &CompletePatternOps, NULL) != 0) ||
493 buf_is_empty(state->string))
494 {
495 goto done;
496 }
497
498 /* compare the *expanded* version of the search pattern in case
499 * $simple_search has changed while we were searching */
500 struct Buffer *tmp = buf_pool_get();
501 buf_copy(tmp, state->string);
502 const char *const c_simple_search = cs_subset_string(NeoMutt->sub, "simple_search");
503 mutt_check_simple(tmp, NONULL(c_simple_search));
504 if (!buf_str_equal(tmp, state->string_expn))
505 {
506 mutt_pattern_free(&state->pattern);
507 buf_copy(state->string_expn, tmp);
508 buf_pool_release(&tmp);
509 }
510 }
511
512 if (!state->pattern)
513 {
514 mutt_message(_("Compiling search pattern..."));
515 mutt_pattern_free(&state->pattern);
516 struct Buffer *err = buf_pool_get();
517 state->pattern = mutt_pattern_comp(mv, state->string_expn->data, MUTT_PC_FULL_MSG, err);
518 pattern_changed = true;
519 if (!state->pattern)
520 {
521 mutt_error("%s", buf_string(err));
522 buf_free(&err);
523 buf_reset(state->string);
524 buf_reset(state->string_expn);
525 return -1;
526 }
527 buf_free(&err);
529 }
530
531 if (pattern_changed)
532 {
533 for (int i = 0; i < m->msg_count; i++)
534 m->emails[i]->searched = false;
535 if ((m->type == MUTT_IMAP) && (!imap_search(m, state->pattern)))
536 return -1;
537 }
538
539 int incr = state->reverse ? -1 : 1;
540 if (flags & SEARCH_OPPOSITE)
541 incr = -incr;
542
543 progress = progress_new(MUTT_PROGRESS_READ, m->vcount);
544 progress_set_message(progress, _("Searching..."));
545
546 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
547 for (int i = cur + incr, j = 0; j != m->vcount; j++)
548 {
549 const char *msg = NULL;
550 progress_update(progress, j, -1);
551 if (i > m->vcount - 1)
552 {
553 i = 0;
554 if (c_wrap_search)
555 {
556 msg = _("Search wrapped to top");
557 }
558 else
559 {
560 mutt_message(_("Search hit bottom without finding match"));
561 goto done;
562 }
563 }
564 else if (i < 0)
565 {
566 i = m->vcount - 1;
567 if (c_wrap_search)
568 {
569 msg = _("Search wrapped to bottom");
570 }
571 else
572 {
573 mutt_message(_("Search hit top without finding match"));
574 goto done;
575 }
576 }
577
578 struct Email *e = mutt_get_virt_email(m, i);
579 if (!e)
580 goto done;
581
582 if (e->searched)
583 {
584 /* if we've already evaluated this message, use the cached value */
585 if (e->matched)
586 {
588 if (msg && *msg)
589 mutt_message("%s", msg);
590 rc = i;
591 goto done;
592 }
593 }
594 else
595 {
596 /* remember that we've already searched this message */
597 e->searched = true;
599 MUTT_MATCH_FULL_ADDRESS, m, e, NULL);
600 if (e->matched)
601 {
603 if (msg && *msg)
604 mutt_message("%s", msg);
605 rc = i;
606 goto done;
607 }
608 }
609
610 if (SigInt)
611 {
612 mutt_error(_("Search interrupted"));
613 SigInt = false;
614 goto done;
615 }
616
617 i += incr;
618 }
619
620 mutt_error(_("Not found"));
621done:
622 progress_free(&progress);
623 return rc;
624}
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
#define SEARCH_OPPOSITE
Search in the opposite direction.
#define SEARCH_PROMPT
Ask for search input.
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 635 of file pattern.c.

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