summaryrefslogtreecommitdiff
path: root/.config/aerc
diff options
context:
space:
mode:
authorMichael Hunteman <michael@huntm.net>2023-08-31 18:56:05 -0500
committerMichael Hunteman <michael@huntm.net>2023-08-31 18:56:22 -0500
commitbc79a9f65ba9f9fdb308b4a8eb75d0ca4e692463 (patch)
treeb73f2c388c73ef5f3f5c62ed48f4748744b6de11 /.config/aerc
parenta35c727df4d1c3bfbb9b8b7908ed202319e4d62a (diff)
Add aerc filters
Diffstat (limited to '.config/aerc')
-rwxr-xr-x.config/aerc/filters/calendar270
-rwxr-xr-x.config/aerc/filters/colorize177
-rwxr-xr-x.config/aerc/filters/hldiff46
-rwxr-xr-x.config/aerc/filters/html11
-rwxr-xr-x.config/aerc/filters/html-unsafe17
-rwxr-xr-x.config/aerc/filters/plaintext17
-rwxr-xr-x.config/aerc/filters/show-ics-details.py89
-rwxr-xr-x.config/aerc/filters/wrapbin0 -> 2455008 bytes
8 files changed, 627 insertions, 0 deletions
diff --git a/.config/aerc/filters/calendar b/.config/aerc/filters/calendar
new file mode 100755
index 0000000..2808e13
--- /dev/null
+++ b/.config/aerc/filters/calendar
@@ -0,0 +1,270 @@
+#!/usr/bin/awk -f
+# ex: ft=awk
+#
+# awk filter for aerc to parse text/calendar mime-types
+#
+# Based on the ical2org.awk script by Eric S Fraga and updated by Guide Van
+# Hoecke. Adapted to aerc by Koni Marti <koni.marti@gmail.com>
+#
+
+BEGIN {
+ UIDS[0];
+ people_attending[0];
+ people_partstat[0];
+ people_rsvp[0];
+
+ # use a colon to separate the type of data line from the actual contents
+ FS = ":";
+}
+
+{
+ # remove carriage return from every line
+ gsub(/\r/, "")
+}
+
+/^[ ]/ {
+ # this block deals with the continuation lines that start with a whitespace
+ #
+ line = $0
+ # remove trailing whitespaces
+ gsub(/^[ ]/, "", line)
+
+ # assumes continuation lines start with a space
+ if (indescription) {
+ entry = entry line
+ } else if (insummary) {
+ summary = summary line
+ } else if (inattendee) {
+ attendee = attendee line
+ } else if (inorganizer) {
+ organizer = organizer line
+ } else if (inlocation) {
+ location = location unescape(line, 0)
+ }
+}
+
+/^BEGIN:VALARM/,/^END:VALARM/ {
+ next
+}
+
+/^BEGIN:VEVENT/ {
+ # start of an event: initialize global values used for each event
+ start_date = "";
+ end_date = "";
+ entry = ""
+ id = ""
+
+ indescription = 0;
+ insummary = 0
+ inattendee = 0
+ inorganizer = 0
+ inlocation = 0
+
+ location = ""
+ status = ""
+ summary = ""
+ attendee = ""
+ organizer = ""
+
+ rrend = ""
+ rcount = ""
+ intfreq = ""
+ idx = 0
+
+ delete people_attending;
+ delete people_partstat;
+ delete people_rsvp;
+}
+
+/^[A-Z]/ {
+ if (attendee != "" && inattendee==1)
+ add_attendee(attendee)
+
+ if (organizer != "" && inorganizer==1)
+ organizer = find_full_name(organizer)
+
+ indescription = 0;
+ insummary = 0;
+ inattendee = 0;
+ inorganizer = 0;
+ inlocation = 0;
+}
+
+/^DTSTART[:;]/ {
+ tz = get_value($0, "TZID=[^:;]*", "=")
+ start_date = datetimestring($2, tz);
+}
+
+/^DTEND[:;]/ {
+ tz = get_value($0, "TZID=[^:;]*", "=")
+ end_date = datetimestring($2, tz);
+}
+
+/^RRULE[:]/ {
+ freq = get_value($0, "FREQ=[^:;]*", "=")
+ interval = get_value($0, "INTERVAL=[^:;]*", "=")
+ rrend = get_value($0, "UNTIL=[^:;]*", "=")
+ rcount = get_value($0, "COUNT=[^:;]*", "=")
+ intfreq = tolower(freq)
+ if (interval != "")
+ intfreq = " +" interval intfreq
+}
+
+/^METHOD/ {
+ method = $2
+}
+
+/^UID/ {
+ line = prepare($0)
+ id = line
+}
+
+/^STATUS/ {
+ line = prepare($0)
+ status = line
+}
+
+/^DESCRIPTION/ {
+ line = prepare($0)
+ entry = entry line
+ indescription = 1;
+}
+
+/^SUMMARY/ {
+ line = prepare($0)
+ summary = line
+ insummary = 1;
+}
+
+/^ORGANIZER/ {
+ organizer = $0
+ inorganizer = 1;
+}
+
+/^LOCATION/ {
+ line = prepare($0)
+ location = unescape(line, 0);
+ inlocation = 1;
+}
+
+/^ATTENDEE/ {
+ attendee = $0
+ inattendee = 1;
+}
+
+/^END:VEVENT/ {
+ #output event
+ if (method != "") {
+ printf "\n This is a meeting %s\n\n", method
+ }
+ fmt = " %-14s%s\n"
+ is_duplicate = (id in UIDS);
+ if(is_duplicate == 0) {
+ printf fmt, "SUMMARY", unescape(summary, 0)
+ if(location != "")
+ printf fmt, "LOCATION", location
+ if(organizer != "")
+ printf fmt, "ORGANIZER", organizer
+ for (idx in people_attending) {
+ printf fmt, "ATTENDEE [" idx "]", people_attending[idx]
+ partstat = people_partstat[idx]
+ if (partstat != "") {
+ printf fmt, "", "STATUS\t" partstat
+ }
+ rsvp = people_rsvp[idx]
+ if (rsvp != "") {
+ printf fmt, "", "RSVP\t" rsvp
+ }
+ }
+ printf fmt, "START", start_date
+ printf fmt, "END", end_date
+ if (intfreq != "") {
+ printf "\n"fmt, "RECURRENCE", intfreq
+ if (rcount != "")
+ printf fmt, "COUNTS", rcount
+ if (rrend != "")
+ printf fmt, "END DATE", rrend
+
+ }
+ if(entry != "")
+ print "\n" unescape(entry, 1);
+ UIDS[id] = 1;
+ }
+}
+
+func prepare(line) {
+ gsub($1, "", line)
+ gsub(/^[: ]/, "", line)
+ return line
+}
+
+function unescape(input, preserve_newlines)
+{
+ ret = input
+ gsub(/\\,/, ",", ret)
+ gsub(/\\;/, ";", ret)
+ if (preserve_newlines)
+ gsub(/\\n/, "\n", ret)
+ else
+ gsub(/\\n/, " ", ret)
+ return ret
+}
+
+
+function datetimestring(input, tzInput)
+{
+ timestr = input
+ pos = index(timestr, "T")
+ if (pos < 0) {
+ return timestr
+ }
+
+ date = substr(timestr, 1, pos)
+ time = substr(timestr, pos+1, length(timestr))
+
+ year = substr(date, 1, 4)
+ month = substr(date, 5, 2)
+ day = substr(date, 7, 2)
+
+ hour = substr(time, 1, 2)
+ min = substr(time, 3, 2)
+ sec = substr(time, 5, 2)
+
+ return sprintf("%4d/%02d/%02d %02d:%02d:%02d %s", year, month, day, hour, min, sec, tzInput)
+}
+
+function add_attendee(attendee)
+{
+ CN = find_full_name(attendee)
+ if (CN != "") {
+ idx = idx + 1
+ people_attending[idx] = CN;
+ people_partstat[idx] = get_value(attendee, "PARTSTAT=[^;:]+", "=")
+ people_rsvp[idx] = get_value(attendee, "RSVP=[^;:]+", "=")
+ }
+}
+
+function find_full_name(line)
+{
+ name = get_value(line, "CN=[^;:]+", "=")
+ gsub(/"[^"]*"/,"",line)
+ email = get_value(line, "(mailto|MAILTO):[^;]+", ":")
+
+ if (name == "") {
+ return sprintf("<%s>", email)
+ } else {
+ return sprintf("%s <%s>", name, email)
+ }
+}
+
+function get_value(line, regexp, sep) {
+ value = ""
+ match(line, regexp)
+ {
+ z = split(substr(line,RSTART,RLENGTH),data,sep)
+ if (z > 1) {
+ value = data[2]
+ }
+ }
+ return value
+}
diff --git a/.config/aerc/filters/colorize b/.config/aerc/filters/colorize
new file mode 100755
index 0000000..9d2a736
--- /dev/null
+++ b/.config/aerc/filters/colorize
@@ -0,0 +1,177 @@
+#!/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/.config/aerc/filters/hldiff b/.config/aerc/filters/hldiff
new file mode 100755
index 0000000..dc8c727
--- /dev/null
+++ b/.config/aerc/filters/hldiff
@@ -0,0 +1,46 @@
+#!/usr/bin/awk -f
+
+BEGIN {
+ bright = "\x1B[1m"
+ red = "\x1B[31m"
+ green = "\x1B[32m"
+ cyan = "\x1B[36m"
+ reset = "\x1B[0m"
+
+ hit_diff = 0
+}
+{
+ if (hit_diff == 0) {
+ # Strip carriage returns from line
+ gsub(/\r/, "", $0)
+
+ if ($0 ~ /^diff /) {
+ hit_diff = 1;
+ print bright $0 reset
+ } else if ($0 ~ /^.*\|.*(\+|-)/) {
+ left = substr($0, 0, index($0, "|")-1)
+ right = substr($0, index($0, "|"))
+ gsub(/-+/, red "&" reset, right)
+ gsub(/\++/, green "&" reset, right)
+ print left right
+ } else {
+ print $0
+ }
+ } else {
+ # Strip carriage returns from line
+ gsub(/\r/, "", $0)
+
+ if ($0 ~ /^-/) {
+ print red $0 reset
+ } else if ($0 ~ /^\+/) {
+ print green $0 reset
+ } else if ($0 ~ /^ /) {
+ print $0
+ } else if ($0 ~ /^@@ (-[0-9]+,[0-9]+ \+[0-9]+,[0-9]+) @@.*/) {
+ sub(/^@@ (-[0-9]+,[0-9]+ \+[0-9]+,[0-9]+) @@/, cyan "&" reset)
+ print $0
+ } else {
+ print bright $0 reset
+ }
+ }
+}
diff --git a/.config/aerc/filters/html b/.config/aerc/filters/html
new file mode 100755
index 0000000..5ceee40
--- /dev/null
+++ b/.config/aerc/filters/html
@@ -0,0 +1,11 @@
+#!/bin/sh
+# aerc filter which runs w3m using socksify (from the dante package) to prevent
+# any phoning home by rendered emails
+export SOCKS_SERVER="127.0.0.1:1"
+exec socksify w3m \
+ -I UTF-8 \
+ -T text/html \
+ -cols $(tput cols) \
+ -dump \
+ -o display_image=false \
+ -o display_link_number=true
diff --git a/.config/aerc/filters/html-unsafe b/.config/aerc/filters/html-unsafe
new file mode 100755
index 0000000..8e0041c
--- /dev/null
+++ b/.config/aerc/filters/html-unsafe
@@ -0,0 +1,17 @@
+#!/bin/sh
+# aerc filter which runs w3m using socksify (from the dante package) to prevent
+# any phoning home by rendered emails. If socksify is not installed then w3m is
+# used without it.
+if [ $(command -v socksify) ]; then
+ export SOCKS_SERVER="127.0.0.1:1"
+ PRE_CMD=socksify
+else
+ PRE_CMD=""
+fi
+exec $PRE_CMD w3m \
+ -I UTF-8 \
+ -T text/html \
+ -cols $(tput cols) \
+ -dump \
+ -o display_image=false \
+ -o display_link_number=true
diff --git a/.config/aerc/filters/plaintext b/.config/aerc/filters/plaintext
new file mode 100755
index 0000000..aa22eb7
--- /dev/null
+++ b/.config/aerc/filters/plaintext
@@ -0,0 +1,17 @@
+#!/usr/bin/awk -f
+
+BEGIN {
+ dim = "\033[2m"
+ cyan = "\033[36m"
+ reset = "\033[0m"
+}
+{
+ # Strip carriage returns from line
+ gsub(/\r/, "", $0)
+
+ if ($0 ~ /^On .*, .* wrote:/ || $0 ~ /^>+/) {
+ print dim cyan $0 reset
+ } else {
+ print $0
+ }
+}
diff --git a/.config/aerc/filters/show-ics-details.py b/.config/aerc/filters/show-ics-details.py
new file mode 100755
index 0000000..18b2b76
--- /dev/null
+++ b/.config/aerc/filters/show-ics-details.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python3
+
+"""Parse a vcard file given via stdin and output some details.
+Currently the following details are displayed if present:
+
+- start date and time
+- the summary information of the event
+- a list of attendees
+- the description of the event
+
+Please note: if multiple events are included in the data then only the
+first one will be parsed and displayed!
+
+REQUIREMENTS:
+- Python 3
+- Python 3 - vobject library
+
+To use as a filter in aerc, add the following line to your aerc.config:
+text/calendar=show-ics-details.py
+"""
+
+import re
+import sys
+
+import vobject
+
+
+def remove_mailto(message: str) -> str:
+ """Remove a possible existing 'mailto:' from the given message.
+
+ Keyword arguments:
+ message -- A message string.
+ """
+ return re.sub(r'^mailto:', '', message, flags=re.IGNORECASE)
+
+def extract_field(cal: vobject.icalendar.VCalendar2_0, name: str) -> str:
+ """Extract the desired field from the given calendar object.
+
+ Keyword arguments:
+ cal -- A VCalendar 2.0 object.
+ name -- The field name.
+ """
+ try:
+ name = name.strip()
+ if name == 'attendees':
+ attendees = []
+ for attendee in cal.vevent.attendee_list:
+ attendees.append(remove_mailto(attendee.valueRepr()).strip())
+ return ', '.join(attendees)
+ elif name == 'description':
+ return cal.vevent.description.valueRepr().strip()
+ elif name == 'dtstart':
+ return str(cal.vevent.dtstart.valueRepr()).strip()
+ elif name == 'organizer':
+ return remove_mailto(cal.vevent.organizer.valueRepr()).strip()
+ elif name == 'summary':
+ return cal.vevent.summary.valueRepr().strip()
+ else:
+ return ''
+ except AttributeError:
+ return ''
+
+attendees = ''
+description = ''
+dtstart = ''
+error = ''
+organizer = ''
+summary = ''
+
+try:
+ cal = vobject.readOne(sys.stdin)
+ attendees = extract_field(cal, 'attendees')
+ description = extract_field(cal, 'description')
+ dtstart = extract_field(cal, 'dtstart')
+ organizer = extract_field(cal, 'organizer')
+ summary = extract_field(cal, 'summary')
+except vobject.base.ParseError:
+ error = '**Sorry, but we could not parse the calendar!**'
+
+if error:
+ print(error)
+ print("")
+
+print(f"Date/Time : {dtstart}")
+print(f"Summary : {summary}")
+print(f"Organizer : {organizer}")
+print(f"Attendees : {attendees}")
+print("")
+print(description)
diff --git a/.config/aerc/filters/wrap b/.config/aerc/filters/wrap
new file mode 100755
index 0000000..0d29ce2
--- /dev/null
+++ b/.config/aerc/filters/wrap
Binary files differ