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