Группа :: Сети/Почта
Пакет: neomutt
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: neomutt-color-group.patch
Скачать
Скачать
From: Alexey Gladkov <gladkov.alexey@gmail.com>
Date: Mon, 22 Jul 2019 20:03:52 +0000 (+0200)
Subject: Add color groups for header and body
X-Git-Url: http://git.altlinux.org/people/glebfm/packages/neomutt.git?p=neomutt.git;a=commitdiff_plain;h=f91e40fd6940d847c557083c33a01440e399fc3d
Add color groups for header and body
Co-authored-by: Gleb Fotengauer-Malinovskiy <glebfm@altlinux.org>
Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
Signed-off-by: Gleb Fotengauer-Malinovskiy <glebfm@altlinux.org>
---
diff --git a/gui/color.c b/gui/color.c
index c21570f..6bdf196 100644
--- a/gui/color.c
+++ b/gui/color.c
@@ -153,6 +153,13 @@ const struct Mapping ComposeFields[] = {
};
// clang-format off
+static const struct Mapping ColorGroupFields[] =
+{
+ { "start", MT_COLOR_GROUP_START },
+ { "end", MT_COLOR_GROUP_END },
+ { NULL, 0 },
+};
+
/**
* defs_free - Free the simple colour definitions
* @param c Colours
@@ -364,6 +371,8 @@ void mutt_colors_free(struct Colors **ptr)
defs_free(c);
quotes_free(c);
notify_free(&c->notify);
+ mutt_free_color_group_stack(&c->group_header_stack);
+ mutt_free_color_group_stack(&c->group_body_stack);
FREE(ptr);
}
@@ -388,6 +397,8 @@ struct Colors *mutt_colors_new(void)
STAILQ_INIT(&c->index_subject_list);
STAILQ_INIT(&c->index_tag_list);
STAILQ_INIT(&c->status_list);
+ c->group_header_stack = NULL;
+ c->group_body_stack = NULL;
#ifdef HAVE_COLOR
start_color();
@@ -953,7 +964,7 @@ enum CommandResult mutt_parse_unmono(struct Buffer *buf, struct Buffer *s,
*/
static enum CommandResult add_pattern(struct Colors *c, struct ColorLineList *top, const char *s,
bool sensitive, uint32_t fg, uint32_t bg, int attr,
- struct Buffer *err, bool is_index, int match)
+ struct Buffer *err, bool is_index, int match, struct ColorGroupStack *cgs)
{
struct ColorLine *tmp = NULL;
@@ -1043,6 +1054,8 @@ static enum CommandResult add_pattern(struct Colors *c, struct ColorLineList *to
}
}
+ if (cgs)
+ tmp->group = cgs->group;
return MUTT_CMD_SUCCESS;
}
@@ -1240,32 +1253,36 @@ static enum CommandResult parse_color(struct Colors *c, struct Buffer *buf, stru
#endif
if (object == MT_COLOR_ATTACH_HEADERS)
- rc = add_pattern(c, &c->attach_list, buf->data, true, fg, bg, attr, err, false, match);
+ rc = add_pattern(c, &c->attach_list, buf->data, true, fg, bg, attr, err, false, match, NULL);
else if (object == MT_COLOR_BODY)
- rc = add_pattern(c, &c->body_list, buf->data, true, fg, bg, attr, err, false, match);
+ rc = add_pattern(c, &c->body_list, buf->data, true, fg, bg, attr,
+ err, false, match, c->group_body_stack);
else if (object == MT_COLOR_HEADER)
- rc = add_pattern(c, &c->hdr_list, buf->data, false, fg, bg, attr, err, false, match);
+ {
+ rc = add_pattern(c, &c->hdr_list, buf->data, false, fg, bg, attr,
+ err, false, match, c->group_header_stack);
+ }
else if (object == MT_COLOR_INDEX)
{
- rc = add_pattern(c, &c->index_list, buf->data, true, fg, bg, attr, err, true, match);
+ rc = add_pattern(c, &c->index_list, buf->data, true, fg, bg, attr, err, true, match, NULL);
}
else if (object == MT_COLOR_INDEX_AUTHOR)
{
rc = add_pattern(c, &c->index_author_list, buf->data, true, fg, bg, attr,
- err, true, match);
+ err, true, match, NULL);
}
else if (object == MT_COLOR_INDEX_FLAGS)
{
- rc = add_pattern(c, &c->index_flags_list, buf->data, true, fg, bg, attr, err, true, match);
+ rc = add_pattern(c, &c->index_flags_list, buf->data, true, fg, bg, attr, err, true, match, NULL);
}
else if (object == MT_COLOR_INDEX_SUBJECT)
{
rc = add_pattern(c, &c->index_subject_list, buf->data, true, fg, bg, attr,
- err, true, match);
+ err, true, match, NULL);
}
else if (object == MT_COLOR_INDEX_TAG)
{
- rc = add_pattern(c, &c->index_tag_list, buf->data, true, fg, bg, attr, err, true, match);
+ rc = add_pattern(c, &c->index_tag_list, buf->data, true, fg, bg, attr, err, true, match, NULL);
}
else if (object == MT_COLOR_QUOTED)
{
@@ -1322,7 +1339,7 @@ static enum CommandResult parse_color(struct Colors *c, struct Buffer *buf, stru
return MUTT_CMD_WARNING;
}
- rc = add_pattern(c, &c->status_list, buf->data, true, fg, bg, attr, err, false, match);
+ rc = add_pattern(c, &c->status_list, buf->data, true, fg, bg, attr, err, false, match, NULL);
}
else // Remaining simple colours
{
@@ -1373,3 +1390,128 @@ enum CommandResult mutt_parse_mono(struct Buffer *buf, struct Buffer *s,
return parse_color(Colors, buf, s, err, parse_attr_spec, dry_run, false);
}
+
+#ifdef HAVE_COLOR
+/* usage: color-group { header | body } { start | end } <regexp>
+ */
+enum CommandResult mutt_parse_color_group(struct Buffer *buf, struct Buffer *s,
+ intptr_t data, struct Buffer *err)
+{
+ int target = 0;
+ int object = 0;
+ int r = 0;
+ regex_t *rx;
+ struct ColorGroup *grp;
+ struct ColorGroupStack **stack, *newStack;
+
+ if(!MoreArgs(s))
+ {
+ mutt_str_copy(err->data, _("(0) Missing arguments."), err->dsize);
+ return MUTT_CMD_ERROR;
+ }
+
+ mutt_extract_token(buf, s, 0);
+
+ if ((target = mutt_map_get_value(buf->data, Fields)) == -1)
+ {
+ snprintf(err->data, err->dsize, _("%s: no such object"), buf->data);
+ return MUTT_CMD_ERROR;
+ }
+
+ if (target == MT_COLOR_HEADER)
+ {
+ stack = &Colors->group_header_stack;
+ }
+ else if (target == MT_COLOR_BODY)
+ {
+ stack = &Colors->group_body_stack;
+ }
+ else
+ {
+ mutt_str_copy(err->data, _("Target must be 'header' or 'body'."), err->dsize);
+ return MUTT_CMD_ERROR;
+ }
+
+ mutt_extract_token(buf, s, 0);
+
+ if ((object = mutt_map_get_value(buf->data, ColorGroupFields)) == -1)
+ {
+ snprintf(err->data, err->dsize, _("%s: no such object"), buf->data);
+ return MUTT_CMD_ERROR;
+ }
+
+ if (!MoreArgs(s))
+ {
+ mutt_str_copy(err->data, _("(1) Missing arguments."), err->dsize);
+ return MUTT_CMD_ERROR;
+ }
+
+ mutt_extract_token(buf, s, 0);
+
+ if (MoreArgs(s))
+ {
+ mutt_str_copy(err->data, _("too many arguments"), err->dsize);
+ return MUTT_CMD_ERROR;
+ }
+
+ if (OptNoCurses || !has_colors())
+ return MUTT_CMD_SUCCESS;
+
+ rx = mutt_mem_calloc(1, sizeof(regex_t));
+
+ int flags = mutt_mb_is_lower(buf->data) ? REG_ICASE : 0;
+ if ((r = REG_COMP(rx, buf->data, flags)) != 0)
+ {
+ regerror(r, rx, err->data, err->dsize);
+ FREE(rx);
+ return MUTT_CMD_ERROR;
+ }
+
+ if (object == MT_COLOR_GROUP_END)
+ {
+ if (!*stack)
+ {
+ mutt_str_copy(err->data, "Unexpected group ending.", err->dsize);
+ regfree(rx);
+ FREE(rx);
+ return MUTT_CMD_ERROR;
+ }
+
+ (*stack)->group->pattern_end = mutt_str_dup(buf->data);
+ (*stack)->group->rx_end = rx;
+
+ newStack = (*stack)->next;
+ FREE(stack);
+ *stack = newStack;
+
+ return MUTT_CMD_SUCCESS;
+ }
+
+ grp = mutt_mem_calloc(1, sizeof(struct ColorGroup));
+ grp->pattern_start = mutt_str_dup(buf->data);
+ grp->rx_start = rx;
+
+ newStack = mutt_mem_calloc(1, sizeof(struct ColorGroupStack));
+ newStack->group = grp;
+ newStack->next = *stack;
+
+ *stack = newStack;
+
+ return MUTT_CMD_SUCCESS;
+}
+#endif
+
+void mutt_free_color_group_stack(struct ColorGroupStack **top)
+{
+ struct ColorGroupStack *t, *e;
+ if (!top)
+ return;
+ t = *top;
+ while (t)
+ {
+ e = t->next;
+ FREE(&t);
+ t = e;
+ }
+ *top = NULL;
+}
diff --git a/gui/color.h b/gui/color.h
index 8f02b32..0bb19b9 100644
--- a/gui/color.h
+++ b/gui/color.h
@@ -29,6 +29,29 @@
#include "mutt/lib.h"
#include "mutt_commands.h"
+enum ColorGroupPart
+{
+ MT_COLOR_GROUP_START,
+ MT_COLOR_GROUP_END,
+};
+
+struct ColorGroup
+{
+ char *pattern_start;
+ char *pattern_end;
+ regex_t *rx_start;
+ regex_t *rx_end;
+ struct ColorGroup *next;
+};
+
+struct ColorGroupStack
+{
+ struct ColorGroup *group;
+ struct ColorGroupStack *next;
+};
+
+void mutt_free_color_group_stack(struct ColorGroupStack **top);
+
/**
* struct ColorLine - A regular expression and a color to highlight a line
*/
@@ -38,6 +61,7 @@ struct ColorLine
int match; ///< Substring to match, 0 for old behaviour
char *pattern; ///< Pattern to match
struct PatternList *color_pattern; ///< Compiled pattern to speed up index color calculation
+ struct ColorGroup *group;
uint32_t fg; ///< Foreground colour
uint32_t bg; ///< Background colour
int pair; ///< Colour pair index
@@ -140,6 +164,9 @@ struct Colors
struct ColorLineList index_tag_list; ///< List of colours applied to tags in the index
struct ColorLineList status_list; ///< List of colours applied to the status bar
+ struct ColorGroupStack *group_header_stack;
+ struct ColorGroupStack *group_body_stack;
+
int *quotes; ///< Array of colours for quoted email text
int quotes_used; ///< Number of colours for quoted email text
@@ -182,6 +209,7 @@ void mutt_colors_free(struct Colors **ptr);
enum CommandResult mutt_parse_color (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err);
enum CommandResult mutt_parse_mono (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err);
enum CommandResult mutt_parse_uncolor(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err);
+enum CommandResult mutt_parse_color_group(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err);
enum CommandResult mutt_parse_unmono (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err);
#endif /* MUTT_COLOR_H */
diff --git a/init.c b/init.c
index 458b07a..8ec1c51 100644
--- a/init.c
+++ b/init.c
@@ -964,6 +964,7 @@ int mutt_init(struct ConfigSet *cs, bool skip_sys_rc, struct ListHead *commands)
done:
mutt_buffer_dealloc(&err);
mutt_buffer_dealloc(&buf);
+
return rc;
}
diff --git a/mutt_commands.c b/mutt_commands.c
index 94f9855..7f23063 100644
--- a/mutt_commands.c
+++ b/mutt_commands.c
@@ -59,6 +59,7 @@ static const struct Command mutt_commands[] = {
{ "charset-hook", mutt_parse_hook, MUTT_CHARSET_HOOK },
#ifdef HAVE_COLOR
{ "color", mutt_parse_color, 0 },
+ { "color-group", mutt_parse_color_group, 0 },
#endif
{ "crypt-hook", mutt_parse_hook, MUTT_CRYPT_HOOK },
{ "echo", parse_echo, 0 },
diff --git a/pager.c b/pager.c
index a180873..258c88b 100644
--- a/pager.c
+++ b/pager.c
@@ -197,6 +197,8 @@ struct PagerRedrawData
struct Line *line_info;
FILE *fp;
struct stat sb;
+ struct ColorGroupStack *group_header_stack;
+ struct ColorGroupStack *group_body_stack;
};
/* hack to return to position when returning from index to same message */
@@ -1006,10 +1008,12 @@ int mutt_is_quote_line(char *line, regmatch_t *pmatch)
*/
static void resolve_types(char *buf, char *raw, struct Line *line_info, int n,
int last, struct QClass **quote_list, int *q_level,
- bool *force_redraw, bool q_classify)
+ bool *force_redraw, bool q_classify,
+ struct PagerRedrawData *rd)
{
struct ColorLine *color_line = NULL;
struct ColorLineList *head = NULL;
+ struct ColorGroupStack **color_stack;
regmatch_t pmatch[1];
bool found;
bool null_rx;
@@ -1129,9 +1133,15 @@ static void resolve_types(char *buf, char *raw, struct Line *line_info, int n,
offset = 0;
line_info[n].chunks = 0;
if (line_info[n].type == MT_COLOR_HDRDEFAULT)
+ {
head = &Colors->hdr_list;
+ color_stack = &rd->group_header_stack;
+ }
else
+ {
head = &Colors->body_list;
+ color_stack = &rd->group_body_stack;
+ }
STAILQ_FOREACH(color_line, head, entries)
{
color_line->stop_matching = false;
@@ -1145,6 +1155,34 @@ static void resolve_types(char *buf, char *raw, struct Line *line_info, int n,
null_rx = false;
STAILQ_FOREACH(color_line, head, entries)
{
+ if (color_line->group)
+ {
+ short is_start_group = (!*color_stack || (*color_stack)->group != color_line->group);
+
+ regex_t *rx = is_start_group
+ ? color_line->group->rx_start
+ : color_line->group->rx_end;
+ if (rx && regexec (rx, buf + offset, 1, pmatch, (offset ? REG_NOTBOL : 0)) == 0)
+ {
+ struct ColorGroupStack *newStack;
+
+ if (is_start_group)
+ {
+ newStack = mutt_mem_calloc(1, sizeof(struct ColorGroupStack));
+ newStack->group = color_line->group;
+ newStack->next = *color_stack;
+ }
+ else
+ {
+ newStack = (*color_stack)->next;
+ FREE(color_stack);
+ }
+
+ *color_stack = newStack;
+ }
+ else if (is_start_group)
+ continue;
+ }
if (!color_line->stop_matching &&
(regexec(&color_line->regex, buf + offset, 1, pmatch,
((offset != 0) ? REG_NOTBOL : 0)) == 0))
@@ -1676,7 +1714,7 @@ static int format_line(struct Line **line_info, int n, unsigned char *buf,
* @retval 0 normal exit, line was not displayed
* @retval >0 normal exit, line was displayed
*/
-static int display_line(FILE *fp, LOFF_T *last_pos, struct Line **line_info,
+static int display_line(struct PagerRedrawData *rd, LOFF_T *last_pos, struct Line **line_info,
int n, int *last, int *max, PagerFlags flags,
struct QClass **quote_list, int *q_level, bool *force_redraw,
regex_t *search_re, struct MuttWindow *win_pager)
@@ -1720,7 +1758,7 @@ static int display_line(FILE *fp, LOFF_T *last_pos, struct Line **line_info,
if (flags & MUTT_PAGER_LOGS)
{
/* determine the line class */
- if (fill_buffer(fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready) < 0)
+ if (fill_buffer(rd->fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready) < 0)
{
if (change_last)
(*last)--;
@@ -1744,7 +1782,7 @@ static int display_line(FILE *fp, LOFF_T *last_pos, struct Line **line_info,
if (curr_line->type == -1)
{
/* determine the line class */
- if (fill_buffer(fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready) < 0)
+ if (fill_buffer(rd->fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready) < 0)
{
if (change_last)
(*last)--;
@@ -1752,7 +1790,7 @@ static int display_line(FILE *fp, LOFF_T *last_pos, struct Line **line_info,
}
resolve_types((char *) fmt, (char *) buf, *line_info, n, *last,
- quote_list, q_level, force_redraw, flags & MUTT_SHOWCOLOR);
+ quote_list, q_level, force_redraw, flags & MUTT_SHOWCOLOR, rd);
/* avoid race condition for continuation lines when scrolling up */
for (m = n + 1; m < *last && (*line_info)[m].offset && (*line_info)[m].continuation; m++)
@@ -1775,7 +1813,7 @@ static int display_line(FILE *fp, LOFF_T *last_pos, struct Line **line_info,
if ((flags & MUTT_SHOWCOLOR) && !curr_line->continuation &&
(curr_line->type == MT_COLOR_QUOTED) && !curr_line->quote)
{
- if (fill_buffer(fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready) < 0)
+ if (fill_buffer(rd->fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready) < 0)
{
if (change_last)
(*last)--;
@@ -1796,7 +1834,7 @@ static int display_line(FILE *fp, LOFF_T *last_pos, struct Line **line_info,
if ((flags & MUTT_SEARCH) && !curr_line->continuation && (curr_line->search_cnt == -1))
{
- if (fill_buffer(fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready) < 0)
+ if (fill_buffer(rd->fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready) < 0)
{
if (change_last)
(*last)--;
@@ -1842,7 +1880,7 @@ static int display_line(FILE *fp, LOFF_T *last_pos, struct Line **line_info,
goto out; /* fake display */
}
- b_read = fill_buffer(fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready);
+ b_read = fill_buffer(rd->fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready);
if (b_read < 0)
{
if (change_last)
@@ -2090,7 +2128,7 @@ static void pager_custom_redraw(struct Menu *pager_menu)
}
int i = -1;
int j = -1;
- while (display_line(rd->fp, &rd->last_pos, &rd->line_info, ++i, &rd->last_line,
+ while (display_line(rd, &rd->last_pos, &rd->line_info, ++i, &rd->last_line,
&rd->max_line, rd->has_types | rd->search_flag | (rd->flags & MUTT_PAGER_NOWRAP),
&rd->quote_list, &rd->q_level, &rd->force_redraw,
&rd->search_re, rd->extra->win_pager) == 0)
@@ -2117,7 +2155,7 @@ static void pager_custom_redraw(struct Menu *pager_menu)
while ((rd->lines < rd->extra->win_pager->state.rows) &&
(rd->line_info[rd->curline].offset <= rd->sb.st_size - 1))
{
- if (display_line(rd->fp, &rd->last_pos, &rd->line_info, rd->curline,
+ if (display_line(rd, &rd->last_pos, &rd->line_info, rd->curline,
&rd->last_line, &rd->max_line,
(rd->flags & MUTT_DISPLAYFLAGS) | rd->hide_quoted |
rd->search_flag | (rd->flags & MUTT_PAGER_NOWRAP),
@@ -2760,7 +2798,7 @@ int mutt_pager(const char *banner, const char *fname, PagerFlags flags, struct P
rd.search_compiled = true;
/* update the search pointers */
int line_num = 0;
- while (display_line(rd.fp, &rd.last_pos, &rd.line_info, line_num,
+ while (display_line(&rd, &rd.last_pos, &rd.line_info, line_num,
&rd.last_line, &rd.max_line,
MUTT_SEARCH | (flags & MUTT_PAGER_NSKIP) | (flags & MUTT_PAGER_NOWRAP),
&rd.quote_list, &rd.q_level, &rd.force_redraw,
@@ -2878,7 +2916,7 @@ int mutt_pager(const char *banner, const char *fname, PagerFlags flags, struct P
{
while (((new_topline < rd.last_line) ||
(0 == (dretval = display_line(
- rd.fp, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
+ &rd, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
&rd.max_line, MUTT_TYPES | (flags & MUTT_PAGER_NOWRAP),
&rd.quote_list, &rd.q_level, &rd.force_redraw,
&rd.search_re, rd.extra->win_pager)))) &&
@@ -2892,7 +2930,7 @@ int mutt_pager(const char *banner, const char *fname, PagerFlags flags, struct P
while ((((new_topline + C_SkipQuotedOffset) < rd.last_line) ||
(0 == (dretval = display_line(
- rd.fp, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
+ &rd, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
&rd.max_line, MUTT_TYPES | (flags & MUTT_PAGER_NOWRAP),
&rd.quote_list, &rd.q_level, &rd.force_redraw,
&rd.search_re, rd.extra->win_pager)))) &&
@@ -2909,7 +2947,7 @@ int mutt_pager(const char *banner, const char *fname, PagerFlags flags, struct P
while ((((new_topline + C_SkipQuotedOffset) < rd.last_line) ||
(0 == (dretval = display_line(
- rd.fp, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
+ &rd, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
&rd.max_line, MUTT_TYPES | (flags & MUTT_PAGER_NOWRAP),
&rd.quote_list, &rd.q_level, &rd.force_redraw,
&rd.search_re, rd.extra->win_pager)))) &&
@@ -2931,7 +2969,7 @@ int mutt_pager(const char *banner, const char *fname, PagerFlags flags, struct P
{
int line_num = rd.curline;
/* make sure the types are defined to the end of file */
- while (display_line(rd.fp, &rd.last_pos, &rd.line_info, line_num, &rd.last_line,
+ while (display_line(&rd, &rd.last_pos, &rd.line_info, line_num, &rd.last_line,
&rd.max_line, rd.has_types | (flags & MUTT_PAGER_NOWRAP),
&rd.quote_list, &rd.q_level, &rd.force_redraw,
&rd.search_re, rd.extra->win_pager) == 0)
@@ -3617,5 +3655,8 @@ int mutt_pager(const char *banner, const char *fname, PagerFlags flags, struct P
window_set_visible(rd.extra->win_pager->parent, false);
mutt_window_reflow(dialog_find(rd.extra->win_pager));
+ mutt_free_color_group_stack(&rd.group_header_stack);
+ mutt_free_color_group_stack(&rd.group_body_stack);
+
return (rc != -1) ? rc : 0;
}