NeoMutt  2024-03-23-147-g885fbc
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 67 of file compile.c.

69{
70 struct Buffer *buf = buf_pool_get();
71 bool rc = false;
72 char *pexpr = s->dptr;
73 if ((parse_extract_token(buf, s, TOKEN_PATTERN | TOKEN_COMMENT) != 0) || !buf->data)
74 {
75 buf_printf(err, _("Error in expression: %s"), pexpr);
76 goto out;
77 }
78 if (buf_is_empty(buf))
79 {
80 buf_addstr(err, _("Empty expression"));
81 goto out;
82 }
83
84 if (pat->string_match)
85 {
86 pat->p.str = mutt_str_dup(buf->data);
87 pat->ign_case = mutt_mb_is_lower(buf->data);
88 }
89 else if (pat->group_match)
90 {
91 pat->p.group = mutt_pattern_group(buf->data);
92 }
93 else
94 {
95 pat->p.regex = mutt_mem_calloc(1, sizeof(regex_t));
96#ifdef USE_DEBUG_GRAPHVIZ
97 pat->raw_pattern = mutt_str_dup(buf->data);
98#endif
99 uint16_t case_flags = mutt_mb_is_lower(buf->data) ? REG_ICASE : 0;
100 int rc2 = REG_COMP(pat->p.regex, buf->data, REG_NEWLINE | REG_NOSUB | case_flags);
101 if (rc2 != 0)
102 {
103 char errmsg[256] = { 0 };
104 regerror(rc2, pat->p.regex, errmsg, sizeof(errmsg));
105 buf_printf(err, "'%s': %s", buf->data, errmsg);
106 FREE(&pat->p.regex);
107 goto out;
108 }
109 }
110
111 rc = true;
112
113out:
114 buf_pool_release(&buf);
115 return rc;
116}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:290
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
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:118
bool mutt_mb_is_lower(const char *s)
Does a multi-byte string contain only lowercase characters?
Definition: mbyte.c:354
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define FREE(x)
Definition: memory.h:45
#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:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:49
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 142 of file compile.c.

144{
145 struct Buffer *cmd_buf = buf_pool_get();
146 struct Buffer *tok_buf = buf_pool_get();
147 bool rc = false;
148
149 FILE *fp = NULL;
150
151 const char *const c_external_search_command = cs_subset_string(NeoMutt->sub, "external_search_command");
152 if (!c_external_search_command)
153 {
154 buf_addstr(err, _("No search command defined"));
155 goto out;
156 }
157
158 char *pexpr = s->dptr;
159 if ((parse_extract_token(tok_buf, s, TOKEN_PATTERN | TOKEN_COMMENT) != 0) ||
160 !tok_buf->data)
161 {
162 buf_printf(err, _("Error in expression: %s"), pexpr);
163 goto out;
164 }
165 if (*tok_buf->data == '\0')
166 {
167 buf_addstr(err, _("Empty expression"));
168 goto out;
169 }
170
171 buf_addstr(cmd_buf, c_external_search_command);
172 buf_addch(cmd_buf, ' ');
173
174 if (m)
175 {
176 char *escaped_folder = mutt_path_escape(mailbox_path(m));
177 mutt_debug(LL_DEBUG2, "escaped folder path: %s\n", escaped_folder);
178 buf_addch(cmd_buf, '\'');
179 buf_addstr(cmd_buf, escaped_folder);
180 buf_addch(cmd_buf, '\'');
181 }
182 else
183 {
184 buf_addch(cmd_buf, '/');
185 }
186 buf_addch(cmd_buf, ' ');
187 buf_addstr(cmd_buf, tok_buf->data);
188
189 mutt_message(_("Running search command: %s ..."), cmd_buf->data);
190 pat->is_multi = true;
192 pid_t pid = filter_create(cmd_buf->data, NULL, &fp, NULL, EnvList);
193 if (pid < 0)
194 {
195 buf_printf(err, "unable to fork command: %s\n", cmd_buf->data);
196 goto out;
197 }
198
200 mutt_file_fclose(&fp);
201 filter_wait(pid);
202
203 rc = true;
204
205out:
206 buf_pool_release(&cmd_buf);
207 buf_pool_release(&tok_buf);
208 return rc;
209}
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
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:907
#define mutt_file_fclose(FP)
Definition: file.h:147
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:40
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 ** EnvList
Private copy of the environment variables.
Definition: globals.c:78
#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:122
void mutt_list_clear(struct ListHead *h)
Free a list, but NOT its strings.
Definition: list.c:167
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
char * mutt_path_escape(const char *src)
Escapes single quotes in a path for a command string.
Definition: path.c:429
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
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 623 of file compile.c.

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

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