209 lines
5.1 KiB
Awk
209 lines
5.1 KiB
Awk
# awk script to generate summary line for iCalendar VJOURNAL and VTODO entries
|
|
#
|
|
# See https://datatracker.ietf.org/doc/html/rfc5545 for the RFC 5545 that
|
|
# describes iCalendar, and its syntax
|
|
|
|
@include "lib/awk/icalendar.awk"
|
|
|
|
# Generate kind-of-pretty date strings.
|
|
#
|
|
# @local variables: ts, ts_y, ts_m, ts_d, delta
|
|
# @input date: Date in the format YYYYMMDD
|
|
# @input todaystamp: Today, seconds since epoch
|
|
# @return: string
|
|
function formatdate(date, todaystamp, ts, ts_y, ts_m, ts_d, delta)
|
|
{
|
|
ts_y = substr(date, 1, 4);
|
|
ts_m = substr(date, 5, 2);
|
|
ts_d = substr(date, 7);
|
|
ts = mktime(ts_y " " ts_m " " ts_d " 00 00 00");
|
|
delta = (ts - todaystamp) / 86400;
|
|
if (delta >= 0 && delta < 1) {
|
|
return " today";
|
|
}
|
|
if (delta >= 1 && delta < 2) {
|
|
return " tomorrow";
|
|
}
|
|
if (delta >= 2 && delta < 3) {
|
|
return " in two days";
|
|
}
|
|
if (delta >= 3 && delta < 4) {
|
|
return " in three days";
|
|
}
|
|
if (delta < 0 && delta >= -1) {
|
|
return " yesterday";
|
|
}
|
|
if (delta < -1 && delta >= -2) {
|
|
return " two days ago";
|
|
}
|
|
if (delta < -2 && delta >= -3) {
|
|
return "three days ago";
|
|
}
|
|
return " " substr(date, 1, 4) "-" substr(date, 5, 2) "-" substr(date, 7);
|
|
}
|
|
|
|
BEGIN {
|
|
# We require the following variables to be set using -v
|
|
# collection_lables: ;-delimited collection=label strings
|
|
# flag_open: symbol for open to-dos
|
|
# flag_completed: symbol for completed to-dos
|
|
# flag_journal: symbol for journal entries
|
|
# flag_note: symbol for note entries
|
|
# flag_priority symbol for prior. task
|
|
# style_collection
|
|
# style_date
|
|
# style_summary
|
|
# style_expired
|
|
# style_category
|
|
|
|
FS = "[:;]";
|
|
# Collections
|
|
split(collection_labels, mapping, ";");
|
|
for (map in mapping)
|
|
{
|
|
split(mapping[map], m, "=");
|
|
collection2label[m[1]] = m[2];
|
|
}
|
|
# Colors
|
|
OFF = "\033[m";
|
|
|
|
# For date comparision
|
|
today = strftime("%Y%m%d");
|
|
todaystamp = mktime(substr(today, 1, 4) " " substr(today, 5, 2) " " substr(today, 7) " 00 00 00");
|
|
}
|
|
|
|
# Reset variables
|
|
BEGINFILE {
|
|
type = "";
|
|
prop = "";
|
|
delete c;
|
|
}
|
|
|
|
/^BEGIN:(VJOURNAL|VTODO)/ {
|
|
type = $2
|
|
}
|
|
|
|
/^END:/ && $2 == type {
|
|
nextfile
|
|
}
|
|
|
|
/^(CATEGORIES|PRIORITY|STATUS|SUMMARY|COMPLETED|DUE|DTSTART|DURATION|CREATED|DTSTAMP|LAST-MODIFIED)/ {
|
|
prop = $1;
|
|
c[prop] = $0;
|
|
next;
|
|
}
|
|
/^[^ ]/ && prop {
|
|
prop = "";
|
|
next;
|
|
}
|
|
/^ / && prop {
|
|
c[prop] = c[prop] substr($0, 2);
|
|
next;
|
|
}
|
|
|
|
ENDFILE {
|
|
if (!type) {
|
|
exit
|
|
}
|
|
# Construct path, and check for validity
|
|
depth = split(FILENAME, path, "/");
|
|
fpath = path[depth-1] "/" path[depth]
|
|
if (index(fpath, " "))
|
|
{
|
|
print 10,
|
|
"-",
|
|
type,
|
|
"-",
|
|
style_expired "ERROR: file '" fpath "' contains whitespaces!" OFF
|
|
exit
|
|
}
|
|
# Collection name
|
|
collection = path[depth-1]
|
|
collection = collection in collection2label ? collection2label[collection] : collection;
|
|
|
|
# Process content lines
|
|
# strings
|
|
cat = singleline(unescape(getcontent(c["CATEGORIES"])))
|
|
sta = singleline(unescape(getcontent(c["STATUS"])))
|
|
sum = singleline(unescape(getcontent(c["SUMMARY"])))
|
|
|
|
# integers
|
|
pri = unescape(getcontent(c["PRIORITY"]))
|
|
pri = pri ? pri + 0 : 0
|
|
|
|
# dates
|
|
due = substr(unescape(getcontent(c["DUE"])), 1, 8)
|
|
dts = substr(unescape(getcontent(c["DTSTART"])), 1, 8)
|
|
|
|
# date-times
|
|
com = unescape(getcontent(c["COMPLETED"]))
|
|
dur = unescape(getcontent(c["DURATION"]))
|
|
cre = unescape(getcontent(c["CREATED"]))
|
|
stp = unescape(getcontent(c["DTSTAMP"]))
|
|
lmd = unescape(getcontent(c["LAST-MODIFIED"]))
|
|
|
|
# Priority field, primarly used for sorting
|
|
psort = 0;
|
|
priotext = ""
|
|
if (pri > 0)
|
|
{
|
|
priotext = flag_priority "(" pri ") "
|
|
psort = 10 - pri
|
|
}
|
|
|
|
# Last modification/creation time stamp, used for sorting
|
|
# LAST-MODIFIED: Optional field for VTODO and VJOURNAL entries, date-time in
|
|
# UTC time format
|
|
# DTSTAMP: mandatory field in VTODO and VJOURNAL, date-time in UTC time
|
|
# format
|
|
mod = lmd ? lmd : stp
|
|
|
|
# Date field. For VTODO entries, we show the due date, for journal entries,
|
|
# the associated date.
|
|
datecolor = style_date
|
|
summarycolor = style_summary
|
|
|
|
if (type == "VTODO")
|
|
{
|
|
# Either DUE or DURATION may appear. If DURATION appears, then also DTSTART
|
|
d = due ? due : (dur ? dts " for " dur : "");
|
|
if (d && d <= today && sta != "COMPLETED")
|
|
{
|
|
datecolor = style_expired;
|
|
summarycolor = style_expired;
|
|
}
|
|
} else {
|
|
d = dts
|
|
}
|
|
d = d ? formatdate(d, todaystamp) : " ";
|
|
|
|
# flag: - "journal" for VJOURNAL with DTSTART
|
|
# - "note" for VJOURNAL without DTSTART
|
|
# - "completed" for VTODO with c["STATUS"] == COMPLETED
|
|
# - "open" for VTODO with c["STATUS"] != COMPLETED
|
|
if (type == "VTODO")
|
|
flag = sta == "COMPLETED" ? flag_completed : flag_open;
|
|
else
|
|
flag = dts ? flag_journal : flag_note;
|
|
|
|
# summary
|
|
# c["SUMMARY"]
|
|
summary = sum ? sum : " "
|
|
|
|
# categories
|
|
categories = cat ? cat : " "
|
|
|
|
# filename
|
|
# FILENAME
|
|
|
|
print psort,
|
|
mod,
|
|
type,
|
|
fpath,
|
|
collection,
|
|
datecolor d OFF,
|
|
flag,
|
|
priotext summarycolor summary OFF,
|
|
style_category categories OFF;
|
|
}
|