aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xfilters/plaintext171
1 files changed, 171 insertions, 0 deletions
diff --git a/filters/plaintext b/filters/plaintext
new file mode 100755
index 00000000..f4801ebf
--- /dev/null
+++ b/filters/plaintext
@@ -0,0 +1,171 @@
+#!/usr/bin/env python3
+# 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,
+}
+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())