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>
This commit is contained in:
parent
9dc2803220
commit
df8c129235
297
filters/colorize
297
filters/colorize
|
@ -1,171 +1,142 @@
|
||||||
#!/usr/bin/env python3
|
#!/bin/awk -f
|
||||||
# Copyright (c) 2022 Robin Jarry
|
# Copyright (c) 2022 Robin Jarry
|
||||||
|
|
||||||
"""
|
BEGIN {
|
||||||
Colorize plaintext email. Write to stdout.
|
# R;G;B colors
|
||||||
"""
|
url = "\x1b[38;2;255;255;175m" # yellow
|
||||||
|
header = "\x1b[38;2;175;135;255m" # purple
|
||||||
import re
|
signature = "\x1b[38;2;175;135;255m" # purple
|
||||||
import sys
|
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
|
||||||
TERM_RESET = "\x1b[0m"
|
diff_del = "\x1b[38;2;205;0;0m" # red
|
||||||
TERM_BOLD = "\x1b[1m"
|
quote_1 = "\x1b[38;2;95;175;255m" # blue
|
||||||
TERM_BG_GRAY = "\x1b[48;5;244m"
|
quote_2 = "\x1b[38;2;255;135;0m" # orange
|
||||||
TERM_FG_GRAY = "\x1b[38;5;244m"
|
quote_3 = "\x1b[38;2;175;135;255m" # purple
|
||||||
TERM_FG_RED = "\x1b[38;5;1m"
|
quote_4 = "\x1b[38;2;255;95;215m" # pink
|
||||||
TERM_FG_GREEN = "\x1b[38;5;2m"
|
quote_x = "\x1b[38;2;128;128;128m" # gray
|
||||||
TERM_FG_CYAN = "\x1b[38;5;6m"
|
reset = "\x1b[0m"
|
||||||
TERM_FG_YELLOW = "\x1b[38;5;229m"
|
# state
|
||||||
TERM_FG_WHITE = "\x1b[38;5;15m"
|
in_diff = 0
|
||||||
TERM_FG_BLUE = "\x1b[38;5;75m"
|
in_signature = 0
|
||||||
TERM_FG_PURPLE = "\x1b[38;5;141m"
|
in_headers = 0
|
||||||
TERM_FG_ORANGE = "\x1b[38;5;208m"
|
in_body = 0
|
||||||
TERM_FG_PINK = "\x1b[38;5;171m"
|
# patterns
|
||||||
QUOTE_COLORS = {
|
header_pattern = @/^[A-Z][[:alnum:]-]+:/
|
||||||
1: TERM_FG_BLUE,
|
url_pattern = @/[a-z]{2,6}:\/\/[[:graph:]]+|[[:alnum:]_\+\.~\/-]*[[:alnum:]_]@[[:lower:]][[:alnum:]\.-]*[[:lower:]]/
|
||||||
2: TERM_FG_ORANGE,
|
|
||||||
3: TERM_FG_PURPLE,
|
|
||||||
4: TERM_FG_PINK,
|
|
||||||
}
|
}
|
||||||
URL_RE = re.compile(
|
function color_quote(line) {
|
||||||
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
|
level = 0
|
||||||
quotes = ""
|
quotes = ""
|
||||||
while line.startswith(">"):
|
while (line ~ /^>/) {
|
||||||
quotes += ">"
|
|
||||||
line = line[1:]
|
|
||||||
level += 1
|
level += 1
|
||||||
while line.startswith(" "):
|
quotes = quotes ">"
|
||||||
quotes += " "
|
line = substr(line, 2)
|
||||||
line = line[1:]
|
while (line ~ /^ /) {
|
||||||
quote_color = QUOTE_COLORS.get(quotes.count(">"), TERM_FG_GRAY)
|
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 line.startswith("+"):
|
if (in_diff) {
|
||||||
line = quote_color + quotes + TERM_FG_GREEN + line + TERM_RESET
|
if ($0 ~ /^-- ?$/) {
|
||||||
elif line.startswith("-"):
|
in_signature = 1
|
||||||
line = quote_color + quotes + TERM_FG_RED + line + TERM_RESET
|
in_diff = 0
|
||||||
else:
|
in_headers = 0
|
||||||
line = (
|
in_body = 0
|
||||||
quote_color
|
$0 = signature $0 reset
|
||||||
+ quotes
|
} else if ($0 ~ /^@@ /) {
|
||||||
+ URL_RE.sub(
|
$0 = diff_chunk $0 reset
|
||||||
replace_match(TERM_FG_YELLOW, quote_color), line
|
} else if ($0 ~ /^(diff --git|index|---|\+\+\+) /) {
|
||||||
)
|
$0 = diff_meta $0 reset
|
||||||
+ TERM_RESET
|
} else if ($0 ~ /^\+/) {
|
||||||
)
|
$0 = diff_add $0 reset
|
||||||
elif line.startswith("diff --git "):
|
} else if ($0 ~ /^-/) {
|
||||||
in_patch = True
|
$0 = diff_del $0 reset
|
||||||
in_body = in_headers = False
|
}
|
||||||
line = TERM_BOLD + TERM_FG_WHITE + line + TERM_RESET
|
} else if (in_signature) {
|
||||||
elif line in ("--", "-- "):
|
$0 = signature $0 reset
|
||||||
in_signature = True
|
gsub(url_pattern, url "&" signature)
|
||||||
in_body = in_patch = in_headers = False
|
} else if (in_headers) {
|
||||||
line = TERM_FG_PURPLE + line + TERM_RESET
|
if ($0 ~ /^$/) {
|
||||||
else:
|
in_signature = 0
|
||||||
line = URL_RE.sub(replace_match(TERM_FG_YELLOW, TERM_RESET), line)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
elif line.startswith("diff --git "):
|
print
|
||||||
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())
|
|
||||||
|
|
Loading…
Reference in New Issue