NeoMutt  2025-09-05-43-g177ed6
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
Parse a pattern API

Prototype for a function to parse a pattern. More...

Functions

static bool eat_regex (struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
 Parse a regex - Implements eat_arg_t -.
 
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 -.
 
static bool eat_range (struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
 Parse a number range - Implements eat_arg_t -.
 
static bool eat_date (struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
 Parse a date pattern - Implements eat_arg_t -.
 
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 -.
 

Detailed Description

Prototype for a function to parse a pattern.

Parameters
patPattern to store the results in
flagsFlags, e.g. MUTT_PC_PATTERN_DYNAMIC
sString to parse
errBuffer for error messages
Return values
trueThe pattern was read successfully

Function Documentation

◆ eat_regex()

static bool eat_regex ( struct Pattern * pat,
PatternCompFlags flags,
struct Buffer * s,
struct Buffer * err )
static

Parse a regex - Implements eat_arg_t -.

Definition at line 64 of file compile.c.

66{
67 struct Buffer *buf = buf_pool_get();
68 bool rc = false;
69 char *pexpr = s->dptr;
70 if ((parse_extract_token(buf, s, TOKEN_PATTERN | TOKEN_COMMENT) != 0) || !buf->data)
71 {
72 buf_printf(err, _("Error in expression: %s"), pexpr);
73 goto out;
74 }
75 if (buf_is_empty(buf))
76 {
77 buf_addstr(err, _("Empty expression"));
78 goto out;
79 }
80
81 if (pat->string_match)
82 {
83 pat->p.str = mutt_str_dup(buf->data);
84 pat->ign_case = mutt_mb_is_lower(buf->data);
85 }
86 else if (pat->group_match)
87 {
88 pat->p.group = mutt_pattern_group(buf->data);
89 }
90 else
91 {
92 pat->p.regex = MUTT_MEM_CALLOC(1, regex_t);
93#ifdef USE_DEBUG_GRAPHVIZ
94 pat->raw_pattern = mutt_str_dup(buf->data);
95#endif
96 uint16_t case_flags = mutt_mb_is_lower(buf->data) ? REG_ICASE : 0;
97 int rc2 = REG_COMP(pat->p.regex, buf->data, REG_NEWLINE | REG_NOSUB | case_flags);
98 if (rc2 != 0)
99 {
100 char errmsg[256] = { 0 };
101 regerror(rc2, pat->p.regex, errmsg, sizeof(errmsg));
102 buf_printf(err, "'%s': %s", buf->data, errmsg);
103 FREE(&pat->p.regex);
104 goto out;
105 }
106 }
107
108 rc = true;
109
110out:
111 buf_pool_release(&buf);
112 return rc;
113}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:226
int parse_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition extract.c:48
#define TOKEN_COMMENT
Don't reap comments.
Definition extract.h:50
#define TOKEN_PATTERN
~%=!| are terms (for patterns)
Definition extract.h:49
struct Group * mutt_pattern_group(const char *pat)
Match a pattern to a Group.
Definition group.c:117
bool mutt_mb_is_lower(const char *s)
Does a multi-byte string contain only lowercase characters?
Definition mbyte.c:354
#define FREE(x)
Definition memory.h:62
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:47
#define _(a)
Definition message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:255
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:96
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition regex3.h:50
String manipulation buffer.
Definition buffer.h:36
char * dptr
Current read/write position.
Definition buffer.h:38
char * data
Pointer to data.
Definition buffer.h:37
bool group_match
Check a group of Addresses.
Definition lib.h:82
union Pattern::@006112053024257132210207314205210350156165326341 p
struct Group * group
Address group if group_match is set.
Definition lib.h:93
bool string_match
Check a string for a match.
Definition lib.h:81
regex_t * regex
Compiled regex, for non-pattern matching.
Definition lib.h:92
char * str
String, if string_match is set.
Definition lib.h:94
bool ign_case
Ignore case for local string_match searches.
Definition lib.h:83
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ eat_query()

static bool eat_query ( struct Pattern * pat,
PatternCompFlags flags,
struct Buffer * s,
struct Buffer * err,
struct Mailbox * m )
static

Parse a query for an external search program - Implements eat_arg_t -.

Parameters
patPattern to store the results in
flagsFlags, e.g. MUTT_PC_PATTERN_DYNAMIC
sString to parse
errBuffer for error messages
mMailbox
Return values
trueThe pattern was read successfully

Definition at line 139 of file compile.c.

141{
142 struct Buffer *cmd_buf = buf_pool_get();
143 struct Buffer *tok_buf = buf_pool_get();
144 bool rc = false;
145
146 FILE *fp = NULL;
147
148 const char *const c_external_search_command = cs_subset_string(NeoMutt->sub, "external_search_command");
149 if (!c_external_search_command)
150 {
151 buf_addstr(err, _("No search command defined"));
152 goto out;
153 }
154
155 char *pexpr = s->dptr;
156 if ((parse_extract_token(tok_buf, s, TOKEN_PATTERN | TOKEN_COMMENT) != 0) ||
157 !tok_buf->data)
158 {
159 buf_printf(err, _("Error in expression: %s"), pexpr);
160 goto out;
161 }
162 if (*tok_buf->data == '\0')
163 {
164 buf_addstr(err, _("Empty expression"));
165 goto out;
166 }
167
168 buf_addstr(cmd_buf, c_external_search_command);
169 buf_addch(cmd_buf, ' ');
170
171 if (m)
172 {
173 char *escaped_folder = mutt_path_escape(mailbox_path(m));
174 mutt_debug(LL_DEBUG2, "escaped folder path: %s\n", escaped_folder);
175 buf_addch(cmd_buf, '\'');
176 buf_addstr(cmd_buf, escaped_folder);
177 buf_addch(cmd_buf, '\'');
178 }
179 else
180 {
181 buf_addch(cmd_buf, '/');
182 }
183 buf_addch(cmd_buf, ' ');
184 buf_addstr(cmd_buf, tok_buf->data);
185
186 mutt_message(_("Running search command: %s ..."), cmd_buf->data);
187 pat->is_multi = true;
189 pid_t pid = filter_create(cmd_buf->data, NULL, &fp, NULL, NeoMutt->env);
190 if (pid < 0)
191 {
192 buf_printf(err, "unable to fork command: %s\n", cmd_buf->data);
193 goto out;
194 }
195
197 mutt_file_fclose(&fp);
198 filter_wait(pid);
199
200 rc = true;
201
202out:
203 buf_pool_release(&cmd_buf);
204 buf_pool_release(&tok_buf);
205 return rc;
206}
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:241
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition mailbox.h:223
bool mutt_file_map_lines(mutt_file_map_t func, void *user_data, FILE *fp, ReadLineFlags flags)
Process lines of text read from a file pointer.
Definition file.c:787
#define mutt_file_fclose(FP)
Definition file.h:139
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition file.h:40
#define mutt_message(...)
Definition logging2.h:92
#define mutt_debug(LEVEL,...)
Definition logging2.h:90
static bool add_query_msgid(char *line, int line_num, void *user_data)
Parse a Message-Id and add it to a list - Implements mutt_file_map_t -.
Definition compile.c:119
void mutt_list_clear(struct ListHead *h)
Free a list, but NOT its strings.
Definition list.c:166
@ LL_DEBUG2
Log at debug level 2.
Definition logging2.h:45
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition filter.c:220
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, char **envlist)
Set up filter program.
Definition filter.c:209
char * mutt_path_escape(const char *src)
Escapes single quotes in a path for a command string.
Definition path.c:433
Container for Accounts, Notifications.
Definition neomutt.h:43
char ** env
Private copy of the environment variables.
Definition neomutt.h:55
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:47
struct ListHead multi_cases
Multiple strings for ~I pattern.
Definition lib.h:95
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:

◆ eat_range()

static bool eat_range ( struct Pattern * pat,
PatternCompFlags flags,
struct Buffer * s,
struct Buffer * err )
static

Parse a number range - Implements eat_arg_t -.

Definition at line 620 of file compile.c.

622{
623 char *tmp = NULL;
624 bool do_exclusive = false;
625 bool skip_quote = false;
626
627 /* If simple_search is set to "~m %s", the range will have double quotes
628 * around it... */
629 if (*s->dptr == '"')
630 {
631 s->dptr++;
632 skip_quote = true;
633 }
634 if (*s->dptr == '<')
635 do_exclusive = true;
636 if ((*s->dptr != '-') && (*s->dptr != '<'))
637 {
638 /* range minimum */
639 if (*s->dptr == '>')
640 {
641 pat->max = MUTT_MAXRANGE;
642 pat->min = strtol(s->dptr + 1, &tmp, 0) + 1; /* exclusive range */
643 }
644 else
645 {
646 pat->min = strtol(s->dptr, &tmp, 0);
647 }
648 if (mutt_toupper(*tmp) == 'K') /* is there a prefix? */
649 {
650 pat->min *= 1024;
651 tmp++;
652 }
653 else if (mutt_toupper(*tmp) == 'M')
654 {
655 pat->min *= 1048576;
656 tmp++;
657 }
658 if (*s->dptr == '>')
659 {
660 s->dptr = tmp;
661 return true;
662 }
663 if (*tmp != '-')
664 {
665 /* exact value */
666 pat->max = pat->min;
667 s->dptr = tmp;
668 return true;
669 }
670 tmp++;
671 }
672 else
673 {
674 s->dptr++;
675 tmp = s->dptr;
676 }
677
678 if (mutt_isdigit(*tmp))
679 {
680 /* range maximum */
681 pat->max = strtol(tmp, &tmp, 0);
682 if (mutt_toupper(*tmp) == 'K')
683 {
684 pat->max *= 1024;
685 tmp++;
686 }
687 else if (mutt_toupper(*tmp) == 'M')
688 {
689 pat->max *= 1048576;
690 tmp++;
691 }
692 if (do_exclusive)
693 (pat->max)--;
694 }
695 else
696 {
697 pat->max = MUTT_MAXRANGE;
698 }
699
700 if (skip_quote && (*tmp == '"'))
701 tmp++;
702
703 SKIPWS(tmp);
704 s->dptr = tmp;
705 return true;
706}
int mutt_toupper(int arg)
Wrapper for toupper(3)
Definition ctype.c:139
bool mutt_isdigit(int arg)
Wrapper for isdigit(3)
Definition ctype.c:65
#define MUTT_MAXRANGE
Definition private.h:141
#define SKIPWS(ch)
Definition string2.h:51
long min
Minimum for range checks.
Definition lib.h:88
long max
Maximum for range checks.
Definition lib.h:89
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ eat_date()

static bool eat_date ( struct Pattern * pat,
PatternCompFlags flags,
struct Buffer * s,
struct Buffer * err )
static

Parse a date pattern - Implements eat_arg_t -.

Definition at line 711 of file compile.c.

713{
714 struct Buffer *tmp = buf_pool_get();
715 bool rc = false;
716
717 char *pexpr = s->dptr;
719 {
720 buf_printf(err, _("Error in expression: %s"), pexpr);
721 goto out;
722 }
723
724 if (buf_is_empty(tmp))
725 {
726 buf_addstr(err, _("Empty expression"));
727 goto out;
728 }
729
730 if (flags & MUTT_PC_PATTERN_DYNAMIC)
731 {
732 pat->dynamic = true;
733 pat->p.str = mutt_str_dup(tmp->data);
734 }
735
736 rc = eval_date_minmax(pat, tmp->data, err);
737
738out:
739 buf_pool_release(&tmp);
740 return rc;
741}
bool eval_date_minmax(struct Pattern *pat, const char *s, struct Buffer *err)
Evaluate a date-range pattern against 'now'.
Definition compile.c:492
#define MUTT_PC_PATTERN_DYNAMIC
Enable runtime date range evaluation.
Definition lib.h:70
bool dynamic
Evaluate date ranges at run time.
Definition lib.h:85
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ eat_message_range()

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

Parameters
patPattern to store the results in
flagsFlags, e.g. MUTT_PC_PATTERN_DYNAMIC
sString to parse
errBuffer for error messages
mvMailbox view
Return values
trueThe pattern was read successfully

Definition at line 281 of file message.c.

283{
284 if (!mv || !mv->mailbox || !mv->menu)
285 {
286 // We need these for pretty much anything
287 buf_strcpy(err, _("No mailbox is open"));
288 return false;
289 }
290
291 bool skip_quote = false;
292
293 /* If simple_search is set to "~m %s", the range will have double quotes
294 * around it... */
295 if (*s->dptr == '"')
296 {
297 s->dptr++;
298 skip_quote = true;
299 }
300
301 for (int i_kind = 0; i_kind != RANGE_K_INVALID; i_kind++)
302 {
303 switch (eat_range_by_regex(pat, s, i_kind, err, mv))
304 {
305 case RANGE_E_MVIEW:
306 /* This means it matched syntactically but lacked context.
307 * No point in continuing. */
308 break;
309 case RANGE_E_SYNTAX:
310 /* Try another syntax, then */
311 continue;
312 case RANGE_E_OK:
313 if (skip_quote && (*s->dptr == '"'))
314 s->dptr++;
315 SKIPWS(s->dptr);
316 return true;
317 }
318 }
319 return false;
320}
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
static int eat_range_by_regex(struct Pattern *pat, struct Buffer *s, int kind, struct Buffer *err, struct MailboxView *mv)
Parse a range given as a regex.
Definition message.c:216
@ RANGE_E_MVIEW
Range requires MailboxView, but none available.
Definition message.c:51
@ RANGE_E_OK
Range is valid.
Definition message.c:49
@ RANGE_E_SYNTAX
Range contains syntax error.
Definition message.c:50
@ RANGE_K_INVALID
Range is invalid.
Definition private.h:96
struct Menu * menu
Needed for pattern compilation.
Definition mview.h:47
struct Mailbox * mailbox
Current Mailbox.
Definition mview.h:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function: