diff options
author | Koni Marti <koni.marti@gmail.com> | 2022-07-24 01:25:24 +0200 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2022-07-24 23:06:36 +0200 |
commit | ab941ebc6a3707e58aab5986f88c1937389fd859 (patch) | |
tree | dde55fde7b2a8b9a4f37573cde56ee4f29b193b2 | |
parent | fb5558da811a49031922ee5582f61ac1d9b08d3c (diff) | |
download | aerc-ab941ebc6a3707e58aab5986f88c1937389fd859.zip |
filters: posix compliant rewrite of calendar filter
Rewrite of the awk calendar filter to make it posix compliant. Tested
with awk --posix (awk -V = GNU Awk 5.1.1). Also added some improvements
to readability and formatting.
This complements commit 3ef4a3ca051a ("filters: try and make awk scripts
posix compliant").
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
-rwxr-xr-x | filters/calendar | 287 |
1 files changed, 109 insertions, 178 deletions
diff --git a/filters/calendar b/filters/calendar index c9ee1e8..b9bd3a0 100755 --- a/filters/calendar +++ b/filters/calendar @@ -9,38 +9,48 @@ 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 = ":"; +} - method = "" - prodid = "" - - first = 0 +{ + # 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 gensub("\r", "", "g", gensub("^[ ]", "", 1, $0)); + entry = entry line } else if (insummary) { - summary = summary gensub("\r", "", "g", gensub("^[ ]", "", 1, $0)) + summary = summary line } else if (inattendee) { - attendee = attendee gensub("\r", "", "g", gensub("^[ ]", "", 1, $0)) + attendee = attendee line } else if (inorganizer) { - organizer = organizer gensub("\r", "", "g", gensub("^[ ]", "", 1, $0)) + organizer = organizer line } else if (inlocation) { - location = location unescape(gensub("\r", "", "g", $0), 0); + location = location unescape(line, 0) } } +/^BEGIN:VALARM/,/^END:VALARM/ { + next +} + /^BEGIN:VEVENT/ { # start of an event: initialize global values used for each event - date = ""; + start_date = ""; + end_date = ""; entry = "" id = "" @@ -49,7 +59,6 @@ BEGIN { inattendee = 0 inorganizer = 0 inlocation = 0 - in_alarm = 0 location = "" status = "" @@ -60,27 +69,11 @@ BEGIN { rrend = "" rcount = "" intfreq = "" + idx = 0 delete people_attending; delete people_partstat; delete people_rsvp; - - if (first == 0) { - first = 1 - if (method != "") - print " METHOD " method - if (prodid != "") - print " PRODID " prodid - print "" - } -} - -/^BEGIN:VALARM/ { - in_alarm = 1 -} - -/^END:VALARM/ { - in_alarm = 0 } /^[A-Z]/ { @@ -97,130 +90,99 @@ BEGIN { inlocation = 0; } -/^DTSTART;VALUE=DATE/ { - date = datestring($2); -} - -/^DTEND;VALUE=DATE/ { - end_date = datestring($2); +/^DTSTART[:;]/ { + tz = get_value($0, "TZID=[^:;]*", "=") + start_date = datetimestring($2, tz); } -/^DTSTART[:;][^V]/ { - tz = ""; - match($0, /TZID=([^:]*)/, a) - { - tz = a[1]; - } - date = datetimestring($2, tz); -} - -/^DTEND[:;][^V]/ { - tz = ""; - match($0, /TZID=([^:]*)/, a) - { - tz = a[1]; - } +/^DTEND[:;]/ { + tz = get_value($0, "TZID=[^:;]*", "=") end_date = datetimestring($2, tz); } -/^RRULE:FREQ=(DAILY|WEEKLY|MONTHLY|YEARLY)/ { - # TODO: handle BYDAY values for events that repeat weekly for multiple days - # (e.g. a "Gym" event) - - # get the d, w, m or y value - freq = tolower(gensub(/.*FREQ=(.).*/, "\\1", 1, $0)) - # get the interval, and use 1 if none specified - interval = $0 ~ /INTERVAL=/ ? gensub(/.*INTERVAL=([0-9]+).*/, "\\1", 1, $0) : 1 - # get the enddate of the rule and use "" if none specified - rrend = $0 ~ /UNTIL=/ ? datestring(gensub(/.*UNTIL=([0-9]{8}).*/, "\\1", 1, $0)) : "" - rcount = $0 ~ /COUNT=/ ? gensub(/.*COUNT=([0-9]+).*/, "\\1", 1, $0) : "" - # build the repetitor value - intfreq = " +" interval freq +/^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 } -/^DESCRIPTION/ { - if (!in_alarm) { - entry = entry gensub("\r", "", "g", gensub($1":", "", 1, $0)); - indescription = 1; - } +/^METHOD/ { + method = $2 } -/^SUMMARY/ { - if (!in_alarm) { - summary = gensub("\r", "", "g", gensub($1":", "", 1, $0)); - insummary = 1; - } +/^UID/ { + id = $2 } -/^UID/ { - if (!in_alarm) { - id = gensub("\r", "", "g", $2); - } +/^STATUS/ { + status = $2 } -/^METHOD/ { - method = gensub("\r", "", "g", $2); +/^DESCRIPTION/ { + entry = entry $2 + indescription = 1; } -/^PRODID/ { - prodid = gensub("\r", "", "g", $2); +/^SUMMARY/ { + summary = $2 + insummary = 1; } /^ORGANIZER/ { - organizer = gensub("\r", "", "g", $0); + organizer = $0 inorganizer = 1; } /^LOCATION/ { - location = unescape(gensub("\r", "", "g", $2), 0); + location = unescape($2, 0); inlocation = 1; } -/^STATUS/ { - status = gensub("\r", "", "g", $2); -} - /^ATTENDEE/ { - attendee = gensub("\r", "", "g", $0); + 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) { - print "* SUMMARY " gensub("^[ ]+", "", "g", unescape(summary, 0)) - if(length(location)) - print " LOCATION " location + printf fmt, "SUMMARY", unescape(summary, 0) + if(location != "") + printf fmt, "LOCATION", location if(organizer != "") - print " ORGANIZER " organizer - for (cn in people_attending) { - print " ATTENDEE " cn - partstat = people_partstat[cn] + printf fmt, "ORGANIZER", organizer + for (idx in people_attending) { + printf fmt, "ATTENDEE [" idx "]", people_attending[idx] + partstat = people_partstat[idx] if (partstat != "") { - print " STATUS " partstat + printf fmt, "", "STATUS\t" partstat } - rsvp = people_rsvp[cn] + rsvp = people_rsvp[idx] if (rsvp != "") { - print " RSVP " rsvp + printf fmt, "", "RSVP\t" rsvp } } - print " START " date - print " END " end_date - + printf fmt, "START", start_date + printf fmt, "END", end_date if (intfreq != "") { - print "" - print " RECURRENCE " intfreq + printf "\n"fmt, "RECURRENCE", intfreq if (rcount != "") - print " COUNTS " rcount + printf fmt, "COUNTS", rcount if (rrend != "") - print " END DATE " rrend + printf fmt, "END DATE", rrend } - - print "" - if(length(entry)>1) - print gensub("^[ ]+", "", "g", unescape(entry, 1)); + if(entry != "") + print "\n" unescape(entry, 1); UIDS[id] = 1; } } @@ -228,101 +190,70 @@ BEGIN { function unescape(input, preserve_newlines) { - ret = gensub("\\\\,", ",", "g", - gensub("\\\\;", ";", "g", input)) + ret = input + gsub(/\\,/, ",", ret) + gsub(/\\;/, ";", ret) if (preserve_newlines) - ret = gensub("\\\\n", "\n", "g", ret) + gsub(/\\n/, "\n", ret) else - ret = gensub("\\\\n", " ", "g", ret) + gsub(/\\n/, " ", ret) return ret } -function datetimestring(input, tz) +function datetimestring(input, tzInput) { - spec = match(input, "([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2})([0-9]{2})([0-9]{2}).*[\r]*", a); - year = a[1] - month = a[2] - day = a[3] - hour = a[4] - min = a[5] - sec = a[6] - - stamp = mktime(year" "month" "day" "hour" "min" "sec); - - if (input ~ /[0-9]{8}T[0-9]{6}Z/ ) { - tz = "UTC" + timestr = input + pos = index(timestr, "T") + if (pos < 0) { + return timestr } - return strftime("%Y-%m-%d %a %H:%M", stamp)" "tz; -} - + date = substr(timestr, 1, pos) + time = substr(timestr, pos+1, length(timestr)) -function datestring(input) -{ - spec = gensub("([0-9]{4})([0-9]{2})([0-9]{2}).*[\r]*", "\\1 \\2 \\3 00 00 00", "g", input); + year = substr(date, 1, 4) + month = substr(date, 5, 2) + day = substr(date, 7, 2) - stamp = mktime(spec); + hour = substr(time, 1, 2) + min = substr(time, 3, 2) + sec = substr(time, 5, 2) - return strftime("%Y-%m-%d %a", stamp); + 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 != "") - people_attending[CN] = 1; - if (CN != "") { - match(attendee, /PARTSTAT=([^;]+)/, m) - { - people_partstat[CN] = m[1] - } - match(attendee, /RSVP=([^;]+)/, m) - { - people_rsvp[CN] = m[1] - } + idx = idx + 1 + people_attending[idx] = CN; + people_partstat[idx] = get_value(attendee, "PARTSTAT=[^;:]+", "=") + people_rsvp[idx] = get_value(attendee, "RSVP=[^;:]+", "=") } } -function extract_email(line) +function find_full_name(line) { - email = "" - match(line,/:[ ]*(mailto|MAILTO):([^;]+)/, m) - { - email = m[2] - } - return email -} + name = get_value(line, "CN=[^;:]+", "=") + email = get_value(line, "(mailto|MAILTO):[^;]+", ":") -function extract_name(line) -{ - name = "" - match(line,/CN="?([^;:"]+)/, m) - { - name = m[1] + if (name == "") { + return sprintf("<%s>", email) + } else { + return sprintf("%s <%s>", name, email) } - return name } -function find_full_name(line) -{ - name = extract_name(line) - email = extract_email(line) - - if (name == "") { - if (email == "") { - return "" - } else { - return name +function get_value(line, regexp, sep) { + value = "" + match(line, regexp) + { + z = split(substr(line,RSTART,RLENGTH),data,sep) + if (z > 1) { + value = data[2] } } - - if (email == "") - return name - - if (email == name) - return "<"email">" - - return name" <"email">" + return value } |