NeoMutt  2025-12-11-769-g906513
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
regex.c
Go to the documentation of this file.
1
23
30
31#include "config.h"
32#include <stdbool.h>
33#include <stddef.h>
34#include <stdint.h>
35#include "mutt/lib.h"
36#include "config/lib.h"
37#include "core/lib.h"
38#include "index/lib.h"
39#include "pattern/lib.h"
40#include "attr.h"
41#include "color.h"
42#include "commands.h"
43#include "debug.h"
44#include "module_data.h"
45#include "notify2.h"
46#include "regex4.h"
47
52{
54 color_debug(LL_DEBUG5, "init AttachList, BodyList, etc\n");
55 STAILQ_INIT(&mod_data->attach_list);
56 STAILQ_INIT(&mod_data->body_list);
57 STAILQ_INIT(&mod_data->header_list);
60 STAILQ_INIT(&mod_data->index_date_list);
61 STAILQ_INIT(&mod_data->index_label_list);
63 STAILQ_INIT(&mod_data->index_size_list);
64 STAILQ_INIT(&mod_data->index_tags_list);
65 STAILQ_INIT(&mod_data->index_flags_list);
66 STAILQ_INIT(&mod_data->index_list);
68 STAILQ_INIT(&mod_data->index_tag_list);
69 STAILQ_INIT(&mod_data->status_list);
70}
71
95
100{
102}
103
111{
112 if (!rcol)
113 return;
114
115 rcol->match = 0;
116 rcol->stop_matching = false;
117
119 FREE(&rcol->pattern);
120 regfree(&rcol->regex);
122}
123
128void regex_color_free(struct RegexColor **ptr)
129{
130 if (!ptr || !*ptr)
131 return;
132
133 struct RegexColor *rcol = *ptr;
134 regex_color_clear(rcol);
135
136 FREE(ptr);
137}
138
144{
145 return MUTT_MEM_CALLOC(1, struct RegexColor);
146}
147
152struct RegexColorList *regex_color_list_new(void)
153{
154 struct RegexColorList *rcl = MUTT_MEM_CALLOC(1, struct RegexColorList);
155
156 STAILQ_INIT(rcl);
157
158 struct RegexColor *rcol = regex_color_new();
159 STAILQ_INSERT_TAIL(rcl, rcol, entries);
160
161 return rcl;
162}
163
172void regex_color_list_clear(struct RegexColorList *rcl)
173{
174 if (!rcl)
175 return;
176
177 struct RegexColor *np = NULL, *tmp = NULL;
178 STAILQ_FOREACH_SAFE(np, rcl, entries, tmp)
179 {
180 STAILQ_REMOVE(rcl, np, RegexColor, entries);
181 regex_color_free(&np);
182 }
183}
184
190struct RegexColorList *regex_colors_get_list(enum ColorId cid)
191{
193 switch (cid)
194 {
196 return &mod_data->attach_list;
197 case MT_COLOR_BODY:
198 return &mod_data->body_list;
199 case MT_COLOR_HEADER:
200 return &mod_data->header_list;
201 case MT_COLOR_INDEX:
202 return &mod_data->index_list;
204 return &mod_data->index_author_list;
206 return &mod_data->index_collapsed_list;
208 return &mod_data->index_date_list;
210 return &mod_data->index_flags_list;
212 return &mod_data->index_label_list;
214 return &mod_data->index_number_list;
216 return &mod_data->index_size_list;
218 return &mod_data->index_subject_list;
220 return &mod_data->index_tag_list;
222 return &mod_data->index_tags_list;
223 case MT_COLOR_STATUS:
224 return &mod_data->status_list;
225 default:
226 return NULL;
227 }
228}
229
243static enum CommandResult add_pattern(struct RegexColorList *rcl, const char *s,
244 struct AttrColor *ac_val,
245 struct Buffer *err, bool is_index, int match)
246{
247 struct RegexColor *rcol = NULL;
248
249 STAILQ_FOREACH(rcol, rcl, entries)
250 {
251 if (mutt_str_equal(s, rcol->pattern))
252 break;
253 }
254
255 if (rcol) // found a matching regex
256 {
257 struct AttrColor *ac = &rcol->attr_color;
258 attr_color_overwrite(ac, ac_val);
259 }
260 else
261 {
262 rcol = regex_color_new();
263 if (is_index)
264 {
265 struct Buffer *buf = buf_pool_get();
266 buf_strcpy(buf, s);
267 const char *const c_simple_search = cs_subset_string(NeoMutt->sub, "simple_search");
268 mutt_check_simple(buf, NONULL(c_simple_search));
269 struct MailboxView *mv_cur = get_current_mailbox_view();
271 buf_pool_release(&buf);
272 if (!rcol->color_pattern)
273 {
274 regex_color_free(&rcol);
275 return MUTT_CMD_ERROR;
276 }
277 }
278 else
279 {
280 // Smart case matching
281 uint16_t flags = mutt_mb_is_lower(s) ? REG_ICASE : 0;
282
283 const int r = REG_COMP(&rcol->regex, s, flags);
284 if (r != 0)
285 {
286 regerror(r, &rcol->regex, err->data, err->dsize);
287 buf_fix_dptr(err);
288 regex_color_free(&rcol);
289 return MUTT_CMD_ERROR;
290 }
291 }
292 rcol->pattern = mutt_str_dup(s);
293 rcol->match = match;
294
295 struct AttrColor *ac = &rcol->attr_color;
296
297 attr_color_overwrite(ac, ac_val);
298
299 STAILQ_INSERT_TAIL(rcl, rcol, entries);
300 }
301
302 if (is_index)
303 {
304 /* force re-caching of index colors */
306 struct EventColor ev_c = { MT_COLOR_INDEX, NULL };
308 }
309
310 return MUTT_CMD_SUCCESS;
311}
312
324bool regex_colors_parse_color_list(enum ColorId cid, const char *pat,
325 struct AttrColor *ac, int *rc, struct Buffer *err)
326
327{
328 if (cid == MT_COLOR_STATUS)
329 return false;
330
331 struct RegexColorList *rcl = regex_colors_get_list(cid);
332 if (!rcl)
333 return false;
334
335 bool is_index = false;
336 switch (cid)
337 {
339 case MT_COLOR_BODY:
340 break;
341 case MT_COLOR_HEADER:
342 break;
343 case MT_COLOR_INDEX:
354 is_index = true;
355 break;
356 default:
357 return false;
358 }
359
360 *rc = add_pattern(rcl, pat, ac, err, is_index, 0);
361
362 struct Buffer *buf = buf_pool_get();
363 get_colorid_name(cid, buf);
364 color_debug(LL_DEBUG5, "NT_COLOR_SET: %s\n", buf_string(buf));
365 buf_pool_release(&buf);
366
367 if (!is_index) // else it will be logged in add_pattern()
368 {
370 struct EventColor ev_c = { cid, NULL };
372 }
373
374 return true;
375}
376
387 struct AttrColor *ac, int match, struct Buffer *err)
388{
389 if (cid != MT_COLOR_STATUS)
390 return MUTT_CMD_ERROR;
391
393 int rc = add_pattern(&mod_data->status_list, pat, ac, err, false, match);
394 if (rc != MUTT_CMD_SUCCESS)
395 return rc;
396
397 struct Buffer *buf = buf_pool_get();
398 get_colorid_name(cid, buf);
399 color_debug(LL_DEBUG5, "NT_COLOR_SET: %s\n", buf_string(buf));
400 buf_pool_release(&buf);
401
402 struct EventColor ev_c = { cid, NULL };
404
405 return rc;
406}
407
414bool regex_colors_parse_uncolor(enum ColorId cid, const char *pat)
415{
416 struct RegexColorList *cl = regex_colors_get_list(cid);
417 if (!cl)
418 return false;
419
421
422 if (!pat) // Reset all patterns
423 {
424 if (STAILQ_EMPTY(cl))
425 return true;
426
427 mutt_debug(LL_NOTIFY, "NT_COLOR_RESET: [ALL]\n");
428 struct EventColor ev_c = { cid, NULL };
430
432 return true;
433 }
434
435 bool rc = false;
436 struct RegexColor *np = NULL, *prev = NULL;
437 prev = NULL;
438 STAILQ_FOREACH(np, cl, entries)
439 {
440 if (mutt_str_equal(pat, np->pattern))
441 {
442 rc = true;
443
444 color_debug(LL_DEBUG1, "Freeing pattern \"%s\" from XXX\n", pat);
445 if (prev)
446 STAILQ_REMOVE_AFTER(cl, prev, entries);
447 else
448 STAILQ_REMOVE_HEAD(cl, entries);
449
450 mutt_debug(LL_NOTIFY, "NT_COLOR_RESET: XXX\n");
451 struct EventColor ev_c = { cid, &np->attr_color };
453
454 regex_color_free(&np);
455 break;
456 }
457 prev = np;
458 }
459
460 return rc;
461}
void attr_color_clear(struct AttrColor *ac)
Free the contents of an AttrColor.
Definition attr.c:47
void attr_color_overwrite(struct AttrColor *ac_old, const struct AttrColor *ac_new)
Update an AttrColor in-place.
Definition attr.c:394
Colour and attributes.
void buf_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition buffer.c:182
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
void get_colorid_name(unsigned int cid, struct Buffer *buf)
Get the name of a Colour ID.
Definition commands.c:128
Parse colour commands.
Color private Module data.
static enum CommandResult add_pattern(struct RegexColorList *rcl, const char *s, struct AttrColor *ac_val, struct Buffer *err, bool is_index, int match)
Associate a colour to a pattern.
Definition regex.c:243
struct RegexColorList * regex_colors_get_list(enum ColorId cid)
Return the RegexColorList for a Colour ID.
Definition regex.c:190
int regex_colors_parse_status_list(enum ColorId cid, const char *pat, struct AttrColor *ac, int match, struct Buffer *err)
Parse a Regex 'color status' command.
Definition regex.c:386
bool regex_colors_parse_color_list(enum ColorId cid, const char *pat, struct AttrColor *ac, int *rc, struct Buffer *err)
Parse a Regex 'color' command.
Definition regex.c:324
void regex_colors_init(void)
Initialise the Regex colours.
Definition regex.c:51
void regex_colors_reset(void)
Reset the Regex colours.
Definition regex.c:75
void regex_color_free(struct RegexColor **ptr)
Free a Regex colour.
Definition regex.c:128
bool regex_colors_parse_uncolor(enum ColorId cid, const char *pat)
Parse a Regex 'uncolor' command.
Definition regex.c:414
void regex_colors_cleanup(void)
Cleanup the Regex colours.
Definition regex.c:99
struct RegexColor * regex_color_new(void)
Create a new RegexColor.
Definition regex.c:143
void regex_color_list_clear(struct RegexColorList *rcl)
Free the contents of a RegexColorList.
Definition regex.c:172
struct RegexColorList * regex_color_list_new(void)
Create a new RegexColorList.
Definition regex.c:152
void regex_color_clear(struct RegexColor *rcol)
Free the contents of a Regex colour.
Definition regex.c:110
Color and attribute parsing.
ColorId
List of all coloured objects.
Definition color.h:35
@ MT_COLOR_INDEX_AUTHOR
Index: author field.
Definition color.h:87
@ MT_COLOR_HEADER
Message headers (takes a pattern)
Definition color.h:48
@ MT_COLOR_STATUS
Status bar (takes a pattern)
Definition color.h:78
@ MT_COLOR_INDEX_SIZE
Index: size field.
Definition color.h:93
@ MT_COLOR_INDEX_TAGS
Index: tags field (g, J)
Definition color.h:96
@ MT_COLOR_INDEX_SUBJECT
Index: subject field.
Definition color.h:94
@ MT_COLOR_BODY
Pager: highlight body of message (takes a pattern)
Definition color.h:39
@ MT_COLOR_INDEX_DATE
Index: date field.
Definition color.h:89
@ MT_COLOR_INDEX_TAG
Index: tag field (G)
Definition color.h:95
@ MT_COLOR_ATTACH_HEADERS
MIME attachment test (takes a pattern)
Definition color.h:38
@ MT_COLOR_INDEX_LABEL
Index: label field.
Definition color.h:91
@ MT_COLOR_INDEX
Index: default colour.
Definition color.h:86
@ MT_COLOR_INDEX_NUMBER
Index: index number.
Definition color.h:92
@ MT_COLOR_INDEX_FLAGS
Index: flags field.
Definition color.h:90
@ MT_COLOR_INDEX_COLLAPSED
Index: number of messages in collapsed thread.
Definition color.h:88
CommandResult
Error codes for command_t parse functions.
Definition command.h:37
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition command.h:40
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition command.h:38
struct PatternList * mutt_pattern_comp(struct MailboxView *mv, const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition compile.c:958
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition compile.c:830
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
Colour Debugging.
static int color_debug(enum LogLevel level, const char *format,...)
Definition debug.h:51
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
GUI manage the main index (list of emails)
struct MailboxView * get_current_mailbox_view(void)
Get the current Mailbox view.
Definition index.c:693
@ LL_DEBUG5
Log at debug level 5.
Definition logging2.h:49
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
@ LL_NOTIFY
Log of notifications.
Definition logging2.h:50
bool mutt_mb_is_lower(const char *s)
Does a multi-byte string contain only lowercase characters?
Definition mbyte.c:355
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:52
@ MODULE_ID_COLOR
ModuleColor, Color
Definition module_api.h:53
Convenience wrapper for the library headers.
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition notify.c:173
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:665
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:665
Colour notifications.
@ NT_COLOR_RESET
Color has been reset/removed.
Definition notify2.h:41
@ NT_COLOR_SET
Color has been set.
Definition notify2.h:40
@ NT_COLOR
Colour has changed, NotifyColor, EventColor.
Definition notify_type.h:41
Match patterns to emails.
#define MUTT_PC_FULL_MSG
Enable body and header matching.
Definition lib.h:70
void mutt_check_simple(struct Buffer *s, const char *simple)
Convert a simple search into a real request.
Definition pattern.c:91
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
#define STAILQ_REMOVE_HEAD(head, field)
Definition queue.h:461
#define STAILQ_REMOVE(head, elm, type, field)
Definition queue.h:441
#define STAILQ_INIT(head)
Definition queue.h:410
#define STAILQ_REMOVE_AFTER(head, elm, field)
Definition queue.h:455
#define STAILQ_FOREACH(var, head, field)
Definition queue.h:390
#define STAILQ_INSERT_TAIL(head, elm, field)
Definition queue.h:427
#define STAILQ_EMPTY(head)
Definition queue.h:382
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition queue.h:400
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition regex3.h:49
Regex Colour.
#define NONULL(x)
Definition string2.h:44
A curses colour and its attributes.
Definition attr.h:65
String manipulation buffer.
Definition buffer.h:36
size_t dsize
Length of data.
Definition buffer.h:39
char * data
Pointer to data.
Definition buffer.h:37
Color private Module data.
Definition module_data.h:35
struct RegexColorList index_collapsed_list
List of colours applied to a collapsed thread in the index.
Definition module_data.h:47
struct RegexColorList index_subject_list
List of colours applied to the subject in the index.
Definition module_data.h:54
struct RegexColorList attach_list
List of colours applied to the attachment headers.
Definition module_data.h:43
struct RegexColorList body_list
List of colours applied to the email body.
Definition module_data.h:44
struct RegexColorList index_flags_list
List of colours applied to the flags in the index.
Definition module_data.h:49
struct RegexColorList index_label_list
List of colours applied to the label in the index.
Definition module_data.h:50
struct RegexColorList index_tags_list
List of colours applied to the tags in the index.
Definition module_data.h:56
struct RegexColorList index_size_list
List of colours applied to the size in the index.
Definition module_data.h:53
struct RegexColorList index_list
List of default colours applied to the index.
Definition module_data.h:51
struct Notify * colors_notify
Notifications: ColorId, EventColor.
Definition module_data.h:40
struct RegexColorList index_author_list
List of colours applied to the author in the index.
Definition module_data.h:46
struct RegexColorList header_list
List of colours applied to the email headers.
Definition module_data.h:45
struct RegexColorList index_date_list
List of colours applied to the date in the index.
Definition module_data.h:48
struct RegexColorList index_number_list
List of colours applied to the message number in the index.
Definition module_data.h:52
struct RegexColorList status_list
List of colours applied to the status bar.
Definition module_data.h:57
struct RegexColorList index_tag_list
List of colours applied to tags in the index.
Definition module_data.h:55
An Event that happened to a Colour.
Definition notify2.h:52
enum ColorId cid
Colour ID that has changed.
Definition notify2.h:53
View of a Mailbox.
Definition mview.h:40
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
A regular expression and a color to highlight a line.
Definition regex4.h:35
regex_t regex
Compiled regex.
Definition regex4.h:38
struct PatternList * color_pattern
Compiled pattern to speed up index color calculation.
Definition regex4.h:40
struct AttrColor attr_color
Colour and attributes to apply.
Definition regex4.h:36
char * pattern
Pattern to match.
Definition regex4.h:37
bool stop_matching
Used by the pager for body patterns, to prevent the color from being retried once it fails.
Definition regex4.h:42
int match
Substring to match, 0 for old behaviour.
Definition regex4.h:39