diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | Makefile | 13 | ||||
-rw-r--r-- | config/style.go | 3 | ||||
-rw-r--r-- | config/ui.go | 4 | ||||
-rw-r--r-- | doc/aerc-config.5.scd | 9 | ||||
-rw-r--r-- | doc/aerc-stylesets.7.scd | 30 | ||||
-rwxr-xr-x | filters/colorize | 177 | ||||
-rw-r--r-- | filters/colorize.c | 681 | ||||
-rw-r--r-- | filters/vectors/colorize-patch.expected | 49 | ||||
-rw-r--r-- | filters/vectors/colorize-patch.in | 49 | ||||
-rw-r--r-- | filters/vectors/colorize-quotes.expected | 65 | ||||
-rw-r--r-- | filters/vectors/colorize-quotes.in | 65 | ||||
-rw-r--r-- | stylesets/blue | 16 | ||||
-rw-r--r-- | stylesets/default | 12 | ||||
-rw-r--r-- | stylesets/dracula | 12 | ||||
-rw-r--r-- | stylesets/nord | 12 | ||||
-rw-r--r-- | stylesets/pink | 16 | ||||
-rw-r--r-- | widgets/msgviewer.go | 2 |
19 files changed, 1030 insertions, 188 deletions
@@ -3,6 +3,7 @@ /aerc /aerc.debug /wrap +/colorize /.aerc.d /linters.so race.log.* diff --git a/CHANGELOG.md b/CHANGELOG.md index ea9ca1d0..6742655c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Filters are now installed in `$PREFIX/libexec/aerc/filters`. The default exec `PATH` has been modified to include all variations of the `libexec` subdirs. +- The built-in `colorize` filter theme is now configured in styleset files into + the `[viewer]` section. ### Deprecated @@ -39,7 +39,7 @@ DOCS := \ aerc-templates.7 \ aerc-stylesets.7 -all: aerc wrap $(DOCS) +all: aerc wrap colorize $(DOCS) build_cmd:=$(GO) build $(BUILD_OPTS) $(GOFLAGS) -ldflags "$(GO_LDFLAGS)" -o aerc @@ -60,6 +60,9 @@ CFLAGS?=-O2 -g wrap: filters/wrap.c $(CC) $(CFLAGS) $(LDFLAGS) -o wrap filters/wrap.c +colorize: filters/colorize.c + $(CC) $(CFLAGS) $(LDFLAGS) -o colorize filters/colorize.c + .PHONY: dev dev: $(MAKE) aerc BUILD_OPTS="-trimpath -race" @@ -86,7 +89,7 @@ vulncheck: $(GO) run golang.org/x/vuln/cmd/govulncheck@latest ./... .PHONY: tests -tests: wrap +tests: wrap colorize $(GO) test $(GOFLAGS) ./... filters/test.sh @@ -113,9 +116,9 @@ doc: $(DOCS) RM?=rm -f clean: - $(RM) $(DOCS) aerc wrap + $(RM) $(DOCS) aerc wrap colorize -install: $(DOCS) aerc wrap +install: $(DOCS) aerc wrap colorize mkdir -m755 -p $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)/man1 $(DESTDIR)$(MANDIR)/man5 $(DESTDIR)$(MANDIR)/man7 \ $(DESTDIR)$(SHAREDIR) $(DESTDIR)$(SHAREDIR)/filters $(DESTDIR)$(SHAREDIR)/templates $(DESTDIR)$(SHAREDIR)/stylesets \ $(DESTDIR)$(PREFIX)/share/applications $(DESTDIR)$(LIBEXECDIR)/filters @@ -137,12 +140,12 @@ install: $(DOCS) aerc wrap install -m644 config/aerc.conf $(DESTDIR)$(SHAREDIR)/aerc.conf install -m644 config/binds.conf $(DESTDIR)$(SHAREDIR)/binds.conf install -m755 filters/calendar $(DESTDIR)$(LIBEXECDIR)/filters/calendar - install -m755 filters/colorize $(DESTDIR)$(LIBEXECDIR)/filters/colorize install -m755 filters/hldiff $(DESTDIR)$(LIBEXECDIR)/filters/hldiff install -m755 filters/html $(DESTDIR)$(LIBEXECDIR)/filters/html install -m755 filters/html-unsafe $(DESTDIR)$(LIBEXECDIR)/filters/html-unsafe install -m755 filters/plaintext $(DESTDIR)$(LIBEXECDIR)/filters/plaintext install -m755 filters/show-ics-details.py $(DESTDIR)$(LIBEXECDIR)/filters/show-ics-details.py + install -m755 colorize $(DESTDIR)$(LIBEXECDIR)/filters/colorize install -m755 wrap $(DESTDIR)$(LIBEXECDIR)/filters/wrap install -m644 templates/new_message $(DESTDIR)$(SHAREDIR)/templates/new_message install -m644 templates/quoted_reply $(DESTDIR)$(SHAREDIR)/templates/quoted_reply diff --git a/config/style.go b/config/style.go index 5ce2c1cf..65c5a3b1 100644 --- a/config/style.go +++ b/config/style.go @@ -254,6 +254,7 @@ func (s Style) composeWith(styles []*Style) Style { type StyleSet struct { objects map[StyleObject]*Style selected map[StyleObject]*Style + path string } func NewStyleSet() StyleSet { @@ -453,6 +454,8 @@ func (ss *StyleSet) LoadStyleSet(stylesetName string, stylesetDirs []string) err return err } + ss.path = filepath + return ss.ParseStyleSet(file) } diff --git a/config/ui.go b/config/ui.go index e9b1a2b2..8385cb97 100644 --- a/config/ui.go +++ b/config/ui.go @@ -519,6 +519,10 @@ func (uiConfig *UIConfig) GetComposedStyleSelected( return uiConfig.style.ComposeSelected(base, styles) } +func (uiConfig *UIConfig) StyleSetPath() string { + return uiConfig.style.path +} + func (base *UIConfig) contextual( ctxType uiContextType, value string, useCache bool, ) *UIConfig { diff --git a/doc/aerc-config.5.scd b/doc/aerc-config.5.scd index cea7d2e7..cc0a5f80 100644 --- a/doc/aerc-config.5.scd +++ b/doc/aerc-config.5.scd @@ -653,11 +653,8 @@ _text/plain_ text/plain=colorize ``` - The built-in _colorize_ filter supports alternative themes: - - ``` - text/plain=colorize -v theme=solarized - ``` + The built-in _colorize_ filter can be configured in the *[viewer]* + section of styleset files. See *aerc-stylesets*(7). Wrap long lines at 100 characters, while not messing up nested quotes. Handles format=flowed emails properly: @@ -766,7 +763,7 @@ _image/\*_ ``` See the wiki at https://man.sr.ht/~rjarry/aerc/ for more examples and possible -customizations of the built-in filters (e.g. colors of _colorize_). +customizations of the built-in filters. # OPENERS diff --git a/doc/aerc-stylesets.7.scd b/doc/aerc-stylesets.7.scd index 1303787c..eaedb4cb 100644 --- a/doc/aerc-stylesets.7.scd +++ b/doc/aerc-stylesets.7.scd @@ -136,6 +136,36 @@ styling. | *selector_chooser* : The item chooser in a selector ui element. +These next style objects only affect the built-in *colorize* filter and must be +declared under a *[viewer]* section of the styleset file. + +[[ *Style Object* +:[ *Description* +| *url* +: URLs. +| *header* +: RFC-822-like header names. +| *signature* +: Email signatures. +| *diff_meta* +: Patch diff meta lines. +| *diff_chunk* +: Patch diff chunks. +| *diff_add* +: Patch diff added lines. +| *diff_del* +: Patch diff deleted lines. +| *quote_1* +: First level quoted text. +| *quote_2* +: Second level quoted text. +| *quote_3* +: Third level quoted text. +| *quote_4* +: Fourth level quoted text. +| *quote_x* +: Above fourth level quoted text. + ## FNMATCH STYLE WILDCARD MATCHING The styleset configuration can be made simpler by using the fnmatch diff --git a/filters/colorize b/filters/colorize deleted file mode 100755 index 9d2a7363..00000000 --- a/filters/colorize +++ /dev/null @@ -1,177 +0,0 @@ -#!/usr/bin/awk -f -# Copyright (c) 2022 Robin Jarry -# -# A filter for the aerc mail program to colorize messages / attachments. -# Basic colour themes are supported. To use a theme set the theme variable -# in your aerc.conf accordingly, for example: -# -# text/plain=colorize -v theme=solarized - -BEGIN { - if (theme == "solarized") { - # R;G;B colors - url = "\033[38;2;181;137;0m" # yellow - header = "\033[38;2;211;54;130m" # magenta - signature = "\033[38;2;211;54;130m" # magenta - diff_meta = "\033[1;38;2;131;148;150m" # bold brblue - diff_chunk = "\033[38;2;42;161;152m" # cyan - diff_add = "\033[38;2;133;153;0m" # green - diff_del = "\033[38;2;220;50;47m" # red - quote_1 = "\033[38;2;38;139;210m" # blue - quote_2 = "\033[38;2;203;75;22m" # brred - quote_3 = "\033[38;2;211;54;130m" # magenta - quote_4 = "\033[38;2;108;113;196m" # brmagenta - quote_x = "\033[38;2;147;161;161m" # brcyan - bold = "\033[1m" - reset = "\033[0m" - } else if (theme == "" || theme == "default") { - # R;G;B colors - url = "\033[38;2;255;255;175m" # yellow - header = "\033[38;2;175;135;255m" # purple - signature = "\033[38;2;175;135;255m" # purple - diff_meta = "\033[1;38;2;255;255;255m" # bold white - diff_chunk = "\033[38;2;0;205;205m" # cyan - diff_add = "\033[38;2;0;205;0m" # green - diff_del = "\033[38;2;205;0;0m" # red - quote_1 = "\033[38;2;95;175;255m" # blue - quote_2 = "\033[38;2;255;135;0m" # orange - quote_3 = "\033[38;2;175;135;255m" # purple - quote_4 = "\033[38;2;255;95;215m" # pink - quote_x = "\033[38;2;128;128;128m" # gray - bold = "\033[1m" - reset = "\033[0m" - } else if (theme == "terminal") { - # terminal respects the users configured terminal color theme - url = "\033[4;34m" # underline blue - header = "\033[35m" # magenta - signature = "\033[35m" # magenta - diff_meta = "\033[2m" # faint - diff_chunk = "\033[36m" # cyan - diff_add = "\033[32m" # green - diff_del = "\033[31m" # red - quote_1 = "\033[37m" # grey - quote_2 = "\033[34m" # blue - quote_3 = "\033[2;37m" # faint grey - quote_4 = "\033[2;34m" # faint blue - quote_x = "\033[2;37m" # faint grey - bold = "\033[1m" - reset = "\033[0m" - } else { - print "error: unknown theme " theme > "/dev/stderr" - exit 1 - } - # state - in_diff = 0 - in_signature = 0 - in_headers = 0 - in_body = 0 - # patterns - header_pattern = "^[A-Z][[:alnum:]-]+:" - url_pattern = "[[:lower:]]+://[[:graph:]]+|(mailto:)?[[:alnum:]_\\+\\.~/-]*[[:alnum:]_]@[[:lower:]][[:alnum:]\\.-]*[[:lower:]]" - meta_pattern = "^(diff --git|(new|deleted) file|similarity index|(rename|copy) (to|from)|index|---|\\+\\+\\+) " -} -function color_quote(line) { - level = 0 - quotes = "" - while (line ~ /^>/) { - level += 1 - quotes = quotes ">" - line = substr(line, 2) - while (line ~ /^ /) { - quotes = quotes " " - line = substr(line, 2) - } - } - if (level == 1) { - color = quote_1 - } else if (level == 2) { - color = quote_2 - } else if (level == 3) { - color = quote_3 - } else if (level == 4) { - color = quote_4 - } else { - color = quote_x - } - if (match(line, meta_pattern)) { - return color quotes bold line reset - } else if (line ~ /^\+/) { - return color quotes diff_add line reset - } else if (line ~ /^-/) { - return color quotes diff_del line reset - } - gsub(url_pattern, url "&" color, line) - return color quotes line reset -} -{ - # Strip carriage returns from line - sub(/\r$/, "") - - if (in_diff) { - if ($0 ~ /^-- ?$/) { - in_diff = 0 - in_signature = 1 - $0 = signature $0 reset - } else if ($0 ~ /^@@ /) { - gsub(/^@@[^@]+@@/, diff_chunk "&" reset) - } else if (match($0, meta_pattern)) { - $0 = diff_meta $0 reset - } else if ($0 ~ /^\+/) { - $0 = diff_add $0 reset - } else if ($0 ~ /^-/) { - $0 = diff_del $0 reset - } else if ($0 !~ /^ / && $0 !~ /^$/) { - in_diff = 0 - in_body = 1 - if ($0 ~ /^>/) { - $0 = color_quote($0) - } else { - gsub(url_pattern, url "&" reset) - } - } - } else if (in_signature) { - gsub(url_pattern, url "&" signature) - $0 = signature $0 reset - } else if (in_headers) { - if ($0 ~ /^$/) { - in_headers = 0 - in_body = 1 - } else { - sub(header_pattern, header "&" reset) - gsub(url_pattern, url "&" reset) - } - } else if (in_body) { - if ($0 ~ /^>/) { - $0 = color_quote($0) - } else if ($0 ~ /^diff --git /) { - in_body = 0 - in_diff = 1 - $0 = diff_meta $0 reset - } else if ($0 ~ /^-- ?$/) { - in_body = 0 - in_signature = 1 - $0 = signature $0 reset - } else { - gsub(url_pattern, url "&" reset) - } - } else if ($0 ~ /^diff --git /) { - in_diff = 1 - $0 = diff_meta $0 reset - } else if ($0 ~ /^-- ?$/) { - in_signature = 1 - $0 = signature $0 reset - } else if (match($0, header_pattern)) { - in_headers = 1 - sub(header_pattern, header "&" reset) - gsub(url_pattern, url "&" reset) - } else { - in_body = 1 - if ($0 ~ /^>/) { - $0 = color_quote($0) - } else { - gsub(url_pattern, url "&" reset) - } - } - - print -} diff --git a/filters/colorize.c b/filters/colorize.c new file mode 100644 index 00000000..17eb548a --- /dev/null +++ b/filters/colorize.c @@ -0,0 +1,681 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright (c) 2023 Robin Jarry */ + +#include <errno.h> +#include <fnmatch.h> +#include <getopt.h> +#include <regex.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static void usage(void) +{ + puts("usage: colorize [-h] [-s FILE] [-f FILE]"); + puts(""); + puts("options:"); + puts(" -h show this help message"); + puts(" -s FILE use styleset file (default $AERC_STYLESET)"); + puts(" -f FILE read from filename (default stdin)"); +} + +enum color_type { + NONE = 0, + DEFAULT, + RGB, + PALETTE, +}; + +struct color { + enum color_type type; + uint32_t rgb; + uint32_t index; +}; + +struct style { + struct color fg; + struct color bg; + int bold; + int blink; + int underline; + int reverse; + int italic; + int dim; + char *sequence; +}; + +__attribute__((malloc,returns_nonnull)) +static void *xmalloc(size_t s) +{ + void *ptr = malloc(s); + if (ptr == NULL) { + perror("fatal: cannot allocate buffer"); + abort(); + } + return ptr; +} + +#define BOLD "\x1b[1m" +#define RESET "\x1b[0m" +#define LONGEST_SEQ "\x1b[1;2;3;4;5;7;38;2;255;255;255;48;2;255;255;255m" + +const char *seq(struct style *s) { + if (!s->sequence) { + char *b, *buf = xmalloc(strlen(LONGEST_SEQ) + 1); + const char *sep = ""; + + b = buf; + b += sprintf(b, "%s", "\x1b["); + if (s->bold) { + b += sprintf(b, "%s1", sep); + sep = ";"; + } + if (s->dim) { + b += sprintf(b, "%s2", sep); + sep = ";"; + } + if (s->italic) { + b += sprintf(b, "%s3", sep); + sep = ";"; + } + if (s->underline) { + b += sprintf(b, "%s4", sep); + sep = ";"; + } + if (s->blink) { + b += sprintf(b, "%s5", sep); + sep = ";"; + } + if (s->reverse) { + b += sprintf(b, "%s7", sep); + sep = ";"; + } + switch (s->fg.type) { + case NONE: + break; + case DEFAULT: + b += sprintf(b, "%s39", sep); + break; + case RGB: + b += sprintf(b, "%s38;2;%d;%d;%d", sep, + (s->fg.rgb >> 16) & 0xff, + (s->fg.rgb >> 8) & 0xff, + s->fg.rgb & 0xff); + sep = ";"; + break; + case PALETTE: + b += sprintf(b, (s->fg.index < 8) ? + "%s3%d" : "%s38;5;%d", sep, s->fg.index); + sep = ";"; + break; + } + switch (s->bg.type) { + case NONE: + break; + case DEFAULT: + b += sprintf(b, "%s49", sep); + break; + case RGB: + b += sprintf(b, "%s48;2;%d;%d;%d", sep, + (s->bg.rgb >> 16) & 0xff, + (s->bg.rgb >> 8) & 0xff, + s->bg.rgb & 0xff); + break; + case PALETTE: + b += sprintf(b, (s->bg.index < 8) ? + "%s4%d" : "%s48;5;%d", sep, s->bg.index); + break; + } + if (strcmp(buf, "\x1b[") == 0) { + b += sprintf(b, "0"); + } + sprintf(b, "m"); + s->sequence = buf; + } + return s->sequence; +} + +struct styles { + struct style url; + struct style header; + struct style signature; + struct style diff_meta; + struct style diff_chunk; + struct style diff_add; + struct style diff_del; + struct style quote_1; + struct style quote_2; + struct style quote_3; + struct style quote_4; + struct style quote_x; +}; + +static FILE *in_file; +static const char *styleset; +static struct styles styles = { + .url = { .underline = 1 }, + .header = { .bold = 1 }, + .signature = { .dim = 1 }, + .diff_meta = { .bold = 1 }, + .diff_chunk = { .dim = 1 }, + .diff_add = { .fg = { .type = PALETTE, .index = 2 } }, + .diff_del = { .fg = { .type = PALETTE, .index = 1 } }, + .quote_1 = { .fg = { .type = PALETTE, .index = 6 } }, + .quote_2 = { .fg = { .type = PALETTE, .index = 6 }, .dim = 1 }, + .quote_3 = { .fg = { .type = PALETTE, .index = 6 }, .dim = 1 }, + .quote_4 = { .fg = { .type = PALETTE, .index = 6 }, .dim = 1 }, + .quote_x = { .fg = { .type = PALETTE, .index = 6 }, .dim = 1 }, +}; + +static inline int startswith(const char *s, const char *prefix) +{ + return !strncmp(s, prefix, strlen(prefix)); +} + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +static struct { const char *n; uint32_t c; } color_names[] = { + {"aliceblue", 0xf0f8ff}, {"antiquewhite", 0xfaebd7}, {"aqua", 0x00ffff}, + {"aquamarine", 0x7fffd4}, {"azure", 0xf0ffff}, {"beige", 0xf5f5dc}, + {"bisque", 0xffe4c4}, {"black", 0x000000}, {"blanchedalmond", 0xffebcd}, + {"blue", 0x0000ff}, {"blueviolet", 0x8a2be2}, {"brown", 0xa52a2a}, + {"burlywood", 0xdeb887}, {"cadetblue", 0x5f9ea0}, {"chartreuse", 0x7fff00}, + {"chocolate", 0xd2691e}, {"coral", 0xff7f50}, {"cornflowerblue", 0x6495ed}, + {"cornsilk", 0xfff8dc}, {"crimson", 0xdc143c}, {"darkblue", 0x00008b}, + {"darkcyan", 0x008b8b}, {"darkgoldenrod", 0xb8860b}, {"darkgray", 0xa9a9a9}, + {"darkgreen", 0x006400}, {"darkkhaki", 0xbdb76b}, {"darkmagenta", 0x8b008b}, + {"darkolivegreen", 0x556b2f}, {"darkorange", 0xff8c00}, {"darkorchid", 0x9932cc}, + {"darkred", 0x8b0000}, {"darksalmon", 0xe9967a}, {"darkseagreen", 0x8fbc8f}, + {"darkslateblue", 0x483d8b}, {"darkslategray", 0x2f4f4f}, {"darkturquoise", 0x00ced1}, + {"darkviolet", 0x9400d3}, {"deeppink", 0xff1493}, {"deepskyblue", 0x00bfff}, + {"dimgray", 0x696969}, {"dodgerblue", 0x1e90ff}, {"firebrick", 0xb22222}, + {"floralwhite", 0xfffaf0}, {"forestgreen", 0x228b22}, {"fuchsia", 0xff00ff}, + {"gainsboro", 0xdcdcdc}, {"ghostwhite", 0xf8f8ff}, {"gold", 0xffd700}, + {"goldenrod", 0xdaa520}, {"gray", 0x808080}, {"green", 0x008000}, + {"greenyellow", 0xadff2f}, {"honeydew", 0xf0fff0}, {"hotpink", 0xff69b4}, + {"indianred", 0xcd5c5c}, {"indigo", 0x4b0082}, {"ivory", 0xfffff0}, + {"khaki", 0xf0e68c}, {"lavender", 0xe6e6fa}, {"lavenderblush", 0xfff0f5}, + {"lawngreen", 0x7cfc00}, {"lemonchiffon", 0xfffacd}, {"lightblue", 0xadd8e6}, + {"lightcoral", 0xf08080}, {"lightcyan", 0xe0ffff}, {"lightgoldenrodyellow", 0xfafad2}, + {"lightgray", 0xd3d3d3}, {"lightgreen", 0x90ee90}, {"lightpink", 0xffb6c1}, + {"lightsalmon", 0xffa07a}, {"lightseagreen", 0x20b2aa}, {"lightskyblue", 0x87cefa}, + {"lightslategray", 0x778899}, {"lightsteelblue", 0xb0c4de}, {"lightyellow", 0xffffe0}, + {"lime", 0x00ff00}, {"limegreen", 0x32cd32}, {"linen", 0xfaf0e6}, + {"maroon", 0x800000}, {"mediumaquamarine", 0x66cdaa}, {"mediumblue", 0x0000cd}, + {"mediumorchid", 0xba55d3}, {"mediumpurple", 0x9370db}, {"mediumseagreen", 0x3cb371}, + {"mediumslateblue", 0x7b68ee}, {"mediumspringgreen", 0x00fa9a}, {"mediumturquoise", 0x48d1cc}, + {"mediumvioletred", 0xc71585}, {"midnightblue", 0x191970}, {"mintcream", 0xf5fffa}, + {"mistyrose", 0xffe4e1}, {"moccasin", 0xffe4b5}, {"navajowhite", 0xffdead}, + {"navy", 0x000080}, {"oldlace", 0xfdf5e6}, {"olive", 0x808000}, + {"olivedrab", 0x6b8e23}, {"orange", 0xffa500}, {"orangered", 0xff4500}, + {"orchid", 0xda70d6}, {"palegoldenrod", 0xeee8aa}, {"palegreen", 0x98fb98}, + {"paleturquoise", 0xafeeee}, {"palevioletred", 0xdb7093}, {"papayawhip", 0xffefd5}, + {"peachpuff", 0xffdab9}, {"peru", 0xcd853f}, {"pink", 0xffc0cb}, + {"plum", 0xdda0dd}, {"powderblue", 0xb0e0e6}, {"purple", 0x800080}, + {"rebeccapurple", 0x663399}, {"red", 0xff0000}, {"rosybrown", 0xbc8f8f}, + {"royalblue", 0x4169e1}, {"saddlebrown", 0x8b4513}, {"salmon", 0xfa8072}, + {"sandybrown", 0xf4a460}, {"seagreen", 0x2e8b57}, {"seashell", 0xfff5ee}, + {"sienna", 0xa0522d}, {"silver", 0xc0c0c0}, {"skyblue", 0x87ceeb}, + {"slateblue", 0x6a5acd}, {"slategray", 0x708090}, {"snow", 0xfffafa}, + {"springgreen", 0x00ff7f}, {"steelblue", 0x4682b4}, {"tan", 0xd2b48c}, + {"teal", 0x008080}, {"thistle", 0xd8bfd8}, {"tomato", 0xff6347}, + {"turquoise", 0x40e0d0}, {"violet", 0xee82ee}, {"wheat", 0xf5deb3}, + {"white", 0xffffff}, {"whitesmoke", 0xf5f5f5}, {"yellow", 0xffff00}, + {"yellowgreen", 0x9acd32}, +}; + +static int color_name(const char *name, uint32_t *color) +{ + for (size_t c = 0; c < ARRAY_SIZE(color_names); c++) { + if (!strcmp(name, color_names[c].n)) { + *color = color_names[c].c; + return 0; + } + } + return 1; +} + +static int parse_color(struct color *c, const char *val) +{ + uint32_t color = 0; + if (!strcmp(val, "default")) { + c->type = DEFAULT; + } else if (sscanf(val, "#%x", &color) == 1 && color <= 0xffffff) { + c->type = RGB; + c->rgb = color; + } else if (sscanf(val, "%d", &color) == 1 && color <= 256) { + c->type = PALETTE; + c->index = color; + } else if (!color_name(val, &color)) { + c->type = RGB; + c->rgb = color; + } else { + fprintf(stderr, "error: invalid color value %s\n", val); + return 1; + } + return 0; +} + +static int parse_bool(int *b, const char *val) +{ + if (!strcmp(val, "true")) { + *b = 1; + } else if (!strcmp(val, "false")) { + *b = 0; + } else if (!strcmp(val, "toggle")) { + *b = !*b; + } else { + fprintf(stderr, "error: invalid bool value %s\n", val); + return 1; + } + return 0; +} + +static int set_attr(struct style *s, const char *attr, const char *val) +{ + if (!strcmp(attr, "fg")) { + if (parse_color(&s->fg, val)) + return 1; + } else if (!strcmp(attr, "bg")) { + if (parse_color(&s->fg, val)) + return 1; + } else if (!strcmp(attr, "bold")) { + if (parse_bool(&s->bold, val)) + return 1; + } else if (!strcmp(attr, "blink")) { + if (parse_bool(&s->blink, val)) + return 1; + } else if (!strcmp(attr, "underline")) { + if (parse_bool(&s->underline, val)) + return 1; + } else if (!strcmp(attr, "reverse")) { + if (parse_bool(&s->reverse, val)) + return 1; + } else if (!strcmp(attr, "italic")) { + if (parse_bool(&s->italic, val)) + return 1; + } else if (!strcmp(attr, "dim")) { + if (parse_bool(&s->dim, val)) + return 1; + } else if (!strcmp(attr, "normal")) { + s->bold = 0; + s->underline = 0; + s->reverse = 0; + s->italic = 0; + s->dim = 0; + } else if (!strcmp(attr, "default")) { + s->fg.type = NONE; + s->fg.type = NONE; + } else { + fprintf(stderr, "error: invalid style attribute %s\n", attr); + return 1; + } + return 0; +} + +static struct {const char *n; struct style *s;} ini_objects[] = { + {"url", &styles.url}, + {"header", &styles.header}, + {"signature", &styles.signature}, + {"diff_meta", &styles.diff_meta}, + {"diff_chunk", &styles.diff_chunk}, + {"diff_add", &styles.diff_add}, + {"diff_del", &styles.diff_del}, + {"quote_1", &styles.quote_1}, + {"quote_2", &styles.quote_2}, + {"quote_3", &styles.quote_3}, + {"quote_4", &styles.quote_4}, + {"quote_x", &styles.quote_x}, +}; + +static int parse_styleset(void) +{ + int in_section = 0; + char buf[BUFSIZ]; + int err = 0; + FILE *f; + + if (!styleset) + return 0; + + f = fopen(styleset, "r"); + if (!f) { + perror("error: failed to open styleset"); + return 1; + } + + while (fgets(buf, sizeof(buf), f)) { + /* strip LF, CR, CRLF, LFCR */ + buf[strcspn(buf, "\r\n")] = '\0'; + if (in_section) { + char obj[64], attr[64], val[64]; + int changed = 0; + + if (sscanf(buf, "%63[^.].%63[^=] = %63s", obj, attr, val) != 3) + continue; + + for (size_t o = 0; o < ARRAY_SIZE(ini_objects); o++) { + if (fnmatch(obj, ini_objects[o].n, 0)) + continue; + if (set_attr(ini_objects[o].s, attr, val)) { + err = 1; + goto end; + } + changed++; + } + if (!changed) { + fprintf(stderr, + "error: unknown style object %s\n", + obj); + err = 1; + goto end; + } + } else if (!strcmp(buf, "[viewer]")) { + in_section = 1; + /* only disable the default theme if there is + * a [viewer] section in the styleset */ + memset(&styles, 0, sizeof(styles)); + } + } + +end: + fclose(f); + return err; +} + +static inline void print(const char *in) +{ + fputs(in, stdout); +} + +static inline size_t print_notabs(const char *in, size_t max_len) +{ + size_t len = 0; + while (*in != '\0' && len < max_len) { + char c = *in++; + if (c == '\t') { + /* Tabs are interpreted as cursor movement and are not + * colored like regular characters. Replace them with + * 8 spaces. */ + fputs(" ", stdout); + } else { + fputc(c, stdout); + } + len++; + } + return len; +} + +static void diff_chunk(const char *in) +{ + size_t len = 0; + print(seq(&styles.diff_chunk)); + while (in[len] == '@') + len++; + while (in[len] != '\0' && in[len] != '@') + len++; + while (in[len] == '@') + len++; + in += print_notabs(in, len); + print(RESET); + print_notabs(in, BUFSIZ); +} + +#define URL_RE \ + "[a-z]{2,8}://[[:graph:]]{4,}" \ + "|(mailto:)?[[:alnum:]_\\+\\.~/-]*[[:alnum:]]@[a-z][[:alnum:]\\.-]*[a-z]" +static regex_t url_re; + +static void urls(const char *in, struct style *ctx) +{ + regmatch_t groups[2]; + size_t len; + int trim; + + while (!regexec(&url_re, in, 2, groups, 0)) { + in += print_notabs(in, groups[0].rm_so); + print(seq(&styles.url)); + len = groups[0].rm_eo - groups[0].rm_so; + /* Heuristic to remove trailing characters that are valid URL + * characters, but typically not at the end of the URL */ + trim = 1; + while (trim && len > 0) { + switch (in[len - 1]) { + case '>': case '.': case ',': case ';': case ')': + case '!': case '?': case '"': case '\'': + len--; + break; + default: + trim = 0; + break; + } + } + in += print_notabs(in, len); + print(RESET); + if (ctx) { + print(seq(ctx)); + } + } + print_notabs(in, BUFSIZ); +} + +static inline void signature(const char *in) +{ + print(seq(&styles.signature)); + urls(in, &styles.signature); + print(RESET); +} + +#define HEADER_RE "^[A-Z][[:alnum:]_-]+:" +static regex_t header_re; + +static void header(const char *in) +{ + regmatch_t groups[1]; + + if (!regexec(&header_re, in, 1, groups, 0)) { + print(seq(&styles.header)); + in += print_notabs(in, groups[0].rm_eo); + print(RESET); + } + urls(in, NULL); +} + +#define DIFF_META_RE \ + "^(diff --git|(new|deleted) file|similarity" \ + " index|(rename|copy) (to|from)|index|---|\\+\\+\\+) " +static regex_t diff_meta_re; + +static void quote(const char *in) +{ + regmatch_t groups[8]; + struct style *s; + int q, level; + + q = level = 0; + while (in[q] == '>') { + level++; + q++; + if (in[q] == ' ') + q++; + } + switch (level) { + case 1: + s = &styles.quote_1; + break; + case 2: + s = &styles.quote_2; + break; + case 3: + s = &styles.quote_3; + break; + case 4: + s = &styles.quote_4; + break; + default: + s = &styles.quote_x; + break; + } + + print(seq(s)); + in += print_notabs(in, q); + if (startswith(in, "+")) { + printf("%s%s", RESET, seq(&styles.diff_add)); + print_notabs(in, BUFSIZ); + } else if (startswith(in, "-")) { + printf("%s%s", RESET, seq(&styles.diff_del)); + print_notabs(in, BUFSIZ); + } else if (!regexec(&diff_meta_re, in, 8, groups, 0)) { + print(BOLD); + print_notabs(in, BUFSIZ); + } else { + urls(in, s); + } + print(RESET); +} + +static void print_style(const char *in, struct style *s) +{ + print(seq(s)); + print_notabs(in, BUFSIZ); + print(RESET); +} + +enum state { INIT, DIFF, SIGNATURE, BODY }; + +static void colorize_line(const char *in) +{ + static enum state state = INIT; + regmatch_t groups[8]; /* enough groups to cover all expressions */ + + switch (state) { + case DIFF: + if (!strcmp(in, "--") || !strcmp(in, "-- ")) { + state = SIGNATURE; + signature(in); + } else if (startswith(in, "@@ ")) { + diff_chunk(in); + } else if (!regexec(&diff_meta_re, in, 8, groups, 0)) { + print_style(in, &styles.diff_meta); + } else if (startswith(in, "+")) { + print_style(in, &styles.diff_add); + } else if (startswith(in, "-")) { + print_style(in, &styles.diff_del); + } else if (!startswith(in, " ") && strcmp(in, "") != 0) { + state = BODY; + if (startswith(in, ">")) { + quote(in); + } else { + urls(in, NULL); + } + } else { + print_notabs(in, BUFSIZ); + } + break; + case SIGNATURE: + signature(in); + break; + case BODY: + if (startswith(in, ">")) { + quote(in); + } else if (startswith(in, "diff --git ")) { + state = DIFF; + print_style(in, &styles.diff_meta); + } else if (!strcmp(in, "--") || !strcmp(in, "-- ")) { + state = SIGNATURE; + signature(in); + } else if (!regexec(&header_re, in, 8, groups, 0)) { + header(in); + } else { + urls(in, NULL); + } + break; + default: /* INIT */ + if (startswith(in, "diff --git ")) { + state = DIFF; + print_style(in, &styles.diff_meta); + } else if (!strcmp(in, "--") || !strcmp(in, "-- ")) { + state = SIGNATURE; + signature(in); + } else { + state = BODY; + if (startswith(in, ">")) { + quote(in); + } else if (!regexec(&header_re, in, 8, groups, 0)) { + header(in); + } else { + urls(in, NULL); + } + } + break; + } +} + +int parse_args(int argc, char **argv) +{ + const char *filename = NULL; + char c; + + styleset = getenv("AERC_STYLESET"); + + while ((c = getopt(argc, argv, "hs:f:")) != -1) { + switch (c) { + case 's': + styleset = optarg; + break; + case 'f': + filename = optarg; + break; + default: + usage(); + return 1; + } + } + if (optind < argc) { + fprintf(stderr, "%s: unexpected argument -- '%s'\n", + argv[0], argv[optind]); + usage(); + return 1; + } + if (filename == NULL || !strcmp(filename, "-")) { + in_file = stdin; + } else { + in_file = fopen(filename, "r"); + if (!in_file) { + perror("error: cannot open file"); + return 1; + } + } + return 0; +} + +int main(int argc, char **argv) +{ + char buf[BUFSIZ]; + int err; + + regcomp(&header_re, HEADER_RE, REG_EXTENDED); + regcomp(&diff_meta_re, DIFF_META_RE, REG_EXTENDED); + regcomp(&url_re, URL_RE, REG_EXTENDED); + + err = parse_args(argc, argv); + if (err) { + goto end; + } + err = parse_styleset(); + if (err) { + goto end; + } + while (fgets(buf, sizeof(buf), in_file)) { + /* strip LF, CR, CRLF, LFCR */ + buf[strcspn(buf, "\r\n")] = '\0'; + colorize_line(buf); + printf("\n"); + } +end: + if (in_file) { + fclose(in_file); + } + return err; +} diff --git a/filters/vectors/colorize-patch.expected b/filters/vectors/colorize-patch.expected new file mode 100644 index 00000000..1a2144a0 --- /dev/null +++ b/filters/vectors/colorize-patch.expected @@ -0,0 +1,49 @@ +[1mFrom:[0m Robin Jarry <[4mrobin@jarry.cc[0m> +[1mDate:[0m Mon, 26 Dec 2022 17:02:14 +0100 +[1mSubject:[0m [PATCH aerc] doc: fix numbered lists + +According to scdoc(5), numbered lists start with a period. + +[1mFixes:[0m af63bd0188d1 ("doc: homogenize scdoc markup") +[1mSigned-off-by:[0m Robin Jarry <[4mrobin@jarry.cc[0m> +--- + doc/aerc-stylesets.7.scd | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +[1mdiff --git a/doc/aerc-stylesets.7.scd b/doc/aerc-stylesets.7.scd[0m +[1mindex d82ba7cf8163..34bbf4af0fc5 100644[0m +[1m--- a/doc/aerc-stylesets.7.scd[0m +[1m+++ b/doc/aerc-stylesets.7.scd[0m +[2m@@ -180,20 +180,20 @@[0m that style applies, unless overridden by a higher layer. + + The order that *msglist_\** styles are applied in is, from first to last: + +[31m-1. *msglist_default*[0m +[31m-2. *msglist_unread*[0m +[31m-3. *msglist_read*[0m +[31m-4. *msglist_flagged*[0m +[31m-5. *msglist_deleted*[0m +[31m-6. *msglist_marked*[0m +[32m+. *msglist_default*[0m +[32m+. *msglist_unread*[0m +[32m+. *msglist_read*[0m +[32m+. *msglist_flagged*[0m +[32m+. *msglist_deleted*[0m +[32m+. *msglist_marked*[0m + + So, the marked style will override all other msglist styles. + + The order for *dirlist_\** styles is: + +[31m-1. *dirlist_default*[0m +[31m-2. *dirlist_unread*[0m +[31m-3. *dirlist_recent*[0m +[32m+. *dirlist_default*[0m +[32m+. *dirlist_unread*[0m +[32m+. *dirlist_recent*[0m + + ## COLORS + +[2m-- [0m +[2m2.39.0[0m +[2m[0m diff --git a/filters/vectors/colorize-patch.in b/filters/vectors/colorize-patch.in new file mode 100644 index 00000000..48e12d8e --- /dev/null +++ b/filters/vectors/colorize-patch.in @@ -0,0 +1,49 @@ +From: Robin Jarry <robin@jarry.cc> +Date: Mon, 26 Dec 2022 17:02:14 +0100 +Subject: [PATCH aerc] doc: fix numbered lists + +According to scdoc(5), numbered lists start with a period. + +Fixes: af63bd0188d1 ("doc: homogenize scdoc markup") +Signed-off-by: Robin Jarry <robin@jarry.cc> +--- + doc/aerc-stylesets.7.scd | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/doc/aerc-stylesets.7.scd b/doc/aerc-stylesets.7.scd +index d82ba7cf8163..34bbf4af0fc5 100644 +--- a/doc/aerc-stylesets.7.scd ++++ b/doc/aerc-stylesets.7.scd +@@ -180,20 +180,20 @@ that style applies, unless overridden by a higher layer. + + The order that *msglist_\** styles are applied in is, from first to last: + +-1. *msglist_default* +-2. *msglist_unread* +-3. *msglist_read* +-4. *msglist_flagged* +-5. *msglist_deleted* +-6. *msglist_marked* ++. *msglist_default* ++. *msglist_unread* ++. *msglist_read* ++. *msglist_flagged* ++. *msglist_deleted* ++. *msglist_marked* + + So, the marked style will override all other msglist styles. + + The order for *dirlist_\** styles is: + +-1. *dirlist_default* +-2. *dirlist_unread* +-3. *dirlist_recent* ++. *dirlist_default* ++. *dirlist_unread* ++. *dirlist_recent* + + ## COLORS + +-- +2.39.0 + diff --git a/filters/vectors/colorize-quotes.expected b/filters/vectors/colorize-quotes.expected new file mode 100644 index 00000000..d350e4f1 --- /dev/null +++ b/filters/vectors/colorize-quotes.expected @@ -0,0 +1,65 @@ +Foo Bar, xxxxx: +[36m> Lorem ipsum dolor sit amet, insolens adolescens ne usu? In pri denique[0m +[36m> argumentum, te autem decore convenire mea! Duo nisl esse an, aliquid[0m +[36m> conceptam sea cu. Ignota copiosae gubergren ad est, ut illum doming vocibus[0m +[36m> sed. Et vis nulla expetendis mediocritatem, errem option gloriatur at nam?[0m +[36m> Brute vidisse corpora ut his, sonet omnesque adipiscing ea quo, cum ea errem[0m +[36m> aliquip reformidans?[0m + +Magna delicatissimi ei vel? Quem petentium scribentur eum ne? Et inani debet +cetero mea, sint conceptam efficiendi mel te. Qui ut senserit interesset, per +nibh petentium at! Sit docendi laboramus ei, animal insolens ad mea. + +[2;36m>> Nostrud alienum nec in, illum errem audiam no per! Saepe alterum vis ea! Ei[0m +[2;36m>> quis minim ius, ut eos mandamus salutandi. Lorem facilisis in nam, ridens[0m +[2;36m>> principes sadipscing et eum, pri graecis singulis ut. Mea dolor primis[0m +[2;36m>> impetus in, his epicurei tacimates id, vis labitur suscipit ad.[0m +[36m> Erat alienum interpretaris has et, te vim aliquam molestie. Nam vivendum[0m +[36m> facilisis qualisque at, ex his mucius qualisque! Fabulas lucilius adversarium[0m +[36m> eu his. Cu soluta inermis accusata usu, his nulla dolore ne, vis id semper[0m +[36m> detracto sententia <[4mhttps://foobar.com[0m[36m> && "[4mhttps://foobaz.org/[0m[36m".[0m +[36m>[0m +[36m> Error libris deleniti ea mei, vis at elit probo munere, his sint unum[0m +[36m> albucius ex.[0m + +Graece definiebas scripserit ne est? Nec nonumes explicari contentiones ne, +vocent iuvaret placerat no vix. Nec et partem salutandi deseruisse, his no +possim malorum pericula. Te quando reprehendunt nam, at consul sadipscing vel? +Velit possim aliquando ei per, ne simul quodsi antiopam sea, ullum choro +facilisi et pri! + +[36m> Dico soleat partem ea pro, ad vix impetus splendide. Primis melius principes[0m +[36m> pri ad, tacimates pertinacia ei pro? Appareat atomorum oportere at nam, eu[0m +[36m> per quod minim reprimique, ornatus graecis ad vel. Malis vulputate ea qui,[0m +[36m> eum tacimates recteque et, usu ea dolore vidisse. Brute mediocrem molestiae[0m +[36m> sed te. No stet prompta pri, rebum populo nominati eos te.[0m +[36m>[0m +[36m> [1mdiff --git a/foo b/foo[0m +[36m> [1mindex 4b0fe8dded3a..518b67134639 100644[0m +[36m> [0m[31m--- a/foo[0m +[36m> [0m[32m+++ b/foo[0m +[36m> @@ -131,6 +131,83 @@ func pouet() int {[0m +[36m> err := doThis()[0m +[36m> [0m +[36m> [0m[31m- err2 := doThat()[0m +[36m> [0m[32m+ err2 := notDoThat()[0m +[36m> [0m +[36m> if err != nil || err2 != nil {[0m + +Id vix referrentur philosophia, veri labores an nec. Noster denique no duo, sit +ei diam inermis vocibus! Mutat principes ex pro, at pericula assueverit vel. +Has putent verterem constituto ex, tale electram duo at! Ei nulla lucilius +intellegat nam, pro quod epicuri dissentiet ut, omnis voluptatibus definitiones +vim at. + +[4mhttps://git-man-page-generator.lokaltog.net/#Y2xhcCQkY29tbWFuZA==[0m + +Eam mundi libris debitis ad, eam regione numquam at. Eum omnes bonorum eu, +oporteat assueverit disputationi nam ne, nonumes iracundia mea ad! Duo libris +recusabo id, ceteros salutatus inciderint vim ea. Et graeco reformidans vel? Ei +has labore quidam? + +[2;36m>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> sympa, non?[0m + +[2m-- [0m +[2mBatman[0m diff --git a/filters/vectors/colorize-quotes.in b/filters/vectors/colorize-quotes.in new file mode 100644 index 00000000..31b04911 --- /dev/null +++ b/filters/vectors/colorize-quotes.in @@ -0,0 +1,65 @@ +Foo Bar, xxxxx: +> Lorem ipsum dolor sit amet, insolens adolescens ne usu? In pri denique +> argumentum, te autem decore convenire mea! Duo nisl esse an, aliquid +> conceptam sea cu. Ignota copiosae gubergren ad est, ut illum doming vocibus +> sed. Et vis nulla expetendis mediocritatem, errem option gloriatur at nam? +> Brute vidisse corpora ut his, sonet omnesque adipiscing ea quo, cum ea errem +> aliquip reformidans? + +Magna delicatissimi ei vel? Quem petentium scribentur eum ne? Et inani debet +cetero mea, sint conceptam efficiendi mel te. Qui ut senserit interesset, per +nibh petentium at! Sit docendi laboramus ei, animal insolens ad mea. + +>> Nostrud alienum nec in, illum errem audiam no per! Saepe alterum vis ea! Ei +>> quis minim ius, ut eos mandamus salutandi. Lorem facilisis in nam, ridens +>> principes sadipscing et eum, pri graecis singulis ut. Mea dolor primis +>> impetus in, his epicurei tacimates id, vis labitur suscipit ad. +> Erat alienum interpretaris has et, te vim aliquam molestie. Nam vivendum +> facilisis qualisque at, ex his mucius qualisque! Fabulas lucilius adversarium +> eu his. Cu soluta inermis accusata usu, his nulla dolore ne, vis id semper +> detracto sententia <https://foobar.com> && "https://foobaz.org/". +> +> Error libris deleniti ea mei, vis at elit probo munere, his sint unum +> albucius ex. + +Graece definiebas scripserit ne est? Nec nonumes explicari contentiones ne, +vocent iuvaret placerat no vix. Nec et partem salutandi deseruisse, his no +possim malorum pericula. Te quando reprehendunt nam, at consul sadipscing vel? +Velit possim aliquando ei per, ne simul quodsi antiopam sea, ullum choro +facilisi et pri! + +> Dico soleat partem ea pro, ad vix impetus splendide. Primis melius principes +> pri ad, tacimates pertinacia ei pro? Appareat atomorum oportere at nam, eu +> per quod minim reprimique, ornatus graecis ad vel. Malis vulputate ea qui, +> eum tacimates recteque et, usu ea dolore vidisse. Brute mediocrem molestiae +> sed te. No stet prompta pri, rebum populo nominati eos te. +> +> diff --git a/foo b/foo +> index 4b0fe8dded3a..518b67134639 100644 +> --- a/foo +> +++ b/foo +> @@ -131,6 +131,83 @@ func pouet() int { +> err := doThis() +> +> - err2 := doThat() +> + err2 := notDoThat() +> +> if err != nil || err2 != nil { + +Id vix referrentur philosophia, veri labores an nec. Noster denique no duo, sit +ei diam inermis vocibus! Mutat principes ex pro, at pericula assueverit vel. +Has putent verterem constituto ex, tale electram duo at! Ei nulla lucilius +intellegat nam, pro quod epicuri dissentiet ut, omnis voluptatibus definitiones +vim at. + +https://git-man-page-generator.lokaltog.net/#Y2xhcCQkY29tbWFuZA== + +Eam mundi libris debitis ad, eam regione numquam at. Eum omnes bonorum eu, +oporteat assueverit disputationi nam ne, nonumes iracundia mea ad! Duo libris +recusabo id, ceteros salutatus inciderint vim ea. Et graeco reformidans vel? Ei +has labore quidam? + +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> sympa, non? + +-- +Batman diff --git a/stylesets/blue b/stylesets/blue index 29e165be..7ae019d2 100644 --- a/stylesets/blue +++ b/stylesets/blue @@ -45,3 +45,19 @@ default.selected.fg=white default.selected.bg=#005f87 completion_default.selected.bg=#005f87 + +[viewer] +url.fg=#ffffaf +url.underline=true +header.fg=#af87ff +signature.fg=#af87ff +diff_meta.fg=#ffffff +diff_meta.bold=true +diff_chunk.fg=#00cdcd +diff_add.fg=#00cd00 +diff_del.fg=#cd0000 +quote_1.fg=#5fafff +quote_2.fg=#ff8700 +quote_3.fg=#af87ff +quote_4.fg=#ff5fd7 +quote_x.fg=#808080 diff --git a/stylesets/default b/stylesets/default index 078920bf..5ee1c4e0 100644 --- a/stylesets/default +++ b/stylesets/default @@ -35,3 +35,15 @@ border.reverse = true selector_focused.reverse=true selector_chooser.bold=true + +[viewer] +url.underline=true +header.bold=true +signature.dim=true +diff_meta.bold=true +diff_chunk.dim=true +diff_add.fg=2 +diff_del.fg=1 +quote_*.fg=6 +quote_*.dim=true +quote_1.dim=false diff --git a/stylesets/dracula b/stylesets/dracula index 10f21a5e..c400865a 100644 --- a/stylesets/dracula +++ b/stylesets/dracula @@ -46,3 +46,15 @@ default.selected.bg=#44475A completion_default.selected.bg=#44475A completion_default.selected.fg=white + +[viewer] +url.underline=true +header.bold=true +signature.dim=true +diff_meta.bold=true +diff_chunk.dim=true +diff_add.fg=2 +diff_del.fg=1 +quote_*.fg=6 +quote_*.dim=true +quote_1.dim=false diff --git a/stylesets/nord b/stylesets/nord index 5f5274f7..8f7d5140 100644 --- a/stylesets/nord +++ b/stylesets/nord @@ -44,3 +44,15 @@ tab.selected.fg=#2c3441 dirlist_unread.fg=#64A6B3 dirlist_recent.fg=#64A6B3 + +[viewer] +url.underline=true +header.bold=true +signature.dim=true +diff_meta.bold=true +diff_chunk.dim=true +diff_add.fg=2 +diff_del.fg=1 +quote_*.fg=6 +quote_*.dim=true +quote_1.dim=false diff --git a/stylesets/pink b/stylesets/pink index 743da359..792771a2 100644 --- a/stylesets/pink +++ b/stylesets/pink @@ -47,3 +47,19 @@ default.selected.fg=white default.selected.bg=#de4e85 completion_default.selected.bg=#de4e85 + +[viewer] +url.fg=#ffffaf +url.underline=true +header.fg=#af87ff +signature.fg=#af87ff +diff_meta.fg=#ffffff +diff_meta.bold=true +diff_chunk.fg=#00cdcd +diff_add.fg=#00cd00 +diff_del.fg=#cd0000 +quote_1.fg=#5fafff +quote_2.fg=#ff8700 +quote_3.fg=#af87ff +quote_4.fg=#ff5fd7 +quote_x.fg=#808080 diff --git a/widgets/msgviewer.go b/widgets/msgviewer.go index 29ad0a83..8d9ca76e 100644 --- a/widgets/msgviewer.go +++ b/widgets/msgviewer.go @@ -605,6 +605,8 @@ func NewPartViewer( fmt.Sprintf("AERC_SUBJECT=%s", info.Envelope.Subject)) filter.Env = append(filter.Env, fmt.Sprintf("AERC_FROM=%s", format.FormatAddresses(info.Envelope.From))) + filter.Env = append(filter.Env, fmt.Sprintf("AERC_STYLESET=%s", + acct.UiConfig().StyleSetPath())) log.Debugf("<%s> part=%v %s: %v | %v", info.Envelope.MessageId, curindex, mime, filter, pager) if pagerin, err = pager.StdinPipe(); err != nil { |