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