NeoMutt  2024-12-12-19-ge4b57e
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 68 of file compile.c.

70{
71 struct Buffer *buf = buf_pool_get();
72 bool rc = false;
73 char *pexpr = s->dptr;
74 if ((parse_extract_token(buf, s, TOKEN_PATTERN | TOKEN_COMMENT) != 0) || !buf->data)
75 {
76 buf_printf(err, _("Error in expression: %s"), pexpr);
77 goto out;
78 }
79 if (buf_is_empty(buf))
80 {
81 buf_addstr(err, _("Empty expression"));
82 goto out;
83 }
84
85 if (pat->string_match)
86 {
87 pat->p.str = mutt_str_dup(buf->data);
88 pat->ign_case = mutt_mb_is_lower(buf->data);
89 }
90 else if (pat->group_match)
91 {
92 pat->p.group = mutt_pattern_group(buf->data);
93 }
94 else
95 {
96 pat->p.regex = MUTT_MEM_CALLOC(1, regex_t);
97#ifdef USE_DEBUG_GRAPHVIZ
98 pat->raw_pattern = mutt_str_dup(buf->data);
99#endif
100 uint16_t case_flags = mutt_mb_is_lower(buf->data) ? REG_ICASE : 0;
101 int rc2 = REG_COMP(pat->p.regex, buf->data, REG_NEWLINE | REG_NOSUB | case_flags);
102 if (rc2 != 0)
103 {
104 char errmsg[256] = { 0 };
105 regerror(rc2, pat->p.regex, errmsg, sizeof(errmsg));
106 buf_printf(err, "'%s': %s", buf->data, errmsg);
107 FREE(&pat->p.regex);
108 goto out;
109 }
110 }
111
112 rc = true;
113
114out:
115 buf_pool_release(&buf);
116 return rc;
117}
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:50
#define TOKEN_COMMENT
Don't reap comments.
Definition: extract.h:52
#define TOKEN_PATTERN
~%=!| are terms (for patterns)
Definition: extract.h:51
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:55
#define MUTT_MEM_CALLOC(n, type)
Definition: memory.h:40
#define _(a)
Definition: message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:253
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 143 of file compile.c.

145{
146 struct Buffer *cmd_buf = buf_pool_get();
147 struct Buffer *tok_buf = buf_pool_get();
148 bool rc = false;
149
150 FILE *fp = NULL;
151
152 const char *const c_external_search_command = cs_subset_string(NeoMutt->sub, "external_search_command");
153 if (!c_external_search_command)
154 {
155 buf_addstr(err, _("No search command defined"));
156 goto out;
157 }
158
159 char *pexpr = s->dptr;
160 if ((parse_extract_token(tok_buf, s, TOKEN_PATTERN | TOKEN_COMMENT) != 0) ||
161 !tok_buf->data)
162 {
163 buf_printf(err, _("Error in expression: %s"), pexpr);
164 goto out;
165 }
166 if (*tok_buf->data == '\0')
167 {
168 buf_addstr(err, _("Empty expression"));
169 goto out;
170 }
171
172 buf_addstr(cmd_buf, c_external_search_command);
173 buf_addch(cmd_buf, ' ');
174
175 if (m)
176 {
177 char *escaped_folder = mutt_path_escape(mailbox_path(m));
178 mutt_debug(LL_DEBUG2, "escaped folder path: %s\n", escaped_folder);
179 buf_addch(cmd_buf, '\'');
180 buf_addstr(cmd_buf, escaped_folder);
181 buf_addch(cmd_buf, '\'');
182 }
183 else
184 {
185 buf_addch(cmd_buf, '/');
186 }
187 buf_addch(cmd_buf, ' ');
188 buf_addstr(cmd_buf, tok_buf->data);
189
190 mutt_message(_("Running search command: %s ..."), cmd_buf->data);
191 pat->is_multi = true;
193 pid_t pid = filter_create(cmd_buf->data, NULL, &fp, NULL, EnvList);
194 if (pid < 0)
195 {
196 buf_printf(err, "unable to fork command: %s\n", cmd_buf->data);
197 goto out;
198 }
199
201 mutt_file_fclose(&fp);
202 filter_wait(pid);
203
204 rc = true;
205
206out:
207 buf_pool_release(&cmd_buf);
208 buf_pool_release(&tok_buf);
209 return rc;
210}
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:910
#define mutt_file_fclose(FP)
Definition: file.h:138
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:40
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:75
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
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:123
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:44
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:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
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 624 of file compile.c.

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

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

284{
285 if (!mv || !mv->mailbox || !mv->menu)
286 {
287 // We need these for pretty much anything
288 buf_strcpy(err, _("No mailbox is open"));
289 return false;
290 }
291
292 bool skip_quote = false;
293
294 /* If simple_search is set to "~m %s", the range will have double quotes
295 * around it... */
296 if (*s->dptr == '"')
297 {
298 s->dptr++;
299 skip_quote = true;
300 }
301
302 for (int i_kind = 0; i_kind != RANGE_K_INVALID; i_kind++)
303 {
304 switch (eat_range_by_regex(pat, s, i_kind, err, mv))
305 {
306 case RANGE_E_MVIEW:
307 /* This means it matched syntactically but lacked context.
308 * No point in continuing. */
309 break;
310 case RANGE_E_SYNTAX:
311 /* Try another syntax, then */
312 continue;
313 case RANGE_E_OK:
314 if (skip_quote && (*s->dptr == '"'))
315 s->dptr++;
316 SKIPWS(s->dptr);
317 return true;
318 }
319 }
320 return false;
321}
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:217
@ RANGE_E_MVIEW
Range requires MailboxView, but none available.
Definition: message.c:52
@ RANGE_E_OK
Range is valid.
Definition: message.c:50
@ RANGE_E_SYNTAX
Range contains syntax error.
Definition: message.c:51
@ 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: