Compare commits
2 Commits
caec86c5a0
...
1093bc15e5
Author | SHA1 | Date | |
---|---|---|---|
1093bc15e5 | |||
9e2e3bc35b |
@ -106,7 +106,9 @@ Here is the list of all available keybindings:
|
||||
| `ctrl-t` | set timezon |
|
||||
| `ctrl-s` | synchronize |
|
||||
| `ctrl-n` | add new entry |
|
||||
| `\` | search all appointment s|
|
||||
| `\` | search all appointment s |
|
||||
| `x` | Cancel and confirm entry |
|
||||
| `c` | Unconfirm and confirm entry |
|
||||
|
||||
### Day view
|
||||
|
||||
|
@ -10,37 +10,54 @@
|
||||
|
||||
# Functions
|
||||
|
||||
# Set event color based on status
|
||||
|
||||
# @input status: Event status, one of TENTATIVE, CONFIRMED, CANCELLED
|
||||
# @return: Color modifier
|
||||
function color_from_status(status) {
|
||||
return status == "CANCELLED" ? STRIKE CYAN : status == "TENTATIVE" ? FAINT CYAN : CYAN
|
||||
}
|
||||
|
||||
# Return line for all-day event.
|
||||
#
|
||||
# @local variables: color
|
||||
# @input collection: Collection symbol
|
||||
# @input desc: Event description
|
||||
# @input status: Event status, one of TENTATIVE, CONFIRMED, CANCELLED
|
||||
# @return: Single-line string
|
||||
function allday(collection, desc) {
|
||||
return collection " " ITALIC FAINT " (allday) " OFF desc
|
||||
function allday(collection, desc, status, color) {
|
||||
color = color_from_status(status)
|
||||
return collection " " LIGHT_CYAN ITALIC FAINT " (allday) " OFF color desc OFF
|
||||
}
|
||||
|
||||
# Return line for multi-day event, or event that starts at midnight, which ends today.
|
||||
#
|
||||
# @local variables: color
|
||||
# @input stop: Time at which the event ends
|
||||
# @input collection: Collection symbol
|
||||
# @input desc: Event description
|
||||
# @input status: Event status, one of TENTATIVE, CONFIRMED, CANCELLED
|
||||
# @return: Single-line string
|
||||
function endstoday(stop, collection, desc) {
|
||||
return collection " " CYAN " -- " stop OFF ": " desc
|
||||
function endstoday(stop, collection, desc, status) {
|
||||
color = color_from_status(status)
|
||||
return collection " " LIGHT_CYAN " -- " stop OFF ": " color desc OFF
|
||||
}
|
||||
|
||||
# Return line for event that starts sometime today.
|
||||
#
|
||||
# @local variables: color
|
||||
# @input start: Time at which the event starts
|
||||
# @input stop: Time at which the event ends
|
||||
# @input collection: Collection symbol
|
||||
# @input desc: Event description
|
||||
# @input status: Event status, one of TENTATIVE, CONFIRMED, CANCELLED
|
||||
# @return: Single-line string
|
||||
function slice(start, stop, collection, desc) {
|
||||
function slice(start, stop, collection, desc, status) {
|
||||
color = color_from_status(status)
|
||||
if (stop == "00:00")
|
||||
return collection " " CYAN start " -- " OFF ": " desc
|
||||
else
|
||||
return collection " " CYAN start OFF " -- " CYAN stop OFF ": " desc
|
||||
return collection " " LIGHT_CYAN start " -- " OFF ": " color desc OFF
|
||||
else
|
||||
return collection " " LIGHT_CYAN start OFF " -- " LIGHT_CYAN stop OFF ": " color desc OFF
|
||||
}
|
||||
|
||||
# Print line for a single hour entry.
|
||||
@ -75,16 +92,18 @@ function hrlines(start, stop, h, starth, stoph, tmp, i) {
|
||||
# AWK program
|
||||
BEGIN {
|
||||
FS = "|"
|
||||
LIGHT_CYAN = "\033[1;36m"
|
||||
CYAN = "\033[1;36m"
|
||||
ITALIC = "\033[3m"
|
||||
FAINT = "\033[2m"
|
||||
STRIKE = "\033[9m"
|
||||
OFF = "\033[m"
|
||||
OFS = "|"
|
||||
}
|
||||
$1 == "00:00" && $2 == "00:00" { print today, $1, $3, $4, $5, allday($6, $7); next }
|
||||
$1 == "00:00" { print today, $1, $3, $4, $5, endstoday($2, $6, $7); next }
|
||||
$1 == "00:00" && $2 == "00:00" { print today, $1, $3, $4, $5, allday($6, $7, $8); next }
|
||||
$1 == "00:00" { print today, $1, $3, $4, $5, endstoday($2, $6, $7, $8); next }
|
||||
$1 ~ /^[0-9]{2}:[0-9]{2}$/ {
|
||||
daystart = hrlines($1, $2, daystart)
|
||||
print today, $1, $3, $4, $5, slice($1, $2, $6, $7)
|
||||
print today, $1, $3, $4, $5, slice($1, $2, $6, $7, $8)
|
||||
}
|
||||
END { hrlines(dayend":00", 0, daystart) }
|
||||
|
@ -129,7 +129,7 @@ END {
|
||||
print "CREATED:" zulu
|
||||
print "SEQUENCE:1"
|
||||
print "LAST-MODIFIED:" zulu
|
||||
print "STATUS:VEVENT"
|
||||
print "STATUS:CONFIRMED"
|
||||
print "DTSTART;VALUE=" from_type ":" from
|
||||
print "DTEND;VALUE=" to_type ":" to
|
||||
if (summary) print_fold("SUMMARY:", summary)
|
||||
|
@ -1,7 +1,7 @@
|
||||
## src/awk/parse.awk
|
||||
## Parse iCalendar file and print its key aspects:
|
||||
## ```
|
||||
## <start> <end> <fpath> <collection> <summary>
|
||||
## <start> <end> <fpath> <collection> <status> <summary>
|
||||
## ```.
|
||||
##
|
||||
## @assign collection_labels: See configuration of the current program.
|
||||
@ -72,7 +72,8 @@ function print_data(start, dur, end, summary, cmd, collection, depth, path) {
|
||||
cmd = "date -d '" end "' +\"%s\""
|
||||
cmd | getline end
|
||||
close(cmd)
|
||||
print start, end, fpath, collection, summary
|
||||
status = status ? status : "CONFIRMED"
|
||||
print start, end, fpath, collection, status, summary
|
||||
}
|
||||
|
||||
# AWK program
|
||||
@ -89,6 +90,7 @@ BEGIN {
|
||||
/^DTSTART/ && inside { start = parse() }
|
||||
/^DTEND/ && inside { end = parse() }
|
||||
/^DURATION/ && inside { end = parse_duration($NF); dur = 1 }
|
||||
/^STATUS/ && inside { status = $NF }
|
||||
/^[^ ]/ && rs { rs = 0 }
|
||||
/^ / && rs { summary = summary substr($0, 2) }
|
||||
/^SUMMARY/ && inside { rs = 1; summary = $0 }
|
||||
|
@ -22,12 +22,21 @@ function escape(str)
|
||||
|
||||
# AWK program
|
||||
|
||||
BEGIN { FS = "[:;]" }
|
||||
BEGIN { FS = "[:;]"; zulu = strftime("%Y%m%dT%H%M%SZ", systime(), 1) }
|
||||
/^BEGIN:VEVENT$/ { inside = 1 }
|
||||
/^END:VEVENT$/ { inside = 0; if (!duplic) print field ":" escape(value) }
|
||||
/^END:VEVENT$/ {
|
||||
inside = 0
|
||||
if (!duplic)
|
||||
print field ":" escape(value)
|
||||
seq = seq ? seq + 1 : 1
|
||||
print "SEQUENCE:" seq
|
||||
print "LAST-MODIFIED:" zulu
|
||||
}
|
||||
$1 == field && inside { con = 1; duplic = 1; print field ":" escape(value); next }
|
||||
$1 == field && duplic { con = 1; next }
|
||||
/^ / && con { next }
|
||||
/^ / && con { next }
|
||||
/^[^ ]/ && con { con = 0 }
|
||||
/^SEQUENCE/ && inside { seq = $2; next } # store sequence number and skip
|
||||
/^LAST-MODIFIED/ && inside { next }
|
||||
{ print }
|
||||
|
102
src/main.sh
102
src/main.sh
@ -124,7 +124,13 @@ if [ "${1:-}" = "--preview-event" ]; then
|
||||
start=$(datetime_str "$start" "%a ")
|
||||
end=$(datetime_str "$end" "%a ")
|
||||
location=$(awk -v field="LOCATION" "$AWK_GET" "$fpath")
|
||||
echo "📅 ${CYAN}$start${OFF} → ${CYAN}$end${OFF}"
|
||||
status=$(awk -v field="STATUS" "$AWK_GET" "$fpath")
|
||||
if [ "$status" = "TENTATIVE" ]; then
|
||||
symb="🟡"
|
||||
elif [ "$status" = "CANCELLED" ]; then
|
||||
symb="❌"
|
||||
fi
|
||||
echo "📅${symb:-} ${CYAN}$start${OFF} → ${CYAN}$end${OFF}"
|
||||
if [ -n "${location:-}" ]; then
|
||||
echo "📍 ${CYAN}$location${OFF}"
|
||||
fi
|
||||
@ -244,6 +250,8 @@ __view_day() {
|
||||
shift
|
||||
collection="$1"
|
||||
shift
|
||||
status="$1"
|
||||
shift
|
||||
description="$(echo "$*" | sed 's/|/:/g')" # we will use | as delimiter
|
||||
#
|
||||
daystart=$(date -d "$today 00:00:00" +"%s")
|
||||
@ -263,7 +271,7 @@ __view_day() {
|
||||
else
|
||||
continue
|
||||
fi
|
||||
echo "$s|$e|$starttime|$endtime|$fpath|$collection|$description"
|
||||
echo "$s|$e|$starttime|$endtime|$fpath|$collection|$description|$status"
|
||||
done)
|
||||
fi
|
||||
echo "$sef" | sort -n | awk -v today="$today" -v daystart="$DAY_START" -v dayend="$DAY_END" "$AWK_DAYVIEW"
|
||||
@ -277,6 +285,7 @@ __view_day() {
|
||||
# @req $ROOT: Path that contains the collections (see configuration)
|
||||
# @req $COLLECTION_LABELS: Mapping between collections and lables (see configuration)
|
||||
# @req $AWK_WEEKVIEW: Week-view awk script
|
||||
# @req colors
|
||||
__view_week() {
|
||||
weeknr=$(date -d "$DISPLAY_DATE" +"%G.%V")
|
||||
files=$(grep "^$weeknr\ " "$WEEKLY_DATA_FILE" | cut -d " " -f 2-)
|
||||
@ -302,7 +311,16 @@ __view_week() {
|
||||
shift
|
||||
#fpath="$1"
|
||||
shift
|
||||
description="$*"
|
||||
collection="$1"
|
||||
shift
|
||||
status="$1"
|
||||
shift
|
||||
if [ "$status" = "TENTATIVE" ]; then
|
||||
symb="$FAINT$CYAN"
|
||||
elif [ "$status" = "CANCELLED" ]; then
|
||||
symb="$STRIKE"
|
||||
fi
|
||||
description="${symb:-}$*$OFF"
|
||||
for i in $(seq 0 7); do
|
||||
daystart=$(date -d "$startofweek +$i days 00:00:00" +"%s")
|
||||
dayend=$(date -d "$startofweek +$i days 23:59:59" +"%s")
|
||||
@ -536,8 +554,9 @@ EOF
|
||||
#RED="\033[1;31m"
|
||||
WHITE="\033[1;97m"
|
||||
CYAN="\033[1;36m"
|
||||
STRIKE="\033[9m"
|
||||
ITALIC="\033[3m"
|
||||
#FAINT="\033[2m"
|
||||
FAINT="\033[2m"
|
||||
OFF="\033[m"
|
||||
|
||||
###
|
||||
@ -596,8 +615,9 @@ __refresh_data() {
|
||||
}
|
||||
|
||||
###
|
||||
### UX helper functions
|
||||
### Helper functions
|
||||
### __datetime_human_machine
|
||||
### __summary_for_commit
|
||||
###
|
||||
|
||||
# __datetime_human_machine()
|
||||
@ -614,6 +634,15 @@ __datetime_human_machine() {
|
||||
date -d "@$s" +"$dfmt"
|
||||
}
|
||||
|
||||
# __summary_for_commit()
|
||||
# Get summary string that can be used in for git-commit messages.
|
||||
#
|
||||
# @input $1: iCalendar file path
|
||||
# @req $AWK_GET: Awk script to extract fields from iCalendar file
|
||||
__summary_for_commit() {
|
||||
awk -v field="SUMMARY" "$AWK_GET" "$1" | tr -c -d "[:alnum:][:blank:]" | head -c 15
|
||||
}
|
||||
|
||||
###
|
||||
### iCalendar modification wrapper
|
||||
###
|
||||
@ -621,6 +650,8 @@ __datetime_human_machine() {
|
||||
### __new
|
||||
### __delete
|
||||
### __import_to_collection
|
||||
### __cancel_toggle
|
||||
### __tentative_toggle
|
||||
|
||||
# __edit()
|
||||
# Edit iCalendar file.
|
||||
@ -661,7 +692,7 @@ __edit() {
|
||||
mv "$filenew" "$fpath"
|
||||
if [ -n "${GIT:-}" ]; then
|
||||
$GIT add "$fpath"
|
||||
$GIT commit -m "Modified event" -- "$fpath"
|
||||
$GIT commit -m "Modified event '$(__summary_for_commit "$fpath") ...'" -- "$fpath"
|
||||
fi
|
||||
__refresh_data
|
||||
else
|
||||
@ -727,7 +758,7 @@ __new() {
|
||||
mv "$filenew" "$fpath"
|
||||
if [ -n "${GIT:-}" ]; then
|
||||
$GIT add "$fpath"
|
||||
$GIT commit -m "Added event" -- "$fpath"
|
||||
$GIT commit -m "Added event '$(__summary_for_commit "$fpath") ...'" -- "$fpath"
|
||||
fi
|
||||
start=$(awk -v field="DTSTART" "$AWK_GET" "$fpath" | grep -o '[0-9]\{8\}')
|
||||
else
|
||||
@ -757,7 +788,7 @@ __delete() {
|
||||
rm -v "$fpath"
|
||||
if [ -n "${GIT:-}" ]; then
|
||||
$GIT add "$fpath"
|
||||
$GIT commit -m "Deleted event" -- "$fpath"
|
||||
$GIT commit -m "Deleted event '$(__summary_for_commit "$fpath") ...'" -- "$fpath"
|
||||
fi
|
||||
break
|
||||
;;
|
||||
@ -793,7 +824,52 @@ __import_to_collection() {
|
||||
mv "$filetmp" "$fpath"
|
||||
if [ -n "${GIT:-}" ]; then
|
||||
$GIT add "$fpath"
|
||||
$GIT commit -m "Imported event" -- "$fpath"
|
||||
$GIT commit -m "Imported event '$(__summary_for_commit "$fpath") ...'" -- "$fpath"
|
||||
fi
|
||||
}
|
||||
|
||||
# __cancel_toggle()
|
||||
# Set status of appointment to CANCELLED or CONFIRMED (toggle)
|
||||
#
|
||||
# @input $1: path to iCalendar file
|
||||
# @req $ROOT: Path that contains the collections (see configuration)
|
||||
# @req $AWK_SET: Awk script to set field value
|
||||
# @req $AWK_GET: Awk script to extract fields from iCalendar file
|
||||
__cancel_toggle() {
|
||||
fpath="$ROOT/$1"
|
||||
status=$(awk -v field="STATUS" "$AWK_GET" "$fpath")
|
||||
newstatus="CANCELLED"
|
||||
if [ "${status:-}" = "$newstatus" ]; then
|
||||
newstatus="CONFIRMED"
|
||||
fi
|
||||
filetmp=$(mktemp)
|
||||
awk -v field="STATUS" -v value="$newstatus" "$AWK_SET" "$fpath" >"$filetmp"
|
||||
mv "$filetmp" "$fpath"
|
||||
if [ -n "${GIT:-}" ]; then
|
||||
$GIT add "$fpath"
|
||||
$GIT commit -m "Event '$(__summary_for_commit "$fpath") ...' has now status $status" -- "$fpath"
|
||||
fi
|
||||
}
|
||||
|
||||
# __tentative_toggle
|
||||
# Toggle status flag: CONFIRMED <-> TENTATIVE
|
||||
# @input $1: path to iCalendar file
|
||||
# @req $ROOT: Path that contains the collections (see configuration)
|
||||
# @req $AWK_SET: Awk script to set field value
|
||||
# @req $AWK_GET: Awk script to extract fields from iCalendar file
|
||||
__tentative_toggle() {
|
||||
fpath="$ROOT/$1"
|
||||
status=$(awk -v field="STATUS" "$AWK_GET" "$fpath")
|
||||
newstatus="TENTATIVE"
|
||||
if [ "${status:-}" = "$newstatus" ]; then
|
||||
newstatus="CONFIRMED"
|
||||
fi
|
||||
filetmp=$(mktemp)
|
||||
awk -v field="STATUS" -v value="$newstatus" "$AWK_SET" "$fpath" >"$filetmp"
|
||||
mv "$filetmp" "$fpath"
|
||||
if [ -n "${GIT:-}" ]; then
|
||||
$GIT add "$fpath"
|
||||
$GIT commit -m "Event '$(__summary_for_commit "$fpath") ...' has now status $status" -- "$fpath"
|
||||
fi
|
||||
}
|
||||
|
||||
@ -946,7 +1022,7 @@ __refresh_data
|
||||
|
||||
### Exports
|
||||
# The preview calls run in subprocesses. These require the following variables:
|
||||
export ROOT CAT AWK_GET AWK_CALSHIFT AWK_CALANNOT CYAN WHITE ITALIC OFF
|
||||
export ROOT CAT AWK_GET AWK_CALSHIFT AWK_CALANNOT CYAN STRIKE FAINT WHITE ITALIC OFF
|
||||
# The reload commands also run in subprocesses, and use in addition
|
||||
export COLLECTION_LABELS DAY_START DAY_END AWK_DAYVIEW AWK_WEEKVIEW AWK_PARSE
|
||||
# as well as the following variables that will be dynamically specified. So, we
|
||||
@ -1055,7 +1131,7 @@ while true; do
|
||||
--with-nth='{6}' \
|
||||
--accept-nth='1,2,3,4,5' \
|
||||
--preview="$0 --preview-event {}" \
|
||||
--expect="ctrl-n,ctrl-t,ctrl-g,ctrl-alt-d,esc,backspace,q,alt-v" \
|
||||
--expect="ctrl-n,ctrl-t,ctrl-g,ctrl-alt-d,esc,backspace,q,alt-v,x,c" \
|
||||
--bind="load:pos(1)+transform(
|
||||
echo change-border-label:🗓️ \$(date -d {1} +\"%A %e %B %Y\")
|
||||
)+transform(
|
||||
@ -1111,6 +1187,10 @@ while true; do
|
||||
set -- "--week" "$DISPLAY_DATE"
|
||||
elif [ "$key" = "alt-v" ] && [ -f "$ROOT/$fpath" ]; then
|
||||
$EDITOR "$ROOT/$fpath"
|
||||
elif [ "$key" = "x" ] && [ -f "$ROOT/$fpath" ]; then
|
||||
__cancel_toggle "$fpath"
|
||||
elif [ "$key" = "c" ] && [ -f "$ROOT/$fpath" ]; then
|
||||
__tentative_toggle "$fpath"
|
||||
elif [ -z "$key" ] && [ -n "$fpath" ]; then
|
||||
__edit "$start" "$end" "$fpath"
|
||||
set -- "--day" "$DISPLAY_DATE"
|
||||
|
Loading…
Reference in New Issue
Block a user