NeoMutt  2025-09-05-7-geaa2bd
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 66 of file compile.c.

68{
69 struct Buffer *buf = buf_pool_get();
70 bool rc = false;
71 char *pexpr = s->dptr;
72 if ((parse_extract_token(buf, s, TOKEN_PATTERN | TOKEN_COMMENT) != 0) || !buf->data)
73 {
74 buf_printf(err, _("Error in expression: %s"), pexpr);
75 goto out;
76 }
77 if (buf_is_empty(buf))
78 {
79 buf_addstr(err, _("Empty expression"));
80 goto out;
81 }
82
83 if (pat->string_match)
84 {
85 pat->p.str = mutt_str_dup(buf->data);
86 pat->ign_case = mutt_mb_is_lower(buf->data);
87 }
88 else if (pat->group_match)
89 {
90 pat->p.group = mutt_pattern_group(buf->data);
91 }
92 else
93 {
94 pat->p.regex = MUTT_MEM_CALLOC(1, regex_t);
95#ifdef USE_DEBUG_GRAPHVIZ
96 pat->raw_pattern = mutt_str_dup(buf->data);
97#endif
98 uint16_t case_flags = mutt_mb_is_lower(buf->data) ? REG_ICASE : 0;
99 int rc2 = REG_COMP(pat->p.regex, buf->data, REG_NEWLINE | REG_NOSUB | case_flags);
100 if (rc2 != 0)
101 {
102 char errmsg[256] = { 0 };
103 regerror(rc2, pat->p.regex, errmsg, sizeof(errmsg));
104 buf_printf(err, "'%s': %s", buf->data, errmsg);
105 FREE(&pat->p.regex);
106 goto out;
107 }
108 }
109
110 rc = true;
111
112out:
113 buf_pool_release(&buf);
114 return rc;
115}
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:254
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::@1 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 141 of file compile.c.

143{
144 struct Buffer *cmd_buf = buf_pool_get();
145 struct Buffer *tok_buf = buf_pool_get();
146 bool rc = false;
147
148 FILE *fp = NULL;
149
150 const char *const c_external_search_command = cs_subset_string(NeoMutt->sub, "external_search_command");
151 if (!c_external_search_command)
152 {
153 buf_addstr(err, _("No search command defined"));
154 goto out;
155 }
156
157 char *pexpr = s->dptr;
158 if ((parse_extract_token(tok_buf, s, TOKEN_PATTERN | TOKEN_COMMENT) != 0) ||
159 !tok_buf->data)
160 {
161 buf_printf(err, _("Error in expression: %s"), pexpr);
162 goto out;
163 }
164 if (*tok_buf->data == '\0')
165 {
166 buf_addstr(err, _("Empty expression"));
167 goto out;
168 }
169
170 buf_addstr(cmd_buf, c_external_search_command);
171 buf_addch(cmd_buf, ' ');
172
173 if (m)
174 {
175 char *escaped_folder = mutt_path_escape(mailbox_path(m));
176 mutt_debug(LL_DEBUG2, "escaped folder path: %s\n", escaped_folder);
177 buf_addch(cmd_buf, '\'');
178 buf_addstr(cmd_buf, escaped_folder);
179 buf_addch(cmd_buf, '\'');
180 }
181 else
182 {
183 buf_addch(cmd_buf, '/');
184 }
185 buf_addch(cmd_buf, ' ');
186 buf_addstr(cmd_buf, tok_buf->data);
187
188 mutt_message(_("Running search command: %s ..."), cmd_buf->data);
189 pat->is_multi = true;
191 pid_t pid = filter_create(cmd_buf->data, NULL, &fp, NULL, NeoMutt->env);
192 if (pid < 0)
193 {
194 buf_printf(err, "unable to fork command: %s\n", cmd_buf->data);
195 goto out;
196 }
197
199 mutt_file_fclose(&fp);
200 filter_wait(pid);
201
202 rc = true;
203
204out:
205 buf_pool_release(&cmd_buf);
206 buf_pool_release(&tok_buf);
207 return rc;
208}
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:121
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 622 of file compile.c.

624{
625 char *tmp = NULL;
626 bool do_exclusive = false;
627 bool skip_quote = false;
628
629 /* If simple_search is set to "~m %s", the range will have double quotes
630 * around it... */
631 if (*s->dptr == '"')
632 {
633 s->dptr++;
634 skip_quote = true;
635 }
636 if (*s->dptr == '<')
637 do_exclusive = true;
638 if ((*s->dptr != '-') && (*s->dptr != '<'))
639 {
640 /* range minimum */
641 if (*s->dptr == '>')
642 {
643 pat->max = MUTT_MAXRANGE;
644 pat->min = strtol(s->dptr + 1, &tmp, 0) + 1; /* exclusive range */
645 }
646 else
647 {
648 pat->min = strtol(s->dptr, &tmp, 0);
649 }
650 if (mutt_toupper(*tmp) == 'K') /* is there a prefix? */
651 {
652 pat->min *= 1024;
653 tmp++;
654 }
655 else if (mutt_toupper(*tmp) == 'M')
656 {
657 pat->min *= 1048576;
658 tmp++;
659 }
660 if (*s->dptr == '>')
661 {
662 s->dptr = tmp;
663 return true;
664 }
665 if (*tmp != '-')
666 {
667 /* exact value */
668 pat->max = pat->min;
669 s->dptr = tmp;
670 return true;
671 }
672 tmp++;
673 }
674 else
675 {
676 s->dptr++;
677 tmp = s->dptr;
678 }
679
680 if (mutt_isdigit(*tmp))
681 {
682 /* range maximum */
683 pat->max = strtol(tmp, &tmp, 0);
684 if (mutt_toupper(*tmp) == 'K')
685 {
686 pat->max *= 1024;
687 tmp++;
688 }
689 else if (mutt_toupper(*tmp) == 'M')
690 {
691 pat->max *= 1048576;
692 tmp++;
693 }
694 if (do_exclusive)
695 (pat->max)--;
696 }
697 else
698 {
699 pat->max = MUTT_MAXRANGE;
700 }
701
702 if (skip_quote && (*tmp == '"'))
703 tmp++;
704
705 SKIPWS(tmp);
706 s->dptr = tmp;
707 return true;
708}
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:44
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 713 of file compile.c.

715{
716 struct Buffer *tmp = buf_pool_get();
717 bool rc = false;
718
719 char *pexpr = s->dptr;
721 {
722 buf_printf(err, _("Error in expression: %s"), pexpr);
723 goto out;
724 }
725
726 if (buf_is_empty(tmp))
727 {
728 buf_addstr(err, _("Empty expression"));
729 goto out;
730 }
731
732 if (flags & MUTT_PC_PATTERN_DYNAMIC)
733 {
734 pat->dynamic = true;
735 pat->p.str = mutt_str_dup(tmp->data);
736 }
737
738 rc = eval_date_minmax(pat, tmp->data, err);
739
740out:
741 buf_pool_release(&tmp);
742 return rc;
743}
bool eval_date_minmax(struct Pattern *pat, const char *s, struct Buffer *err)
Evaluate a date-range pattern against 'now'.
Definition: compile.c:494
#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: