rename the project ics2txt - ics2txt - convert icalendar .ics file to plain text | |
git clone git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
--- | |
commit 481f690766d5999510f088b675ee9038f2007754 | |
parent d587bdf097f3d058457675df00434427fb664976 | |
Author: Josuah Demangeon <[email protected]> | |
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(-) | |
--- | |
diff --git a/Makefile b/Makefile | |
@@ -1,5 +1,5 @@ | |
-BIN = agenda | |
-MAN1 = agenda.1 | |
+BIN = ics2txt | |
+MAN1 = ics2txt.1 | |
all: | |
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 les… | |
- a++; | |
- while (a < b && array[b] > array[beg]) # end: skip grea… | |
- 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, su… | |
- (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(); | |
- } | |
-} | |
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 [email protected] | |
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 les… | |
+ a++; | |
+ while (a < b && array[b] > array[beg]) # end: skip grea… | |
+ 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, su… | |
+ (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(); | |
+ } | |
+} | |
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 [email protected] |