improvement: lib's parse() now uses arguments, added newline escape

This commit is contained in:
Ämin Baumeler 2025-06-27 20:37:11 +02:00
parent 8a23f451b3
commit 80dbfc0264
3 changed files with 33 additions and 16 deletions

View File

@ -57,8 +57,8 @@ BEGIN {
} }
BEGINFILE { inside = 0; rs = 0; dur = 0; summary = ""; start = "ERROR"; end = "ERROR" } BEGINFILE { inside = 0; rs = 0; dur = 0; summary = ""; start = "ERROR"; end = "ERROR" }
/^END:VEVENT/ { print "~", start, dur ? start " " end : end, title(start, summary), fn(FILENAME); nextfile } /^END:VEVENT/ { print "~", start, dur ? start " " end : end, title(start, summary), fn(FILENAME); nextfile }
/^DTSTART/ && inside { start = parse() } /^DTSTART/ && inside { start = parse_dt(getparam($0), getcontent($0)) }
/^DTEND/ && inside { end = parse() } /^DTEND/ && inside { end = parse_dt(getparam($0), getcontent($0)) }
/^DURATION/ && inside { end = parse_duration($NF); dur = 1 } /^DURATION/ && inside { end = parse_duration($NF); dur = 1 }
/^[^ ]/ && rs { rs = 0 } /^[^ ]/ && rs { rs = 0 }
/^ / && rs { summary = summary substr($0, 2) } /^ / && rs { summary = summary substr($0, 2) }

View File

@ -48,8 +48,8 @@ BEGIN {
} }
} }
/^END:VEVENT/ && inside { print_data(start, dur, end, summary); exit } /^END:VEVENT/ && inside { print_data(start, dur, end, summary); exit }
/^DTSTART/ && inside { start = parse() } /^DTSTART/ && inside { start = parse_dt(getparam($0), getcontent($0)) }
/^DTEND/ && inside { end = parse() } /^DTEND/ && inside { end = parse_dt(getparam($0), getcontent($0)) }
/^DURATION/ && inside { end = parse_duration($NF); dur = 1 } /^DURATION/ && inside { end = parse_duration($NF); dur = 1 }
/^STATUS/ && inside { status = $NF } /^STATUS/ && inside { status = $NF }
/^[^ ]/ && rs { rs = 0 } /^[^ ]/ && rs { rs = 0 }

View File

@ -5,6 +5,7 @@
function escape(str) function escape(str)
{ {
gsub("\\\\", "\\\\", str) gsub("\\\\", "\\\\", str)
gsub("\\n", "\\n", str)
gsub(";", "\\;", str) gsub(";", "\\;", str)
gsub(",", "\\,", str) gsub(",", "\\,", str)
return str return str
@ -57,6 +58,17 @@ function unescape(str, i, c, c2, res) {
return res return res
} }
# Isolate parameter part of an iCalendar line.
#
# @input str: String
# @return: Parameter part
function getparam(str, i) {
i = index(str, ";")
if (!i)
return ""
return substr(str, i + 1, index(str, ":") - i)
}
# Isolate content part of an iCalendar line, and unescape. # Isolate content part of an iCalendar line, and unescape.
# #
# @input str: String # @input str: String
@ -65,22 +77,27 @@ function getcontent(str) {
return unescape(substr(str, index(str, ":") + 1)) return unescape(substr(str, index(str, ":") + 1))
} }
# Time-zone aware parsing of the date/date-time entry at the current record. # Time-zone aware parsing of DTSTART or DTEND entries.
# #
# @local variables: dt # @local variables: tz
# @input dt_param: iCalendar DTSTART or DTEND parameter string
# @input dt_content: iCalendar DTSTART or DTEND content string
# @return: date or date-time string that can be used in date (1) # @return: date or date-time string that can be used in date (1)
function parse( dt) { function parse_dt(dt_param, dt_content, tz, a, i, k) {
# Get timezone information if (dt_param) {
for (i=2; i<NF-1; i+=2) { split(dt_param, a, ";")
if ($i == "TZID") { for (i in a) {
dt = "TZ=\"" $(i+1) "\" " k = index(a[i], "=")
if (substr(a[i], 1, k-1) == "TZID") {
tz = "TZ=\"" substr(a[i], k + 1) "\" "
break break
} }
} }
}
# Get date/date-time # Get date/date-time
return length($NF) == 8 ? return length(dt_content) == 8 ?
dt $NF : dt dt_content :
dt gensub(/^([0-9]{8})T([0-9]{2})([0-9]{2})([0-9]{2})(Z)?$/, "\\1 \\2:\\3:\\4\\5", "g", $NF) dt gensub(/^([0-9]{8})T([0-9]{2})([0-9]{2})([0-9]{2})(Z)?$/, "\\1 \\2:\\3:\\4\\5", "g", dt_content)
} }
# Map iCalendar duration specification into the format to be used in date (1). # Map iCalendar duration specification into the format to be used in date (1).