Compare commits
5 Commits
dev
...
76fa32da39
| Author | SHA1 | Date | |
|---|---|---|---|
| 76fa32da39 | |||
| 609d9712a6 | |||
| de4650d1ac | |||
| 7656da2a71 | |||
| 6c78213587 |
12
README.md
12
README.md
@@ -13,14 +13,22 @@ with a CalDav server, such as [Radicale](https://radicale.org/), and a synchroni
|
|||||||
|
|
||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
Download the file `fzf-vjour` from the [latest release](https://github.com/baumea/fzf-vjour/releases/latest), or run `./scripts/build.sh`, then
|
|
||||||
copy `fzf-vjour` to your preferred location, e.g., `~/.local/bin`, and make it executable.
|
### Manual
|
||||||
|
|
||||||
|
Run `./scripts/build.sh`, then copy `fzf-vjour` to your preferred location, e.g., `~/.local/bin`, and make it executable.
|
||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
This is a POSIX script with inline `awk` elements.
|
This is a POSIX script with inline `awk` elements.
|
||||||
Make sure you have [fzf](https://github.com/junegunn/fzf) installed.
|
Make sure you have [fzf](https://github.com/junegunn/fzf) installed.
|
||||||
I also suggest to install [batcat](https://github.com/sharkdp/bat) for colorful previews.
|
I also suggest to install [batcat](https://github.com/sharkdp/bat) for colorful previews.
|
||||||
|
|
||||||
|
### Arch Linux
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yay -S fzf-vjour-git
|
||||||
|
```
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
--------------
|
--------------
|
||||||
This application is configured with a file located at `$HOME/.config/fzf-vjour/config`.
|
This application is configured with a file located at `$HOME/.config/fzf-vjour/config`.
|
||||||
|
|||||||
@@ -1,34 +1,41 @@
|
|||||||
function getcontent(content_line, prop)
|
# unescape
|
||||||
{
|
# Isolate and unescape the content part of an iCalendar line.
|
||||||
return substr(content_line[prop], index(content_line[prop], ":") + 1);
|
#
|
||||||
|
# @local variables: tmp
|
||||||
|
# @input str: String
|
||||||
|
# @return: Unescaped string
|
||||||
|
function unescape(str) {
|
||||||
|
gsub("\\\\n", "\n", str)
|
||||||
|
gsub("\\\\N", "\n", str)
|
||||||
|
gsub("\\\\,", ",", str)
|
||||||
|
gsub("\\\\;", ";", str)
|
||||||
|
gsub("\\\\\\\\", "\\", str)
|
||||||
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
function storetext_line(content_line, c, prop)
|
# getcontent
|
||||||
{
|
# Isolate content part of an iCalendar line, and unescape.
|
||||||
c[prop] = getcontent(content_line, prop);
|
#
|
||||||
gsub("\\\\n", "\n", c[prop]);
|
# @input str: String
|
||||||
gsub("\\\\N", "\n", c[prop]);
|
# @return: Unescaped content part
|
||||||
gsub("\\\\,", ",", c[prop]);
|
function getcontent(str) {
|
||||||
gsub("\\\\;", ";", c[prop]);
|
return unescape(substr(str, index(str, ":") + 1))
|
||||||
gsub("\\\\\\\\", "\\", c[prop]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BEGIN { FS = "[:;]"; }
|
BEGIN { FS = "[:;]"; }
|
||||||
/^BEGIN:(VJOURNAL|VTODO)/ { type = $2 }
|
/^BEGIN:(VJOURNAL|VTODO)/ { type = $2 }
|
||||||
/^END:/ && $2 == type { exit }
|
/^END:/ && $2 == type { exit }
|
||||||
/^(CATEGORIES|DESCRIPTION|SUMMARY|DUE)/ { prop = $1; content_line[prop] = $0; next; }
|
/^(CATEGORIES|DESCRIPTION|SUMMARY|DUE)/ { prop = $1; c[prop] = $0; next; }
|
||||||
/^[^ ]/ && prop { prop = ""; next; }
|
/^[^ ]/ && prop { prop = ""; next; }
|
||||||
/^ / && prop { content_line[prop] = content_line[prop] substr($0, 2); next; }
|
/^ / && prop { c[prop] = c[prop] substr($0, 2); next; }
|
||||||
|
|
||||||
END {
|
END {
|
||||||
if (!type) {
|
if (!type)
|
||||||
exit
|
exit
|
||||||
}
|
|
||||||
# Process content lines
|
# Process content lines
|
||||||
storetext_line(content_line, c, "CATEGORIES" );
|
c["CATEGORIES"] = getcontent(c["CATEGORIES"])
|
||||||
storetext_line(content_line, c, "DESCRIPTION");
|
c["DESCRIPTION"] = getcontent(c["DESCRIPTION"])
|
||||||
storetext_line(content_line, c, "SUMMARY" );
|
c["SUMMARY"] = getcontent(c["SUMMARY"])
|
||||||
storetext_line(content_line, c, "DUE" );
|
c["DUE"] = getcontent(c["DUE"])
|
||||||
# Print
|
# Print
|
||||||
if (c["DUE"])
|
if (c["DUE"])
|
||||||
print "::: <| " substr(c["DUE"], 1, 4) "-" substr(c["DUE"], 5, 2) "-" substr(c["DUE"], 7, 2);
|
print "::: <| " substr(c["DUE"], 1, 4) "-" substr(c["DUE"], 5, 2) "-" substr(c["DUE"], 7, 2);
|
||||||
|
|||||||
@@ -1,18 +1,36 @@
|
|||||||
|
# unescape
|
||||||
|
# Isolate and unescape the content part of an iCalendar line.
|
||||||
|
#
|
||||||
|
# @local variables: tmp
|
||||||
|
# @input str: String
|
||||||
|
# @return: Unescaped string
|
||||||
|
function unescape(str) {
|
||||||
|
gsub("\\\\n", "\n", str)
|
||||||
|
gsub("\\\\N", "\n", str)
|
||||||
|
gsub("\\\\,", ",", str)
|
||||||
|
gsub("\\\\;", ";", str)
|
||||||
|
gsub("\\\\\\\\", "\\", str)
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
# getcontent
|
||||||
|
# Isolate content part of an iCalendar line, and unescape.
|
||||||
|
#
|
||||||
|
# @input str: String
|
||||||
|
# @return: Unescaped content part
|
||||||
|
function getcontent(str) {
|
||||||
|
return unescape(substr(str, index(str, ":") + 1))
|
||||||
|
}
|
||||||
|
|
||||||
# print content of field `field`
|
# print content of field `field`
|
||||||
BEGIN { FS = ":"; regex = "^" field; }
|
BEGIN { FS = ":"; regex = "^" field; }
|
||||||
/^BEGIN:(VJOURNAL|VTODO)/ { type = $2 }
|
/^BEGIN:(VJOURNAL|VTODO)/ { type = $2 }
|
||||||
/^END:/ && $2 == type { exit }
|
/^END:/ && $2 == type { exit }
|
||||||
$0 ~ field { content = $0; next; }
|
$0 ~ field { line = $0; next; }
|
||||||
/^ / && content { content = content substr($0, 2); next; }
|
/^ / && line { line = line substr($0, 2); next; }
|
||||||
/^[^ ]/ && content { exit }
|
/^[^ ]/ && line { exit }
|
||||||
END {
|
END {
|
||||||
if (!type) { exit }
|
if (!type) { exit }
|
||||||
# Process content line
|
# Process line
|
||||||
content = substr(content, index(content, ":") + 1);
|
print getcontent(line)
|
||||||
gsub("\\\\n", "\n", content);
|
|
||||||
gsub("\\\\N", "\n", content);
|
|
||||||
gsub("\\\\,", ",", content);
|
|
||||||
gsub("\\\\;", ";", content);
|
|
||||||
gsub("\\\\\\\\", "\\", content);
|
|
||||||
print content;
|
|
||||||
}
|
}
|
||||||
|
|||||||
117
src/awk/list.awk
117
src/awk/list.awk
@@ -3,9 +3,28 @@
|
|||||||
# See https://datatracker.ietf.org/doc/html/rfc5545 for the RFC 5545 that
|
# See https://datatracker.ietf.org/doc/html/rfc5545 for the RFC 5545 that
|
||||||
# describes iCalendar, and its syntax
|
# describes iCalendar, and its syntax
|
||||||
|
|
||||||
function getcontent(content_line, prop)
|
# unescape
|
||||||
{
|
# Isolate and unescape the content part of an iCalendar line.
|
||||||
return substr(content_line[prop], index(content_line[prop], ":") + 1);
|
#
|
||||||
|
# @local variables: tmp
|
||||||
|
# @input str: String
|
||||||
|
# @return: Unescaped string
|
||||||
|
function unescape(str) {
|
||||||
|
gsub("\\\\n", "\n", str)
|
||||||
|
gsub("\\\\N", "\n", str)
|
||||||
|
gsub("\\\\,", ",", str)
|
||||||
|
gsub("\\\\;", ";", str)
|
||||||
|
gsub("\\\\\\\\", "\\", str)
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
# getcontent
|
||||||
|
# Isolate content part of an iCalendar line, and unescape.
|
||||||
|
#
|
||||||
|
# @input str: String
|
||||||
|
# @return: Unescaped content part
|
||||||
|
function getcontent(str) {
|
||||||
|
return unescape(substr(str, index(str, ":") + 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
function storetext_line(content_line, c, prop)
|
function storetext_line(content_line, c, prop)
|
||||||
@@ -19,23 +38,14 @@ function storetext_line(content_line, c, prop)
|
|||||||
#gsub(" ", "_", c[prop]);
|
#gsub(" ", "_", c[prop]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function storeinteger(content_line, c, prop)
|
# formatdate
|
||||||
{
|
# Generate kind-of-pretty date strings.
|
||||||
c[prop] = getcontent(content_line, prop);
|
#
|
||||||
c[prop] = c[prop] ? c[prop] : 0;
|
# @local variables: ts, ts_y, ts_m, ts_d, delta
|
||||||
}
|
# @input date: Date in the format YYYYMMDD
|
||||||
|
# @input todaystamp: Today, seconds since epoch
|
||||||
function storedatetime(content_line, c, prop)
|
# @return: string
|
||||||
{
|
function formatdate(date, todaystamp, ts, ts_y, ts_m, ts_d, delta)
|
||||||
c[prop] = getcontent(content_line, prop);
|
|
||||||
}
|
|
||||||
|
|
||||||
function storedate(content_line, c, prop)
|
|
||||||
{
|
|
||||||
c[prop] = substr(getcontent(content_line, prop), 1, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatdate(date, today, todaystamp, ts, ts_y, ts_m, ts_d, delta)
|
|
||||||
{
|
{
|
||||||
ts_y = substr(date, 1, 4);
|
ts_y = substr(date, 1, 4);
|
||||||
ts_m = substr(date, 5, 2);
|
ts_m = substr(date, 5, 2);
|
||||||
@@ -87,7 +97,6 @@ BEGIN {
|
|||||||
RED = "\033[1;31m";
|
RED = "\033[1;31m";
|
||||||
WHITE = "\033[1;97m";
|
WHITE = "\033[1;97m";
|
||||||
CYAN = "\033[1;36m";
|
CYAN = "\033[1;36m";
|
||||||
FAINT = "\033[2m";
|
|
||||||
OFF = "\033[m";
|
OFF = "\033[m";
|
||||||
|
|
||||||
# For date comparision
|
# For date comparision
|
||||||
@@ -99,7 +108,6 @@ BEGIN {
|
|||||||
BEGINFILE {
|
BEGINFILE {
|
||||||
type = "";
|
type = "";
|
||||||
prop = "";
|
prop = "";
|
||||||
delete content_line;
|
|
||||||
delete c;
|
delete c;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -114,7 +122,7 @@ BEGINFILE {
|
|||||||
|
|
||||||
/^(CATEGORIES|DESCRIPTION|PRIORITY|STATUS|SUMMARY|COMPLETED|DUE|DTSTART|DURATION|CREATED|DTSTAMP|LAST-MODIFIED)/ {
|
/^(CATEGORIES|DESCRIPTION|PRIORITY|STATUS|SUMMARY|COMPLETED|DUE|DTSTART|DURATION|CREATED|DTSTAMP|LAST-MODIFIED)/ {
|
||||||
prop = $1;
|
prop = $1;
|
||||||
content_line[prop] = $0;
|
c[prop] = $0;
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
/^[^ ]/ && prop {
|
/^[^ ]/ && prop {
|
||||||
@@ -122,7 +130,7 @@ BEGINFILE {
|
|||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
/^ / && prop {
|
/^ / && prop {
|
||||||
content_line[prop] = content_line[prop] substr($0, 2);
|
c[prop] = c[prop] substr($0, 2);
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,26 +154,33 @@ ENDFILE {
|
|||||||
collection = collection in collection2label ? collection2label[collection] : collection;
|
collection = collection in collection2label ? collection2label[collection] : collection;
|
||||||
|
|
||||||
# Process content lines
|
# Process content lines
|
||||||
storetext_line(content_line, c, "CATEGORIES" );
|
# strings
|
||||||
storetext_line(content_line, c, "DESCRIPTION" );
|
cat = unescape(getcontent(c["CATEGORIES"]))
|
||||||
storeinteger( content_line, c, "PRIORITY" );
|
des = unescape(getcontent(c["DESCRIPTION"]))
|
||||||
storetext_line(content_line, c, "STATUS" );
|
sta = unescape(getcontent(c["STATUS"]))
|
||||||
storetext_line(content_line, c, "SUMMARY" );
|
sum = unescape(getcontent(c["SUMMARY"]))
|
||||||
storedatetime( content_line, c, "COMPLETED" );
|
|
||||||
storedate( content_line, c, "DUE" );
|
# integers
|
||||||
storedate( content_line, c, "DTSTART" );
|
pri = unescape(getcontent(c["PRIORITY"]))
|
||||||
storedatetime( content_line, c, "DURATION" );
|
pri = pri ? pri + 0 : 0
|
||||||
storedatetime( content_line, c, "CREATED" );
|
|
||||||
storedatetime( content_line, c, "DTSTAMP" );
|
# dates
|
||||||
storedatetime( content_line, c, "LAST-MODIFIED");
|
due = substr(unescape(getcontent(c["DUE"])), 1, 8)
|
||||||
|
dts = substr(unescape(getcontent(c["DTSTART"])), 1, 8)
|
||||||
|
|
||||||
|
# date-times
|
||||||
|
com = unescape(getcontent(c["COMPLETED"]))
|
||||||
|
dur = unescape(getcontent(c["DURATION"]))
|
||||||
|
cre = unescape(getcontent(c["CREATED"]))
|
||||||
|
stp = unescape(getcontent(c["DTSTAMP"]))
|
||||||
|
lmd = unescape(getcontent(c["LAST-MODIFIED"]))
|
||||||
|
|
||||||
# Priority field, primarly used for sorting
|
# Priority field, primarly used for sorting
|
||||||
priotext = "";
|
psort = 0;
|
||||||
prio = 0;
|
if (pri > 0)
|
||||||
if (c["PRIORITY"] > 0)
|
|
||||||
{
|
{
|
||||||
priotext = "❗(" c["PRIORITY"] ") ";
|
priotext = "❗(" pri ") "
|
||||||
prio = 10 - c["PRIORITY"];
|
psort = 10 - pri
|
||||||
}
|
}
|
||||||
|
|
||||||
# Last modification/creation time stamp, used for sorting
|
# Last modification/creation time stamp, used for sorting
|
||||||
@@ -173,7 +188,7 @@ ENDFILE {
|
|||||||
# UTC time format
|
# UTC time format
|
||||||
# DTSTAMP: mandatory field in VTODO and VJOURNAL, date-time in UTC time
|
# DTSTAMP: mandatory field in VTODO and VJOURNAL, date-time in UTC time
|
||||||
# format
|
# format
|
||||||
mod = c["LAST-MODIFIED"] ? c["LAST-MODIFIED"] : c["DTSTAMP"];
|
mod = lmd ? lmd : stp
|
||||||
|
|
||||||
# Date field. For VTODO entries, we show the due date, for journal entries,
|
# Date field. For VTODO entries, we show the due date, for journal entries,
|
||||||
# the associated date.
|
# the associated date.
|
||||||
@@ -183,9 +198,9 @@ ENDFILE {
|
|||||||
if (type == "VTODO")
|
if (type == "VTODO")
|
||||||
{
|
{
|
||||||
# Either DUE or DURATION may appear. If DURATION appears, then also DTSTART
|
# Either DUE or DURATION may appear. If DURATION appears, then also DTSTART
|
||||||
d = c["DUE"] ? c["DUE"] :
|
d = due ? due :
|
||||||
(c["DURATION"] ? c["DTSTART"] " for " c["DURATION"] : "");
|
(dur ? dts " for " dur : "");
|
||||||
if (d && d <= today && c["STATUS"] != "COMPLETED")
|
if (d && d <= today && sta != "COMPLETED")
|
||||||
{
|
{
|
||||||
datecolor = RED;
|
datecolor = RED;
|
||||||
summarycolor = RED;
|
summarycolor = RED;
|
||||||
@@ -193,28 +208,28 @@ ENDFILE {
|
|||||||
} else {
|
} else {
|
||||||
d = c["DTSTART"];
|
d = c["DTSTART"];
|
||||||
}
|
}
|
||||||
d = d ? formatdate(d, today, todaystamp ts, ts_y, ts_m, ts_d, delta) : " ";
|
d = d ? formatdate(d, todaystamp) : " ";
|
||||||
|
|
||||||
# flag: - "journal" for VJOURNAL with DTSTART
|
# flag: - "journal" for VJOURNAL with DTSTART
|
||||||
# - "note" for VJOURNAL without DTSTART
|
# - "note" for VJOURNAL without DTSTART
|
||||||
# - "completed" for VTODO with c["STATUS"] == COMPLETED
|
# - "completed" for VTODO with c["STATUS"] == COMPLETED
|
||||||
# - "open" for VTODO with c["STATUS"] != COMPLETED
|
# - "open" for VTODO with c["STATUS"] != COMPLETED
|
||||||
if (type == "VTODO")
|
if (type == "VTODO")
|
||||||
flag = c["STATUS"] == "COMPLETED" ? flag_completed : flag_open;
|
flag = sta == "COMPLETED" ? flag_completed : flag_open;
|
||||||
else
|
else
|
||||||
flag = c["DTSTART"] ? flag_journal : flag_note;
|
flag = dts ? flag_journal : flag_note;
|
||||||
|
|
||||||
# summary
|
# summary
|
||||||
# c["SUMMARY"]
|
# c["SUMMARY"]
|
||||||
summary = c["SUMMARY"] ? c["SUMMARY"] : " "
|
summary = sum ? sum : " "
|
||||||
|
|
||||||
# categories
|
# categories
|
||||||
categories = c["CATEGORIES"] ? c["CATEGORIES"] : " "
|
categories = cat ? cat : " "
|
||||||
|
|
||||||
# filename
|
# filename
|
||||||
# FILENAME
|
# FILENAME
|
||||||
|
|
||||||
print prio,
|
print psort,
|
||||||
mod,
|
mod,
|
||||||
fpath,
|
fpath,
|
||||||
collection,
|
collection,
|
||||||
|
|||||||
@@ -1,27 +1,44 @@
|
|||||||
function escape_categories(str)
|
# Escape string to be used as content in iCalendar files.
|
||||||
{
|
#
|
||||||
gsub("\\\\", "\\\\", str);
|
# @input str: String to escape
|
||||||
gsub(";", "\\\\;", str);
|
# @return: Escaped string
|
||||||
}
|
|
||||||
|
|
||||||
function escape(str)
|
function escape(str)
|
||||||
{
|
{
|
||||||
escape_categories(str)
|
gsub("\\\\", "\\", str)
|
||||||
gsub(",", "\\\\,", str);
|
gsub(";", "\\;", str)
|
||||||
|
gsub(",", "\\,", str)
|
||||||
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Escape string to be used as content in iCalendar files.
|
||||||
|
#
|
||||||
|
# @input str: String to escape
|
||||||
|
# @return: Escaped string
|
||||||
|
function escape_categories(str)
|
||||||
|
{
|
||||||
|
gsub("\\\\", "\\", str)
|
||||||
|
gsub(";", "\\;", str)
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print property with its content and fold according to the iCalendar
|
||||||
|
# specification.
|
||||||
|
#
|
||||||
|
# @local variables: i, s
|
||||||
|
# @input nameparam: Property name with optional parameters
|
||||||
|
# @input content: Escaped content
|
||||||
function print_fold(nameparam, content, i, s)
|
function print_fold(nameparam, content, i, s)
|
||||||
{
|
{
|
||||||
i = 74 - length(nameparam);
|
i = 74 - length(nameparam)
|
||||||
s = substr(content, 1, i);
|
s = substr(content, 1, i)
|
||||||
print nameparam s;
|
print nameparam s
|
||||||
s = substr(content, i+1, 73);
|
s = substr(content, i+1, 73)
|
||||||
i = i + 73;
|
i = i + 73
|
||||||
while (s)
|
while (s)
|
||||||
{
|
{
|
||||||
print " " s;
|
print " " s
|
||||||
s = substr(content, i+1, 73);
|
s = substr(content, i+1, 73)
|
||||||
i = i + 73;
|
i = i + 73
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,9 +76,9 @@ END {
|
|||||||
cmd | getline res
|
cmd | getline res
|
||||||
due = res ? res : ""
|
due = res ? res : ""
|
||||||
}
|
}
|
||||||
escape(summary);
|
summary = escape(summary);
|
||||||
escape(desc);
|
desc = escape(desc);
|
||||||
escape_categories(categories);
|
categories = escape_categories(categories);
|
||||||
|
|
||||||
# print ical
|
# print ical
|
||||||
print "BEGIN:VCALENDAR";
|
print "BEGIN:VCALENDAR";
|
||||||
@@ -88,9 +105,9 @@ END {
|
|||||||
if (start)
|
if (start)
|
||||||
print "DTSTART;VALUE=DATE:" start;
|
print "DTSTART;VALUE=DATE:" start;
|
||||||
}
|
}
|
||||||
if (summary) print_fold("SUMMARY:", summary, i, s);
|
if (summary) print_fold("SUMMARY:", summary);
|
||||||
if (categories) print_fold("CATEGORIES:", categories, i, s);
|
if (categories) print_fold("CATEGORIES:", categories);
|
||||||
if (desc) print_fold("DESCRIPTION:", desc, i, s);
|
if (desc) print_fold("DESCRIPTION:", desc);
|
||||||
print "END:" type;
|
print "END:" type;
|
||||||
print "END:VCALENDAR"
|
print "END:VCALENDAR"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,44 @@
|
|||||||
function getcontent(content_line, prop)
|
# Escape string to be used as content in iCalendar files.
|
||||||
{
|
#
|
||||||
return substr(content_line[prop], index(content_line[prop], ":") + 1);
|
# @input str: String to escape
|
||||||
}
|
# @return: Escaped string
|
||||||
|
|
||||||
function escape_categories(str)
|
|
||||||
{
|
|
||||||
gsub("\\\\", "\\\\", str);
|
|
||||||
gsub(";", "\\\\;", str);
|
|
||||||
}
|
|
||||||
|
|
||||||
function escape(str)
|
function escape(str)
|
||||||
{
|
{
|
||||||
escape_categories(str)
|
gsub("\\\\", "\\", str)
|
||||||
gsub(",", "\\\\,", str);
|
gsub(";", "\\;", str)
|
||||||
|
gsub(",", "\\,", str)
|
||||||
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Escape string to be used as content in iCalendar files.
|
||||||
|
#
|
||||||
|
# @input str: String to escape
|
||||||
|
# @return: Escaped string
|
||||||
|
function escape_categories(str)
|
||||||
|
{
|
||||||
|
gsub("\\\\", "\\", str)
|
||||||
|
gsub(";", "\\;", str)
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print property with its content and fold according to the iCalendar
|
||||||
|
# specification.
|
||||||
|
#
|
||||||
|
# @local variables: i, s
|
||||||
|
# @input nameparam: Property name with optional parameters
|
||||||
|
# @input content: Escaped content
|
||||||
function print_fold(nameparam, content, i, s)
|
function print_fold(nameparam, content, i, s)
|
||||||
{
|
{
|
||||||
i = 74 - length(nameparam);
|
i = 74 - length(nameparam)
|
||||||
s = substr(content, 1, i);
|
s = substr(content, 1, i)
|
||||||
print nameparam s;
|
print nameparam s
|
||||||
s = substr(content, i+1, 73);
|
s = substr(content, i+1, 73)
|
||||||
i = i + 73;
|
i = i + 73
|
||||||
while (s)
|
while (s)
|
||||||
{
|
{
|
||||||
print " " s;
|
print " " s
|
||||||
s = substr(content, i+1, 73);
|
s = substr(content, i+1, 73)
|
||||||
i = i + 73;
|
i = i + 73
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,9 +57,9 @@ ENDFILE {
|
|||||||
cmd | getline res
|
cmd | getline res
|
||||||
due = res ? res : ""
|
due = res ? res : ""
|
||||||
}
|
}
|
||||||
escape(summary);
|
summary = escape(summary);
|
||||||
escape(desc);
|
desc = escape(desc);
|
||||||
escape_categories(categories);
|
categories = escape_categories(categories);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,9 +89,9 @@ NR == FNR {
|
|||||||
print "SEQUENCE:" seq;
|
print "SEQUENCE:" seq;
|
||||||
print "LAST-MODIFIED:" zulu;
|
print "LAST-MODIFIED:" zulu;
|
||||||
if (due) print "DUE;VALUE=DATE:" due;
|
if (due) print "DUE;VALUE=DATE:" due;
|
||||||
print_fold("SUMMARY:", summary, i, s);
|
print_fold("SUMMARY:", summary);
|
||||||
print_fold("CATEGORIES:", categories, i, s);
|
print_fold("CATEGORIES:", categories);
|
||||||
print_fold("DESCRIPTION:", desc, i, s);
|
print_fold("DESCRIPTION:", desc);
|
||||||
type = "";
|
type = "";
|
||||||
}
|
}
|
||||||
{ print }
|
{ print }
|
||||||
|
|||||||
Reference in New Issue
Block a user