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