NeoMutt  2023-03-22-27-g3cb248
Teaching an old dog new tricks
DOXYGEN
lib.h File Reference

Match patterns to emails. More...

#include "config.h"
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "mutt/lib.h"
#include "mutt.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"
 
#define MUTT_PC_NO_FLAGS   0
 No flags are set. More...
 
#define MUTT_PC_FULL_MSG   (1 << 0)
 Enable body and header matching. More...
 
#define MUTT_PC_PATTERN_DYNAMIC   (1 << 1)
 Enable runtime date range evaluation. More...
 
#define MUTT_PC_SEND_MODE_SEARCH   (1 << 2)
 Allow send-mode body searching. More...
 
#define MUTT_PAT_EXEC_NO_FLAGS   0
 No flags are set. More...
 
#define MUTT_MATCH_FULL_ADDRESS   (1 << 0)
 Match the full address. More...
 

Typedefs

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

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...
 

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. More...
 
bool mutt_pattern_alias_exec (struct Pattern *pat, PatternExecFlags flags, struct AliasView *av, struct PatternCache *cache)
 Match a pattern against an alias. More...
 
struct PatternList * mutt_pattern_comp (struct Mailbox *m, struct Menu *menu, const char *s, PatternCompFlags flags, struct Buffer *err)
 Create a Pattern. More...
 
void mutt_check_simple (struct Buffer *s, const char *simple)
 Convert a simple search into a real request. More...
 
void mutt_pattern_free (struct PatternList **pat)
 Free a Pattern. More...
 
bool dlg_select_pattern (char *buf, size_t buflen)
 Show menu to select a Pattern. More...
 
int mutt_which_case (const char *s)
 
bool mutt_is_list_recipient (bool all_addr, struct Envelope *env)
 Matches known mailing lists. More...
 
bool mutt_is_subscribed_list_recipient (bool all_addr, struct Envelope *env)
 Matches subscribed mailing lists. More...
 
int mutt_pattern_func (struct MailboxView *mv, int op, char *prompt)
 Perform some Pattern matching. More...
 
int mutt_pattern_alias_func (char *prompt, struct AliasMenuData *mdata, struct Menu *menu)
 Perform some Pattern matching for Alias. More...
 
int mutt_search_command (struct Mailbox *m, struct Menu *menu, int cur, int op)
 Perform a search. More...
 
int mutt_search_alias_command (struct Menu *menu, int cur, int op)
 Perform a search. More...
 
bool mutt_limit_current_thread (struct MailboxView *mv, struct Email *e)
 Limit the email view to the current thread. More...
 

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"

Definition at line 58 of file lib.h.

◆ MUTT_PC_NO_FLAGS

#define MUTT_PC_NO_FLAGS   0

No flags are set.

Definition at line 61 of file lib.h.

◆ MUTT_PC_FULL_MSG

#define MUTT_PC_FULL_MSG   (1 << 0)

Enable body and header matching.

Definition at line 62 of file lib.h.

◆ MUTT_PC_PATTERN_DYNAMIC

#define MUTT_PC_PATTERN_DYNAMIC   (1 << 1)

Enable runtime date range evaluation.

Definition at line 63 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 64 of file lib.h.

◆ MUTT_PAT_EXEC_NO_FLAGS

#define MUTT_PAT_EXEC_NO_FLAGS   0

No flags are set.

Definition at line 98 of file lib.h.

◆ MUTT_MATCH_FULL_ADDRESS

#define MUTT_MATCH_FULL_ADDRESS   (1 << 0)

Match the full address.

Definition at line 99 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 60 of file lib.h.

◆ PatternExecFlags

typedef uint8_t PatternExecFlags

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

Definition at line 97 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 128 of file lib.h.

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

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 1119 of file exec.c.

1121{
1122 const bool needs_msg = pattern_needs_msg(m, pat);
1123 struct Message *msg = needs_msg ? mx_msg_open(m, e->msgno) : NULL;
1124 if (needs_msg && !msg)
1125 {
1126 return false;
1127 }
1128 const bool matched = pattern_exec(pat, flags, m, e, msg, cache);
1129 mx_msg_close(m, &msg);
1130 return matched;
1131}
static bool pattern_needs_msg(const struct Mailbox *m, const struct Pattern *pat)
Check whether a pattern needs a full message.
Definition: exec.c:760
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:806
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1200
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
Return a stream pointer for a message.
Definition: mx.c:1154
int msgno
Number displayed to the user.
Definition: email.h:110
A local copy of an email.
Definition: mxapi.h:43
struct Message::@0 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 1146 of file exec.c.

1148{
1149 switch (pat->op)
1150 {
1151 case MUTT_PAT_FROM: /* alias */
1152 if (!av->alias)
1153 return false;
1154 return pat->pat_not ^ (av->alias->name && patmatch(pat, av->alias->name));
1155 case MUTT_PAT_CC: /* comment */
1156 if (!av->alias)
1157 return false;
1158 return pat->pat_not ^ (av->alias->comment && patmatch(pat, av->alias->comment));
1159 case MUTT_PAT_TO: /* alias address list */
1160 if (!av->alias)
1161 return false;
1162 return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
1163 1, &av->alias->addr);
1164 case MUTT_PAT_AND:
1165 return pat->pat_not ^ (perform_alias_and(pat->child, flags, av, cache) > 0);
1166 case MUTT_PAT_OR:
1167 return pat->pat_not ^ (perform_alias_or(pat->child, flags, av, cache) > 0);
1168 }
1169
1170 return false;
1171}
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:308
static int match_addrlist(struct Pattern *pat, bool match_personal, int n,...)
Match a Pattern against an Address list.
Definition: exec.c:382
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:357
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: lib.h:99
struct Alias * alias
Alias.
Definition: gui.h:44
char * comment
Free-form comment string.
Definition: alias.h:37
char * name
Short name.
Definition: alias.h:35
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
struct PatternList * child
Arguments to logical operation.
Definition: lib.h:83
short op
Operation, e.g. MUTT_PAT_SCORE.
Definition: lib.h:71
bool pat_not
Pattern should be inverted (not)
Definition: lib.h:72
+ 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 Mailbox m,
struct Menu menu,
const char *  s,
PatternCompFlags  flags,
struct Buffer err 
)

Create a Pattern.

Parameters
mMailbox
menuCurrent Menu
sPattern string
flagsFlags, e.g. MUTT_PC_FULL_MSG
errBuffer for error messages
Return values
ptrNewly allocated Pattern

Definition at line 1173 of file compile.c.

1175{
1176 /* curlist when assigned will always point to a list containing at least one node
1177 * with a Pattern value. */
1178 struct PatternList *curlist = NULL;
1179 bool pat_not = false;
1180 bool all_addr = false;
1181 bool pat_or = false;
1182 bool implicit = true; /* used to detect logical AND operator */
1183 bool is_alias = false;
1184 const struct PatternFlags *entry = NULL;
1185 char *p = NULL;
1186 char *buf = NULL;
1187 struct Buffer ps;
1188
1189 if (!s || (s[0] == '\0'))
1190 {
1191 mutt_buffer_strcpy(err, _("empty pattern"));
1192 return NULL;
1193 }
1194
1195 mutt_buffer_init(&ps);
1196 ps.dptr = (char *) s;
1197 ps.dsize = mutt_str_len(s);
1198
1199 while (*ps.dptr)
1200 {
1201 SKIPWS(ps.dptr);
1202 switch (*ps.dptr)
1203 {
1204 case '^':
1205 ps.dptr++;
1206 all_addr = !all_addr;
1207 break;
1208 case '!':
1209 ps.dptr++;
1210 pat_not = !pat_not;
1211 break;
1212 case '@':
1213 ps.dptr++;
1214 is_alias = !is_alias;
1215 break;
1216 case '|':
1217 if (!pat_or)
1218 {
1219 if (!curlist)
1220 {
1221 mutt_buffer_printf(err, _("error in pattern at: %s"), ps.dptr);
1222 return NULL;
1223 }
1224
1225 struct Pattern *pat = SLIST_FIRST(curlist);
1226 if (SLIST_NEXT(pat, entries))
1227 {
1228 /* A & B | C == (A & B) | C */
1229 struct Pattern *root = attach_new_root(&curlist);
1230 root->op = MUTT_PAT_AND;
1231 }
1232
1233 pat_or = true;
1234 }
1235 ps.dptr++;
1236 implicit = false;
1237 pat_not = false;
1238 all_addr = false;
1239 is_alias = false;
1240 break;
1241 case '%':
1242 case '=':
1243 case '~':
1244 {
1245 if (ps.dptr[1] == '\0')
1246 {
1247 mutt_buffer_printf(err, _("missing pattern: %s"), ps.dptr);
1248 goto cleanup;
1249 }
1250 short thread_op = 0;
1251 if (ps.dptr[1] == '(')
1252 thread_op = MUTT_PAT_THREAD;
1253 else if ((ps.dptr[1] == '<') && (ps.dptr[2] == '('))
1254 thread_op = MUTT_PAT_PARENT;
1255 else if ((ps.dptr[1] == '>') && (ps.dptr[2] == '('))
1256 thread_op = MUTT_PAT_CHILDREN;
1257 if (thread_op != 0)
1258 {
1259 ps.dptr++; /* skip ~ */
1260 if ((thread_op == MUTT_PAT_PARENT) || (thread_op == MUTT_PAT_CHILDREN))
1261 ps.dptr++;
1262 p = find_matching_paren(ps.dptr + 1);
1263 if (p[0] != ')')
1264 {
1265 mutt_buffer_printf(err, _("mismatched parentheses: %s"), ps.dptr);
1266 goto cleanup;
1267 }
1268 struct Pattern *leaf = attach_new_leaf(&curlist);
1269 leaf->op = thread_op;
1270 leaf->pat_not = pat_not;
1271 leaf->all_addr = all_addr;
1272 leaf->is_alias = is_alias;
1273 pat_not = false;
1274 all_addr = false;
1275 is_alias = false;
1276 /* compile the sub-expression */
1277 buf = mutt_strn_dup(ps.dptr + 1, p - (ps.dptr + 1));
1278 leaf->child = mutt_pattern_comp(m, menu, buf, flags, err);
1279 if (!leaf->child)
1280 {
1281 FREE(&buf);
1282 goto cleanup;
1283 }
1284 FREE(&buf);
1285 ps.dptr = p + 1; /* restore location */
1286 SKIPWS(ps.dptr);
1287 break;
1288 }
1289 if (implicit && pat_or)
1290 {
1291 /* A | B & C == (A | B) & C */
1292 struct Pattern *root = attach_new_root(&curlist);
1293 root->op = MUTT_PAT_OR;
1294 pat_or = false;
1295 }
1296
1297 entry = lookup_tag(ps.dptr[1]);
1298 if (!entry)
1299 {
1300 mutt_buffer_printf(err, _("%c: invalid pattern modifier"), *ps.dptr);
1301 goto cleanup;
1302 }
1303 if (entry->flags && ((flags & entry->flags) == 0))
1304 {
1305 mutt_buffer_printf(err, _("%c: not supported in this mode"), *ps.dptr);
1306 goto cleanup;
1307 }
1308
1309 struct Pattern *leaf = attach_new_leaf(&curlist);
1310 leaf->pat_not = pat_not;
1311 leaf->all_addr = all_addr;
1312 leaf->is_alias = is_alias;
1313 leaf->string_match = (ps.dptr[0] == '=');
1314 leaf->group_match = (ps.dptr[0] == '%');
1315 leaf->sendmode = (flags & MUTT_PC_SEND_MODE_SEARCH);
1316 leaf->op = entry->op;
1317 pat_not = false;
1318 all_addr = false;
1319 is_alias = false;
1320
1321 ps.dptr++; /* move past the ~ */
1322 ps.dptr++; /* eat the operator and any optional whitespace */
1323 SKIPWS(ps.dptr);
1324 if (entry->eat_arg)
1325 {
1326 if (ps.dptr[0] == '\0')
1327 {
1328 mutt_buffer_printf(err, "%s", _("missing parameter"));
1329 goto cleanup;
1330 }
1331 switch (entry->eat_arg)
1332 {
1333 case EAT_REGEX:
1334 if (!eat_regex(leaf, flags, &ps, err))
1335 goto cleanup;
1336 break;
1337 case EAT_DATE:
1338 if (!eat_date(leaf, flags, &ps, err))
1339 goto cleanup;
1340 break;
1341 case EAT_RANGE:
1342 if (!eat_range(leaf, flags, &ps, err))
1343 goto cleanup;
1344 break;
1345 case EAT_MESSAGE_RANGE:
1346 if (!eat_message_range(leaf, flags, &ps, err, m, menu))
1347 goto cleanup;
1348 break;
1349 case EAT_QUERY:
1350 if (!eat_query(leaf, flags, &ps, err, m))
1351 goto cleanup;
1352 break;
1353 default:
1354 break;
1355 }
1356 }
1357 implicit = true;
1358 break;
1359 }
1360
1361 case '(':
1362 {
1363 p = find_matching_paren(ps.dptr + 1);
1364 if (p[0] != ')')
1365 {
1366 mutt_buffer_printf(err, _("mismatched parentheses: %s"), ps.dptr);
1367 goto cleanup;
1368 }
1369 /* compile the sub-expression */
1370 buf = mutt_strn_dup(ps.dptr + 1, p - (ps.dptr + 1));
1371 struct PatternList *sub = mutt_pattern_comp(m, menu, buf, flags, err);
1372 FREE(&buf);
1373 if (!sub)
1374 goto cleanup;
1375 struct Pattern *leaf = SLIST_FIRST(sub);
1376 if (curlist)
1377 {
1378 attach_leaf(curlist, leaf);
1379 FREE(&sub);
1380 }
1381 else
1382 {
1383 curlist = sub;
1384 }
1385 leaf->pat_not ^= pat_not;
1386 leaf->all_addr |= all_addr;
1387 leaf->is_alias |= is_alias;
1388 pat_not = false;
1389 all_addr = false;
1390 is_alias = false;
1391 ps.dptr = p + 1; /* restore location */
1392 SKIPWS(ps.dptr);
1393 break;
1394 }
1395
1396 default:
1397 mutt_buffer_printf(err, _("error in pattern at: %s"), ps.dptr);
1398 goto cleanup;
1399 }
1400 }
1401
1402 if (!curlist)
1403 {
1404 mutt_buffer_strcpy(err, _("empty pattern"));
1405 return NULL;
1406 }
1407
1408 if (SLIST_NEXT(SLIST_FIRST(curlist), entries))
1409 {
1410 struct Pattern *root = attach_new_root(&curlist);
1411 root->op = pat_or ? MUTT_PAT_OR : MUTT_PAT_AND;
1412 }
1413
1414 return curlist;
1415
1416cleanup:
1417 mutt_pattern_free(&curlist);
1418 return NULL;
1419}
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:365
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:52
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:168
static struct Pattern * attach_new_root(struct PatternList **curlist)
Create a new Pattern as a parent for a List.
Definition: compile.c:1136
static struct Pattern * attach_new_leaf(struct PatternList **curlist)
Attach a new Pattern to a List.
Definition: compile.c:1152
static struct Pattern * attach_leaf(struct PatternList *list, struct Pattern *leaf)
Attach a Pattern to a Pattern List.
Definition: compile.c:1114
static char * find_matching_paren(char *s)
Find the matching parenthesis.
Definition: compile.c:1027
struct PatternList * mutt_pattern_comp(struct Mailbox *m, struct Menu *menu, const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition: compile.c:1173
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:1051
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:154
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:635
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:988
static bool eat_message_range(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err, struct Mailbox *m, struct Menu *menu)
Parse a range of message numbers - Implements eat_arg_t -.
Definition: compile.c:943
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:79
#define FREE(x)
Definition: memory.h:43
#define _(a)
Definition: message.h:28
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:451
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
const struct PatternFlags * lookup_tag(char tag)
Lookup a pattern modifier.
Definition: flags.c:200
#define MUTT_PC_SEND_MODE_SEARCH
Allow send-mode body searching.
Definition: lib.h:64
@ EAT_RANGE
Process a number (range)
Definition: private.h:51
@ EAT_MESSAGE_RANGE
Process a message number (range)
Definition: private.h:52
@ EAT_DATE
Process a date (range)
Definition: private.h:50
@ EAT_QUERY
Process a query string.
Definition: private.h:53
@ EAT_REGEX
Process a regex.
Definition: private.h:49
#define SLIST_NEXT(elm, field)
Definition: queue.h:270
#define SLIST_FIRST(head)
Definition: queue.h:229
#define SKIPWS(ch)
Definition: string2.h:46
String manipulation buffer.
Definition: buffer.h:34
Mapping between user character and internal constant.
Definition: private.h:60
enum PatternEat eat_arg
Type of function needed to parse flag, e.g. EAT_DATE.
Definition: private.h:65
PatternCompFlags flags
Pattern flags, e.g. MUTT_PC_FULL_MSG.
Definition: private.h:63
int op
Operation to perform, e.g. MUTT_PAT_SCORE.
Definition: private.h:62
A simple (non-regex) pattern.
Definition: lib.h:70
bool group_match
Check a group of Addresses.
Definition: lib.h:75
union Pattern::@1 p
bool all_addr
All Addresses in the list must match.
Definition: lib.h:73
bool string_match
Check a string for a match.
Definition: lib.h:74
bool is_alias
Is there an alias for this Address?
Definition: lib.h:77
bool sendmode
Evaluate searches in send-mode.
Definition: lib.h:79
+ 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 115 of file pattern.c.

116{
117 bool do_simple = true;
118
119 for (const char *p = mutt_buffer_string(buf); p && (p[0] != '\0'); p++)
120 {
121 if ((p[0] == '\\') && (p[1] != '\0'))
122 {
123 p++;
124 }
125 else if ((p[0] == '~') || (p[0] == '=') || (p[0] == '%'))
126 {
127 do_simple = false;
128 break;
129 }
130 }
131
132 /* XXX - is mutt_istr_cmp() right here, or should we use locale's
133 * equivalences? */
134
135 if (do_simple) /* yup, so spoof a real request */
136 {
137 /* convert old tokens into the new format */
138 if (mutt_istr_equal("all", mutt_buffer_string(buf)) ||
140 mutt_str_equal(".", mutt_buffer_string(buf))) /* ~A is more efficient */
141 {
142 mutt_buffer_strcpy(buf, "~A");
143 }
144 else if (mutt_istr_equal("del", mutt_buffer_string(buf)))
145 mutt_buffer_strcpy(buf, "~D");
146 else if (mutt_istr_equal("flag", mutt_buffer_string(buf)))
147 mutt_buffer_strcpy(buf, "~F");
148 else if (mutt_istr_equal("new", mutt_buffer_string(buf)))
149 mutt_buffer_strcpy(buf, "~N");
150 else if (mutt_istr_equal("old", mutt_buffer_string(buf)))
151 mutt_buffer_strcpy(buf, "~O");
152 else if (mutt_istr_equal("repl", mutt_buffer_string(buf)))
153 mutt_buffer_strcpy(buf, "~Q");
154 else if (mutt_istr_equal("read", mutt_buffer_string(buf)))
155 mutt_buffer_strcpy(buf, "~R");
156 else if (mutt_istr_equal("tag", mutt_buffer_string(buf)))
157 mutt_buffer_strcpy(buf, "~T");
158 else if (mutt_istr_equal("unread", mutt_buffer_string(buf)))
159 mutt_buffer_strcpy(buf, "~U");
160 else
161 {
162 struct Buffer *tmp = mutt_buffer_pool_get();
164 mutt_file_expand_fmt(buf, simple, mutt_buffer_string(tmp));
166 }
167 }
168}
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:78
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:1490
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:819
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
static void quote_simple(const char *str, struct Buffer *buf)
Apply simple quoting to a string.
Definition: pattern.c:97
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
+ 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 1051 of file compile.c.

1052{
1053 if (!pat || !*pat)
1054 return;
1055
1056 struct Pattern *np = SLIST_FIRST(*pat), *next = NULL;
1057
1058 while (np)
1059 {
1060 next = SLIST_NEXT(np, entries);
1061
1062 if (np->is_multi)
1064 else if (np->string_match || np->dynamic)
1065 FREE(&np->p.str);
1066 else if (np->group_match)
1067 np->p.group = NULL;
1068 else if (np->p.regex)
1069 {
1070 regfree(np->p.regex);
1071 FREE(&np->p.regex);
1072 }
1073
1074#ifdef USE_DEBUG_GRAPHVIZ
1075 FREE(&np->raw_pattern);
1076#endif
1078 FREE(&np);
1079
1080 np = next;
1081 }
1082
1083 FREE(pat);
1084}
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
struct Group * group
Address group if group_match is set.
Definition: lib.h:86
regex_t * regex
Compiled regex, for non-pattern matching.
Definition: lib.h:85
struct ListHead multi_cases
Multiple strings for ~I pattern.
Definition: lib.h:88
char * str
String, if string_match is set.
Definition: lib.h:87
bool dynamic
Evaluate date ranges at run time.
Definition: lib.h:78
bool is_multi
Multiple case (only for ~I pattern now)
Definition: lib.h:80
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dlg_select_pattern()

bool dlg_select_pattern ( char *  buf,
size_t  buflen 
)

Show menu to select a Pattern.

Parameters
bufBuffer for the selected Pattern
buflenLength of buffer
Return values
trueA selection was made

Definition at line 335 of file dlg_pattern.c.

336{
338 struct Menu *menu = create_pattern_menu(dlg);
339
340 struct PatternData pd = { false, false, buf, buflen, menu };
341 dlg->wdata = &pd;
342
343 // NT_COLOR is handled by the SimpleDialog
346
347 // ---------------------------------------------------------------------------
348 // Event Loop
349 int op = OP_NULL;
350 do
351 {
353 window_redraw(NULL);
354
355 struct KeyEvent event = km_dokey_event(MENU_GENERIC);
356 if (event.ch == 'q')
357 op = OP_EXIT;
358 else
359 op = event.op;
360
361 mutt_debug(LL_DEBUG1, "Got op %s (%d)\n", opcodes_get_name(op), op);
362 if (op < 0)
363 continue;
364 if (op == OP_NULL)
365 {
367 continue;
368 }
370
371 int rc = pattern_function_dispatcher(dlg, op);
372
373 if (rc == FR_UNKNOWN)
374 rc = menu_function_dispatcher(menu->win, op);
375 if (rc == FR_UNKNOWN)
376 rc = global_function_dispatcher(NULL, op);
377 } while (!pd.done);
378 // ---------------------------------------------------------------------------
379
380 simple_dialog_free(&dlg);
381 return pd.selection;
382}
@ FR_UNKNOWN
Unknown function.
Definition: dispatcher.h:33
static const struct Mapping PatternHelp[]
Help Bar for the Pattern selection dialog.
Definition: dlg_pattern.c:89
static struct Menu * create_pattern_menu(struct MuttWindow *dlg)
Create the Pattern Completion menu.
Definition: dlg_pattern.c:170
int menu_tagging_dispatcher(struct MuttWindow *win, int op)
Perform tagging operations on the Menu - Implements function_dispatcher_t -.
Definition: tagging.c:223
int pattern_function_dispatcher(struct MuttWindow *win, int op)
Perform a Pattern function - Implements function_dispatcher_t -.
Definition: functions.c:78
int global_function_dispatcher(struct MuttWindow *win, int op)
Perform a Global function - Implements function_dispatcher_t -.
Definition: global.c:164
int menu_function_dispatcher(struct MuttWindow *win, int op)
Perform a Menu function - Implements function_dispatcher_t -.
Definition: functions.c:320
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
static int pattern_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition: dlg_pattern.c:306
static int pattern_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: dlg_pattern.c:280
void simple_dialog_free(struct MuttWindow **ptr)
Destroy a simple index Dialog.
Definition: simple.c:166
struct MuttWindow * simple_dialog_new(enum MenuType mtype, enum WindowType wtype, const struct Mapping *help_data)
Create a simple index Dialog.
Definition: simple.c:129
struct KeyEvent km_dokey_event(enum MenuType mtype)
Determine what a keypress should do.
Definition: keymap.c:637
void km_error_key(enum MenuType mtype)
Handle an unbound key sequence.
Definition: keymap.c:1065
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
bool notify_observer_add(struct Notify *notify, enum NotifyType type, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:189
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:605
@ WT_DLG_PATTERN
Pattern Dialog, create_pattern_menu()
Definition: mutt_window.h:87
@ NT_WINDOW
MuttWindow has changed, NotifyWindow, EventWindow.
Definition: notify_type.h:55
@ NT_CONFIG
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:43
const char * opcodes_get_name(int op)
Get the name of an opcode.
Definition: opcodes.c:46
An event such as a keypress.
Definition: keymap.h:65
int op
Function opcode, e.g. OP_HELP.
Definition: keymap.h:67
int ch
Raw key pressed.
Definition: keymap.h:66
Definition: lib.h:70
struct MuttWindow * win
Window holding the Menu.
Definition: lib.h:77
void * wdata
Private data.
Definition: mutt_window.h:145
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
Definition: mutt_window.h:138
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
Data to pass to the Pattern Functions.
Definition: functions.h:35
char * buf
Buffer for the results.
Definition: functions.h:38
struct Menu * menu
Pattern Menu.
Definition: functions.h:40
bool done
Should we close the Dialog?
Definition: functions.h:36
size_t buflen
Length of the results buffer.
Definition: functions.h:39
bool selection
Was a selection made?
Definition: functions.h:37
@ MENU_GENERIC
Generic selection list.
Definition: type.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_which_case()

int mutt_which_case ( const char *  s)

◆ 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 471 of file exec.c.

472{
473 return mutt_is_predicate_recipient(all_addr, env, &mutt_is_mail_list);
474}
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:434
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list? - Implements addr_predicate_t -.
Definition: maillist.c:44
+ 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 458 of file exec.c.

459{
461}
bool mutt_is_subscribed_list(const struct Address *addr)
Is this the email address of a user-subscribed mailing list? - Implements addr_predicate_t -.
Definition: maillist.c:56
+ 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 344 of file pattern.c.

345{
346 if (!mv || !mv->mailbox)
347 return -1;
348
349 struct Mailbox *m = mv->mailbox;
350
351 struct Buffer *err = NULL;
352 int rc = -1;
353 struct Progress *progress = NULL;
354 struct Buffer *buf = mutt_buffer_pool_get();
355
357 if (prompt || (op != MUTT_LIMIT))
358 {
360 false, NULL, NULL, NULL) != 0) ||
362 {
364 return -1;
365 }
366 }
367
368 mutt_message(_("Compiling search pattern..."));
369
370 char *simple = mutt_buffer_strdup(buf);
371 const char *const c_simple_search = cs_subset_string(NeoMutt->sub, "simple_search");
372 mutt_check_simple(buf, NONULL(c_simple_search));
373 const char *pbuf = buf->data;
374 while (*pbuf == ' ')
375 pbuf++;
376 const bool match_all = mutt_str_equal(pbuf, "~A");
377
378 err = mutt_buffer_pool_get();
379 struct PatternList *pat = mutt_pattern_comp(m, mv->menu, buf->data, MUTT_PC_FULL_MSG, err);
380 if (!pat)
381 {
382 mutt_error("%s", mutt_buffer_string(err));
383 goto bail;
384 }
385
386#ifdef USE_IMAP
387 if ((m->type == MUTT_IMAP) && (!imap_search(m, pat)))
388 goto bail;
389#endif
390
391 progress = progress_new(_("Executing command on matching messages..."), MUTT_PROGRESS_READ,
392 (op == MUTT_LIMIT) ? m->msg_count : m->vcount);
393
394 if (op == MUTT_LIMIT)
395 {
396 m->vcount = 0;
397 mv->vsize = 0;
398 mv->collapsed = false;
399 int padding = mx_msg_padding_size(m);
400
401 for (int i = 0; i < m->msg_count; i++)
402 {
403 struct Email *e = m->emails[i];
404 if (!e)
405 break;
406
407 progress_update(progress, i, -1);
408 /* new limit pattern implicitly uncollapses all threads */
409 e->vnum = -1;
410 e->visible = false;
411 e->limit_visited = true;
412 e->collapsed = false;
413 e->num_hidden = 0;
414
415 if (match_all ||
417 {
418 e->vnum = m->vcount;
419 e->visible = true;
420 m->v2r[m->vcount] = i;
421 m->vcount++;
422 struct Body *b = e->body;
423 mv->vsize += b->length + b->offset - b->hdr_offset + padding;
424 }
425 }
426 }
427 else
428 {
429 for (int i = 0; i < m->vcount; i++)
430 {
431 struct Email *e = mutt_get_virt_email(m, i);
432 if (!e)
433 continue;
434 progress_update(progress, i, -1);
436 {
437 switch (op)
438 {
439 case MUTT_UNDELETE:
440 mutt_set_flag(m, e, MUTT_PURGE, false);
441 /* fallthrough */
442 case MUTT_DELETE:
443 mutt_set_flag(m, e, MUTT_DELETE, (op == MUTT_DELETE));
444 break;
445 case MUTT_TAG:
446 case MUTT_UNTAG:
447 mutt_set_flag(m, e, MUTT_TAG, (op == MUTT_TAG));
448 break;
449 }
450 }
451 }
452 }
453 progress_free(&progress);
454
456
457 if (op == MUTT_LIMIT)
458 {
459 /* drop previous limit pattern */
460 FREE(&mv->pattern);
462
463 if (m->msg_count && !m->vcount)
464 mutt_error(_("No messages matched criteria"));
465
466 /* record new limit pattern, unless match all */
467 if (!match_all)
468 {
469 mv->pattern = simple;
470 simple = NULL; /* don't clobber it */
471 mv->limit_pattern = mutt_pattern_comp(m, mv->menu, buf->data, MUTT_PC_FULL_MSG, err);
472 }
473 }
474
475 rc = 0;
476
477bail:
480 FREE(&simple);
481 mutt_pattern_free(&pat);
482
483 return rc;
484}
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:298
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:485
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
Definition: window.c:180
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:1119
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
bool imap_search(struct Mailbox *m, const struct PatternList *pat)
Find messages in mailbox matching a pattern.
Definition: search.c:229
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:50
#define MUTT_COMP_PATTERN
Pattern mode (in pattern dialog)
Definition: mutt.h:64
@ MUTT_UNDELETE
Messages to be un-deleted.
Definition: mutt.h:84
@ MUTT_LIMIT
Messages in limited view.
Definition: mutt.h:90
@ MUTT_UNTAG
Messages to be un-tagged.
Definition: mutt.h:89
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:85
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:88
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:83
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:65
struct Email * mutt_get_virt_email(struct Mailbox *m, int vnum)
Get a virtual Email.
Definition: mview.c:414
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size()
Definition: mx.c:1556
#define MUTT_PC_FULL_MSG
Enable body and header matching.
Definition: lib.h:62
void mutt_check_simple(struct Buffer *buf, const char *simple)
Convert a simple search into a real request.
Definition: pattern.c:115
static unsigned char * pbuf
Cached PGP data packet.
Definition: pgppacket.c:38
@ MUTT_PROGRESS_READ
Progress tracks elements, according to $read_inc
Definition: lib.h:49
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:86
bool progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:73
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:118
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:63
#define NONULL(x)
Definition: string2.h:37
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:80
char * data
Pointer to data.
Definition: buffer.h:35
The envelope/body of an email.
Definition: email.h:37
bool visible
Is this message part of the view?
Definition: email.h:120
bool limit_visited
Has the limit pattern been applied to this message?
Definition: email.h:121
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:119
struct Body * body
List of MIME parts.
Definition: email.h:67
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
Definition: email.h:122
int vnum
Virtual message number.
Definition: email.h:113
bool collapsed
Are all threads collapsed?
Definition: mview.h:47
struct Menu * menu
Needed for pattern compilation.
Definition: mview.h:45
off_t vsize
Size (in bytes) of the messages shown.
Definition: mview.h:39
struct PatternList * limit_pattern
Compiled limit pattern.
Definition: mview.h:41
struct Mailbox * mailbox
Current Mailbox.
Definition: mview.h:49
char * pattern
Limit pattern string.
Definition: mview.h:40
A mailbox.
Definition: mailbox.h:79
int vcount
The number of virtual messages.
Definition: mailbox.h:99
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:98
int msg_count
Total number of messages.
Definition: mailbox.h:88
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
struct Email ** emails
Array of Emails.
Definition: mailbox.h:96
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ 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,
struct Menu menu 
)

Perform some Pattern matching for Alias.

Parameters
promptPrompt to show the user
mdataMenu data holding Aliases
menuCurrent menu
Return values
0Success
-1Failure

Definition at line 244 of file pattern.c.

245{
246 int rc = -1;
247 struct Progress *progress = NULL;
248 struct Buffer *buf = mutt_buffer_pool_get();
249
250 mutt_buffer_strcpy(buf, mdata->limit);
251 if (prompt)
252 {
254 false, NULL, NULL, NULL) != 0) ||
256 {
258 return -1;
259 }
260 }
261
262 mutt_message(_("Compiling search pattern..."));
263
264 bool match_all = false;
265 struct PatternList *pat = NULL;
266 char *simple = mutt_buffer_strdup(buf);
267 if (simple)
268 {
270 const char *pbuf = buf->data;
271 while (*pbuf == ' ')
272 pbuf++;
273 match_all = mutt_str_equal(pbuf, "~A");
274
275 struct Buffer err = mutt_buffer_make(0);
276 pat = mutt_pattern_comp(NULL, menu, buf->data, MUTT_PC_FULL_MSG, &err);
277 if (!pat)
278 {
279 mutt_error("%s", mutt_buffer_string(&err));
281 goto bail;
282 }
283 }
284 else
285 {
286 match_all = true;
287 }
288
289 progress = progress_new(_("Executing command on matching messages..."),
291
292 int vcounter = 0;
293 struct AliasView *avp = NULL;
294 ARRAY_FOREACH(avp, &mdata->ava)
295 {
296 progress_update(progress, ARRAY_FOREACH_IDX, -1);
297
298 if (match_all ||
300 {
301 avp->is_visible = true;
302 vcounter++;
303 }
304 else
305 {
306 avp->is_visible = false;
307 }
308 }
309 progress_free(&progress);
310
311 FREE(&mdata->limit);
312 if (!match_all)
313 {
314 mdata->limit = simple;
315 simple = NULL;
316 }
317
318 if (menu)
319 {
320 menu->max = vcounter;
321 menu_set_index(menu, 0);
322 }
323
325
326 rc = 0;
327
328bail:
330 FREE(&simple);
331 mutt_pattern_free(&pat);
332
333 return rc;
334}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:211
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:86
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:67
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:347
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:1146
MenuRedrawFlags menu_set_index(struct Menu *menu, int index)
Set the current selection in the Menu.
Definition: menu.c:168
#define MUTT_ALIAS_SIMPLESEARCH
Definition: lib.h:58
char * limit
Limit being used.
Definition: gui.h:58
struct AliasViewArray ava
All Aliases/Queries.
Definition: gui.h:53
GUI data wrapping an Alias.
Definition: gui.h:36
bool is_visible
Is visible?
Definition: gui.h:43
int max
Number of entries in the menu.
Definition: lib.h:72
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_search_command()

int mutt_search_command ( struct Mailbox m,
struct Menu menu,
int  cur,
int  op 
)

Perform a search.

Parameters
mMailbox to search through
menuCurrent Menu
curIndex number of current email
opOperation to perform, e.g. OP_SEARCH_NEXT
Return values
>=0Index of matching email
-1No match, or error

Definition at line 495 of file pattern.c.

496{
497 struct Progress *progress = NULL;
498 struct Buffer *buf = NULL;
499 int rc = -1;
500
501 if ((*LastSearch == '\0') || ((op != OP_SEARCH_NEXT) && (op != OP_SEARCH_OPPOSITE)))
502 {
503 buf = mutt_buffer_pool_get();
504 mutt_buffer_strcpy(buf, (LastSearch[0] != '\0') ? LastSearch : "");
505 if ((mutt_buffer_get_field(((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ?
506 _("Search for: ") :
507 _("Reverse search for: "),
509 NULL, NULL, NULL) != 0) ||
511 {
512 goto done;
513 }
514
515 if ((op == OP_SEARCH) || (op == OP_SEARCH_NEXT))
516 OptSearchReverse = false;
517 else
518 OptSearchReverse = true;
519
520 /* compare the *expanded* version of the search pattern in case
521 * $simple_search has changed while we were searching */
522 struct Buffer *tmp = mutt_buffer_pool_get();
523 mutt_buffer_copy(tmp, buf);
524 const char *const c_simple_search = cs_subset_string(NeoMutt->sub, "simple_search");
525 mutt_check_simple(tmp, NONULL(c_simple_search));
526
528 {
529 struct Buffer err;
530 mutt_buffer_init(&err);
531 OptSearchInvalid = true;
534 mutt_message(_("Compiling search pattern..."));
536 err.dsize = 256;
537 err.data = mutt_mem_malloc(err.dsize);
539 if (!SearchPattern)
540 {
543 mutt_error("%s", err.data);
544 FREE(&err.data);
545 LastSearch[0] = '\0';
546 LastSearchExpn[0] = '\0';
547 return -1;
548 }
549 FREE(&err.data);
551 }
552
554 }
555
557 {
558 for (int i = 0; i < m->msg_count; i++)
559 m->emails[i]->searched = false;
560#ifdef USE_IMAP
561 if ((m->type == MUTT_IMAP) && (!imap_search(m, SearchPattern)))
562 return -1;
563#endif
564 OptSearchInvalid = false;
565 }
566
567 int incr = OptSearchReverse ? -1 : 1;
568 if (op == OP_SEARCH_OPPOSITE)
569 incr = -incr;
570
571 progress = progress_new(_("Searching..."), MUTT_PROGRESS_READ, m->vcount);
572
573 for (int i = cur + incr, j = 0; j != m->vcount; j++)
574 {
575 const char *msg = NULL;
576 progress_update(progress, j, -1);
577 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
578 if (i > m->vcount - 1)
579 {
580 i = 0;
581 if (c_wrap_search)
582 {
583 msg = _("Search wrapped to top");
584 }
585 else
586 {
587 mutt_message(_("Search hit bottom without finding match"));
588 goto done;
589 }
590 }
591 else if (i < 0)
592 {
593 i = m->vcount - 1;
594 if (c_wrap_search)
595 {
596 msg = _("Search wrapped to bottom");
597 }
598 else
599 {
600 mutt_message(_("Search hit top without finding match"));
601 goto done;
602 }
603 }
604
605 struct Email *e = mutt_get_virt_email(m, i);
606 if (e->searched)
607 {
608 /* if we've already evaluated this message, use the cached value */
609 if (e->matched)
610 {
612 if (msg && *msg)
613 mutt_message(msg);
614 rc = i;
615 goto done;
616 }
617 }
618 else
619 {
620 /* remember that we've already searched this message */
621 e->searched = true;
623 MUTT_MATCH_FULL_ADDRESS, m, e, NULL);
624 if (e->matched > 0)
625 {
627 if (msg && *msg)
628 mutt_message(msg);
629 rc = i;
630 goto done;
631 }
632 }
633
634 if (SigInt)
635 {
636 mutt_error(_("Search interrupted"));
637 SigInt = false;
638 goto done;
639 }
640
641 i += incr;
642 }
643
644 mutt_error(_("Not found"));
645done:
646 progress_free(&progress);
648 return rc;
649}
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:500
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
bool OptSearchInvalid
(pseudo) used to invalidate the search pattern
Definition: globals.c:85
SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.c:58
bool OptSearchReverse
(pseudo) used by ci_search_command
Definition: globals.c:86
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:652
static struct PatternList * SearchPattern
current search pattern
Definition: pattern.c:88
static char LastSearchExpn[1024]
expanded version of LastSearch
Definition: pattern.c:90
static char LastSearch[256]
last pattern searched for
Definition: pattern.c:89
bool searched
Email has been searched.
Definition: email.h:104
bool matched
Search matches this Email.
Definition: email.h:101
+ 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,
int  op 
)

Perform a search.

Parameters
menuMenu to search through
curIndex number of current alias
opOperation to perform, e.g. OP_SEARCH_NEXT
Return values
>=0Index of matching alias
-1No match, or error

Definition at line 659 of file pattern.c.

660{
661 struct Progress *progress = NULL;
662 const struct AliasMenuData *mdata = menu->mdata;
663 const struct AliasViewArray *ava = &mdata->ava;
664 struct Buffer *buf = NULL;
665 int rc = -1;
666
667 if ((*LastSearch == '\0') || ((op != OP_SEARCH_NEXT) && (op != OP_SEARCH_OPPOSITE)))
668 {
669 buf = mutt_buffer_pool_get();
670 mutt_buffer_strcpy(buf, (LastSearch[0] != '\0') ? LastSearch : "");
671 if ((mutt_buffer_get_field(((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ?
672 _("Search for: ") :
673 _("Reverse search for: "),
675 NULL, NULL, NULL) != 0) ||
677 {
678 goto done;
679 }
680
681 if ((op == OP_SEARCH) || (op == OP_SEARCH_NEXT))
682 OptSearchReverse = false;
683 else
684 OptSearchReverse = true;
685
686 /* compare the *expanded* version of the search pattern in case
687 * $simple_search has changed while we were searching */
688 struct Buffer *tmp = mutt_buffer_pool_get();
689 mutt_buffer_copy(tmp, buf);
691
693 {
694 struct Buffer err;
695 mutt_buffer_init(&err);
696 OptSearchInvalid = true;
699 mutt_message(_("Compiling search pattern..."));
701 err.dsize = 256;
702 err.data = mutt_mem_malloc(err.dsize);
703 SearchPattern = mutt_pattern_comp(NULL, menu, tmp->data, MUTT_PC_FULL_MSG, &err);
704 if (!SearchPattern)
705 {
707 mutt_error("%s", err.data);
708 FREE(&err.data);
709 LastSearch[0] = '\0';
710 LastSearchExpn[0] = '\0';
711 return -1;
712 }
713 FREE(&err.data);
715 }
716
718 }
719
721 {
722 struct AliasView *av = NULL;
723 ARRAY_FOREACH(av, ava)
724 {
725 av->is_searched = false;
726 }
727
728 OptSearchInvalid = false;
729 }
730
731 int incr = OptSearchReverse ? -1 : 1;
732 if (op == OP_SEARCH_OPPOSITE)
733 incr = -incr;
734
735 progress = progress_new(_("Searching..."), MUTT_PROGRESS_READ, ARRAY_SIZE(ava));
736
737 for (int i = cur + incr, j = 0; j != ARRAY_SIZE(ava); j++)
738 {
739 const char *msg = NULL;
740 progress_update(progress, j, -1);
741 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
742 if (i > ARRAY_SIZE(ava) - 1)
743 {
744 i = 0;
745 if (c_wrap_search)
746 {
747 msg = _("Search wrapped to top");
748 }
749 else
750 {
751 mutt_message(_("Search hit bottom without finding match"));
752 goto done;
753 }
754 }
755 else if (i < 0)
756 {
757 i = ARRAY_SIZE(ava) - 1;
758 if (c_wrap_search)
759 {
760 msg = _("Search wrapped to bottom");
761 }
762 else
763 {
764 mutt_message(_("Search hit top without finding match"));
765 goto done;
766 }
767 }
768
769 struct AliasView *av = ARRAY_GET(ava, i);
770 if (av->is_searched)
771 {
772 /* if we've already evaluated this message, use the cached value */
773 if (av->is_matched)
774 {
776 if (msg && *msg)
777 mutt_message(msg);
778 rc = i;
779 goto done;
780 }
781 }
782 else
783 {
784 /* remember that we've already searched this message */
785 av->is_searched = true;
787 MUTT_MATCH_FULL_ADDRESS, av, NULL);
788 if (av->is_matched > 0)
789 {
791 if (msg && *msg)
792 mutt_message(msg);
793 rc = i;
794 goto done;
795 }
796 }
797
798 if (SigInt)
799 {
800 mutt_error(_("Search interrupted"));
801 SigInt = false;
802 goto done;
803 }
804
805 i += incr;
806 }
807
808 mutt_error(_("Not found"));
809done:
810 progress_free(&progress);
812 return rc;
813}
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:108
AliasView array wrapper with Pattern information -.
Definition: gui.h:52
struct Menu * menu
Menu.
Definition: gui.h:56
bool is_matched
Search matches this Alias.
Definition: gui.h:40
bool is_searched
Alias has been searched.
Definition: gui.h:39
void * mdata
Private data.
Definition: lib.h:138
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_limit_current_thread()

bool mutt_limit_current_thread ( struct MailboxView mv,
struct Email e 
)

Limit the email view to the current thread.

Parameters
mvMailbox View
eEmail
Return values
trueSuccess
falseFailure

Definition at line 196 of file pattern.c.

197{
198 if (!mv || !mv->mailbox || !e)
199 return false;
200
201 struct Mailbox *m = mv->mailbox;
202
203 struct MuttThread *me = top_of_thread(e);
204 if (!me)
205 return false;
206
207 m->vcount = 0;
208 mv->vsize = 0;
209 mv->collapsed = false;
210
211 for (int i = 0; i < m->msg_count; i++)
212 {
213 e = m->emails[i];
214 if (!e)
215 break;
216
217 e->vnum = -1;
218 e->visible = false;
219 e->collapsed = false;
220 e->num_hidden = 0;
221
222 if (top_of_thread(e) == me)
223 {
224 struct Body *body = e->body;
225
226 e->vnum = m->vcount;
227 e->visible = true;
228 m->v2r[m->vcount] = i;
229 m->vcount++;
230 mv->vsize += (body->length + body->offset - body->hdr_offset);
231 }
232 }
233 return true;
234}
static struct MuttThread * top_of_thread(struct Email *e)
Find the first email in the current thread.
Definition: pattern.c:176
An Email conversation.
Definition: thread.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function: