URI: 
       rename the project ics2txt - ics2txt - convert icalendar .ics file to plain text
  HTML git clone git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ics2txt
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
       ---
   DIR commit 481f690766d5999510f088b675ee9038f2007754
   DIR parent d587bdf097f3d058457675df00434427fb664976
  HTML Author: Josuah Demangeon <mail@josuah.net>
       Date:   Sat,  5 May 2018 22:22:31 +0200
       
       rename the project ics2txt
       
       'agenda' was too generic (name clash?), and it is not only a one-way
       conversion tool so ics2txt explains everything in a breeze.
       
       Diffstat:
         M Makefile                            |       4 ++--
         D agenda                              |     183 -------------------------------
         D agenda.1                            |      81 ------------------------------
         A ics2txt                             |     183 +++++++++++++++++++++++++++++++
         A ics2txt.1                           |      81 ++++++++++++++++++++++++++++++
       
       5 files changed, 266 insertions(+), 266 deletions(-)
       ---
   DIR diff --git a/Makefile b/Makefile
       @@ -1,5 +1,5 @@
       -BIN        = agenda
       -MAN1        = agenda.1
       +BIN        = ics2txt
       +MAN1        = ics2txt.1
        
        all:
        
   DIR diff --git a/agenda b/agenda
       @@ -1,183 +0,0 @@
       -#!/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("\r", " "); gsub("\\\\[ntr]", "  "); gsub("\\\\", "");
       -                gsub("^ *", ""); gsub(" *$", "");
       -                gsub(" *<[a-zA-Z0-9/]*>* *", "");
       -
       -                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_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);
       -                des = substr(des, length(line) + 2);
       -                sub("^ *", "", line);
       -                sub("^ *", "", des);
       -                printf("           %s\n", line);
       -        }
       -        l_mth = b_mth;
       -        l_day = b_day;
       -}
       -
       -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 tsv(off)
       -{
       -        nb = parse_ical(list, off);
       -        for (i = 0; i < nb; 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
       @@ -1,81 +0,0 @@
       -.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 Oo +- Oc Ns Ar offset Op Ar ics file...
       -.Nm Ic tsv Oo +- Oc Ns Ar offset Op Ar ics file...
       -.
       -.
       -.Sh DESCRIPTION
       -.
       -.Nm
       -displays iCalendar 
       -.Pq ical, Pa .ics
       -.Ar file
       -or stdin if not specified in the format described by the command:
       -.
       -.Bl -tag -width indent
       -.
       -.It Ic txt
       -Display the agenda(s)
       -.Ar file
       -as plain text sorted by date.
       -.
       -.It Ic tsv
       -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
   DIR diff --git a/ics2txt b/ics2txt
       @@ -0,0 +1,183 @@
       +#!/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("\r", " "); gsub("\\\\[ntr]", "  "); gsub("\\\\", "");
       +                gsub("^ *", ""); gsub(" *$", "");
       +                gsub(" *<[a-zA-Z0-9/]*>* *", "");
       +
       +                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_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);
       +                des = substr(des, length(line) + 2);
       +                sub("^ *", "", line);
       +                sub("^ *", "", des);
       +                printf("           %s\n", line);
       +        }
       +        l_mth = b_mth;
       +        l_day = b_day;
       +}
       +
       +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 tsv(off)
       +{
       +        nb = parse_ical(list, off);
       +        for (i = 0; i < nb; i++)
       +                print(list[i]);
       +}
       +
       +function usage()
       +{
       +        print("usage: ics2txt txt file.ics...");
       +        print("       ics2txt 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/ics2txt.1 b/ics2txt.1
       @@ -0,0 +1,81 @@
       +.Dd $Mdocdate: February 23 2018$
       +.Dt AGENDA 1
       +.Os
       +.
       +.
       +.Sh NAME
       +.
       +.Nm ics2txt
       +.Nd convert ics file to plain text or TSV
       +.
       +.
       +.Sh SYNOPSIS
       +.
       +.Nm Ic txt Oo +- Oc Ns Ar offset Op Ar ics file...
       +.Nm Ic tsv Oo +- Oc Ns Ar offset Op Ar ics file...
       +.
       +.
       +.Sh DESCRIPTION
       +.
       +.Nm
       +displays iCalendar 
       +.Pq ical, Pa .ics
       +.Ar file
       +or stdin if not specified in the format described by the command:
       +.
       +.Bl -tag -width indent
       +.
       +.It Ic txt
       +Display the ics2txt(s)
       +.Ar file
       +as plain text sorted by date.
       +.
       +.It Ic tsv
       +Display the ics2txt(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