NeoMutt
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
pattern.c
Go to the documentation of this file.
1
31#include "config.h"
32#include <stddef.h>
33#include <stdbool.h>
34#include "private.h"
35#include "mutt/lib.h"
36#include "config/lib.h"
37#include "email/lib.h"
38#include "core/lib.h"
39#include "alias/gui.h" // IWYU pragma: keep
40#include "alias/lib.h"
41#include "mutt.h"
42#include "lib.h"
43#include "editor/lib.h"
44#include "history/lib.h"
45#include "menu/lib.h"
46#include "progress/lib.h"
47#include "globals.h" // IWYU pragma: keep
48#include "mutt_logging.h"
49#include "mview.h"
50#include "mx.h"
51#include "opcodes.h"
52#include "protos.h"
53#include "search_state.h"
54#ifndef USE_FMEMOPEN
55#include <sys/stat.h>
56#endif
57#ifdef USE_IMAP
58#include "imap/lib.h"
59#endif
60
67 // clang-format off
68 [RANGE_K_REL] = { RANGE_REL_RX, 1, 3, 0, { 0 } },
69 [RANGE_K_ABS] = { RANGE_ABS_RX, 1, 3, 0, { 0 } },
70 [RANGE_K_LT] = { RANGE_LT_RX, 1, 2, 0, { 0 } },
71 [RANGE_K_GT] = { RANGE_GT_RX, 2, 1, 0, { 0 } },
72 [RANGE_K_BARE] = { RANGE_BARE_RX, 1, 1, 0, { 0 } },
73 // clang-format on
74};
75
87typedef bool (*eat_arg_t)(struct Pattern *pat, PatternCompFlags flags,
88 struct Buffer *s, struct Buffer *err);
89
95static void quote_simple(const char *str, struct Buffer *buf)
96{
97 buf_reset(buf);
98 buf_addch(buf, '"');
99 while (*str)
100 {
101 if ((*str == '\\') || (*str == '"'))
102 buf_addch(buf, '\\');
103 buf_addch(buf, *str++);
104 }
105 buf_addch(buf, '"');
106}
107
113void mutt_check_simple(struct Buffer *buf, const char *simple)
114{
115 bool do_simple = true;
116
117 for (const char *p = buf_string(buf); p && (p[0] != '\0'); p++)
118 {
119 if ((p[0] == '\\') && (p[1] != '\0'))
120 {
121 p++;
122 }
123 else if ((p[0] == '~') || (p[0] == '=') || (p[0] == '%'))
124 {
125 do_simple = false;
126 break;
127 }
128 }
129
130 /* XXX - is mutt_istr_cmp() right here, or should we use locale's
131 * equivalences? */
132
133 if (do_simple) /* yup, so spoof a real request */
134 {
135 /* convert old tokens into the new format */
136 if (mutt_istr_equal("all", buf_string(buf)) || mutt_str_equal("^", buf_string(buf)) ||
137 mutt_str_equal(".", buf_string(buf))) /* ~A is more efficient */
138 {
139 buf_strcpy(buf, "~A");
140 }
141 else if (mutt_istr_equal("del", buf_string(buf)))
142 {
143 buf_strcpy(buf, "~D");
144 }
145 else if (mutt_istr_equal("flag", buf_string(buf)))
146 {
147 buf_strcpy(buf, "~F");
148 }
149 else if (mutt_istr_equal("new", buf_string(buf)))
150 {
151 buf_strcpy(buf, "~N");
152 }
153 else if (mutt_istr_equal("old", buf_string(buf)))
154 {
155 buf_strcpy(buf, "~O");
156 }
157 else if (mutt_istr_equal("repl", buf_string(buf)))
158 {
159 buf_strcpy(buf, "~Q");
160 }
161 else if (mutt_istr_equal("read", buf_string(buf)))
162 {
163 buf_strcpy(buf, "~R");
164 }
165 else if (mutt_istr_equal("tag", buf_string(buf)))
166 {
167 buf_strcpy(buf, "~T");
168 }
169 else if (mutt_istr_equal("unread", buf_string(buf)))
170 {
171 buf_strcpy(buf, "~U");
172 }
173 else
174 {
175 struct Buffer *tmp = buf_pool_get();
176 quote_simple(buf_string(buf), tmp);
177 mutt_file_expand_fmt(buf, simple, buf_string(tmp));
178 buf_pool_release(&tmp);
179 }
180 }
181}
182
191int mutt_pattern_alias_func(char *prompt, struct AliasMenuData *mdata, struct Menu *menu)
192{
193 int rc = -1;
194 struct Progress *progress = NULL;
195 struct Buffer *buf = buf_pool_get();
196
197 buf_strcpy(buf, mdata->limit);
198 if (prompt)
199 {
200 if ((mw_get_field(prompt, buf, MUTT_COMP_CLEAR, HC_PATTERN, &CompletePatternOps, NULL) != 0) ||
201 buf_is_empty(buf))
202 {
203 buf_pool_release(&buf);
204 return -1;
205 }
206 }
207
208 mutt_message(_("Compiling search pattern..."));
209
210 bool match_all = false;
211 struct PatternList *pat = NULL;
212 char *simple = buf_strdup(buf);
213 if (simple)
214 {
216 const char *pbuf = buf->data;
217 while (*pbuf == ' ')
218 pbuf++;
219 match_all = mutt_str_equal(pbuf, "~A");
220
221 struct Buffer err = buf_make(0);
222 pat = mutt_pattern_comp(NULL, menu, buf->data, MUTT_PC_FULL_MSG, &err);
223 if (!pat)
224 {
225 mutt_error("%s", buf_string(&err));
226 buf_dealloc(&err);
227 goto bail;
228 }
229 }
230 else
231 {
232 match_all = true;
233 }
234
235 progress = progress_new(_("Executing command on matching messages..."),
237
238 int vcounter = 0;
239 struct AliasView *avp = NULL;
240 ARRAY_FOREACH(avp, &mdata->ava)
241 {
242 progress_update(progress, ARRAY_FOREACH_IDX, -1);
243
244 if (match_all ||
246 {
247 avp->is_visible = true;
248 vcounter++;
249 }
250 else
251 {
252 avp->is_visible = false;
253 }
254 }
255 progress_free(&progress);
256
257 FREE(&mdata->limit);
258 if (!match_all)
259 {
260 mdata->limit = simple;
261 simple = NULL;
262 }
263
264 if (menu)
265 {
266 menu->max = vcounter;
267 menu_set_index(menu, 0);
268 }
269
271
272 rc = 0;
273
274bail:
275 buf_pool_release(&buf);
276 FREE(&simple);
277 mutt_pattern_free(&pat);
278
279 return rc;
280}
281
290int mutt_pattern_func(struct MailboxView *mv, int op, char *prompt)
291{
292 if (!mv || !mv->mailbox)
293 return -1;
294
295 struct Mailbox *m = mv->mailbox;
296
297 struct Buffer *err = NULL;
298 int rc = -1;
299 struct Progress *progress = NULL;
300 struct Buffer *buf = buf_pool_get();
301
302 buf_strcpy(buf, NONULL(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#ifdef USE_IMAP
332 if ((m->type == MUTT_IMAP) && (!imap_search(m, pat)))
333 goto bail;
334#endif
335
336 progress = progress_new(_("Executing command on matching messages..."), MUTT_PROGRESS_READ,
337 (op == MUTT_LIMIT) ? m->msg_count : m->vcount);
338
339 if (op == MUTT_LIMIT)
340 {
341 m->vcount = 0;
342 mv->vsize = 0;
343 mv->collapsed = false;
344 int padding = mx_msg_padding_size(m);
345
346 for (int i = 0; i < m->msg_count; i++)
347 {
348 struct Email *e = m->emails[i];
349 if (!e)
350 break;
351
352 progress_update(progress, i, -1);
353 /* new limit pattern implicitly uncollapses all threads */
354 e->vnum = -1;
355 e->visible = false;
356 e->limit_visited = true;
357 e->collapsed = false;
358 e->num_hidden = 0;
359
360 if (match_all ||
362 {
363 e->vnum = m->vcount;
364 e->visible = true;
365 m->v2r[m->vcount] = i;
366 m->vcount++;
367 struct Body *b = e->body;
368 mv->vsize += b->length + b->offset - b->hdr_offset + padding;
369 }
370 }
371 }
372 else
373 {
374 for (int i = 0; i < m->vcount; i++)
375 {
376 struct Email *e = mutt_get_virt_email(m, i);
377 if (!e)
378 continue;
379 progress_update(progress, i, -1);
381 {
382 switch (op)
383 {
384 case MUTT_UNDELETE:
385 mutt_set_flag(m, e, MUTT_PURGE, false, true);
386 /* fallthrough */
387 case MUTT_DELETE:
388 mutt_set_flag(m, e, MUTT_DELETE, (op == MUTT_DELETE), true);
389 break;
390 case MUTT_TAG:
391 case MUTT_UNTAG:
392 mutt_set_flag(m, e, MUTT_TAG, (op == MUTT_TAG), true);
393 break;
394 }
395 }
396 }
397 }
398 progress_free(&progress);
399
401
402 if (op == MUTT_LIMIT)
403 {
404 /* drop previous limit pattern */
405 FREE(&mv->pattern);
407
408 if (m->msg_count && !m->vcount)
409 mutt_error(_("No messages matched criteria"));
410
411 /* record new limit pattern, unless match all */
412 if (!match_all)
413 {
414 mv->pattern = simple;
415 simple = NULL; /* don't clobber it */
416 mv->limit_pattern = mutt_pattern_comp(mv, mv->menu, buf->data, MUTT_PC_FULL_MSG, err);
417 }
418 }
419
420 rc = 0;
421
422bail:
423 buf_pool_release(&buf);
424 buf_pool_release(&err);
425 FREE(&simple);
426 mutt_pattern_free(&pat);
427
428 return rc;
429}
430
441int mutt_search_command(struct MailboxView *mv, struct Menu *menu, int cur,
442 struct SearchState *state, SearchFlags flags)
443{
444 struct Progress *progress = NULL;
445 int rc = -1;
446 struct Mailbox *m = mv ? mv->mailbox : NULL;
447 if (!m)
448 return -1;
449 bool pattern_changed = false;
450
451 if (buf_is_empty(state->string) || (flags & SEARCH_PROMPT))
452 {
453 if ((mw_get_field((state->reverse) ? _("Reverse search for: ") : _("Search for: "),
455 &CompletePatternOps, NULL) != 0) ||
456 buf_is_empty(state->string))
457 {
458 goto done;
459 }
460
461 /* compare the *expanded* version of the search pattern in case
462 * $simple_search has changed while we were searching */
463 struct Buffer *tmp = buf_pool_get();
464 buf_copy(tmp, state->string);
465 const char *const c_simple_search = cs_subset_string(NeoMutt->sub, "simple_search");
466 mutt_check_simple(tmp, NONULL(c_simple_search));
467 if (!buf_str_equal(tmp, state->string_expn))
468 {
469 mutt_pattern_free(&state->pattern);
470 buf_copy(state->string_expn, tmp);
471 buf_pool_release(&tmp);
472 }
473 }
474
475 if (!state->pattern)
476 {
477 mutt_message(_("Compiling search pattern..."));
478 mutt_pattern_free(&state->pattern);
479 struct Buffer *err = buf_pool_get();
480 state->pattern = mutt_pattern_comp(mv, menu, state->string_expn->data,
481 MUTT_PC_FULL_MSG, err);
482 pattern_changed = true;
483 if (!state->pattern)
484 {
485 mutt_error("%s", buf_string(err));
486 buf_free(&err);
487 buf_reset(state->string);
488 buf_reset(state->string_expn);
489 return -1;
490 }
491 buf_free(&err);
493 }
494
495 if (pattern_changed)
496 {
497 for (int i = 0; i < m->msg_count; i++)
498 m->emails[i]->searched = false;
499#ifdef USE_IMAP
500 if ((m->type == MUTT_IMAP) && (!imap_search(m, state->pattern)))
501 return -1;
502#endif
503 }
504
505 int incr = state->reverse ? -1 : 1;
506 if (flags & SEARCH_OPPOSITE)
507 incr = -incr;
508
509 progress = progress_new(_("Searching..."), MUTT_PROGRESS_READ, m->vcount);
510
511 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
512 for (int i = cur + incr, j = 0; j != m->vcount; j++)
513 {
514 const char *msg = NULL;
515 progress_update(progress, j, -1);
516 if (i > m->vcount - 1)
517 {
518 i = 0;
519 if (c_wrap_search)
520 {
521 msg = _("Search wrapped to top");
522 }
523 else
524 {
525 mutt_message(_("Search hit bottom without finding match"));
526 goto done;
527 }
528 }
529 else if (i < 0)
530 {
531 i = m->vcount - 1;
532 if (c_wrap_search)
533 {
534 msg = _("Search wrapped to bottom");
535 }
536 else
537 {
538 mutt_message(_("Search hit top without finding match"));
539 goto done;
540 }
541 }
542
543 struct Email *e = mutt_get_virt_email(m, i);
544 if (!e)
545 goto done;
546
547 if (e->searched)
548 {
549 /* if we've already evaluated this message, use the cached value */
550 if (e->matched)
551 {
553 if (msg && *msg)
554 mutt_message("%s", msg);
555 rc = i;
556 goto done;
557 }
558 }
559 else
560 {
561 /* remember that we've already searched this message */
562 e->searched = true;
564 MUTT_MATCH_FULL_ADDRESS, m, e, NULL);
565 if (e->matched)
566 {
568 if (msg && *msg)
569 mutt_message("%s", msg);
570 rc = i;
571 goto done;
572 }
573 }
574
575 if (SigInt)
576 {
577 mutt_error(_("Search interrupted"));
578 SigInt = false;
579 goto done;
580 }
581
582 i += incr;
583 }
584
585 mutt_error(_("Not found"));
586done:
587 progress_free(&progress);
588 return rc;
589}
590
600int mutt_search_alias_command(struct Menu *menu, int cur,
601 struct SearchState *state, SearchFlags flags)
602{
603 struct Progress *progress = NULL;
604 const struct AliasMenuData *mdata = menu->mdata;
605 const struct AliasViewArray *ava = &mdata->ava;
606 int rc = -1;
607 bool pattern_changed = false;
608
609 if (buf_is_empty(state->string) || flags & SEARCH_PROMPT)
610 {
611 if ((mw_get_field((flags & OP_SEARCH_REVERSE) ? _("Reverse search for: ") : _("Search for: "),
613 &CompletePatternOps, NULL) != 0) ||
614 buf_is_empty(state->string))
615 {
616 goto done;
617 }
618
619 /* compare the *expanded* version of the search pattern in case
620 * $simple_search has changed while we were searching */
621 struct Buffer *tmp = buf_pool_get();
622 buf_copy(tmp, state->string);
624 if (!buf_str_equal(tmp, state->string_expn))
625 {
626 mutt_pattern_free(&state->pattern);
627 buf_copy(state->string_expn, tmp);
628 buf_pool_release(&tmp);
629 }
630 }
631
632 if (!state->pattern)
633 {
634 mutt_message(_("Compiling search pattern..."));
635 struct Buffer *err = buf_pool_get();
636 state->pattern = mutt_pattern_comp(NULL, menu, state->string_expn->data,
637 MUTT_PC_FULL_MSG, err);
638 pattern_changed = true;
639 if (!state->pattern)
640 {
641 mutt_error("%s", buf_string(err));
642 buf_free(&err);
643 buf_reset(state->string);
644 buf_reset(state->string_expn);
645 return -1;
646 }
647 buf_free(&err);
649 }
650
651 if (pattern_changed)
652 {
653 struct AliasView *av = NULL;
654 ARRAY_FOREACH(av, ava)
655 {
656 av->is_searched = false;
657 }
658 }
659
660 int incr = state->reverse ? -1 : 1;
661 if (flags & SEARCH_OPPOSITE)
662 incr = -incr;
663
664 progress = progress_new(_("Searching..."), MUTT_PROGRESS_READ, ARRAY_SIZE(ava));
665
666 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
667 for (int i = cur + incr, j = 0; j != ARRAY_SIZE(ava); j++)
668 {
669 const char *msg = NULL;
670 progress_update(progress, j, -1);
671 if (i > ARRAY_SIZE(ava) - 1)
672 {
673 i = 0;
674 if (c_wrap_search)
675 {
676 msg = _("Search wrapped to top");
677 }
678 else
679 {
680 mutt_message(_("Search hit bottom without finding match"));
681 goto done;
682 }
683 }
684 else if (i < 0)
685 {
686 i = ARRAY_SIZE(ava) - 1;
687 if (c_wrap_search)
688 {
689 msg = _("Search wrapped to bottom");
690 }
691 else
692 {
693 mutt_message(_("Search hit top without finding match"));
694 goto done;
695 }
696 }
697
698 struct AliasView *av = ARRAY_GET(ava, i);
699 if (av->is_searched)
700 {
701 /* if we've already evaluated this message, use the cached value */
702 if (av->is_matched)
703 {
705 if (msg && *msg)
706 mutt_message("%s", msg);
707 rc = i;
708 goto done;
709 }
710 }
711 else
712 {
713 /* remember that we've already searched this message */
714 av->is_searched = true;
716 MUTT_MATCH_FULL_ADDRESS, av, NULL);
717 if (av->is_matched)
718 {
720 if (msg && *msg)
721 mutt_message("%s", msg);
722 rc = i;
723 goto done;
724 }
725 }
726
727 if (SigInt)
728 {
729 mutt_error(_("Search interrupted"));
730 SigInt = false;
731 goto done;
732 }
733
734 i += incr;
735 }
736
737 mutt_error(_("Not found"));
738done:
739 progress_free(&progress);
740 return rc;
741}
Email Aliases.
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:211
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:86
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:108
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:389
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:88
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:303
struct Buffer buf_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:70
void buf_free(struct Buffer **ptr)
Deallocates a buffer.
Definition: buffer.c:331
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:253
bool buf_str_equal(const struct Buffer *a, const struct Buffer *b)
Return if two buffers are equal.
Definition: buffer.c:653
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:407
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:572
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:542
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
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
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
Enter a string.
Structs that make up an email.
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:1164
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:1137
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:1512
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:54
SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.c:59
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:276
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_message(...)
Definition: logging2.h:91
Shared code for the Alias and Query Dialogs.
Read/write command history from/to a file.
@ HC_PATTERN
Patterns.
Definition: lib.h:53
IMAP network mailbox.
bool imap_search(struct Mailbox *m, const struct PatternList *pat)
Find messages in mailbox matching a pattern.
Definition: search.c:229
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:50
#define FREE(x)
Definition: memory.h:45
GUI present the user with a selectable list.
MenuRedrawFlags menu_set_index(struct Menu *menu, int index)
Set the current selection in the Menu.
Definition: menu.c:170
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:810
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
Many unsorted constants and some structs.
@ MUTT_UNDELETE
Messages to be un-deleted.
Definition: mutt.h:75
@ MUTT_LIMIT
Messages in limited view.
Definition: mutt.h:81
@ MUTT_UNTAG
Messages to be un-tagged.
Definition: mutt.h:80
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:76
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:79
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:74
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:56
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
NeoMutt Logging.
struct Email * mutt_get_virt_email(struct Mailbox *m, int vnum)
Get a virtual Email.
Definition: mview.c:407
View of a Mailbox.
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size()
Definition: mx.c:1566
API for mailboxes.
All user-callable functions.
const struct CompleteOps CompletePatternOps
Auto-Completion of Patterns.
Definition: complete.c:82
uint8_t PatternCompFlags
Flags for mutt_pattern_comp(), e.g. MUTT_PC_FULL_MSG.
Definition: lib.h:67
#define MUTT_PC_FULL_MSG
Enable body and header matching.
Definition: lib.h:69
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: lib.h:106
#define MUTT_ALIAS_SIMPLESEARCH
Definition: lib.h:63
#define RANGE_GT_RX
Definition: private.h:108
#define RANGE_ABS_RX
Definition: private.h:104
#define RANGE_LT_RX
Definition: private.h:107
#define RANGE_BARE_RX
Definition: private.h:111
#define RANGE_REL_RX
Definition: private.h:100
@ RANGE_K_REL
Relative range.
Definition: private.h:88
@ RANGE_K_ABS
Absolute range.
Definition: private.h:89
@ RANGE_K_LT
Less-than range.
Definition: private.h:90
@ RANGE_K_BARE
Single symbol.
Definition: private.h:92
@ RANGE_K_GT
Greater-than range.
Definition: private.h:91
bool(* eat_arg_t)(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
Definition: pattern.c:87
static void quote_simple(const char *str, struct Buffer *buf)
Apply simple quoting to a string.
Definition: pattern.c:95
int mutt_search_command(struct MailboxView *mv, struct Menu *menu, int cur, struct SearchState *state, SearchFlags flags)
Perform a search.
Definition: pattern.c:441
struct RangeRegex RangeRegexes[]
Set of Regexes for various range types.
Definition: pattern.c:66
int mutt_search_alias_command(struct Menu *menu, int cur, struct SearchState *state, SearchFlags flags)
Perform a search.
Definition: pattern.c:600
int mutt_pattern_alias_func(char *prompt, struct AliasMenuData *mdata, struct Menu *menu)
Perform some Pattern matching for Alias.
Definition: pattern.c:191
void mutt_check_simple(struct Buffer *buf, const char *simple)
Convert a simple search into a real request.
Definition: pattern.c:113
int mutt_pattern_func(struct MailboxView *mv, int op, char *prompt)
Perform some Pattern matching.
Definition: pattern.c:290
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
Progress bar.
@ MUTT_PROGRESS_READ
Progress tracks elements, according to $read_inc
Definition: lib.h:49
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:92
bool progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:73
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:124
Prototypes for many functions.
#define SLIST_FIRST(head)
Definition: queue.h:229
Holds state of a search.
#define SEARCH_OPPOSITE
Search in the opposite direction.
Definition: search_state.h:45
uint8_t SearchFlags
Flags for a specific search, e.g. SEARCH_PROMPT.
Definition: search_state.h:42
#define SEARCH_PROMPT
Ask for search input.
Definition: search_state.h:44
GUI display the mailboxes in a side panel.
Key value store.
#define NONULL(x)
Definition: string2.h:37
AliasView array wrapper with Pattern information -.
Definition: gui.h:52
char * limit
Limit being used.
Definition: gui.h:58
struct AliasViewArray ava
All Aliases/Queries.
Definition: gui.h:53
struct Menu * menu
Menu.
Definition: gui.h:56
GUI data wrapping an Alias.
Definition: gui.h:36
bool is_visible
Is visible?
Definition: gui.h:43
bool is_matched
Search matches this Alias.
Definition: gui.h:40
bool is_searched
Alias has been searched.
Definition: gui.h:39
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
String manipulation buffer.
Definition: buffer.h:34
char * data
Pointer to data.
Definition: buffer.h:35
The envelope/body of an email.
Definition: email.h:37
bool searched
Email has been searched.
Definition: email.h:104
bool matched
Search matches this Email.
Definition: email.h:101
bool visible
Is this message part of the view?
Definition: email.h:120
bool limit_visited
Has the limit pattern been applied to this message?
Definition: email.h:121
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:119
struct Body * body
List of MIME parts.
Definition: email.h:67
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
Definition: email.h:122
int vnum
Virtual message number.
Definition: email.h:113
View of a Mailbox.
Definition: mview.h:39
bool collapsed
Are all threads collapsed?
Definition: mview.h:48
struct Menu * menu
Needed for pattern compilation.
Definition: mview.h:46
off_t vsize
Size (in bytes) of the messages shown.
Definition: mview.h:40
struct PatternList * limit_pattern
Compiled limit pattern.
Definition: mview.h:42
struct Mailbox * mailbox
Current Mailbox.
Definition: mview.h:50
char * pattern
Limit pattern string.
Definition: mview.h:41
A mailbox.
Definition: mailbox.h:79
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
Definition: lib.h:70
void * mdata
Private data.
Definition: lib.h:137
int max
Number of entries in the menu.
Definition: lib.h:72
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
A simple (non-regex) pattern.
Definition: lib.h:77
Regular expression representing a range.
Definition: private.h:75
Holds state of a search.
Definition: search_state.h:35
struct Buffer * string
search string
Definition: search_state.h:37
struct Buffer * string_expn
expanded search string
Definition: search_state.h:38
bool reverse
search backwards
Definition: search_state.h:39
struct PatternList * pattern
compiled search pattern
Definition: search_state.h:36