Compare commits

...

21 Commits

Author SHA1 Message Date
6dcaf3fbab lic and readme 2025-06-11 22:19:31 +02:00
e1d26fa2e1 help and improvements 2025-06-11 22:02:50 +02:00
29f1672020 improvements 2025-06-11 16:18:37 +02:00
87a41be6de reload instead of become 2025-06-11 16:09:34 +02:00
e91035c43a improved smootheness 2025-06-11 13:32:03 +02:00
66ca05f744 auto hide preview 2025-06-11 13:22:36 +02:00
9e59e7a923 more months preview 2025-06-11 12:28:35 +02:00
afdf8430d0 gaps in week view 2025-06-11 12:18:54 +02:00
b33acff21e improved info line 2025-06-11 10:21:53 +02:00
f463b957bd bug fix, removed prints in awk 2025-06-11 10:18:43 +02:00
e254463b0e bug fix 2025-06-11 10:16:40 +02:00
9291137b94 improved new selector 2025-06-11 10:12:30 +02:00
ad32fcdb0f show tz in info 2025-06-11 10:09:45 +02:00
f025ecd0bb goto functionality 2025-06-11 10:03:04 +02:00
5ebcc4feb6 general improvements in prog flow 2025-06-11 09:56:31 +02:00
3a95c1e162 cal on top 2025-06-11 09:25:38 +02:00
c9759a0fc5 color cal 2025-06-11 09:11:36 +02:00
9558a1d593 cal as preview 2025-06-10 22:33:10 +02:00
7cd8d0ffa8 added quit key 2025-06-10 15:26:55 +02:00
e4fe586db3 minor improvements 2025-06-10 15:11:49 +02:00
6357eddbec new fixes 2025-06-10 15:05:14 +02:00
7 changed files with 349 additions and 75 deletions

7
LICENSE Normal file
View File

@@ -0,0 +1,7 @@
Copyright © 2025 Ämin Baumeler
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

103
README.md Normal file
View File

@@ -0,0 +1,103 @@
A [fzf](https://github.com/junegunn/fzf)-based **calendar** application with CalDav support.
Description and Use Case
------------------------
This application allows for a keyboard-controlled maneuvering of your calendar entries.
These entries are stored as [iCalendar](https://datatracker.ietf.org/doc/html/rfc5545) files of the type `VEVENT`.
For instance, you could use this application in a setup with a CalDav server,
such as [Radicale](https://radicale.org/), and a synchronization tool like
[vdirsyncer](http://vdirsyncer.pimutils.org/).
Installation
------------
Download the file `fzf-vcal` from the [latest release](https://github.com/baumea/fzf-vcal/releases/latest), or run `./scripts/build.sh`, then
copy `fzf-vcal` to your preferred location, e.g., `~/.local/bin`, and make it executable.
### Requirements
This is a POSIX script with inline `awk` elements.
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.
Configuration
--------------
This application is configured with a file located at `$HOME/.config/fzf-vcal/config`.
The entry `ROOT` specifies the root directory of your calendar entries.
This directory may contain several subfolders, called _collections_.
The entry `COLLECTION_LABELS` is a `;`-delimited list, where each item specifies a subfolder and a label (see example below).
In the application, the user sees the collection labels instead of the collection names.
This is particularly useful, because some servers use randomly generated names.
Finally, a third entry `SYNC_CMD` specifies the command to be executed for synchronizing.
Consider the following example:
```sh
ROOT=~/.calendar/
COLLECTION_LABELS="745ae7a0-d723-4cd8-80c4-75f52f5b7d90=👫🏼;12cacb18-d3e1-4ad4-a1d0-e5b209012e85=💼;"
SYNC_CMD="vdirsyncer sync calendar"
```
Here, the files are stored in
`~/.journal/12cacb18-d3e1-4ad4-a1d0-e5b209012e85` (work-related entries)
and
`~/.journal/745ae7a0-d723-4cd8-80c4-75f52f5b7d90` (shared collection).
This configuration will work well with a `vdirsyncer` configuration such as
```confini
[pair calendar]
a = "local"
b = "remote"
collections = ["from a", "from b"]
[storage local]
type = "filesystem"
fileext = ".ics"
path = "~/.calendar"
[storage remote]
type = "caldav"
item_types = ["VEVENT"]
...
```
Usage
-----
Use the default `fzf` keys to navigate your calendar entries, e.g., `ctrl-j`
and `ctrl-k` for going down/up in the list.
After starting `fzf-vcal`, you are presented with a view on the current week.
Hit `<enter>` on any day, and you will see all entries for that date, including
previews. In both, the week and day views, you can add entries by hitting
`ctrl-n`.
Here is the list of available keybindings:
| Key | View | Action |
| --- | ---- | ------ |
| `enter` | week view | Switch to day view |
| `ctrl-n` | week view | Make a new entry |
| any letter | week view | Search in the list of all entries |
| `backspace` on empty query | week view | Undo search |
| `ctrl-u` | week view | Go back one week |
| `ctrl-d` | week view | Go forth one week |
| `ctrl-alt-u` | week view | Go back one month |
| `ctrl-alt-d` | week view | Go forth one month |
| `ctrl-s` | week view | Run the synchronization command |
| `ctrl-l` | week view | Go to current week |
| `ctrl-g` | week view | Goto date |
| `enter` | day view | Open selected calendar entry in your favorite `$EDITOR` |
| `ctrl-n` | day view | Make a new entry |
| `esc`, `backspace` or `q` | day view | Go back to week view |
| `ctrl-s` | day view | Run the synchronization command |
| `ctrl-alt-d` | day view | Delete selected entry |
| `j` | day view | Scroll down in preview window |
| `k` | day view | Scroll up in preview window |
| `w` | day view | Toggle line wrap in preview window ||
You may also invoke the script with `--help` to see further command-line options.
Also, you may set `LC_TIME` to your preferred language, and `TZ` to your
preferred timezone. The latter is in particular helpful if you want to take a
look at your calendar relative to being in another timezone.
License
-------
This project is licensed under the [MIT License](./LICENSE).

18
src/awk/cal.awk Normal file
View File

@@ -0,0 +1,18 @@
BEGIN {
BLACK = "\033[1;30m"
GREEN = "\033[1;32m"
RED = "\033[1;31m"
FAINT = "\033[2m"
BOLD = "\033[1m"
BG = "\033[41m"
OFF = "\033[m"
day = day + 0
cur = cur + 0
}
NR == 1 { print GREEN $0 OFF; next }
NR == 2 { print FAINT $0 OFF; next }
{
sub("\\y"cur"\\y", BG BLACK BOLD cur OFF)
sub("\\y"day"\\y", RED BOLD day OFF)
print
}

View File

@@ -23,7 +23,10 @@ function hrlines(start, stop, h, starth, stoph, tmp, i) {
for (i=h; i < starth + tmp; i++) for (i=h; i < starth + tmp; i++)
hrline(i) hrline(i)
tmp = substr(stop, 4, 2) == "00" ? 0 : 1 tmp = substr(stop, 4, 2) == "00" ? 0 : 1
return stoph + tmp if (stoph + tmp < daystart)
return daystart
else
return stoph + tmp
} }
BEGIN { BEGIN {
FS = "|" FS = "|"

View File

@@ -46,19 +46,15 @@ END {
cmd | getline t cmd | getline t
close(cmd) close(cmd)
t = t + 0 t = t + 0
print "fromnano="t
if (t == 0) { if (t == 0) {
print "ok, DATE-TIME type"
from_type = "DATE-TIME" from_type = "DATE-TIME"
cmd = "date -d \"" from "\" +\"@%s\" | xargs date -u +\"%Y%m%dT%H%M00Z\" -d" cmd = "date -d \"" from "\" +\"@%s\" | xargs date -u +\"%Y%m%dT%H%M00Z\" -d"
} else { } else {
print "ok, DATE type"
from_type = "DATE" from_type = "DATE"
cmd = "date -d \"" from "\" +\"%Y%m%d\""; cmd = "date -d \"" from "\" +\"%Y%m%d\"";
} }
cmd | getline from cmd | getline from
close(cmd) close(cmd)
print "FROM="from
# #
to = to ? to : "now" to = to ? to : "now"
cmd = "date -d \"" to "\" +\"%N\""; cmd = "date -d \"" to "\" +\"%N\"";

View File

@@ -11,8 +11,8 @@ BEGIN {
OFS = "|" OFS = "|"
} }
/^[0-7] 00:00 -- 00:00/ { dayline = dayline " " c(); next } /^[0-7] 00:00 -- 00:00/ { dayline = dayline " " c(); next }
/^[0-7] 00:00 -- / { dayline = dayline " <-|" $4 " " 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} -- 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] [0-9]{2}:[0-9]{2} -- [0-9]{2}:[0-9]{2}/ { dayline = dayline " " $2 " - " $4 " " c(); next }
/^[0-7]$/ && dayline { print "+", startofweek " +" $0-1 " days", "", dayline; } /^[0-7]$/ && dayline { print "+", startofweek " +" $0-1 " days", "", dayline; }
/^[0-7]$/ { /^[0-7]$/ {

View File

@@ -32,7 +32,7 @@ if [ -z "${FZF_VCAL_USE_EXPORTED:-}" ]; then
# Tools # Tools
if command -v "fzf" >/dev/null; then if command -v "fzf" >/dev/null; then
FZF="fzf" FZF="fzf --black"
else else
err "Did not find the command-line fuzzy finder fzf." err "Did not find the command-line fuzzy finder fzf."
exit 1 exit 1
@@ -112,6 +112,13 @@ EOF
EOF EOF
) )
export AWK_NEW export AWK_NEW
AWK_CAL=$(
cat <<'EOF'
@@include src/awk/cal.awk
EOF
)
export AWK_CAL
### END OF AWK SCRIPTS ### END OF AWK SCRIPTS
## Colors ## Colors
@@ -313,10 +320,7 @@ __refresh_data() {
export WEEKLY_DATA_FILE export WEEKLY_DATA_FILE
} }
if [ -z "${APPROX_DATA_FILE:-}" ]; then ## Start
__refresh_data
fi
if [ "${1:-}" = "--help" ]; then if [ "${1:-}" = "--help" ]; then
echo "Usage: $0 [OPTION]" echo "Usage: $0 [OPTION]"
echo "" echo ""
@@ -324,8 +328,16 @@ if [ "${1:-}" = "--help" ]; then
echo " --help Show this help and exit" echo " --help Show this help and exit"
echo " --new Create new entry" echo " --new Create new entry"
echo " --today Show today's appointments" echo " --today Show today's appointments"
echo " --goto Interactively enter date to jump to"
echo " --day <day> Show appointments of specified day" echo " --day <day> Show appointments of specified day"
echo " --date <date> Show week of specified date" echo " --date <date> Show week of specified date"
echo ""
echo "You may also start this program with setting locale and timezone"
echo "information. For instance, to see and modify all of your calendar"
echo "entries from the perspective of Saigon, run"
echo "TZ='Asia/Saigon' $0"
echo "Likewise, you may specify the usage of Greek with"
echo "LC_TIME=el_GR.UTF-8 $0"
exit exit
fi fi
@@ -333,14 +345,25 @@ if [ "${1:-}" = "--today" ]; then
exec $0 --day "today" exec $0 --day "today"
fi fi
if [ "${1:-}" = "--goto" ]; then
DISPLAY_DATE=""
while [ -z "$DISPLAY_DATE" ]; do
printf "Enter date you want to jump to, e.g., today + 1 month or 2024-1-14: " >/dev/tty
read -r tmp
if date -d "$tmp"; then
DISPLAY_DATE="$tmp"
fi
done
fi
if [ "${1:-}" = "--new" ]; then if [ "${1:-}" = "--new" ]; then
collection=$(echo "$COLLECTION_LABELS" | tr ';' '\n' | $FZF --delimiter='=' --with-nth=2 --accept-nth=1) collection=$(echo "$COLLECTION_LABELS" | tr ';' '\n' | awk '/./ {print}' | $FZF --margin="30%" --no-info --delimiter='=' --with-nth=2 --accept-nth=1)
fpath="" fpath=""
while [ -f "$fpath" ] || [ -z "$fpath" ]; do while [ -f "$fpath" ] || [ -z "$fpath" ]; do
uuid=$($UUIDGEN) uuid=$($UUIDGEN)
fpath="$ROOT/$collection/$uuid.ics" fpath="$ROOT/$collection/$uuid.ics"
done done
startsec=$(date -d "$2" +"%s") startsec=$(date -d "${2:-today 8:00}" +"%s")
endsec=$((startsec + 3600)) endsec=$((startsec + 3600))
start=$(__canonical_datetime_hm "$startsec") start=$(__canonical_datetime_hm "$startsec")
end=$(__canonical_datetime_hm "$endsec") end=$(__canonical_datetime_hm "$endsec")
@@ -364,6 +387,64 @@ if [ "${1:-}" = "--new" ]; then
rm "$filetmp" rm "$filetmp"
fi fi
if [ -z "${APPROX_DATA_FILE:-}" ]; then
__refresh_data
fi
if [ "${1:-}" = "--day" ]; then
DISPLAY_DATE="${2:-today}"
export DISPLAY_DATE
selection=$(
__show_day |
$FZF \
--reverse \
--ansi \
--no-sort \
--no-input \
--margin='20%,5%' \
--border='double' \
--border-label="🗓️ $(date -d "$DISPLAY_DATE" +"%A %e %B %Y")" \
--color=label:bold:green \
--border-label-pos=3 \
--cycle \
--delimiter='|' \
--with-nth='{5}' \
--accept-nth='1,2,3,4' \
--preview="$0 --preview {}" \
--expect="ctrl-n,esc,backspace,q" \
--bind='start:hide-preview' \
--bind='ctrl-j:down+hide-preview+transform:echo {} | grep \|\| || echo show-preview' \
--bind='ctrl-k:up+hide-preview+transform:echo {} | grep \|\| || echo show-preview' \
--bind="ctrl-s:execute($SYNC_CMD ; printf 'Press <enter> to continue.'; read -r tmp)" \
--bind="ctrl-alt-d:become($0 --delete {})" \
--bind="j:preview-down" \
--bind="k:preview-down" \
--bind="w:toggle-preview-wrap"
)
key=$(echo "$selection" | head -1)
line=$(echo "$selection" | tail -1)
if [ "$line" = "$key" ]; then
line=""
fi
hour=$(echo "$line" | cut -d '|' -f 1)
start=$(echo "$line" | cut -d '|' -f 2)
end=$(echo "$line" | cut -d '|' -f 3)
fpath=$(echo "$line" | cut -d '|' -f 4 | sed "s/ /|/g")
if [ "$key" = "ctrl-n" ]; then
if echo "$hour" | grep ":"; then
hour="$DAY_START"
fi
exec $0 --new "$DISPLAY_DATE $hour:00"
elif [ -z "$key" ] && [ -n "$fpath" ]; then
fpath="$ROOT/$fpath"
__edit "$start" "$end" "$fpath"
fi
fi
if [ "${1:-}" = "--date" ]; then
DISPLAY_DATE="$2"
fi
if [ "${1:-}" = "--preview" ]; then if [ "${1:-}" = "--preview" ]; then
hour=$(echo "$2" | cut -d '|' -f 1) hour=$(echo "$2" | cut -d '|' -f 1)
start=$(echo "$2" | cut -d '|' -f 2) start=$(echo "$2" | cut -d '|' -f 2)
@@ -381,6 +462,91 @@ if [ "${1:-}" = "--preview" ]; then
exit exit
fi fi
month_previous() {
month="$1"
year="$2"
if [ "$month" -eq 1 ]; then
month=12
year=$((year - 1))
else
month=$((month - 1))
fi
echo "$month $year"
}
month_next() {
month="$1"
year="$2"
if [ "$month" -eq 12 ]; then
month=1
year=$((year + 1))
else
month=$((month + 1))
fi
echo "$month $year"
}
if [ "${1:-}" = "--preview-week" ]; then
sign=$(echo "$2" | cut -d '|' -f 1)
if [ "$sign" = "+" ]; then
startdate=$(echo "$2" | cut -d '|' -f 2)
set -- $(date -d "$startdate" +"%Y %m %d")
year=$1
month=$2
day=$3
set -- $(date -d "today" +"%Y %m %d")
year_cur=$1
month_cur=$2
day_cur=$3
# Previous months
set -- $(month_previous "$month" "$year")
month_pre="$1"
year_pre="$2"
set -- $(month_previous "$month_pre" "$year_pre")
month_pre2="$1"
year_pre2="$2"
# Next months
set -- $(month_next "$month" "$year")
month_nex="$1"
year_nex="$2"
set -- $(month_next "$month_nex" "$year_nex")
month_nex2="$1"
year_nex2="$2"
set -- $(month_next "$month_nex2" "$year_nex2")
month_nex3="$1"
year_nex3="$2"
# Highlight today
if [ "$month_pre2" -eq "$month_cur" ] && [ "$year_pre2" -eq "$year_cur" ]; then
var_pre2=$day_cur
fi
if [ "$month_pre" -eq "$month_cur" ] && [ "$year_pre" -eq "$year_cur" ]; then
var_pre=$day_cur
fi
if [ "$month" -eq "$month_cur" ] && [ "$year" -eq "$year_cur" ]; then
var=$day_cur
fi
if [ "$month_nex" -eq "$month_cur" ] && [ "$year_nex" -eq "$year_cur" ]; then
var_nex=$day_cur
fi
if [ "$month_nex2" -eq "$month_cur" ] && [ "$year_nex2" -eq "$year_cur" ]; then
var_nex2=$day_cur
fi
if [ "$month_nex3" -eq "$month_cur" ] && [ "$year_nex3" -eq "$year_cur" ]; then
var_nex3=$day_cur
fi
# show
(
cal "$month_pre2" "$year_pre2" | awk -v cur="${var_pre2:-}" "$AWK_CAL"
cal "$month_pre" "$year_pre" | awk -v cur="${var_pre:-}" "$AWK_CAL"
cal "$month" "$year" | awk -v cur="${var:-}" -v day="$day" "$AWK_CAL"
cal "$month_nex" "$year_nex" | awk -v cur="${var_nex:-}" "$AWK_CAL"
cal "$month_nex2" "$year_nex2" | awk -v cur="${var_nex2:-}" "$AWK_CAL"
cal "$month_nex3" "$year_nex3" | awk -v cur="${var_nex3:-}" "$AWK_CAL"
) | awk '{ l[NR%8] = l[NR%8] " " $0 } END {for (i in l) if (i>0) print l[i] }'
fi
exit
fi
if [ "${1:-}" = "--delete" ]; then if [ "${1:-}" = "--delete" ]; then
fpath=$(echo "$2" | cut -d '|' -f 4 | sed "s/ /|/g") fpath=$(echo "$2" | cut -d '|' -f 4 | sed "s/ /|/g")
if [ -n "$fpath" ]; then if [ -n "$fpath" ]; then
@@ -407,91 +573,72 @@ if [ "${1:-}" = "--delete" ]; then
exec $0 --day "$DISPLAY_DATE" exec $0 --day "$DISPLAY_DATE"
fi fi
if [ "${1:-}" = "--day" ]; then if [ "${1:-}" = "--all" ]; then
DISPLAY_DATE="$2" cat "$APPROX_DATA_FILE"
export DISPLAY_DATE exit
selection=$(
__show_day |
$FZF \
--reverse \
--ansi \
--no-sort \
--no-input \
--margin='20%' \
--border='double' \
--border-label="🗓️ $(date -d "$DISPLAY_DATE" +"%A %e %B %Y")" \
--color=label:bold:green \
--border-label-pos=3 \
--delimiter='|' \
--with-nth='{5}' \
--accept-nth='1,2,3,4' \
--preview="$0 --preview {}" \
--expect="ctrl-n,esc,backspace" \
--bind="ctrl-s:execute($SYNC_CMD ; printf 'Press <enter> to continue.'; read -r tmp)" \
--bind="ctrl-alt-d:become($0 --delete {})"
)
key=$(echo "$selection" | head -1)
line=$(echo "$selection" | tail -1)
hour=$(echo "$line" | cut -d '|' -f 1)
start=$(echo "$line" | cut -d '|' -f 2)
end=$(echo "$line" | cut -d '|' -f 3)
fpath=$(echo "$line" | cut -d '|' -f 4 | sed "s/ /|/g")
if [ "$key" = "ctrl-n" ]; then
if echo "$hour" | grep ":"; then
hour="$DAY_START"
fi
exec $0 --new "$DISPLAY_DATE $hour:00"
elif [ -n "$fpath" ]; then
fpath="$ROOT/$fpath"
__edit "$start" "$end" "$fpath"
fi
fi fi
if [ "${1:-}" = "--date" ]; then
DISPLAY_DATE="$2"
fi
DISPLAY_DATE=${DISPLAY_DATE:-today} DISPLAY_DATE=${DISPLAY_DATE:-today}
DISPLAY_DATE=$(date -d "$DISPLAY_DATE" +"%D") DISPLAY_DATE=$(date -d "$DISPLAY_DATE" +"%D")
DISPLAY_POS=$((8 - $(date -d "$DISPLAY_DATE" +"%u"))) DISPLAY_POS=$((8 - $(date -d "$DISPLAY_DATE" +"%u")))
DISPLAY_DATE_PREV=$(date -d "$DISPLAY_DATE -1 week" +"%D")
DISPLAY_DATE_NEXT=$(date -d "$DISPLAY_DATE +1 week" +"%D") if [ "${1:-}" = "--list" ]; then
DISPLAY_DATE_PREV_MONTH=$(date -d "$DISPLAY_DATE -1 month" +"%D") shift
DISPLAY_DATE_NEXT_MONTH=$(date -d "$DISPLAY_DATE +1 month" +"%D") DISPLAY_DATE=${*:-today}
DISPLAY_POS=$((8 - $(date -d "$DISPLAY_DATE" +"%u")))
__list
exit
fi
selection=$( selection=$(
( __list |
cat "$APPROX_DATA_FILE"
yes " " | head -n 50
__list
) |
$FZF \ $FZF \
--tac \ --tac \
--no-sort \ --no-sort \
--no-hscroll \ --no-hscroll \
--ellipsis='' \ --ellipsis="" \
--delimiter='|' \ --delimiter="|" \
--with-nth='{4}' \ --with-nth="{4}" \
--accept-nth=1,2 \ --accept-nth=1,2 \
--no-info \
--ansi \ --ansi \
--no-clear \ --gap 1 \
--no-scrollbar \ --no-scrollbar \
--info=right \
--info-command="printf \"$(date +"%R %Z")\"" \
--preview-window=up,7,border-bottom \
--preview="$0 --preview-week {}" \
--expect="ctrl-n" \ --expect="ctrl-n" \
--bind="ctrl-j:transform:[ \$FZF_POS -le 1 ] &&
echo unbind\(load\)+reload:$0 --list {2} '+1 day'||
echo down" \
--bind="ctrl-k:transform:[ \$FZF_POS -ge 7 ] &&
echo unbind\(load\)+reload:$0 --list {2} '-1 day'||
echo up" \
--bind="change:reload($0 --all)+hide-preview" \
--bind="backward-eof:rebind(load)+reload($0 --list)+show-preview" \
--bind="load:pos($DISPLAY_POS)" \ --bind="load:pos($DISPLAY_POS)" \
--bind="ctrl-u:become($0 --date '$DISPLAY_DATE_PREV')" \ --bind="ctrl-u:unbind(load)+reload:$0 --list {2} '-1 week'" \
--bind="ctrl-d:become($0 --date '$DISPLAY_DATE_NEXT')" \ --bind="ctrl-d:unbind(load)+reload:$0 --list {2} '+1 week'" \
--bind="ctrl-alt-u:become($0 --date '$DISPLAY_DATE_PREV_MONTH')" \ --bind="ctrl-alt-u:unbind(load)+reload:$0 --list {2} '-1 month'" \
--bind="ctrl-alt-d:become($0 --date '$DISPLAY_DATE_NEXT_MONTH')" \ --bind="ctrl-alt-d:unbind(load)+reload:$0 --list {2} '+1 month'" \
--bind="ctrl-l:become($0)" --bind="ctrl-s:execute($SYNC_CMD ; printf 'Press <enter> to continue.'; read -r tmp)" \
--bind="ctrl-g:become($0 --goto)" \
--bind="ctrl-l:rebind(load)+reload:$0 --list"
) )
key=$(echo "$selection" | head -1) key=$(echo "$selection" | head -1)
line=$(echo "$selection" | tail -1) line=$(echo "$selection" | tail -1)
if [ "$line" = "$key" ]; then
line=""
fi
sign=$(echo "$line" | cut -d '|' -f 1) sign=$(echo "$line" | cut -d '|' -f 1)
startdate=$(echo "$line" | cut -d '|' -f 2) startdate=$(echo "$line" | cut -d '|' -f 2)
if [ "$key" = "ctrl-n" ]; then if [ "$key" = "ctrl-n" ]; then
# Add new # Add new
exec $0 --new "$startdate $DAY_START:00" if [ "$sign" = "~" ]; then
startdate=""
fi
exec $0 --new "${startdate:-today} $DAY_START:00"
fi fi
if [ -z "$key" ] && [ -z "$line" ]; then if [ -z "$key" ] && [ -z "$line" ]; then
rm "$WEEKLY_DATA_FILE" "$APPROX_DATA_FILE" rm "$WEEKLY_DATA_FILE" "$APPROX_DATA_FILE"