NeoMutt  2022-04-29-178-g3b62e6
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_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)
 
int mutt_is_list_recipient (bool all_addr, struct Envelope *env)
 Matches known mailing lists. More...
 
int 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_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{
171#ifdef USE_NNTP
173#endif
175};
@ MUTT_MT_MAX
Definition: mutt.h:107
@ MUTT_PAT_HEADER
Pattern matches email's header.
Definition: lib.h:148
@ MUTT_PAT_WHOLE_MSG
Pattern matches raw email text.
Definition: lib.h:150
@ MUTT_PAT_BROKEN
Message is part of a broken thread.
Definition: lib.h:144
@ MUTT_PAT_ID_EXTERNAL
Message-Id is among results from an external query.
Definition: lib.h:146
@ 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:155
@ MUTT_PAT_FROM
Pattern matches 'From:' field.
Definition: lib.h:139
@ MUTT_PAT_DRIVER_TAGS
Pattern matches message tags.
Definition: lib.h:168
@ MUTT_PAT_COLLAPSED
Thread is collapsed.
Definition: lib.h:137
@ MUTT_PAT_CRYPT_VERIFIED
Message is crypographically verified.
Definition: lib.h:163
@ MUTT_PAT_HORMEL
Pattern matches email's spam score.
Definition: lib.h:149
@ MUTT_PAT_SUBJECT
Pattern matches 'Subject:' field.
Definition: lib.h:138
@ MUTT_PAT_LIST
Email is on mailing list.
Definition: lib.h:157
@ MUTT_PAT_NEWSGROUPS
Pattern matches newsgroup.
Definition: lib.h:172
@ MUTT_PAT_PERSONAL_RECIP
Email is addressed to the user.
Definition: lib.h:159
@ MUTT_PAT_CC
Pattern matches 'Cc:' field.
Definition: lib.h:136
@ MUTT_PAT_SUBSCRIBED_LIST
Email is on subscribed mailing list.
Definition: lib.h:158
@ MUTT_PAT_SERVERSEARCH
Server-side pattern matches.
Definition: lib.h:167
@ MUTT_PAT_RECIPIENT
User is a recipient of the email.
Definition: lib.h:156
@ MUTT_PAT_CRYPT_ENCRYPT
Message is encrypted.
Definition: lib.h:164
@ MUTT_PAT_UNREFERENCED
Message is unreferenced in the thread.
Definition: lib.h:143
@ MUTT_PAT_CRYPT_SIGN
Message is signed.
Definition: lib.h:162
@ MUTT_PAT_MESSAGE
Pattern matches message number.
Definition: lib.h:152
@ MUTT_PAT_AND
Both patterns must match.
Definition: lib.h:130
@ MUTT_PAT_DATE
Pattern matches 'Date:' field.
Definition: lib.h:140
@ MUTT_PAT_XLABEL
Pattern matches keyword/label.
Definition: lib.h:166
@ MUTT_PAT_SCORE
Pattern matches email's score.
Definition: lib.h:153
@ MUTT_PAT_MIMEATTACH
Pattern matches number of attachments.
Definition: lib.h:169
@ MUTT_PAT_DUPLICATED
Duplicate message.
Definition: lib.h:142
@ MUTT_PAT_PERSONAL_FROM
Email is from the user.
Definition: lib.h:160
@ MUTT_PAT_TO
Pattern matches 'To:' field.
Definition: lib.h:135
@ MUTT_PAT_SENDER
Pattern matches sender.
Definition: lib.h:151
@ MUTT_PAT_DATE_RECEIVED
Pattern matches date received.
Definition: lib.h:141
@ MUTT_PAT_ADDRESS
Pattern matches any address field.
Definition: lib.h:161
@ MUTT_PAT_MAX
Definition: lib.h:174
@ MUTT_PAT_MIMETYPE
Pattern matches MIME type.
Definition: lib.h:170
@ MUTT_PAT_PGP_KEY
Message has PGP key.
Definition: lib.h:165
@ MUTT_PAT_ID
Pattern matches email's Message-Id.
Definition: lib.h:145
@ MUTT_PAT_THREAD
Pattern matches email thread.
Definition: lib.h:132
@ MUTT_PAT_SIZE
Pattern matches email's size.
Definition: lib.h:154
@ MUTT_PAT_BODY
Pattern matches email's body.
Definition: lib.h:147

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

1109{
1110 const bool needs_msg = pattern_needs_msg(m, pat);
1111 struct Message *msg = needs_msg ? mx_msg_open(m, e->msgno) : NULL;
1112 if (needs_msg && !msg)
1113 {
1114 return false;
1115 }
1116 const bool matched = pattern_exec(pat, flags, m, e, msg, cache);
1117 mx_msg_close(m, &msg);
1118 return matched;
1119}
static bool pattern_needs_msg(const struct Mailbox *m, const struct Pattern *pat)
Check whether a pattern needs a full message.
Definition: exec.c:762
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:808
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1193
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
Return a stream pointer for a message.
Definition: mx.c:1147
int msgno
Number displayed to the user.
Definition: email.h:111
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 1134 of file exec.c.

1136{
1137 switch (pat->op)
1138 {
1139 case MUTT_PAT_FROM: /* alias */
1140 if (!av->alias)
1141 return false;
1142 return pat->pat_not ^ (av->alias->name && patmatch(pat, av->alias->name));
1143 case MUTT_PAT_CC: /* comment */
1144 if (!av->alias)
1145 return false;
1146 return pat->pat_not ^ (av->alias->comment && patmatch(pat, av->alias->comment));
1147 case MUTT_PAT_TO: /* alias address list */
1148 if (!av->alias)
1149 return false;
1150 return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
1151 1, &av->alias->addr);
1152 case MUTT_PAT_AND:
1153 return pat->pat_not ^ (perform_alias_and(pat->child, flags, av, cache) > 0);
1154 case MUTT_PAT_OR:
1155 return pat->pat_not ^ (perform_alias_or(pat->child, flags, av, cache) > 0);
1156 }
1157
1158 return false;
1159}
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:309
static int match_addrlist(struct Pattern *pat, bool match_personal, int n,...)
Match a Pattern against an Address list.
Definition: exec.c:383
static bool patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: exec.c:71
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:358
#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 1160 of file compile.c.

1162{
1163 /* curlist when assigned will always point to a list containing at least one node
1164 * with a Pattern value. */
1165 struct PatternList *curlist = NULL;
1166 bool pat_not = false;
1167 bool all_addr = false;
1168 bool pat_or = false;
1169 bool implicit = true; /* used to detect logical AND operator */
1170 bool is_alias = false;
1171 const struct PatternFlags *entry = NULL;
1172 char *p = NULL;
1173 char *buf = NULL;
1174 struct Buffer ps;
1175
1176 if (!s || (s[0] == '\0'))
1177 {
1178 mutt_buffer_strcpy(err, _("empty pattern"));
1179 return NULL;
1180 }
1181
1182 mutt_buffer_init(&ps);
1183 ps.dptr = (char *) s;
1184 ps.dsize = mutt_str_len(s);
1185
1186 while (*ps.dptr)
1187 {
1188 SKIPWS(ps.dptr);
1189 switch (*ps.dptr)
1190 {
1191 case '^':
1192 ps.dptr++;
1193 all_addr = !all_addr;
1194 break;
1195 case '!':
1196 ps.dptr++;
1197 pat_not = !pat_not;
1198 break;
1199 case '@':
1200 ps.dptr++;
1201 is_alias = !is_alias;
1202 break;
1203 case '|':
1204 if (!pat_or)
1205 {
1206 if (!curlist)
1207 {
1208 mutt_buffer_printf(err, _("error in pattern at: %s"), ps.dptr);
1209 return NULL;
1210 }
1211
1212 struct Pattern *pat = SLIST_FIRST(curlist);
1213 if (SLIST_NEXT(pat, entries))
1214 {
1215 /* A & B | C == (A & B) | C */
1216 struct Pattern *root = attach_new_root(&curlist);
1217 root->op = MUTT_PAT_AND;
1218 }
1219
1220 pat_or = true;
1221 }
1222 ps.dptr++;
1223 implicit = false;
1224 pat_not = false;
1225 all_addr = false;
1226 is_alias = false;
1227 break;
1228 case '%':
1229 case '=':
1230 case '~':
1231 {
1232 if (ps.dptr[1] == '\0')
1233 {
1234 mutt_buffer_printf(err, _("missing pattern: %s"), ps.dptr);
1235 goto cleanup;
1236 }
1237 short thread_op = 0;
1238 if (ps.dptr[1] == '(')
1239 thread_op = MUTT_PAT_THREAD;
1240 else if ((ps.dptr[1] == '<') && (ps.dptr[2] == '('))
1241 thread_op = MUTT_PAT_PARENT;
1242 else if ((ps.dptr[1] == '>') && (ps.dptr[2] == '('))
1243 thread_op = MUTT_PAT_CHILDREN;
1244 if (thread_op != 0)
1245 {
1246 ps.dptr++; /* skip ~ */
1247 if ((thread_op == MUTT_PAT_PARENT) || (thread_op == MUTT_PAT_CHILDREN))
1248 ps.dptr++;
1249 p = find_matching_paren(ps.dptr + 1);
1250 if (p[0] != ')')
1251 {
1252 mutt_buffer_printf(err, _("mismatched parentheses: %s"), ps.dptr);
1253 goto cleanup;
1254 }
1255 struct Pattern *leaf = attach_new_leaf(&curlist);
1256 leaf->op = thread_op;
1257 leaf->pat_not = pat_not;
1258 leaf->all_addr = all_addr;
1259 leaf->is_alias = is_alias;
1260 pat_not = false;
1261 all_addr = false;
1262 is_alias = false;
1263 /* compile the sub-expression */
1264 buf = mutt_strn_dup(ps.dptr + 1, p - (ps.dptr + 1));
1265 leaf->child = mutt_pattern_comp(m, menu, buf, flags, err);
1266 if (!leaf->child)
1267 {
1268 FREE(&buf);
1269 goto cleanup;
1270 }
1271 FREE(&buf);
1272 ps.dptr = p + 1; /* restore location */
1273 SKIPWS(ps.dptr);
1274 break;
1275 }
1276 if (implicit && pat_or)
1277 {
1278 /* A | B & C == (A | B) & C */
1279 struct Pattern *root = attach_new_root(&curlist);
1280 root->op = MUTT_PAT_OR;
1281 pat_or = false;
1282 }
1283
1284 entry = lookup_tag(ps.dptr[1]);
1285 if (!entry)
1286 {
1287 mutt_buffer_printf(err, _("%c: invalid pattern modifier"), *ps.dptr);
1288 goto cleanup;
1289 }
1290 if (entry->flags && ((flags & entry->flags) == 0))
1291 {
1292 mutt_buffer_printf(err, _("%c: not supported in this mode"), *ps.dptr);
1293 goto cleanup;
1294 }
1295
1296 struct Pattern *leaf = attach_new_leaf(&curlist);
1297 leaf->pat_not = pat_not;
1298 leaf->all_addr = all_addr;
1299 leaf->is_alias = is_alias;
1300 leaf->string_match = (ps.dptr[0] == '=');
1301 leaf->group_match = (ps.dptr[0] == '%');
1302 leaf->sendmode = (flags & MUTT_PC_SEND_MODE_SEARCH);
1303 leaf->op = entry->op;
1304 pat_not = false;
1305 all_addr = false;
1306 is_alias = false;
1307
1308 ps.dptr++; /* move past the ~ */
1309 ps.dptr++; /* eat the operator and any optional whitespace */
1310 SKIPWS(ps.dptr);
1311 if (entry->eat_arg)
1312 {
1313 if (ps.dptr[0] == '\0')
1314 {
1315 mutt_buffer_printf(err, "%s", _("missing parameter"));
1316 goto cleanup;
1317 }
1318 switch (entry->eat_arg)
1319 {
1320 case EAT_REGEX:
1321 if (!eat_regex(leaf, flags, &ps, err))
1322 goto cleanup;
1323 break;
1324 case EAT_DATE:
1325 if (!eat_date(leaf, flags, &ps, err))
1326 goto cleanup;
1327 break;
1328 case EAT_RANGE:
1329 if (!eat_range(leaf, flags, &ps, err))
1330 goto cleanup;
1331 break;
1332 case EAT_MESSAGE_RANGE:
1333 if (!eat_message_range(leaf, flags, &ps, err, m, menu))
1334 goto cleanup;
1335 break;
1336 case EAT_QUERY:
1337 if (!eat_query(leaf, flags, &ps, err, m))
1338 goto cleanup;
1339 break;
1340 default:
1341 break;
1342 }
1343 }
1344 implicit = true;
1345 break;
1346 }
1347
1348 case '(':
1349 {
1350 p = find_matching_paren(ps.dptr + 1);
1351 if (p[0] != ')')
1352 {
1353 mutt_buffer_printf(err, _("mismatched parentheses: %s"), ps.dptr);
1354 goto cleanup;
1355 }
1356 /* compile the sub-expression */
1357 buf = mutt_strn_dup(ps.dptr + 1, p - (ps.dptr + 1));
1358 struct PatternList *sub = mutt_pattern_comp(m, menu, buf, flags, err);
1359 FREE(&buf);
1360 if (!sub)
1361 goto cleanup;
1362 struct Pattern *leaf = SLIST_FIRST(sub);
1363 if (curlist)
1364 {
1365 attach_leaf(curlist, leaf);
1366 FREE(&sub);
1367 }
1368 else
1369 {
1370 curlist = sub;
1371 }
1372 leaf->pat_not ^= pat_not;
1373 leaf->all_addr |= all_addr;
1374 leaf->is_alias |= is_alias;
1375 pat_not = false;
1376 all_addr = false;
1377 is_alias = false;
1378 ps.dptr = p + 1; /* restore location */
1379 SKIPWS(ps.dptr);
1380 break;
1381 }
1382
1383 default:
1384 mutt_buffer_printf(err, _("error in pattern at: %s"), ps.dptr);
1385 goto cleanup;
1386 }
1387 }
1388
1389 if (!curlist)
1390 {
1391 mutt_buffer_strcpy(err, _("empty pattern"));
1392 return NULL;
1393 }
1394
1395 if (SLIST_NEXT(SLIST_FIRST(curlist), entries))
1396 {
1397 struct Pattern *root = attach_new_root(&curlist);
1398 root->op = pat_or ? MUTT_PAT_OR : MUTT_PAT_AND;
1399 }
1400
1401 return curlist;
1402
1403cleanup:
1404 mutt_pattern_free(&curlist);
1405 return NULL;
1406}
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:310
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:48
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:158
static struct Pattern * attach_new_root(struct PatternList **curlist)
Create a new Pattern as a parent for a List.
Definition: compile.c:1123
static struct Pattern * attach_new_leaf(struct PatternList **curlist)
Attach a new Pattern to a List.
Definition: compile.c:1139
static struct Pattern * attach_leaf(struct PatternList *list, struct Pattern *leaf)
Attach a Pattern to a Pattern List.
Definition: compile.c:1101
static char * find_matching_paren(char *s)
Find the matching parenthesis.
Definition: compile.c:1016
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:1160
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:1038
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:155
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:628
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:977
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:932
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:80
#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:428
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:544
const struct PatternFlags * lookup_tag(char tag)
Lookup a pattern modifier.
Definition: flags.c:197
#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 116 of file pattern.c.

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

1039{
1040 if (!pat || !*pat)
1041 return;
1042
1043 struct Pattern *np = SLIST_FIRST(*pat), *next = NULL;
1044
1045 while (np)
1046 {
1047 next = SLIST_NEXT(np, entries);
1048
1049 if (np->is_multi)
1051 else if (np->string_match || np->dynamic)
1052 FREE(&np->p.str);
1053 else if (np->group_match)
1054 np->p.group = NULL;
1055 else if (np->p.regex)
1056 {
1057 regfree(np->p.regex);
1058 FREE(&np->p.regex);
1059 }
1060
1061#ifdef USE_DEBUG_GRAPHVIZ
1062 FREE(&np->raw_pattern);
1063#endif
1065 FREE(&np);
1066
1067 np = next;
1068 }
1069
1070 FREE(pat);
1071}
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:1061
@ 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:74
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:604
@ 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:69
struct MuttWindow * win
Window holding the Menu.
Definition: lib.h:76
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()

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

473{
474 return mutt_is_predicate_recipient(all_addr, env, &mutt_is_mail_list);
475}
static int 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:435
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()

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

460{
462}
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 343 of file pattern.c.

344{
345 if (!mv || !mv->mailbox)
346 return -1;
347
348 struct Mailbox *m = mv->mailbox;
349
350 struct Buffer *err = NULL;
351 int rc = -1;
352 struct Progress *progress = NULL;
353 struct Buffer *buf = mutt_buffer_pool_get();
354
356 if (prompt || (op != MUTT_LIMIT))
357 {
359 false, NULL, NULL, NULL) != 0) ||
361 {
363 return -1;
364 }
365 }
366
367 mutt_message(_("Compiling search pattern..."));
368
369 char *simple = mutt_buffer_strdup(buf);
370 const char *const c_simple_search = cs_subset_string(NeoMutt->sub, "simple_search");
371 mutt_check_simple(buf, NONULL(c_simple_search));
372 const char *pbuf = buf->data;
373 while (*pbuf == ' ')
374 pbuf++;
375 const bool match_all = mutt_str_equal(pbuf, "~A");
376
377 err = mutt_buffer_pool_get();
378 struct PatternList *pat = mutt_pattern_comp(m, mv->menu, buf->data, MUTT_PC_FULL_MSG, err);
379 if (!pat)
380 {
381 mutt_error("%s", mutt_buffer_string(err));
382 goto bail;
383 }
384
385#ifdef USE_IMAP
386 if ((m->type == MUTT_IMAP) && (!imap_search(m, pat)))
387 goto bail;
388#endif
389
390 progress = progress_new(_("Executing command on matching messages..."), MUTT_PROGRESS_READ,
391 (op == MUTT_LIMIT) ? m->msg_count : m->vcount);
392
393 if (op == MUTT_LIMIT)
394 {
395 m->vcount = 0;
396 mv->vsize = 0;
397 mv->collapsed = false;
398 int padding = mx_msg_padding_size(m);
399
400 for (int i = 0; i < m->msg_count; i++)
401 {
402 struct Email *e = m->emails[i];
403 if (!e)
404 break;
405
406 progress_update(progress, i, -1);
407 /* new limit pattern implicitly uncollapses all threads */
408 e->vnum = -1;
409 e->visible = false;
410 e->collapsed = false;
411 e->num_hidden = 0;
412 if (match_all ||
414 {
415 e->vnum = m->vcount;
416 e->visible = true;
417 m->v2r[m->vcount] = i;
418 m->vcount++;
419 struct Body *b = e->body;
420 mv->vsize += b->length + b->offset - b->hdr_offset + padding;
421 }
422 }
423 }
424 else
425 {
426 for (int i = 0; i < m->vcount; i++)
427 {
428 struct Email *e = mutt_get_virt_email(m, i);
429 if (!e)
430 continue;
431 progress_update(progress, i, -1);
433 {
434 switch (op)
435 {
436 case MUTT_UNDELETE:
437 mutt_set_flag(m, e, MUTT_PURGE, false);
438 /* fallthrough */
439 case MUTT_DELETE:
440 mutt_set_flag(m, e, MUTT_DELETE, (op == MUTT_DELETE));
441 break;
442 case MUTT_TAG:
443 case MUTT_UNTAG:
444 mutt_set_flag(m, e, MUTT_TAG, (op == MUTT_TAG));
445 break;
446 }
447 }
448 }
449 }
450 progress_free(&progress);
451
453
454 if (op == MUTT_LIMIT)
455 {
456 /* drop previous limit pattern */
457 FREE(&mv->pattern);
459
460 if (m->msg_count && !m->vcount)
461 mutt_error(_("No messages matched criteria"));
462
463 /* record new limit pattern, unless match all */
464 if (!match_all)
465 {
466 mv->pattern = simple;
467 simple = NULL; /* don't clobber it */
468 mv->limit_pattern = mutt_pattern_comp(m, mv->menu, buf->data, MUTT_PC_FULL_MSG, err);
469 }
470 }
471
472 rc = 0;
473
474bail:
477 FREE(&simple);
478 mutt_pattern_free(&pat);
479
480 return rc;
481}
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:250
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:430
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:1107
#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:61
@ MUTT_UNDELETE
Messages to be un-deleted.
Definition: mutt.h:96
@ MUTT_LIMIT
Messages in limited view.
Definition: mutt.h:102
@ MUTT_UNTAG
Messages to be un-tagged.
Definition: mutt.h:101
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:97
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:100
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:95
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:62
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:1549
#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:116
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:64
#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:121
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:120
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:114
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 243 of file pattern.c.

244{
245 int rc = -1;
246 struct Progress *progress = NULL;
247 struct Buffer *buf = mutt_buffer_pool_get();
248
249 mutt_buffer_strcpy(buf, mdata->limit);
250 if (prompt)
251 {
253 false, NULL, NULL, NULL) != 0) ||
255 {
257 return -1;
258 }
259 }
260
261 mutt_message(_("Compiling search pattern..."));
262
263 bool match_all = false;
264 struct PatternList *pat = NULL;
265 char *simple = mutt_buffer_strdup(buf);
266 if (simple)
267 {
269 const char *pbuf = buf->data;
270 while (*pbuf == ' ')
271 pbuf++;
272 match_all = mutt_str_equal(pbuf, "~A");
273
274 struct Buffer err = mutt_buffer_make(0);
275 pat = mutt_pattern_comp(NULL, menu, buf->data, MUTT_PC_FULL_MSG, &err);
276 if (!pat)
277 {
278 mutt_error("%s", mutt_buffer_string(&err));
280 goto bail;
281 }
282 }
283 else
284 {
285 match_all = true;
286 }
287
288 progress = progress_new(_("Executing command on matching messages..."),
290
291 int vcounter = 0;
292 struct AliasView *avp = NULL;
293 ARRAY_FOREACH(avp, &mdata->ava)
294 {
295 progress_update(progress, ARRAY_FOREACH_IDX, -1);
296
297 if (match_all ||
299 {
300 avp->is_visible = true;
301 vcounter++;
302 }
303 else
304 {
305 avp->is_visible = false;
306 }
307 }
308 progress_free(&progress);
309
310 FREE(&mdata->limit);
311 if (!match_all)
312 {
313 mdata->limit = simple;
314 simple = NULL;
315 }
316
317 if (menu)
318 {
319 menu->max = vcounter;
320 menu_set_index(menu, 0);
321 }
322
324
325 rc = 0;
326
327bail:
329 FREE(&simple);
330 mutt_pattern_free(&pat);
331
332 return rc;
333}
#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:63
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:292
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:1134
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:71
+ 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 492 of file pattern.c.

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

653{
654 struct Progress *progress = NULL;
655 const struct AliasMenuData *mdata = menu->mdata;
656 const struct AliasViewArray *ava = &mdata->ava;
657 struct Buffer *buf = NULL;
658 int rc = -1;
659
660 if ((*LastSearch == '\0') || ((op != OP_SEARCH_NEXT) && (op != OP_SEARCH_OPPOSITE)))
661 {
662 buf = mutt_buffer_pool_get();
663 mutt_buffer_strcpy(buf, (LastSearch[0] != '\0') ? LastSearch : "");
664 if ((mutt_buffer_get_field(((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ?
665 _("Search for: ") :
666 _("Reverse search for: "),
668 NULL, NULL, NULL) != 0) ||
670 {
671 goto done;
672 }
673
674 if ((op == OP_SEARCH) || (op == OP_SEARCH_NEXT))
675 OptSearchReverse = false;
676 else
677 OptSearchReverse = true;
678
679 /* compare the *expanded* version of the search pattern in case
680 * $simple_search has changed while we were searching */
681 struct Buffer *tmp = mutt_buffer_pool_get();
682 mutt_buffer_copy(tmp, buf);
684
686 {
687 struct Buffer err;
688 mutt_buffer_init(&err);
689 OptSearchInvalid = true;
692 mutt_message(_("Compiling search pattern..."));
694 err.dsize = 256;
695 err.data = mutt_mem_malloc(err.dsize);
696 SearchPattern = mutt_pattern_comp(NULL, menu, tmp->data, MUTT_PC_FULL_MSG, &err);
697 if (!SearchPattern)
698 {
700 mutt_error("%s", err.data);
701 FREE(&err.data);
702 LastSearch[0] = '\0';
703 LastSearchExpn[0] = '\0';
704 return -1;
705 }
706 FREE(&err.data);
708 }
709
711 }
712
714 {
715 struct AliasView *av = NULL;
716 ARRAY_FOREACH(av, ava)
717 {
718 av->is_searched = false;
719 }
720
721 OptSearchInvalid = false;
722 }
723
724 int incr = OptSearchReverse ? -1 : 1;
725 if (op == OP_SEARCH_OPPOSITE)
726 incr = -incr;
727
728 progress = progress_new(_("Searching..."), MUTT_PROGRESS_READ, ARRAY_SIZE(ava));
729
730 for (int i = cur + incr, j = 0; j != ARRAY_SIZE(ava); j++)
731 {
732 const char *msg = NULL;
733 progress_update(progress, j, -1);
734 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
735 if (i > ARRAY_SIZE(ava) - 1)
736 {
737 i = 0;
738 if (c_wrap_search)
739 msg = _("Search wrapped to top");
740 else
741 {
742 mutt_message(_("Search hit bottom without finding match"));
743 goto done;
744 }
745 }
746 else if (i < 0)
747 {
748 i = ARRAY_SIZE(ava) - 1;
749 if (c_wrap_search)
750 msg = _("Search wrapped to bottom");
751 else
752 {
753 mutt_message(_("Search hit top without finding match"));
754 goto done;
755 }
756 }
757
758 struct AliasView *av = ARRAY_GET(ava, i);
759 if (av->is_searched)
760 {
761 /* if we've already evaluated this message, use the cached value */
762 if (av->is_matched)
763 {
765 if (msg && *msg)
766 mutt_message(msg);
767 rc = i;
768 goto done;
769 }
770 }
771 else
772 {
773 /* remember that we've already searched this message */
774 av->is_searched = true;
776 MUTT_MATCH_FULL_ADDRESS, av, NULL);
777 if (av->is_matched > 0)
778 {
780 if (msg && *msg)
781 mutt_message(msg);
782 rc = i;
783 goto done;
784 }
785 }
786
787 if (SigInt)
788 {
789 mutt_error(_("Search interrupted"));
790 SigInt = false;
791 goto done;
792 }
793
794 i += incr;
795 }
796
797 mutt_error(_("Not found"));
798done:
799 progress_free(&progress);
801 return rc;
802}
#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:137
+ 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 195 of file pattern.c.

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