aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Jarry <robin@jarry.cc>2022-02-21 15:54:08 +0100
committerRobin Jarry <robin@jarry.cc>2022-02-22 19:44:07 +0100
commitf5aa6433f7c3ba4d8bc09f3e243f7acb40920743 (patch)
tree96013ee3fc7dfe3d476c8d46005b3937d752127e
parent35a71140f94a5c91cc1b19cfc43b30b3aef16130 (diff)
downloadaerc-f5aa6433f7c3ba4d8bc09f3e243f7acb40920743.tar.gz
aerc-f5aa6433f7c3ba4d8bc09f3e243f7acb40920743.zip
filters: port colorize to awk
Python is not available on all systems. Port the colorize filter to awk as it is a more widespread POSIX utility. Users are free to copy the filter into their home dir and tweak the colors to their needs. The highlighted items are: =============== ======= ======= ========= ================= Item Red Green Blue Color =============== ======= ======= ========= ================= quoted text 1 95 175 255 Blue quoted text 2 255 135 0 Orange quoted text 3 175 135 255 Purple quoted text 4 255 95 215 Pink quoted text * 128 128 128 Grey diff meta 255 255 255 White bold diff chunk 205 0 205 Cyan diff added 0 205 0 Red diff removed 205 0 0 Green signature 175 135 255 Purple header 175 135 255 Purple url 255 255 175 Yellow =============== ======= ======= ========= ================= This assumes a terminal emulator with true color support and with a dark/black background. Link: https://github.com/termstandard/colors Signed-off-by: Robin Jarry <robin@jarry.cc> (cherry picked from commit df8c129235d9f26892caf89f056adc0e16b3d6b6)
-rwxr-xr-xfilters/colorize307
1 files changed, 139 insertions, 168 deletions
diff --git a/filters/colorize b/filters/colorize
index f4801ebf..2e6001c0 100755
--- a/filters/colorize
+++ b/filters/colorize
@@ -1,171 +1,142 @@
-#!/usr/bin/env python3
+#!/bin/awk -f
# Copyright (c) 2022 Robin Jarry
-"""
-Colorize plaintext email. Write to stdout.
-"""
-
-import re
-import sys
-
-
-TERM_RESET = "\x1b[0m"
-TERM_BOLD = "\x1b[1m"
-TERM_BG_GRAY = "\x1b[48;5;244m"
-TERM_FG_GRAY = "\x1b[38;5;244m"
-TERM_FG_RED = "\x1b[38;5;1m"
-TERM_FG_GREEN = "\x1b[38;5;2m"
-TERM_FG_CYAN = "\x1b[38;5;6m"
-TERM_FG_YELLOW = "\x1b[38;5;229m"
-TERM_FG_WHITE = "\x1b[38;5;15m"
-TERM_FG_BLUE = "\x1b[38;5;75m"
-TERM_FG_PURPLE = "\x1b[38;5;141m"
-TERM_FG_ORANGE = "\x1b[38;5;208m"
-TERM_FG_PINK = "\x1b[38;5;171m"
-QUOTE_COLORS = {
- 1: TERM_FG_BLUE,
- 2: TERM_FG_ORANGE,
- 3: TERM_FG_PURPLE,
- 4: TERM_FG_PINK,
+BEGIN {
+ # R;G;B colors
+ url = "\x1b[38;2;255;255;175m" # yellow
+ header = "\x1b[38;2;175;135;255m" # purple
+ signature = "\x1b[38;2;175;135;255m" # purple
+ diff_meta = "\x1b[1;38;2;255;255;255m" # bold white
+ diff_chunk = "\x1b[38;205;0;205m" # cyan
+ diff_add = "\x1b[38;2;0;205;0m" # green
+ diff_del = "\x1b[38;2;205;0;0m" # red
+ quote_1 = "\x1b[38;2;95;175;255m" # blue
+ quote_2 = "\x1b[38;2;255;135;0m" # orange
+ quote_3 = "\x1b[38;2;175;135;255m" # purple
+ quote_4 = "\x1b[38;2;255;95;215m" # pink
+ quote_x = "\x1b[38;2;128;128;128m" # gray
+ reset = "\x1b[0m"
+ # state
+ in_diff = 0
+ in_signature = 0
+ in_headers = 0
+ in_body = 0
+ # patterns
+ header_pattern = @/^[A-Z][[:alnum:]-]+:/
+ url_pattern = @/[a-z]{2,6}:\/\/[[:graph:]]+|[[:alnum:]_\+\.~\/-]*[[:alnum:]_]@[[:lower:]][[:alnum:]\.-]*[[:lower:]]/
+}
+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 (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_signature = 1
+ in_diff = 0
+ in_headers = 0
+ in_body = 0
+ $0 = signature $0 reset
+ } else if ($0 ~ /^@@ /) {
+ $0 = diff_chunk $0 reset
+ } else if ($0 ~ /^(diff --git|index|---|\+\+\+) /) {
+ $0 = diff_meta $0 reset
+ } else if ($0 ~ /^\+/) {
+ $0 = diff_add $0 reset
+ } else if ($0 ~ /^-/) {
+ $0 = diff_del $0 reset
+ }
+ } else if (in_signature) {
+ $0 = signature $0 reset
+ gsub(url_pattern, url "&" signature)
+ } else if (in_headers) {
+ if ($0 ~ /^$/) {
+ in_signature = 0
+ in_diff = 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_signature = 0
+ in_diff = 1
+ in_headers = 0
+ in_body = 0
+ $0 = diff_meta $0 reset
+ } else if ($0 ~ /^-- ?$/) {
+ in_signature = 1
+ in_diff = 0
+ in_headers = 0
+ in_body = 0
+ $0 = signature $0 reset
+ } else {
+ gsub(url_pattern, url "&" reset)
+ }
+ } else if ($0 ~ /^diff --git /) {
+ in_signature = 0
+ in_diff = 1
+ in_headers = 0
+ in_body = 0
+ $0 = diff_meta $0 reset
+ } else if ($0 ~ /^-- ?$/) {
+ in_signature = 1
+ in_diff = 0
+ in_headers = 0
+ in_body = 0
+ $0 = signature $0 reset
+ } else if ($0 ~ header_pattern) {
+ in_signature = 0
+ in_diff = 0
+ in_headers = 1
+ in_body = 0
+ sub(header_pattern, header "&" reset)
+ gsub(url_pattern, url "&" reset)
+ } else {
+ in_signature = 0
+ in_diff = 0
+ in_headers = 0
+ in_body = 1
+ if ($0 ~ /^>/) {
+ $0 = color_quote($0)
+ } else {
+ gsub(url_pattern, url "&" reset)
+ }
+ }
+
+ print
}
-URL_RE = re.compile(
- r"""
- (
- https?://[\w,;:!/#%^=@~\&\*\+\?\.\-]+
- |
- [\w\-\+\.~/]*\w@\w[\w\-\.]+\w
- )
- """,
- re.VERBOSE,
-)
-HEADER_RE = re.compile(r"^[A-Z][\w-]+:")
-DIFF_META = ("diff --git ", "index ", "--- ", "+++ ")
-
-
-def replace_match(color, context_color):
- def replace_func(match):
- return color + match.group(0) + context_color
-
- return replace_func
-
-
-def main():
- in_patch = in_signature = in_headers = in_body = False
-
- for line in sys.stdin.buffer:
- line = line.decode("utf-8", errors="replace").rstrip("\r\n")
- if in_patch:
- if line in ("--", "-- "):
- in_signature = True
- in_body = in_patch = in_headers = False
- line = TERM_FG_PURPLE + line + TERM_RESET
- elif line.startswith("@@ "):
- line = TERM_FG_CYAN + line + TERM_RESET
- elif any(line.startswith(m) for m in DIFF_META):
- line = TERM_BOLD + TERM_FG_WHITE + line + TERM_RESET
- elif line.startswith("+"):
- line = TERM_FG_GREEN + line + TERM_RESET
- elif line.startswith("-"):
- line = TERM_FG_RED + line + TERM_RESET
-
- elif in_signature:
- line = (
- TERM_FG_PURPLE
- + URL_RE.sub(replace_match(TERM_FG_YELLOW, TERM_FG_PURPLE), line)
- + TERM_RESET
- )
-
- elif in_headers:
- if line == "":
- in_body = True
- in_headers = False
- else:
- line = HEADER_RE.sub(replace_match(TERM_FG_PURPLE, TERM_RESET), line)
- line = URL_RE.sub(replace_match(TERM_FG_YELLOW, TERM_RESET), line)
-
- elif in_body:
- if line.startswith(">"):
- level = 0
- quotes = ""
- while line.startswith(">"):
- quotes += ">"
- line = line[1:]
- level += 1
- while line.startswith(" "):
- quotes += " "
- line = line[1:]
- quote_color = QUOTE_COLORS.get(quotes.count(">"), TERM_FG_GRAY)
-
- if line.startswith("+"):
- line = quote_color + quotes + TERM_FG_GREEN + line + TERM_RESET
- elif line.startswith("-"):
- line = quote_color + quotes + TERM_FG_RED + line + TERM_RESET
- else:
- line = (
- quote_color
- + quotes
- + URL_RE.sub(
- replace_match(TERM_FG_YELLOW, quote_color), line
- )
- + TERM_RESET
- )
- elif line.startswith("diff --git "):
- in_patch = True
- in_body = in_headers = False
- line = TERM_BOLD + TERM_FG_WHITE + line + TERM_RESET
- elif line in ("--", "-- "):
- in_signature = True
- in_body = in_patch = in_headers = False
- line = TERM_FG_PURPLE + line + TERM_RESET
- else:
- line = URL_RE.sub(replace_match(TERM_FG_YELLOW, TERM_RESET), line)
-
- elif line.startswith("diff --git "):
- in_patch = True
- in_body = in_headers = False
- line = TERM_BOLD + TERM_FG_WHITE + line + TERM_RESET
-
- elif line in ("--", "-- "):
- in_signature = True
- in_body = in_patch = in_headers = False
- line = TERM_FG_PURPLE + line + TERM_RESET
-
- elif HEADER_RE.search(line):
- in_headers = True
- line = HEADER_RE.sub(replace_match(TERM_FG_PURPLE, TERM_RESET), line)
- line = URL_RE.sub(replace_match(TERM_FG_YELLOW, TERM_RESET), line)
-
- else:
- in_body = True
- if line.startswith(">"):
- level = 0
- quotes = ""
- while line.startswith(">"):
- quotes += ">"
- line = line[1:]
- level += 1
- while line.startswith(" "):
- quotes += " "
- line = line[1:]
- quote_color = QUOTE_COLORS.get(quotes.count(">"), TERM_FG_GRAY)
-
- if line.startswith("+"):
- line = quote_color + quotes + TERM_FG_GREEN + line + TERM_RESET
- elif line.startswith("-"):
- line = quote_color + quotes + TERM_FG_RED + line + TERM_RESET
- else:
- line = (
- quote_color
- + quotes
- + URL_RE.sub(
- replace_match(TERM_FG_YELLOW, quote_color), line
- )
- + TERM_RESET
- )
-
- sys.stdout.write(line + "\r\n")
- sys.stdout.flush()
-
-
-if __name__ == "__main__":
- sys.exit(main())