NeoMutt  2024-04-25-76-g20fe7b
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
lib.h File Reference

Match patterns to emails. More...

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

Go to the source code of this file.

Data Structures

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

Macros

#define MUTT_ALIAS_SIMPLESEARCH   "~f %s | ~t %s | ~c %s"
 
#define MUTT_PC_NO_FLAGS   0
 No flags are set.
 
#define MUTT_PC_FULL_MSG   (1 << 0)
 Enable body and header matching.
 
#define MUTT_PC_PATTERN_DYNAMIC   (1 << 1)
 Enable runtime date range evaluation.
 
#define MUTT_PC_SEND_MODE_SEARCH   (1 << 2)
 Allow send-mode body searching.
 
#define MUTT_PAT_EXEC_NO_FLAGS   0
 No flags are set.
 
#define MUTT_MATCH_FULL_ADDRESS   (1 << 0)
 Match the full address.
 

Typedefs

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

Enumerations

enum  PatternType {
  MUTT_PAT_AND = MUTT_MT_MAX , MUTT_PAT_OR , MUTT_PAT_THREAD , MUTT_PAT_PARENT ,
  MUTT_PAT_CHILDREN , MUTT_PAT_TO , MUTT_PAT_CC , MUTT_PAT_BCC ,
  MUTT_PAT_COLLAPSED , MUTT_PAT_SUBJECT , MUTT_PAT_FROM , MUTT_PAT_DATE ,
  MUTT_PAT_DATE_RECEIVED , MUTT_PAT_DUPLICATED , MUTT_PAT_UNREFERENCED , MUTT_PAT_BROKEN ,
  MUTT_PAT_ID , MUTT_PAT_ID_EXTERNAL , MUTT_PAT_BODY , MUTT_PAT_HEADER ,
  MUTT_PAT_HORMEL , MUTT_PAT_WHOLE_MSG , MUTT_PAT_SENDER , MUTT_PAT_MESSAGE ,
  MUTT_PAT_SCORE , MUTT_PAT_SIZE , MUTT_PAT_REFERENCE , MUTT_PAT_RECIPIENT ,
  MUTT_PAT_LIST , MUTT_PAT_SUBSCRIBED_LIST , MUTT_PAT_PERSONAL_RECIP , MUTT_PAT_PERSONAL_FROM ,
  MUTT_PAT_ADDRESS , MUTT_PAT_CRYPT_SIGN , MUTT_PAT_CRYPT_VERIFIED , MUTT_PAT_CRYPT_ENCRYPT ,
  MUTT_PAT_PGP_KEY , MUTT_PAT_XLABEL , MUTT_PAT_SERVERSEARCH , MUTT_PAT_DRIVER_TAGS ,
  MUTT_PAT_MIMEATTACH , MUTT_PAT_MIMETYPE , MUTT_PAT_NEWSGROUPS , MUTT_PAT_MAX
}
 Types of pattern to match. More...
 

Functions

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

Variables

const struct CompleteOps CompletePatternOps
 Auto-Completion of Patterns.
 

Detailed Description

Match patterns to emails.

Authors
  • Richard Russon
  • Pietro Cerutti

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

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

Definition in file lib.h.

Macro Definition Documentation

◆ MUTT_ALIAS_SIMPLESEARCH

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

Definition at line 63 of file lib.h.

◆ MUTT_PC_NO_FLAGS

#define MUTT_PC_NO_FLAGS   0

No flags are set.

Definition at line 68 of file lib.h.

◆ MUTT_PC_FULL_MSG

#define MUTT_PC_FULL_MSG   (1 << 0)

Enable body and header matching.

Definition at line 69 of file lib.h.

◆ MUTT_PC_PATTERN_DYNAMIC

#define MUTT_PC_PATTERN_DYNAMIC   (1 << 1)

Enable runtime date range evaluation.

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

◆ MUTT_PAT_EXEC_NO_FLAGS

#define MUTT_PAT_EXEC_NO_FLAGS   0

No flags are set.

Definition at line 105 of file lib.h.

◆ MUTT_MATCH_FULL_ADDRESS

#define MUTT_MATCH_FULL_ADDRESS   (1 << 0)

Match the full address.

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

◆ PatternExecFlags

typedef uint8_t PatternExecFlags

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

Definition at line 104 of file lib.h.

Enumeration Type Documentation

◆ PatternType

Types of pattern to match.

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

Both patterns must match.

MUTT_PAT_OR 

Either pattern can match.

MUTT_PAT_THREAD 

Pattern matches email thread.

MUTT_PAT_PARENT 

Pattern matches parent.

MUTT_PAT_CHILDREN 

Pattern matches a child email.

MUTT_PAT_TO 

Pattern matches 'To:' field.

MUTT_PAT_CC 

Pattern matches 'Cc:' field.

MUTT_PAT_BCC 

Pattern matches 'Bcc:' field.

MUTT_PAT_COLLAPSED 

Thread is collapsed.

MUTT_PAT_SUBJECT 

Pattern matches 'Subject:' field.

MUTT_PAT_FROM 

Pattern matches 'From:' field.

MUTT_PAT_DATE 

Pattern matches 'Date:' field.

MUTT_PAT_DATE_RECEIVED 

Pattern matches date received.

MUTT_PAT_DUPLICATED 

Duplicate message.

MUTT_PAT_UNREFERENCED 

Message is unreferenced in the thread.

MUTT_PAT_BROKEN 

Message is part of a broken thread.

MUTT_PAT_ID 

Pattern matches email's Message-Id.

MUTT_PAT_ID_EXTERNAL 

Message-Id is among results from an external query.

MUTT_PAT_BODY 

Pattern matches email's body.

MUTT_PAT_HEADER 

Pattern matches email's header.

MUTT_PAT_HORMEL 

Pattern matches email's spam score.

MUTT_PAT_WHOLE_MSG 

Pattern matches raw email text.

MUTT_PAT_SENDER 

Pattern matches sender.

MUTT_PAT_MESSAGE 

Pattern matches message number.

MUTT_PAT_SCORE 

Pattern matches email's score.

MUTT_PAT_SIZE 

Pattern matches email's size.

MUTT_PAT_REFERENCE 

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

MUTT_PAT_RECIPIENT 

User is a recipient of the email.

MUTT_PAT_LIST 

Email is on mailing list.

MUTT_PAT_SUBSCRIBED_LIST 

Email is on subscribed mailing list.

MUTT_PAT_PERSONAL_RECIP 

Email is addressed to the user.

MUTT_PAT_PERSONAL_FROM 

Email is from the user.

MUTT_PAT_ADDRESS 

Pattern matches any address field.

MUTT_PAT_CRYPT_SIGN 

Message is signed.

MUTT_PAT_CRYPT_VERIFIED 

Message is crypographically verified.

MUTT_PAT_CRYPT_ENCRYPT 

Message is encrypted.

MUTT_PAT_PGP_KEY 

Message has PGP key.

MUTT_PAT_XLABEL 

Pattern matches keyword/label.

MUTT_PAT_SERVERSEARCH 

Server-side pattern matches.

MUTT_PAT_DRIVER_TAGS 

Pattern matches message tags.

MUTT_PAT_MIMEATTACH 

Pattern matches number of attachments.

MUTT_PAT_MIMETYPE 

Pattern matches MIME type.

MUTT_PAT_NEWSGROUPS 

Pattern matches newsgroup.

MUTT_PAT_MAX 

Definition at line 135 of file lib.h.

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

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

1134{
1135 const bool needs_msg = pattern_needs_msg(m, pat);
1136 struct Message *msg = needs_msg ? mx_msg_open(m, e) : NULL;
1137 if (needs_msg && !msg)
1138 {
1139 return false;
1140 }
1141 const bool matched = pattern_exec(pat, flags, m, e, msg, cache);
1142 mx_msg_close(m, &msg);
1143 return matched;
1144}
static bool pattern_needs_msg(const struct Mailbox *m, const struct Pattern *pat)
Check whether a pattern needs a full message.
Definition: exec.c:780
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:822
int mx_msg_close(struct Mailbox *m, struct Message **ptr)
Close a message.
Definition: mx.c:1180
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition: mx.c:1134
A local copy of an email.
Definition: message.h:34
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 1159 of file exec.c.

1161{
1162 switch (pat->op)
1163 {
1164 case MUTT_PAT_FROM: /* alias */
1165 if (!av->alias)
1166 return false;
1167 return pat->pat_not ^ (av->alias->name && patmatch(pat, av->alias->name));
1168 case MUTT_PAT_CC: /* comment */
1169 if (!av->alias)
1170 return false;
1171 return pat->pat_not ^ (av->alias->comment && patmatch(pat, av->alias->comment));
1172 case MUTT_PAT_TO: /* alias address list */
1173 if (!av->alias)
1174 return false;
1175 return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
1176 1, &av->alias->addr);
1178 {
1179 if (!av->alias)
1180 return false;
1181
1182 struct Buffer *tags = buf_pool_get();
1183 alias_tags_to_buffer(&av->alias->tags, tags);
1184
1185 bool rc = false;
1186 if (!buf_is_empty(tags))
1187 {
1188 rc = (pat->pat_not ^ (patmatch(pat, buf_string(tags))));
1189 }
1190
1191 buf_pool_release(&tags);
1192 return rc;
1193 }
1194
1195 case MUTT_PAT_AND:
1196 return pat->pat_not ^ (perform_alias_and(pat->child, flags, av, cache) > 0);
1197 case MUTT_PAT_OR:
1198 return pat->pat_not ^ (perform_alias_or(pat->child, flags, av, cache) > 0);
1199 }
1200
1201 return false;
1202}
void alias_tags_to_buffer(struct TagList *tl, struct Buffer *buf)
Write a comma-separated list of tags to a Buffer.
Definition: commands.c:49
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:291
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
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:327
static int match_addrlist(struct Pattern *pat, bool match_personal, int n,...)
Match a Pattern against an Address list.
Definition: exec.c:401
static bool patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: exec.c:72
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:376
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: lib.h:106
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
struct Alias * alias
Alias.
Definition: gui.h:46
struct TagList tags
Tags.
Definition: alias.h:39
char * comment
Free-form comment string.
Definition: alias.h:38
char * name
Short name.
Definition: alias.h:36
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:37
String manipulation buffer.
Definition: buffer.h:36
struct PatternList * child
Arguments to logical operation.
Definition: lib.h:90
short op
Operation, e.g. MUTT_PAT_SCORE.
Definition: lib.h:78
bool pat_not
Pattern should be inverted (not)
Definition: lib.h:79
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_pattern_comp()

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

Create a Pattern.

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

Definition at line 906 of file compile.c.

909{
910 /* curlist when assigned will always point to a list containing at least one node
911 * with a Pattern value. */
912 struct PatternList *curlist = NULL;
913 bool pat_not = false;
914 bool all_addr = false;
915 bool pat_or = false;
916 bool implicit = true; /* used to detect logical AND operator */
917 bool is_alias = false;
918 const struct PatternFlags *entry = NULL;
919 char *p = NULL;
920 char *buf = NULL;
921 struct Mailbox *m = mv ? mv->mailbox : NULL;
922
923 if (!s || (s[0] == '\0'))
924 {
925 buf_strcpy(err, _("empty pattern"));
926 return NULL;
927 }
928
929 struct Buffer *ps = buf_pool_get();
930 buf_strcpy(ps, s);
931 buf_seek(ps, 0);
932
933 SKIPWS(ps->dptr);
934 while (*ps->dptr)
935 {
936 switch (*ps->dptr)
937 {
938 case '^':
939 ps->dptr++;
940 all_addr = !all_addr;
941 break;
942 case '!':
943 ps->dptr++;
944 pat_not = !pat_not;
945 break;
946 case '@':
947 ps->dptr++;
948 is_alias = !is_alias;
949 break;
950 case '|':
951 if (!pat_or)
952 {
953 if (!curlist)
954 {
955 buf_printf(err, _("error in pattern at: %s"), ps->dptr);
956 buf_pool_release(&ps);
957 return NULL;
958 }
959
960 struct Pattern *pat = SLIST_FIRST(curlist);
961 if (SLIST_NEXT(pat, entries))
962 {
963 /* A & B | C == (A & B) | C */
964 struct Pattern *root = attach_new_root(&curlist);
965 root->op = MUTT_PAT_AND;
966 }
967
968 pat_or = true;
969 }
970 ps->dptr++;
971 implicit = false;
972 pat_not = false;
973 all_addr = false;
974 is_alias = false;
975 break;
976 case '%':
977 case '=':
978 case '~':
979 {
980 if (ps->dptr[1] == '\0')
981 {
982 buf_printf(err, _("missing pattern: %s"), ps->dptr);
983 goto cleanup;
984 }
985 short thread_op = 0;
986 if (ps->dptr[1] == '(')
987 thread_op = MUTT_PAT_THREAD;
988 else if ((ps->dptr[1] == '<') && (ps->dptr[2] == '('))
989 thread_op = MUTT_PAT_PARENT;
990 else if ((ps->dptr[1] == '>') && (ps->dptr[2] == '('))
991 thread_op = MUTT_PAT_CHILDREN;
992 if (thread_op != 0)
993 {
994 ps->dptr++; /* skip ~ */
995 if ((thread_op == MUTT_PAT_PARENT) || (thread_op == MUTT_PAT_CHILDREN))
996 ps->dptr++;
997 p = find_matching_paren(ps->dptr + 1);
998 if (p[0] != ')')
999 {
1000 buf_printf(err, _("mismatched parentheses: %s"), ps->dptr);
1001 goto cleanup;
1002 }
1003 struct Pattern *leaf = attach_new_leaf(&curlist);
1004 leaf->op = thread_op;
1005 leaf->pat_not = pat_not;
1006 leaf->all_addr = all_addr;
1007 leaf->is_alias = is_alias;
1008 pat_not = false;
1009 all_addr = false;
1010 is_alias = false;
1011 /* compile the sub-expression */
1012 buf = mutt_strn_dup(ps->dptr + 1, p - (ps->dptr + 1));
1013 leaf->child = mutt_pattern_comp(mv, menu, buf, flags, err);
1014 if (!leaf->child)
1015 {
1016 FREE(&buf);
1017 goto cleanup;
1018 }
1019 FREE(&buf);
1020 ps->dptr = p + 1; /* restore location */
1021 break;
1022 }
1023 if (implicit && pat_or)
1024 {
1025 /* A | B & C == (A | B) & C */
1026 struct Pattern *root = attach_new_root(&curlist);
1027 root->op = MUTT_PAT_OR;
1028 pat_or = false;
1029 }
1030
1031 entry = lookup_tag(ps->dptr[1]);
1032 if (!entry)
1033 {
1034 buf_printf(err, _("%c: invalid pattern modifier"), *ps->dptr);
1035 goto cleanup;
1036 }
1037 if (entry->flags && ((flags & entry->flags) == 0))
1038 {
1039 buf_printf(err, _("%c: not supported in this mode"), *ps->dptr);
1040 goto cleanup;
1041 }
1042
1043 struct Pattern *leaf = attach_new_leaf(&curlist);
1044 leaf->pat_not = pat_not;
1045 leaf->all_addr = all_addr;
1046 leaf->is_alias = is_alias;
1047 leaf->string_match = (ps->dptr[0] == '=');
1048 leaf->group_match = (ps->dptr[0] == '%');
1049 leaf->sendmode = (flags & MUTT_PC_SEND_MODE_SEARCH);
1050 leaf->op = entry->op;
1051 pat_not = false;
1052 all_addr = false;
1053 is_alias = false;
1054
1055 ps->dptr++; /* move past the ~ */
1056 ps->dptr++; /* eat the operator and any optional whitespace */
1057 SKIPWS(ps->dptr);
1058 if (entry->eat_arg)
1059 {
1060 if (ps->dptr[0] == '\0')
1061 {
1062 buf_addstr(err, _("missing parameter"));
1063 goto cleanup;
1064 }
1065 switch (entry->eat_arg)
1066 {
1067 case EAT_REGEX:
1068 if (!eat_regex(leaf, flags, ps, err))
1069 goto cleanup;
1070 break;
1071 case EAT_DATE:
1072 if (!eat_date(leaf, flags, ps, err))
1073 goto cleanup;
1074 break;
1075 case EAT_RANGE:
1076 if (!eat_range(leaf, flags, ps, err))
1077 goto cleanup;
1078 break;
1079 case EAT_MESSAGE_RANGE:
1080 if (!eat_message_range(leaf, flags, ps, err, mv))
1081 goto cleanup;
1082 break;
1083 case EAT_QUERY:
1084 if (!eat_query(leaf, flags, ps, err, m))
1085 goto cleanup;
1086 break;
1087 default:
1088 break;
1089 }
1090 }
1091 implicit = true;
1092 break;
1093 }
1094
1095 case '(':
1096 {
1097 p = find_matching_paren(ps->dptr + 1);
1098 if (p[0] != ')')
1099 {
1100 buf_printf(err, _("mismatched parentheses: %s"), ps->dptr);
1101 goto cleanup;
1102 }
1103 /* compile the sub-expression */
1104 buf = mutt_strn_dup(ps->dptr + 1, p - (ps->dptr + 1));
1105 struct PatternList *sub = mutt_pattern_comp(mv, menu, buf, flags, err);
1106 FREE(&buf);
1107 if (!sub)
1108 goto cleanup;
1109 struct Pattern *leaf = SLIST_FIRST(sub);
1110 if (curlist)
1111 {
1112 attach_leaf(curlist, leaf);
1113 FREE(&sub);
1114 }
1115 else
1116 {
1117 curlist = sub;
1118 }
1119 leaf->pat_not ^= pat_not;
1120 leaf->all_addr |= all_addr;
1121 leaf->is_alias |= is_alias;
1122 pat_not = false;
1123 all_addr = false;
1124 is_alias = false;
1125 ps->dptr = p + 1; /* restore location */
1126 break;
1127 }
1128
1129 default:
1130 buf_printf(err, _("error in pattern at: %s"), ps->dptr);
1131 goto cleanup;
1132 }
1133 SKIPWS(ps->dptr);
1134 }
1135 buf_pool_release(&ps);
1136
1137 if (!curlist)
1138 {
1139 buf_strcpy(err, _("empty pattern"));
1140 return NULL;
1141 }
1142
1143 if (SLIST_NEXT(SLIST_FIRST(curlist), entries))
1144 {
1145 struct Pattern *root = attach_new_root(&curlist);
1146 root->op = pat_or ? MUTT_PAT_OR : MUTT_PAT_AND;
1147 }
1148
1149 return curlist;
1150
1151cleanup:
1152 mutt_pattern_free(&curlist);
1153 buf_pool_release(&ps);
1154 return NULL;
1155}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:161
void buf_seek(struct Buffer *buf, size_t offset)
Set current read/write position to offset from beginning.
Definition: buffer.c:622
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:226
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:395
static struct Pattern * attach_new_root(struct PatternList **curlist)
Create a new Pattern as a parent for a List.
Definition: compile.c:869
static struct Pattern * attach_new_leaf(struct PatternList **curlist)
Attach a new Pattern to a List.
Definition: compile.c:885
static struct Pattern * attach_leaf(struct PatternList *list, struct Pattern *leaf)
Attach a Pattern to a Pattern List.
Definition: compile.c:847
static char * find_matching_paren(char *s)
Find the matching parenthesis.
Definition: compile.c:754
struct PatternList * mutt_pattern_comp(struct MailboxView *mv, struct Menu *menu, const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition: compile.c:906
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:778
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:143
bool eat_message_range(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err, struct MailboxView *mv)
Parse a range of message numbers - Implements eat_arg_t -.
Definition: message.c:282
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:624
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:715
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:68
#define FREE(x)
Definition: memory.h:45
#define _(a)
Definition: message.h:28
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:380
const struct PatternFlags * lookup_tag(char tag)
Lookup a pattern modifier.
Definition: flags.c:198
#define MUTT_PC_SEND_MODE_SEARCH
Allow send-mode body searching.
Definition: lib.h:71
@ EAT_RANGE
Process a number (range)
Definition: private.h:66
@ EAT_MESSAGE_RANGE
Process a message number (range)
Definition: private.h:67
@ EAT_DATE
Process a date (range)
Definition: private.h:65
@ EAT_QUERY
Process a query string.
Definition: private.h:68
@ EAT_REGEX
Process a regex.
Definition: private.h:64
#define SLIST_NEXT(elm, field)
Definition: queue.h:270
#define SLIST_FIRST(head)
Definition: queue.h:229
#define SKIPWS(ch)
Definition: string2.h:45
char * dptr
Current read/write position.
Definition: buffer.h:38
struct Mailbox * mailbox
Current Mailbox.
Definition: mview.h:51
A mailbox.
Definition: mailbox.h:79
Mapping between user character and internal constant.
Definition: private.h:75
enum PatternEat eat_arg
Type of function needed to parse flag, e.g. EAT_DATE.
Definition: private.h:80
PatternCompFlags flags
Pattern flags, e.g. MUTT_PC_FULL_MSG.
Definition: private.h:78
int op
Operation to perform, e.g. MUTT_PAT_SCORE.
Definition: private.h:77
A simple (non-regex) pattern.
Definition: lib.h:77
bool group_match
Check a group of Addresses.
Definition: lib.h:82
union Pattern::@1 p
bool all_addr
All Addresses in the list must match.
Definition: lib.h:80
bool string_match
Check a string for a match.
Definition: lib.h:81
bool is_alias
Is there an alias for this Address?
Definition: lib.h:84
bool sendmode
Evaluate searches in send-mode.
Definition: lib.h:86
+ 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 112 of file pattern.c.

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

779{
780 if (!pat || !*pat)
781 return;
782
783 struct Pattern *np = SLIST_FIRST(*pat), *next = NULL;
784
785 while (np)
786 {
787 next = SLIST_NEXT(np, entries);
788
789 if (np->is_multi)
790 {
792 }
793 else if (np->string_match || np->dynamic)
794 {
795 FREE(&np->p.str);
796 }
797 else if (np->group_match)
798 {
799 np->p.group = NULL;
800 }
801 else if (np->p.regex)
802 {
803 regfree(np->p.regex);
804 FREE(&np->p.regex);
805 }
806
807#ifdef USE_DEBUG_GRAPHVIZ
808 FREE(&np->raw_pattern);
809#endif
811 FREE(&np);
812
813 np = next;
814 }
815
816 FREE(pat);
817}
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:123
struct Group * group
Address group if group_match is set.
Definition: lib.h:93
regex_t * regex
Compiled regex, for non-pattern matching.
Definition: lib.h:92
struct ListHead multi_cases
Multiple strings for ~I pattern.
Definition: lib.h:95
char * str
String, if string_match is set.
Definition: lib.h:94
bool dynamic
Evaluate date ranges at run time.
Definition: lib.h:85
bool is_multi
Multiple case (only for ~I pattern now)
Definition: lib.h:87
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_is_list_recipient()

bool mutt_is_list_recipient ( bool  all_addr,
struct Envelope env 
)

Matches known mailing lists.

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

Definition at line 491 of file exec.c.

492{
493 return mutt_is_predicate_recipient(all_addr, env, &mutt_is_mail_list);
494}
static bool mutt_is_predicate_recipient(bool all_addr, struct Envelope *env, addr_predicate_t p)
Test an Envelopes Addresses using a predicate function.
Definition: exec.c:454
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:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_is_subscribed_list_recipient()

bool mutt_is_subscribed_list_recipient ( bool  all_addr,
struct Envelope env 
)

Matches subscribed mailing lists.

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

Definition at line 478 of file exec.c.

479{
481}
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:57
+ 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 289 of file pattern.c.

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

191{
192 int rc = -1;
193 struct Progress *progress = NULL;
194 struct Buffer *buf = buf_pool_get();
195
196 buf_strcpy(buf, mdata->limit);
197 if (prompt)
198 {
199 if ((mw_get_field(prompt, buf, MUTT_COMP_CLEAR, HC_PATTERN, &CompletePatternOps, NULL) != 0) ||
200 buf_is_empty(buf))
201 {
202 buf_pool_release(&buf);
203 return -1;
204 }
205 }
206
207 mutt_message(_("Compiling search pattern..."));
208
209 bool match_all = false;
210 struct PatternList *pat = NULL;
211 char *simple = buf_strdup(buf);
212 if (simple)
213 {
215 const char *pbuf = buf->data;
216 while (*pbuf == ' ')
217 pbuf++;
218 match_all = mutt_str_equal(pbuf, "~A");
219
220 struct Buffer *err = buf_pool_get();
221 pat = mutt_pattern_comp(NULL, menu, buf->data, MUTT_PC_FULL_MSG, err);
222 if (!pat)
223 {
224 mutt_error("%s", buf_string(err));
225 buf_pool_release(&err);
226 goto bail;
227 }
228 }
229 else
230 {
231 match_all = true;
232 }
233
234 progress = progress_new(MUTT_PROGRESS_READ, ARRAY_SIZE(&mdata->ava));
235 progress_set_message(progress, _("Executing command on matching messages..."));
236
237 int vcounter = 0;
238 struct AliasView *avp = NULL;
239 ARRAY_FOREACH(avp, &mdata->ava)
240 {
241 progress_update(progress, ARRAY_FOREACH_IDX, -1);
242
243 if (match_all ||
245 {
246 avp->is_visible = true;
247 vcounter++;
248 }
249 else
250 {
251 avp->is_visible = false;
252 }
253 }
254 progress_free(&progress);
255
256 FREE(&mdata->limit);
257 if (!match_all)
258 {
259 mdata->limit = simple;
260 simple = NULL;
261 }
262
263 if (menu)
264 {
265 menu->max = vcounter;
266 menu_set_index(menu, 0);
267 }
268
270
271 rc = 0;
272
273bail:
274 buf_pool_release(&buf);
275 FREE(&simple);
276 mutt_pattern_free(&pat);
277
278 return rc;
279}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:212
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:87
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:1159
MenuRedrawFlags menu_set_index(struct Menu *menu, int index)
Set the current selection in the Menu.
Definition: menu.c:174
#define MUTT_ALIAS_SIMPLESEARCH
Definition: lib.h:63
char * limit
Limit being used.
Definition: gui.h:60
struct AliasViewArray ava
All Aliases/Queries.
Definition: gui.h:55
GUI data wrapping an Alias.
Definition: gui.h:38
bool is_visible
Is visible?
Definition: gui.h:45
int max
Number of entries in the menu.
Definition: lib.h:81
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_search_command()

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

Perform a search.

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

Definition at line 456 of file pattern.c.

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

◆ mutt_search_alias_command()

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

Perform a search.

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

Definition at line 614 of file pattern.c.

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

Variable Documentation

◆ CompletePatternOps

const struct CompleteOps CompletePatternOps
extern

Auto-Completion of Patterns.

Definition at line 82 of file complete.c.