NeoMutt  2021-10-29-220-g2b1eec
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 *e)
 Matches known mailing lists. More...
 
int mutt_is_subscribed_list_recipient (bool all_addr, struct Envelope *e)
 Matches subscribed mailing lists. More...
 
int mutt_pattern_func (struct Context *ctx, 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 Context *ctx, 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 57 of file lib.h.

◆ MUTT_PC_NO_FLAGS

#define MUTT_PC_NO_FLAGS   0

No flags are set.

Definition at line 60 of file lib.h.

◆ MUTT_PC_FULL_MSG

#define MUTT_PC_FULL_MSG   (1 << 0)

Enable body and header matching.

Definition at line 61 of file lib.h.

◆ MUTT_PC_PATTERN_DYNAMIC

#define MUTT_PC_PATTERN_DYNAMIC   (1 << 1)

Enable runtime date range evaluation.

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

◆ MUTT_PAT_EXEC_NO_FLAGS

#define MUTT_PAT_EXEC_NO_FLAGS   0

No flags are set.

Definition at line 94 of file lib.h.

◆ MUTT_MATCH_FULL_ADDRESS

#define MUTT_MATCH_FULL_ADDRESS   (1 << 0)

Match the full address.

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

◆ PatternExecFlags

typedef uint8_t PatternExecFlags

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

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

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

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

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

1137 {
1138  switch (pat->op)
1139  {
1140  case MUTT_PAT_FROM: /* alias */
1141  if (!av->alias)
1142  return false;
1143  return pat->pat_not ^ (av->alias->name && patmatch(pat, av->alias->name));
1144  case MUTT_PAT_CC: /* comment */
1145  if (!av->alias)
1146  return false;
1147  return pat->pat_not ^ (av->alias->comment && patmatch(pat, av->alias->comment));
1148  case MUTT_PAT_TO: /* alias address list */
1149  if (!av->alias)
1150  return false;
1151  return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
1152  1, &av->alias->addr);
1153  case MUTT_PAT_AND:
1154  return pat->pat_not ^ (perform_alias_and(pat->child, flags, av, cache) > 0);
1155  case MUTT_PAT_OR:
1156  return pat->pat_not ^ (perform_alias_or(pat->child, flags, av, cache) > 0);
1157  }
1158 
1159  return false;
1160 }
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:310
static int match_addrlist(struct Pattern *pat, bool match_personal, int n,...)
Match a Pattern against an Address list.
Definition: exec.c:384
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:359
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: lib.h:95
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:82
short op
Operation, e.g. MUTT_PAT_SCORE.
Definition: lib.h:70
bool pat_not
Pattern should be inverted (not)
Definition: lib.h:71
+ 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 1092 of file compile.c.

1094 {
1095  /* curlist when assigned will always point to a list containing at least one node
1096  * with a Pattern value. */
1097  struct PatternList *curlist = NULL;
1098  struct PatternList *tmp = NULL, *tmp2 = NULL;
1099  struct PatternList *last = NULL;
1100  bool pat_not = false;
1101  bool all_addr = false;
1102  bool pat_or = false;
1103  bool implicit = true; /* used to detect logical AND operator */
1104  bool is_alias = false;
1105  const struct PatternFlags *entry = NULL;
1106  char *p = NULL;
1107  char *buf = NULL;
1108  struct Buffer ps;
1109 
1110  if (!s || (s[0] == '\0'))
1111  {
1112  mutt_buffer_strcpy(err, _("empty pattern"));
1113  return NULL;
1114  }
1115 
1116  mutt_buffer_init(&ps);
1117  ps.dptr = (char *) s;
1118  ps.dsize = mutt_str_len(s);
1119 
1120  while (*ps.dptr)
1121  {
1122  SKIPWS(ps.dptr);
1123  switch (*ps.dptr)
1124  {
1125  case '^':
1126  ps.dptr++;
1127  all_addr = !all_addr;
1128  break;
1129  case '!':
1130  ps.dptr++;
1131  pat_not = !pat_not;
1132  break;
1133  case '@':
1134  ps.dptr++;
1135  is_alias = !is_alias;
1136  break;
1137  case '|':
1138  if (!pat_or)
1139  {
1140  if (!curlist)
1141  {
1142  mutt_buffer_printf(err, _("error in pattern at: %s"), ps.dptr);
1143  return NULL;
1144  }
1145 
1146  struct Pattern *pat = SLIST_FIRST(curlist);
1147 
1148  if (SLIST_NEXT(pat, entries))
1149  {
1150  /* A & B | C == (A & B) | C */
1151  tmp = mutt_pattern_node_new();
1152  pat = SLIST_FIRST(tmp);
1153  pat->op = MUTT_PAT_AND;
1154  pat->child = curlist;
1155 
1156  curlist = tmp;
1157  last = curlist;
1158  }
1159 
1160  pat_or = true;
1161  }
1162  ps.dptr++;
1163  implicit = false;
1164  pat_not = false;
1165  all_addr = false;
1166  is_alias = false;
1167  break;
1168  case '%':
1169  case '=':
1170  case '~':
1171  {
1172  struct Pattern *pat = NULL;
1173  if (ps.dptr[1] == '\0')
1174  {
1175  mutt_buffer_printf(err, _("missing pattern: %s"), ps.dptr);
1176  goto cleanup;
1177  }
1178  short thread_op = 0;
1179  if (ps.dptr[1] == '(')
1180  thread_op = MUTT_PAT_THREAD;
1181  else if ((ps.dptr[1] == '<') && (ps.dptr[2] == '('))
1182  thread_op = MUTT_PAT_PARENT;
1183  else if ((ps.dptr[1] == '>') && (ps.dptr[2] == '('))
1184  thread_op = MUTT_PAT_CHILDREN;
1185  if (thread_op != 0)
1186  {
1187  ps.dptr++; /* skip ~ */
1188  if ((thread_op == MUTT_PAT_PARENT) || (thread_op == MUTT_PAT_CHILDREN))
1189  ps.dptr++;
1190  p = find_matching_paren(ps.dptr + 1);
1191  if (p[0] != ')')
1192  {
1193  mutt_buffer_printf(err, _("mismatched parentheses: %s"), ps.dptr);
1194  goto cleanup;
1195  }
1196  tmp = mutt_pattern_node_new();
1197  pat = SLIST_FIRST(tmp);
1198  pat->op = thread_op;
1199  if (last)
1200  {
1201  SLIST_NEXT(SLIST_FIRST(last), entries) = pat;
1202  if (last != curlist)
1203  FREE(&last);
1204  }
1205  else
1206  {
1207  curlist = tmp;
1208  }
1209  last = tmp;
1210  pat->pat_not ^= pat_not;
1211  pat->all_addr |= all_addr;
1212  pat->is_alias |= is_alias;
1213  pat_not = false;
1214  all_addr = false;
1215  is_alias = false;
1216  /* compile the sub-expression */
1217  buf = mutt_strn_dup(ps.dptr + 1, p - (ps.dptr + 1));
1218  tmp2 = mutt_pattern_comp(m, menu, buf, flags, err);
1219  if (!tmp2)
1220  {
1221  FREE(&buf);
1222  goto cleanup;
1223  }
1224  FREE(&buf);
1225  pat->child = tmp2;
1226  ps.dptr = p + 1; /* restore location */
1227  SKIPWS(ps.dptr);
1228  break;
1229  }
1230  if (implicit && pat_or)
1231  {
1232  /* A | B & C == (A | B) & C */
1233  tmp = mutt_pattern_node_new();
1234  pat = SLIST_FIRST(tmp);
1235  pat->op = MUTT_PAT_OR;
1236  pat->child = curlist;
1237  curlist = tmp;
1238  last = tmp;
1239  pat_or = false;
1240  }
1241 
1242  tmp = mutt_pattern_node_new();
1243  pat = SLIST_FIRST(tmp);
1244  pat->pat_not = pat_not;
1245  pat->all_addr = all_addr;
1246  pat->is_alias = is_alias;
1247  pat->string_match = (ps.dptr[0] == '=');
1248  pat->group_match = (ps.dptr[0] == '%');
1249  pat_not = false;
1250  all_addr = false;
1251  is_alias = false;
1252 
1253  if (last)
1254  SLIST_NEXT(SLIST_FIRST(last), entries) = pat;
1255  else
1256  curlist = tmp;
1257  if (curlist != last)
1258  FREE(&last);
1259  last = tmp;
1260 
1261  ps.dptr++; /* move past the ~ */
1262  entry = lookup_tag(*ps.dptr);
1263  if (!entry)
1264  {
1265  mutt_buffer_printf(err, _("%c: invalid pattern modifier"), *ps.dptr);
1266  goto cleanup;
1267  }
1268  if (entry->flags && ((flags & entry->flags) == 0))
1269  {
1270  mutt_buffer_printf(err, _("%c: not supported in this mode"), *ps.dptr);
1271  goto cleanup;
1272  }
1273  if (flags & MUTT_PC_SEND_MODE_SEARCH)
1274  pat->sendmode = true;
1275 
1276  pat->op = entry->op;
1277 
1278  ps.dptr++; /* eat the operator and any optional whitespace */
1279  SKIPWS(ps.dptr);
1280 
1281  if (entry->eat_arg)
1282  {
1283  if (ps.dptr[0] == '\0')
1284  {
1285  mutt_buffer_printf(err, "%s", _("missing parameter"));
1286  goto cleanup;
1287  }
1288  switch (entry->eat_arg)
1289  {
1290  case EAT_REGEX:
1291  if (!eat_regex(pat, flags, &ps, err))
1292  goto cleanup;
1293  break;
1294  case EAT_DATE:
1295  if (!eat_date(pat, flags, &ps, err))
1296  goto cleanup;
1297  break;
1298  case EAT_RANGE:
1299  if (!eat_range(pat, flags, &ps, err))
1300  goto cleanup;
1301  break;
1302  case EAT_MESSAGE_RANGE:
1303  if (!eat_message_range(pat, flags, &ps, err, m, menu))
1304  goto cleanup;
1305  break;
1306  case EAT_QUERY:
1307  if (!eat_query(pat, flags, &ps, err, m))
1308  goto cleanup;
1309  break;
1310  default:
1311  break;
1312  }
1313  }
1314  implicit = true;
1315  break;
1316  }
1317 
1318  case '(':
1319  {
1320  p = find_matching_paren(ps.dptr + 1);
1321  if (p[0] != ')')
1322  {
1323  mutt_buffer_printf(err, _("mismatched parentheses: %s"), ps.dptr);
1324  goto cleanup;
1325  }
1326  /* compile the sub-expression */
1327  buf = mutt_strn_dup(ps.dptr + 1, p - (ps.dptr + 1));
1328  tmp = mutt_pattern_comp(m, menu, buf, flags, err);
1329  FREE(&buf);
1330  if (!tmp)
1331  goto cleanup;
1332  struct Pattern *pat = SLIST_FIRST(tmp);
1333  if (last)
1334  SLIST_NEXT(SLIST_FIRST(last), entries) = pat;
1335  else
1336  curlist = tmp;
1337  last = tmp;
1338  pat = SLIST_FIRST(tmp);
1339  pat->pat_not ^= pat_not;
1340  pat->all_addr |= all_addr;
1341  pat->is_alias |= is_alias;
1342  pat_not = false;
1343  all_addr = false;
1344  is_alias = false;
1345  ps.dptr = p + 1; /* restore location */
1346  SKIPWS(ps.dptr);
1347  break;
1348  }
1349 
1350  default:
1351  mutt_buffer_printf(err, _("error in pattern at: %s"), ps.dptr);
1352  goto cleanup;
1353  }
1354  }
1355  if (!curlist)
1356  {
1357  mutt_buffer_strcpy(err, _("empty pattern"));
1358  return NULL;
1359  }
1360  if (curlist != tmp)
1361  FREE(&tmp);
1362  if (SLIST_NEXT(SLIST_FIRST(curlist), entries))
1363  {
1364  tmp = mutt_pattern_node_new();
1365  struct Pattern *pat = SLIST_FIRST(tmp);
1366  pat->op = pat_or ? MUTT_PAT_OR : MUTT_PAT_AND;
1367  pat->child = curlist;
1368  curlist = tmp;
1369  }
1370 
1371  return curlist;
1372 
1373 cleanup:
1374  mutt_pattern_free(&curlist);
1375  return NULL;
1376 }
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:46
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
static struct PatternList * mutt_pattern_node_new(void)
Create a new list containing a Pattern.
Definition: compile.c:1074
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:1092
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:627
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:976
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:931
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:40
#define _(a)
Definition: message.h:28
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:359
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:475
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:63
@ EAT_RANGE
Process a number (range)
Definition: private.h:41
@ EAT_MESSAGE_RANGE
Process a message number (range)
Definition: private.h:42
@ EAT_DATE
Process a date (range)
Definition: private.h:40
@ EAT_QUERY
Process a query string.
Definition: private.h:43
@ EAT_REGEX
Process a regex.
Definition: private.h:39
#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:50
enum PatternEat eat_arg
Type of function needed to parse flag, e.g. EAT_DATE.
Definition: private.h:55
PatternCompFlags flags
Pattern flags, e.g. MUTT_PC_FULL_MSG.
Definition: private.h:53
int op
Operation to perform, e.g. MUTT_PAT_SCORE.
Definition: private.h:52
A simple (non-regex) pattern.
Definition: lib.h:69
bool group_match
Check a group of Addresses.
Definition: lib.h:74
union Pattern::@1 p
bool all_addr
All Addresses in the list must match.
Definition: lib.h:72
bool string_match
Check a string for a match.
Definition: lib.h:73
bool is_alias
Is there an alias for this Address?
Definition: lib.h:76
bool sendmode
Evaluate searches in send-mode.
Definition: lib.h:78
+ 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)) ||
138  mutt_str_equal("^", 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();
162  quote_simple(mutt_buffer_string(buf), tmp);
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:1478
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:727
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:715
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  mutt_pattern_free(&np->child);
1062  FREE(&np);
1063 
1064  np = next;
1065  }
1066 
1067  FREE(pat);
1068 }
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:85
regex_t * regex
Compiled regex, for non-pattern matching.
Definition: lib.h:84
struct ListHead multi_cases
Multiple strings for ~I pattern.
Definition: lib.h:87
char * str
String, if string_match is set.
Definition: lib.h:86
bool dynamic
Evaluate date ranges at run time.
Definition: lib.h:77
bool is_multi
Multiple case (only for ~I pattern now)
Definition: lib.h:79
+ 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 343 of file dlgpattern.c.

344 {
346  struct Menu *menu = create_pattern_menu(dlg);
347 
348  struct MuttWindow *win_menu = menu->win;
349 
350  // NT_COLOR is handled by the SimpleDialog
353 
354  bool rc = false;
355  bool done = false;
356  while (!done)
357  {
358  switch (menu_loop(menu))
359  {
360  case OP_GENERIC_SELECT_ENTRY:
361  {
362  const int index = menu_get_index(menu);
363  struct PatternEntry *entry = ((struct PatternEntry *) menu->mdata) + index;
364  mutt_str_copy(buf, entry->tag, buflen);
365  rc = true;
366  done = true;
367  break;
368  }
369 
370  case OP_EXIT:
371  done = true;
372  break;
373  }
374  }
375 
376  simple_dialog_free(&dlg);
377  return rc;
378 }
static struct Menu * create_pattern_menu(struct MuttWindow *dlg)
Create the Pattern Completion menu.
Definition: dlgpattern.c:177
static const struct Mapping PatternHelp[]
Help Bar for the Pattern selection dialog.
Definition: dlgpattern.c:97
static int pattern_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition: dlgpattern.c:315
static int pattern_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: dlgpattern.c:291
struct MuttWindow * simple_dialog_new(enum MenuType mtype, enum WindowType wtype, const struct Mapping *help_data)
Create a simple index Dialog.
Definition: simple.c:126
void simple_dialog_free(struct MuttWindow **ptr)
Destroy a simple index Dialog.
Definition: simple.c:163
int menu_get_index(struct Menu *menu)
Get the current selection in the Menu.
Definition: menu.c:624
int menu_loop(struct Menu *menu)
Menu event loop.
Definition: menu.c:295
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
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:560
@ WT_DLG_PATTERN
Pattern Dialog, create_pattern_menu()
Definition: mutt_window.h:87
@ NT_WINDOW
MuttWindow has changed, NotifyWindow, EventWindow.
Definition: notify_type.h:53
@ NT_CONFIG
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:42
Definition: lib.h:69
struct MuttWindow * win
Window holding the Menu.
Definition: lib.h:76
void * mdata
Private data.
Definition: lib.h:154
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
A line in the Pattern Completion menu.
Definition: dlgpattern.c:89
const char * tag
Copied to buffer if selected.
Definition: dlgpattern.c:91
@ 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 e 
)

Matches known mailing lists.

Parameters
all_addrIf true, ALL Addresses must be mailing lists
eEnvelope
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 473 of file exec.c.

474 {
475  return mutt_is_predicate_recipient(all_addr, e, &mutt_is_mail_list);
476 }
static int mutt_is_predicate_recipient(bool all_addr, struct Envelope *e, addr_predicate_t p)
Test an Envelopes Addresses using a predicate function.
Definition: exec.c:436
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 e 
)

Matches subscribed mailing lists.

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

Definition at line 460 of file exec.c.

461 {
463 }
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 Context ctx,
int  op,
char *  prompt 
)

Perform some Pattern matching.

Parameters
ctxCurrent Mailbox
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 (!ctx || !ctx->mailbox)
346  return -1;
347 
348  struct Mailbox *m = ctx->mailbox;
349 
350  struct Buffer err;
351  int rc = -1;
352  struct Progress *progress = NULL;
353  struct Buffer *buf = mutt_buffer_pool_get();
354 
355  mutt_buffer_strcpy(buf, NONULL(ctx->pattern));
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 =
371  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  mutt_buffer_init(&err);
379  err.dsize = 256;
380  err.data = mutt_mem_malloc(err.dsize);
381  struct PatternList *pat =
382  mutt_pattern_comp(m, ctx->menu, buf->data, MUTT_PC_FULL_MSG, &err);
383  if (!pat)
384  {
385  mutt_error("%s", err.data);
386  goto bail;
387  }
388 
389 #ifdef USE_IMAP
390  if ((m->type == MUTT_IMAP) && (!imap_search(m, pat)))
391  goto bail;
392 #endif
393 
394  progress = progress_new(_("Executing command on matching messages..."), MUTT_PROGRESS_READ,
395  (op == MUTT_LIMIT) ? m->msg_count : m->vcount);
396 
397  if (op == MUTT_LIMIT)
398  {
399  m->vcount = 0;
400  ctx->vsize = 0;
401  ctx->collapsed = false;
402  int padding = mx_msg_padding_size(m);
403 
404  for (int i = 0; i < m->msg_count; i++)
405  {
406  struct Email *e = m->emails[i];
407  if (!e)
408  break;
409 
410  progress_update(progress, i, -1);
411  /* new limit pattern implicitly uncollapses all threads */
412  e->vnum = -1;
413  e->visible = false;
414  e->collapsed = false;
415  e->num_hidden = 0;
416  if (match_all ||
418  {
419  e->vnum = m->vcount;
420  e->visible = true;
421  m->v2r[m->vcount] = i;
422  m->vcount++;
423  struct Body *b = e->body;
424  ctx->vsize += b->length + b->offset - b->hdr_offset + padding;
425  }
426  }
427  }
428  else
429  {
430  for (int i = 0; i < m->vcount; i++)
431  {
432  struct Email *e = mutt_get_virt_email(m, i);
433  if (!e)
434  continue;
435  progress_update(progress, i, -1);
437  {
438  switch (op)
439  {
440  case MUTT_UNDELETE:
441  mutt_set_flag(m, e, MUTT_PURGE, false);
442  /* fallthrough */
443  case MUTT_DELETE:
444  mutt_set_flag(m, e, MUTT_DELETE, (op == MUTT_DELETE));
445  break;
446  case MUTT_TAG:
447  case MUTT_UNTAG:
448  mutt_set_flag(m, e, MUTT_TAG, (op == MUTT_TAG));
449  break;
450  }
451  }
452  }
453  }
454  progress_free(&progress);
455 
457 
458  if (op == MUTT_LIMIT)
459  {
460  /* drop previous limit pattern */
461  FREE(&ctx->pattern);
463 
464  if (m->msg_count && !m->vcount)
465  mutt_error(_("No messages matched criteria"));
466 
467  /* record new limit pattern, unless match all */
468  if (!match_all)
469  {
470  ctx->pattern = simple;
471  simple = NULL; /* don't clobber it */
472  ctx->limit_pattern =
473  mutt_pattern_comp(m, ctx->menu, buf->data, MUTT_PC_FULL_MSG, &err);
474  }
475  }
476 
477  rc = 0;
478 
479 bail:
481  FREE(&simple);
482  mutt_pattern_free(&pat);
483  FREE(&err.data);
484 
485  return rc;
486 }
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:432
struct Email * mutt_get_virt_email(struct Mailbox *m, int vnum)
Get a virtual Email.
Definition: context.c:412
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: curs_lib.c:267
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:1108
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
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:53
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define MUTT_COMP_PATTERN
Pattern mode (in pattern dialog)
Definition: mutt.h:61
@ MUTT_UNDELETE
Messages to be un-deleted.
Definition: mutt.h:95
@ MUTT_LIMIT
Messages in limited view.
Definition: mutt.h:101
@ MUTT_UNTAG
Messages to be un-tagged.
Definition: mutt.h:100
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:96
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:99
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:94
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:62
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
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:61
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:46
void progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:177
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:232
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:252
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:66
#define NONULL(x)
Definition: string2.h:37
The body of an email.
Definition: body.h:35
LOFF_T offset
offset where the actual data begins
Definition: body.h:51
LOFF_T length
length (in bytes) of attachment
Definition: body.h:52
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:79
char * data
Pointer to data.
Definition: buffer.h:35
char * pattern
Limit pattern string.
Definition: context.h:40
struct Mailbox * mailbox
Current Mailbox.
Definition: context.h:49
off_t vsize
Size (in bytes) of the messages shown.
Definition: context.h:39
struct PatternList * limit_pattern
Compiled limit pattern.
Definition: context.h:41
bool collapsed
Are all threads collapsed?
Definition: context.h:47
struct Menu * menu
Needed for pattern compilation.
Definition: context.h:45
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
A mailbox.
Definition: mailbox.h:82
int vcount
The number of virtual messages.
Definition: mailbox.h:102
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:101
int msg_count
Total number of messages.
Definition: mailbox.h:91
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
A Progress Bar.
Definition: progress.c:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_pattern_alias_func()

int mutt_pattern_alias_func ( char *  prompt,
struct AliasMenuData mdata,
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->str);
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));
279  mutt_buffer_dealloc(&err);
280  goto bail;
281  }
282  }
283  else
284  {
285  match_all = true;
286  }
287 
288  progress = progress_new(_("Executing command on matching messages..."),
289  MUTT_PROGRESS_READ, ARRAY_SIZE(&mdata->ava));
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->str);
311  if (!match_all)
312  {
313  mdata->str = 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 
327 bail:
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:208
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:83
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
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:1135
MenuRedrawFlags menu_set_index(struct Menu *menu, int index)
Set the current selection in the Menu.
Definition: menu.c:638
#define MUTT_ALIAS_SIMPLESEARCH
Definition: lib.h:57
struct AliasViewArray ava
Array of AliasView.
Definition: gui.h:54
char * str
String representing the limit being used.
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 497 of file pattern.c.

498 {
499  struct Progress *progress = NULL;
500  struct Buffer *buf = NULL;
501  int rc = -1;
502 
503  if ((*LastSearch == '\0') || ((op != OP_SEARCH_NEXT) && (op != OP_SEARCH_OPPOSITE)))
504  {
505  buf = mutt_buffer_pool_get();
506  mutt_buffer_strcpy(buf, (LastSearch[0] != '\0') ? LastSearch : "");
508  ((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ? _("Search for: ") : _("Reverse search for: "),
509  buf, MUTT_COMP_CLEAR | MUTT_COMP_PATTERN, false, 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 =
525  cs_subset_string(NeoMutt->sub, "simple_search");
526  mutt_check_simple(tmp, NONULL(c_simple_search));
527 
529  {
530  struct Buffer err;
531  mutt_buffer_init(&err);
532  OptSearchInvalid = true;
535  mutt_message(_("Compiling search pattern..."));
537  err.dsize = 256;
538  err.data = mutt_mem_malloc(err.dsize);
539  SearchPattern = mutt_pattern_comp(m, menu, tmp->data, MUTT_PC_FULL_MSG, &err);
540  if (!SearchPattern)
541  {
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 
556  if (OptSearchInvalid)
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  msg = _("Search wrapped to top");
583  else
584  {
585  mutt_message(_("Search hit bottom without finding match"));
586  goto done;
587  }
588  }
589  else if (i < 0)
590  {
591  i = m->vcount - 1;
592  if (c_wrap_search)
593  msg = _("Search wrapped to bottom");
594  else
595  {
596  mutt_message(_("Search hit top without finding match"));
597  goto done;
598  }
599  }
600 
601  struct Email *e = mutt_get_virt_email(m, i);
602  if (e->searched)
603  {
604  /* if we've already evaluated this message, use the cached value */
605  if (e->matched)
606  {
608  if (msg && *msg)
609  mutt_message(msg);
610  rc = i;
611  goto done;
612  }
613  }
614  else
615  {
616  /* remember that we've already searched this message */
617  e->searched = true;
619  MUTT_MATCH_FULL_ADDRESS, m, e, NULL);
620  if (e->matched > 0)
621  {
623  if (msg && *msg)
624  mutt_message(msg);
625  rc = i;
626  goto done;
627  }
628  }
629 
630  if (SigInt)
631  {
632  mutt_error(_("Search interrupted"));
633  SigInt = false;
634  goto done;
635  }
636 
637  i += incr;
638  }
639 
640  mutt_error(_("Not found"));
641 done:
642  progress_free(&progress);
644  return rc;
645 }
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:447
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: mutt_globals.h:71
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 655 of file pattern.c.

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

Limit the email view to the current thread.

Parameters
ctxCurrent Mailbox
eCurrent Email
Return values
trueSuccess
falseFailure

Definition at line 195 of file pattern.c.

196 {
197  if (!ctx || !ctx->mailbox || !e)
198  return false;
199 
200  struct Mailbox *m = ctx->mailbox;
201 
202  struct MuttThread *me = top_of_thread(e);
203  if (!me)
204  return false;
205 
206  m->vcount = 0;
207  ctx->vsize = 0;
208  ctx->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  ctx->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: