Introduction
Introduction Statistics Contact Development Disclaimer Help
split the role of parsing and formatting through a simple TSV intermediate form…
git clone git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws…
Log
Files
Refs
Tags
README
---
commit 37b4e99568c76d39376244f8f85fcf0dcfc95bd9
parent 7ef52e239bfc8757d45f3d868920dba32dcb5b61
Author: Josuah Demangeon <[email protected]>
Date: Mon, 2 Mar 2020 01:15:03 +0100
split the role of parsing and formatting through a simple TSV intermediate form…
Diffstat:
M Makefile | 2 +-
M README | 84 ++---------------------------…
D ics2txt | 168 -----------------------------…
A ics2txt-back | 81 ++++++++++++++++++++++++++++++
A ics2txt-ics | 91 +++++++++++++++++++++++++++++…
A ics2txt-tsv | 64 +++++++++++++++++++++++++++++…
A ics2txt-txt | 97 ++++++++++++++++++++++++++++++
M ics2txt.1 | 49 +++++++++++++++++++++++------…
8 files changed, 374 insertions(+), 262 deletions(-)
---
diff --git a/Makefile b/Makefile
@@ -1,4 +1,4 @@
-BIN = ics2txt
+BIN = ics2txt-*
MAN1 = ics2txt.1
all:
diff --git a/README b/README
@@ -1,83 +1,7 @@
-ics2txt
-=======
+sical
+=====
-*ics2txt* is an awk scripts to deal with iCal [1] format to publish,
-display and convert *.ics files.
+*sical* is set of awk scripts to deal with iCal [1] format to publish,
+display and convert *.ics files, though a simple central TSV format.
[1]: https://tools.ietf.org/rfc/rfc5545.txt
-
-Sample output:
-
-2019-02-02
-
-07:30 Welcome to FOSDEM 2019
-07:55 Janson
- FOSDEM welcome and opening talk.
-
-08:30 The State of Go
-09:00 UD2.120 (Chavanne)
- Go 1.12 is planned to be released in February 2019 and this talk
- covers what's coming up with it.We'll talk about Go Modules, the
- proposals for Go 2, and all of the new things you might have missed.
-
-09:30 HTTP/3
-10:30 UD2.208 (Decroly)
- HTTP/3 is the next coming HTTP version. This time TCP is replaced by
- the new transport protocol QUIC and things are different yet again!
-
-10:05 Minimalism matters
-10:25 K.4.201
- Minimalism matters in computing. To trust systems we need to be able
- to understand them completely. Openssl heartbleed disaster was caused
- by code no longer being minimalistic, even if it is free and open
- source software. Hardware manfucturers and proprietary closed source
- solutions make things even worse with expectations of intrusion to
- privacy and backdoors if we don't aim for free hardware, software and
- minimalism. In this talk I will discuss minimalism in a broad context
- and narrow down on what the free software community can aim for.
-
-2019-02-03
-
-07:55 Microkernel virtualization under one roof
-08:30 AW1.121
- Today's off-the-shell virtualization solution is ridden with
- complexity. Application of virtualization call for trustworthy
- solutions. Complexity defeats trust.Microkernels with virtualization
- extensions and user-level VMMs on top are a approach to mitigate
- complexity. Modern microkernels like seL4, the NOVA microhypervisor,
- Genode's -hw- kernel or Fiasco.OC are such promising candidates.
- Fortunately and unfortunately, the diversity come with fragmentation
- of the small microkernel community. There are several VMMs for each
- platform tight to a specific microkernel, rendering it unusable
- across various kernels.Genode supports several kernels already, so
- that unification of virtualization interfaces for VMMs across kernels
- seem to come into reach. Does it ? The talk will cover the venture
- and current state of harmonization hardware-assisted virtualization
- interfaces to fit into the Genode OS framework.
-
-14:40 FOSDEM infrastructure review
-14:55 H.2215 (Ferrer)
- Informational and fun.
-
-15:00 2019 - Fifty years of Unix and Linux advances
-15:50 Janson
- 2019 marks the fiftieth anniversary of Unix, but it is also the
- fiftieth anniversary of the ArpaNet/Internet, and people walking on
- the moon. It marks the 50th anniversary of Woodstock, the beginning
- of America's LGBTQ movement at the Stonewall Inn in New York City,
- and maddog wrote his first program fifty years ago. It was also in
- 1969 that he shaved for the last time.2019 marks the 30th year of the
- World Wide Web, the 25th anniversary of V1.0 of the Linux kernel, and
- of many GNU/Linux distributions starting. 2019 also marks the
- twentieth anniversary of the Linux Professional Institute.All of
- these years, and anniversaries.....but why has Unix (and its younger
- offspring Linux) lasted so long? What was different about Unix that
- caused it to survive and flourish? Why is it important today, and
- how can we take it further? How should we celebrate 2019? While
- maddog does not have all the answers, he tries to make the answers he
- does have interesting and fun to know.
-
-15:55 Closing FOSDEM 2019
-16:00 Janson
- Some closing words. Don't miss it!
-
diff --git a/ics2txt b/ics2txt
@@ -1,168 +0,0 @@
-#!/usr/bin/awk -f
-
-# display iCal entries 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, offset) {
- 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)
- if (substr(str, 16, 1) == "Z")
- return to_sec(yrs, mth, day, hrs, min, 0)
- else
- return to_sec(yrs, mth, day, hrs, min, 0) - offset
-}
-
-function date_iso8601(date, offset)
-{
- 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) - offset
-}
-
-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, offset)
-{
- 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[++n] = sprintf("%d\t%d\t%s\t%s\t%s\t%s",
- date_ical(event["DTSTART"], offset),
- date_ical(event["DTEND"], offset),
- event["SUMMARY"],
- event["LOCATION"],
- event["DESCRIPTION"])
- }
- sort(list, 1, n)
- return n
-}
-
-function print_fold(prefix, s, n)
-{
- while (s != "") {
- line = substr(s, 1, n)
- if (length(s) > n) sub(" +[^ \t\r\n]*$", "", line)
- print prefix line
- s = substr(s, length(line) + 2)
- }
-}
-
-function print_entry(beg, end, summary, location, description, offset)
-{
- b = to_date("%04d-%02d-%02d %02d:%02d", beg + offset)
- e = to_date("%04d-%02d-%02d %02d:%02d", end + offset)
- date = substr(b, 1, 10)
- hour_beg = substr(b, 12)
- hour_end = substr(e, 12)
-
- if (date != last_date) print "\n" date
- print "\n" hour_beg "\t" summary
- done = 0
- if (category) printf("%s\t%s\n", !done++ ? hour_end : "", category)
- if (location) printf("%s\t%s\n", !done++ ? hour_end : "", location)
- if (description) {
- printf("%s", !done++ ? hour_end : "")
- print_fold("\t", description, 70)
- }
-
- last_date = date
-}
-
-BEGIN {
- "date +%z" | getline offset_str
- close("date +%z")
-
- offset = substr(offset_str, 2, 2) * 3600
- offset += substr(offset_str, 4, 2) * 60
- if (substr(offset_str, 1, 1) == "-")
- offset *= -1
-
- n = parse_ical(list, offset)
- for (i = 1; i <= n; i++) {
- split(list[i], arr, "\t")
- print_entry(arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], of…
- }
- print ""
-}
diff --git a/ics2txt-back b/ics2txt-back
@@ -0,0 +1,81 @@
+#!/usr/bin/awk -f
+
+function isleap(year)
+{
+ return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)
+}
+
+function mdays(mon, year)
+{
+ return (mon == 2) ? (28 + isleap(year)) : (30 + (mon + (mon > 7)) % 2)
+}
+
+function timegm(year, mon, mday, hour, min, sec)
+{
+ while (--mon >= 1)
+ mday += mdays(mon, year)
+ while (--year >= 1970)
+ mday += 365 + isleap(year)
+ return (((((mday - 1) * 24) + hour) * 60) + min) * 60 + sec
+}
+
+function date_text(str, offset,
+ year, mon, mday, hour, min)
+{
+ year = substr(str, 1, 4)
+ mon = substr(str, 6, 2)
+ mday = substr(str, 9, 2)
+ hour = substr(str, 12, 2)
+ min = substr(str, 15, 2)
+ return timegm(year, mon, mday, hour, min, 0) - offset
+}
+
+{
+ gsub(/\t/, " ")
+}
+
+/^TZ[+-]/ {
+ hour = substr($0, 4, 2)
+ min = substr($0, 6, 2)
+ tzoffset = substr(zone, 3, 1) hour * 3600 + min * 60
+ next
+}
+
+/^[0-9]+-[0-9]+-[0-9]+ / {
+ time = date_text($1 " " $2, tzoffset)
+ row++
+}
+
+/^ / {
+ d = $0
+ sub(/^ */, "", d)
+ des = des " " d
+}
+
+/^$/ {
+ if (beg)
+ printf "%d\t%d\t%s\t%s\t%s\t%s\n", beg, end, cat, loc, sum, des
+ beg = end = cat = loc = sum = des = ""
+}
+
+row == 1 {
+ beg = time
+ sum = $0
+ sub(/^[^ ]+ +[^ ]+ +/, "", sum)
+}
+
+row == 2 {
+ end = time
+
+ line = $0
+ sub(/^[^ ]+ +[^ ]+ +/, "", line)
+
+ cat = line
+ sub(/\].*/, "", cat)
+ sub(/^\[/, "", cat)
+
+ loc = line
+ sub(/[^]]*\] */, "", loc)
+
+ row = 0
+}
diff --git a/ics2txt-ics b/ics2txt-ics
@@ -0,0 +1,91 @@
+#!/usr/bin/awk -f
+
+function isleap(year)
+{
+ return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)
+}
+
+function mdays(mon, year)
+{
+ return (mon == 2) ? (28 + isleap(year)) : (30 + (mon + (mon > 7)) % 2)
+}
+
+# Split the time in seconds since epoch into a table, with fields
+# named as with gmtime(3): tm["year"], tm["mon"], tm["mday"],
+# tm["hour"], tm["min"], tm["sec"]
+function gmtime(sec, tm,
+ s)
+{
+ tm["year"] = 1970
+ while (sec >= (s = 86400 * (365 + isleap(tm["year"])))) {
+ tm["year"]++
+ sec -= s
+ }
+
+ tm["mon"] = 1
+ while (sec >= (s = 86400 * mdays(tm["mon"], tm["year"]))) {
+ tm["mon"]++
+ sec -= s
+ }
+
+ tm["mday"] = 1
+ while (sec >= (s = 86400)) {
+ tm["mday"]++
+ sec -= s
+ }
+
+ tm["hour"] = 0
+ while (sec >= 3600) {
+ tm["hour"]++
+ sec -= 3600
+ }
+
+ tm["min"] = 0
+ while (sec >= 60) {
+ tm["min"]++
+ sec -= 60
+ }
+
+ tm["sec"] = sec
+}
+
+function print_fold(prefix, s, n)
+{
+ while (s != "") {
+ line = substr(s, 1, n)
+ if (length(s) > n) sub(" +[^ \t\r\n]*$", "", line)
+ print prefix line
+ s = substr(s, length(line) + 2)
+ }
+}
+
+BEGIN {
+ print "BEGIN:VCALENDAR"
+ print "VERSION:2.0"
+ print "CALSCALE:GREGORIAN"
+ print "METHOD:PUBLISH"
+}
+
+{
+ split($0, a, "\t")
+ gmtime(a[1] + offset, beg)
+ gmtime(a[2] + offset, end)
+ cat = a[3]; loc = a[4]; sum = a[5]; des = a[6]
+
+ print ""
+ print "BEGIN:VEVENT"
+ printf "DTSTART:%04d%02d%02dT%02d%02d00Z\n",
+ beg["year"], beg["mon"], beg["mday"], beg["hour"], beg["min"]
+ printf "DTEND:%04d%02d%02dT%02d%02d00Z\n",
+ end["year"], end["mon"], end["mday"], end["hour"], end["min"]
+ print "SUMMARY:" sum
+ print "DESCRIPTION:" des
+ print "CATEGORIES:" cat
+ print "LOCATION:" loc
+ print "END:VEVENT"
+}
+
+END {
+ print ""
+ print "END:VCALENDAR"
+}
diff --git a/ics2txt-tsv b/ics2txt-tsv
@@ -0,0 +1,64 @@
+#!/usr/bin/awk -f
+
+function isleap(year)
+{
+ return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)
+}
+
+function mdays(mon, year)
+{
+ return (mon == 2) ? (28 + isleap(year)) : (30 + (mon + (mon > 7)) % 2)
+}
+
+function timegm(year, mon, mday, hour, min, sec)
+{
+ while (--mon >= 1)
+ mday += mdays(mon, year)
+ while (--year >= 1970)
+ mday += 365 + isleap(year)
+ return (((((mday - 1) * 24) + hour) * 60) + min) * 60 + sec
+}
+
+function date_ical(str, offset,
+ year, mon, mday, hour, min)
+{
+ year = substr(str, 1, 4)
+ mon = substr(str, 5, 2)
+ mday = substr(str, 7, 2)
+ hour = substr(str, 10, 2)
+ min = substr(str, 12, 2)
+ offset = (substr(str, 16, 1) == "Z" ? 0 : offset)
+ return timegm(year, mon, mday, hour, min, 0) - offset
+}
+
+BEGIN {
+ "date +%z" | getline offset_str
+ close("date +%z")
+ hour = substr($0, 4, 2)
+ min = substr($0, 6, 2)
+ tzoffset = substr(zone, 3, 1) hour * 3600 + min * 60
+
+ FS = "[:;]"
+}
+
+{
+ gsub("\r", ""); gsub("\t", "\\\\t")
+ gsub("^ *", ""); 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/)
+ printf("%d\t%d\t%s\t%s\t%s\t%s\n",
+ date_ical(event["DTSTART"], offset),
+ date_ical(event["DTEND"], offset),
+ event["CATEGORIES"],
+ event["LOCATION"],
+ event["SUMMARY"],
+ event["DESCRIPTION"])
+}
diff --git a/ics2txt-txt b/ics2txt-txt
@@ -0,0 +1,97 @@
+#!/usr/bin/awk -f
+
+function isleap(year)
+{
+ return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)
+}
+
+function mdays(mon, year)
+{
+ return (mon == 2) ? (28 + isleap(year)) : (30 + (mon + (mon > 7)) % 2)
+}
+
+# Split the time in seconds since epoch into a table, with fields
+# named as with gmtime(3): tm["year"], tm["mon"], tm["mday"],
+# tm["hour"], tm["min"], tm["sec"]
+function gmtime(sec, tm,
+ s)
+{
+ tm["year"] = 1970
+ while (sec >= (s = 86400 * (365 + isleap(tm["year"])))) {
+ tm["year"]++
+ sec -= s
+ }
+
+ tm["mon"] = 1
+ while (sec >= (s = 86400 * mdays(tm["mon"], tm["year"]))) {
+ tm["mon"]++
+ sec -= s
+ }
+
+ tm["mday"] = 1
+ while (sec >= (s = 86400)) {
+ tm["mday"]++
+ sec -= s
+ }
+
+ tm["hour"] = 0
+ while (sec >= 3600) {
+ tm["hour"]++
+ sec -= 3600
+ }
+
+ tm["min"] = 0
+ while (sec >= 60) {
+ tm["min"]++
+ sec -= 60
+ }
+
+ tm["sec"] = sec
+}
+
+function print_fold(prefix, s, n)
+{
+ while (s != "") {
+ line = substr(s, 1, n)
+ if (length(s) > n) sub(" +[^ \t\r\n]*$", "", line)
+ print prefix line
+ s = substr(s, length(line) + 2)
+ }
+}
+
+BEGIN {
+ cmd = "date +%z"
+ cmd | getline zone
+ close(cmd)
+
+ hour = substr(zone, 2, 2)
+ min = substr(zone, 4, 2)
+
+ offset = (substr(zone, 1, 1) "1") * (hour * 3600 + min * 60)
+ print "TZ" zone
+}
+
+{
+ split($0, a, "\t")
+ gmtime(a[1] + offset, beg)
+ gmtime(a[2] + offset, end)
+ cat = a[3]; loc = a[4]; sum = a[5]; des = a[6]
+
+ print ""
+ printf "%04d-%02d-%02d %02d:%02d ",
+ beg["year"], beg["mon"], beg["mday"], beg["hour"], beg["min"]
+ print sum
+
+ printf "%04d-%02d-%02d %02d:%02d ",
+ end["year"], end["mon"], end["mday"], end["hour"], end["min"]
+ print "[" cat "] " loc
+
+ sub("^ *", "", des)
+ sub(" *$", "", des)
+ if (des)
+ print_fold(" ", des, 80)
+}
+
+END {
+ print ""
+}
diff --git a/ics2txt.1 b/ics2txt.1
@@ -1,4 +1,4 @@
-.Dd $Mdocdate: May 21 2018$
+.Dd $Mdocdate: Mar 1 2020$
.Dt ICS2TXT 1
.Os
.
@@ -6,32 +6,54 @@
.Sh NAME
.
.Nm ics2txt
-.Nd convert ics file to a simple plain text format
+.Nd convert ics file to simpler tsv or txt formats
.
.
.Sh SYNOPSIS
.
-.Nm Ar ics-file...
-.
+.Nm ics2txt-tsv Ar <file.ics >file.tsv
+.Nm ics2txt-txt Ar <file.tsv >file.txt
+.Nm ics2txt-ics Ar <file.tsv >file.ics
+.Nm ics2txt-back Ar <file.txt >file.tsv
.
.Sh DESCRIPTION
.
.Nm
-displays iCalendar
-.Pq ical, Pa .ics
-.Ar file
-or stdin if not specified in the format described by the command:
+convert iCalendar
+.Pq ical
+.Ar file.ics
+or stdin if not specified to a tab separated value format, with one
+line per entry, and one column per field:
+.
+.Bl -offset 1n -width 1n -enum -compact
+.
+.It
+Begining (epoch)
.
+.It
+End (epoch)
.
-.Sh ENVIRONMENT
+.It
+Category
.
-.Bl -tag -width 6n
+.It
+Location
.
-.It Ev TZ
-Timezone to use for printing the dates.
+.It
+Summary
+.
+.It description
+description
.
.El
.
+.Pp
+The
+.Sq \en
+and
+.Sq \et
+charaters may represent newlines and tabs.
+.
.
.Sh SEE ALSO
.
@@ -39,6 +61,7 @@ Timezone to use for printing the dates.
.Xr calendar 1 ,
.Xr date 1
.
+.
.Sh STANDARDS
.
.Rs
@@ -51,4 +74,4 @@ Timezone to use for printing the dates.
.
.Sh AUTHORS
.
-.An Josuah Demangeon Aq Mt [email protected]
+.An Josuah Demangeon Aq Mt [email protected]
You are viewing proxied material from bitreich.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.