imported project from ~/bin repo - ics2txt - convert icalendar .ics file to plain text
(HTM) git clone git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ics2txt
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Tags
(DIR) README
---
(DIR) commit c2ed3821e4f01043c1e8b3c9572c36ee6ff49af3
(HTM) Author: Josuah Demangeon <mail@josuah.net>
Date: Thu, 19 Apr 2018 03:41:16 +0200
imported project from ~/bin repo
Diffstat:
A Makefile | 10 ++++++++++
A agenda | 182 +++++++++++++++++++++++++++++++
A agenda.1 | 80 +++++++++++++++++++++++++++++++
3 files changed, 272 insertions(+), 0 deletions(-)
---
(DIR) diff --git a/Makefile b/Makefile
@@ -0,0 +1,10 @@
+BIN = agenda
+MAN1 = agenda.1
+
+all:
+
+install:
+ mkdir -p $(PREFIX)/bin
+ cp $(BIN) $(PREFIX)/bin
+ mkdir -p $(PREFIX)/share/man/man1
+ cp $(MAN1) $(PREFIX)/share/man/man1
(DIR) diff --git a/agenda b/agenda
@@ -0,0 +1,182 @@
+#!/usr/bin/awk -f
+
+# handle ical agenda and display them in plain text
+
+function leap(yrs)
+{
+ return (yrs % 4 == 0) && (yrs % 100 != 0) || (yrs % 400 == 0);
+}
+
+function days_per_month(mth, yrs)
+{
+ if (mth == 2)
+ return 28 + leap(yrs);
+ else
+ return 30 + (mth - (mth > 7)) % 2;
+}
+
+function to_sec(yrs, mth, day, hrs, min, sec)
+{
+ while (--mth >= 1)
+ day += days_per_month(mth, yrs);
+ while (--yrs >= 1970)
+ day += 365 + leap(yrs);
+ return (((((day - 1) * 24) + hrs) * 60) + min) * 60 + sec;
+}
+
+function to_date(fmt, sec)
+{
+ for (yrs = 1970; sec >= (s = 3600 * 24 * (365 + leap(yrs))); yrs++)
+ sec -= s;
+ for (mth = 1; sec >= (s = 3600 * 24 * days_per_month(mth, yrs)); mth++)
+ sec -= s;
+ for (day = 1; sec >= (s = 3600 * 24); day++)
+ sec -= s;
+ for (hrs = 0; sec >= 3600; hrs++)
+ sec -= 3600;
+ for (min = 0; sec >= 60; min++)
+ sec -= 60;
+ return sprintf(fmt, yrs, mth, day, hrs, min, sec);
+}
+
+function date_ical(str, off) {
+ yrs = substr(str, 1, 4);
+ mth = substr(str, 5, 2);
+ day = substr(str, 7, 2);
+ hrs = substr(str, 10, 2);
+ min = substr(str, 12, 2);
+ return to_sec(yrs, mth, day, hrs, min, 0) - off;
+}
+
+function date_iso8601(date, off)
+{
+ yrs = substr(date, 1, 4);
+ mth = substr(date, 6, 2);
+ day = substr(date, 9, 2);
+ hrs = substr(date, 12, 2);
+ min = substr(date, 15, 2);
+ return to_sec(yrs, mth, day, hrs, min, 0) - off;
+}
+
+function swap(array, a, b)
+{
+ tmp = array[a];
+ array[a] = array[b];
+ array[b] = tmp;
+}
+
+function sort(array, beg, end)
+{
+ if (beg >= end) # end recursion
+ return;
+
+ a = beg + 1; # #1 is the pivot
+ b = end;
+ while (a < b) {
+ while (a < b && array[a] <= array[beg]) # beg: skip lesser
+ a++;
+ while (a < b && array[b] > array[beg]) # end: skip greater
+ b--;
+ swap(array, a, b); # found 2 misplaced
+ }
+
+ if (array[beg] > array[a]) # put the pivot back
+ swap(array, beg, a);
+
+ sort(array, beg, a - 1); # sort lower half
+ sort(array, a, end); # sort higher half
+}
+
+function parse_ical(list, off)
+{
+ FS = "[:;]";
+
+ while (getline) {
+ gsub("\\\\[ntr]", " ");
+ gsub("[ \t]*<[a-zA-Z0-9/]*>*[ \t]*", "");
+ gsub("\\\\", "");
+
+ if (match($0, "^ ")) {
+ event[type] = event[type] substr($0, 2, length($0) - 1);
+ } else {
+ type = $1;
+ i = index($0, ":");
+ event[type] = substr($0, i + 1, length($0) - i);
+ }
+
+ if ($0 ~ /END:VEVENT/)
+ list[++nb] = sprintf("%d\t%d\t%s\t%s\t%s\t%s",
+ date_ical(event["DTSTART"], off),
+ date_ical(event["DTEND"], off),
+ event["CATEGORIES"],
+ event["SUMMARY"],
+ event["LOCATION"],
+ event["DESCRIPTION"]);
+ }
+ sort(list, 1, nb);
+ return nb;
+}
+
+function txt(off)
+{
+ nb = parse_ical(list, off);
+ for (i = 1; i <= nb; i++) {
+ split(list[i], arr, "\t");
+ txt_one(arr[1], arr[2], arr[3], arr[4], arr[5], arr[6]);
+ }
+}
+
+function txt_one(beg, end, cat, sum, loc, des, off) {
+ b = to_date("%04d/%02d/%02d %02d:%02d", beg + off);
+ e = to_date("%04d/%02d/%02d %02d:%02d", end + off);
+ b_mth = substr(b, 1, 7);
+ b_day = substr(b, 9, 2);
+ e_day = substr(e, 9, 2);
+ b_hrs = substr(b, 12);
+ e_hrs = substr(e, 12);
+
+ printf("%s\n%2s %2s %s\n%2s %2s %s%s\n",
+ (b_mth != l_mth) ? ("\n[" b_mth "]\n") : (""),
+ (b_day != l_day) ? (b_day) : (""), b_hrs, sum,
+ (b_day != e_day) ? (e_day) : (""), e_hrs,
+ (cat) ? ("[" cat "] ") : (""), loc);
+
+ while ((line = substr(des, 1, 66)) != "") {
+ if (length(line) == 66)
+ sub(" +[^ ]*$", "", line);
+ printf(" %s\n", line);
+ des = substr(des, length(line) + 1);
+ sub("^ *", "", des);
+ }
+ l_mth = b_mth;
+ l_day = b_day;
+}
+
+function tsv(off)
+{
+ n = parse_ical(list, off);
+ for (i = 0; i < n; i++)
+ print(list[i]);
+}
+
+function usage()
+{
+ print("usage: agenda txt file.ics...");
+ print(" agenda tsv file.ics...");
+}
+
+BEGIN {
+ "date +%z" | getline off;
+ close("date +%z");
+ off = substr(off, 1, 3) * 3600;
+
+ if (ARGV[1] == "txt") {
+ ARGV[1] = ARGV[--ARGC];
+ txt(off);
+ } else if (ARGV[1] == "tsv") {
+ ARGV[1] = ARGV[--ARGC];
+ tsv(off);
+ } else {
+ usage();
+ }
+}
(DIR) diff --git a/agenda.1 b/agenda.1
@@ -0,0 +1,80 @@
+.Dd $Mdocdate: February 23 2018$
+.Dt AGENDA 1
+.Os
+.
+.
+.Sh NAME
+.
+.Nm agenda
+.Nd plain text agenda with ical support
+.
+.
+.Sh SYNOPSIS
+.
+.Nm Ic txt Op +- Ar offset Op Ar ics file...
+.Nm Ic tsv Op +- Ar offset Op Ar ics file...
+.
+.
+.Sh DESCRIPTION
+.
+.Nm
+displays iCalendar
+.Pq ical, Pa .ics
+files created by.
+.
+.Bl -tag -width indent
+.
+.It Nm Ic txt Op +- Ar offset Op Ar ics file...
+Display the agenda(s)
+.Ar file
+as plain text sorted by date.
+.
+.It Nm Ic tsv Op +- Ar offset Op Ar ics file...
+Display the agenda(s)
+.Ar file
+as a tab-separated values
+.Pq tsv
+one entry per line, with the following fields in order:
+.
+.Bl -tag -width xDESCRIPTIONx -compact
+.
+.It Dq Li DTSTART
+begin date as an UNIX timestamp
+.
+.It Dq Li DTEND
+end date as an UNIX timestamp
+.
+.It Dq Li CATEGORY
+category
+.
+.It Dq Li SUMMARY
+symmary
+.
+.It Dq Li LOCATION
+location
+.
+.It Dq Li DESCRIPTION
+description
+.
+.El
+.
+.
+.Sh ENVIRONMENT
+.
+.Bl -tag -width 6n
+.
+.It Ev TZ
+Timezone to use for printing the dates.
+.
+.El
+.
+.
+.Sh SEE ALSO
+.
+.Xr calendar 1 ,
+.Xr date 1 ,
+.
+.
+.Sh AUTHORS
+.
+.An Josuah Demangeon Aq Mt mail@josuah.net