commit 79930608f2f6c8235ca9a8982fee256cc4f030a0 Author: Ämin Baumeler Date: Fri May 30 20:39:19 2025 +0200 initial commit diff --git a/fzf-cal b/fzf-cal new file mode 100755 index 0000000..5149fe3 --- /dev/null +++ b/fzf-cal @@ -0,0 +1,96 @@ +#!/bin/sh + +set -eu + +. "$HOME/.config/fzf-vcal/config" + +__load_weeks() { + # TODO: Make sensitive to failures. I don't want to miss appointments! + file_weeks=$(mktemp) + find "$ROOT" -type f -name '*.ics' -print0 | + xargs -0 -P0 \ + awk -f "src/weeks.awk" >"$file_weeks" + dates=$(awk -F'|' '{ print $1; print $2 }' "$file_weeks") + file_dates=$(mktemp) + echo "$dates" | date --file="/dev/stdin" +"%s" >"$file_dates" + awk -f "src/merge.awk" "$file_dates" "$file_weeks" + rm "$file_weeks" "$file_dates" +} + +if [ -z "${WEEKLY_DATA:-}" ]; then + WEEKLY_DATA=$(__load_weeks) + export WEEKLY_DATA +fi + +__list() { + weeknr=$(date -d "$DISPLAY_DATE" +"%s") + weeknr=$(((weeknr - 259200) / 604800)) # shift, because epoch origin is a Thursday + files=$(echo "$WEEKLY_DATA" | grep "^$weeknr " | cut -d " " -f 2) + dayofweek=$(date -d "$DISPLAY_DATE" +"%u") + delta=$((1 - dayofweek)) + startofweek=$(date -d "$DISPLAY_DATE -$delta days" +"%D") + # loop over files + sef=$({ + IFS=';' + set -- $files + for file in "$@"; do + file="$ROOT/$file" + awk -f "src/parse.awk" "$file" + done + }) + if [ -n "$sef" ]; then + sef=$(echo "$sef" | while IFS= read -r line; do + set -- $line + starttime="$1" + shift + endtime="$1" + shift + description="$*" + 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") + if [ "$starttime" -gt "$daystart" ] && [ "$starttime" -lt "$dayend" ]; then + s=$(date -d "@$starttime" +"%H:%M") + s="$s -" + elif [ "$starttime" -le "$daystart" ] && [ "$endtime" -gt "$daystart" ]; then + s="00:00 -" + else + continue + fi + if [ "$endtime" -gt "$daystart" ] && [ "$endtime" -lt "$dayend" ]; then + e=$(date -d "@$endtime" +"%H:%M") + e="- $e" + elif [ "$endtime" -ge "$dayend" ] && [ "$starttime" -lt "$dayend" ]; then + e="- 00:00" + else + continue + fi + echo "$i $s$e >$description" + done + done) + fi + sef=$({ + echo "$sef" + seq 0 7 + } | sort -n) + echo "$sef" | awk -v startofweek="$startofweek" -f "src/weekview.awk" + #seq -f "$startofweek +%g days" 0 6 | + # LC_ALL=c xargs -I {} date -d "{}" +"%a %e %b %Y" +} + +DISPLAY_DATE="today" +if [ "${1:-}" = "--date" ]; then + DISPLAY_DATE="$2" + echo "Jumping to date $2!" +fi +DISPLAY_DATE=$(date -d "$DISPLAY_DATE" +"%D") +DISPLAY_DATE_PREV=$(date -d "$DISPLAY_DATE -1 week" +"%D") +DISPLAY_DATE_NEXT=$(date -d "$DISPLAY_DATE +1 week" +"%D") + +__list | + fzf \ + --tac \ + --no-sort \ + --ansi \ + --bind="ctrl-p:become($0 --date '$DISPLAY_DATE_PREV')" \ + --bind="ctrl-n:become($0 --date '$DISPLAY_DATE_NEXT')" diff --git a/src/merge.awk b/src/merge.awk new file mode 100644 index 0000000..de8a7a5 --- /dev/null +++ b/src/merge.awk @@ -0,0 +1,14 @@ +BEGIN { FS="|"; i=0; dlt = -259200; spw = 604800; } +NR == FNR { + i = i + 1; + from[i] = int(($1 + dtl)/ spw); + getline; + to[i] = int(($1 + dlt) / spw); + next +} # Load start and end week numbers from first file + +{ for(i=from[FNR]; i<=to[FNR]; i++) { + week[i] = week[i] ? week[i] ";" $3 : $3 + } +} +END { for (i in week) print i, week[i]; } diff --git a/src/parse.awk b/src/parse.awk new file mode 100644 index 0000000..9502e12 --- /dev/null +++ b/src/parse.awk @@ -0,0 +1,58 @@ +function parse( dt) { + # Get timezone information + dt = ""; + for (i=2; i") + 1) " " RED "/" OFF +} +BEGIN { + GREEN = "\033[1;32m"; + RED = "\033[1;31m"; + WHITE = "\033[1;97m"; + CYAN = "\033[1;36m"; + FAINT = "\033[2m"; + OFF = "\033[m"; +} +/^[0-7] 00:00 -- 00:00/ { dayline = dayline " " c(); next } +/^[0-7] 00:00 -- / { dayline = dayline " <-|" $4 " " c(); next } +/^[0-7] [0-9]{2}:[0-9]{2} -- 00:00/ { dayline = dayline " " $2 "|-> " c(); next } +/^[0-7] [0-9]{2}:[0-9]{2} -- [0-9]{2}:[0-9]{2}/ { dayline = dayline " " $2 " - " $4 " " c(); next } +/^[0-7]$/ && dayline { print dayline; } +/^[0-7]$/ { + cmd = "date -d '" startofweek " +" $0 " days' +\"%a %e %b %Y\""; + cmd | getline dayline; + close(cmd); + dayline = GREEN dayline ": " OFF +}