#!/bin/bash shopt -s inherit_errexit set -euo pipefail IFS=$'\n\t' # set -x # export PS4=':.$LINENO:' # ---------------------------------------------------------------------- stop_task() { HM=`date +%H:%M`; perl -i -pe "s/\t_____\t/\t$HM\t/" $FILE } add_task() { printf "%s\t%s\t%s\t%s\t%s\n" "`date -I`" "`date +%H:%M`" "_____" "$tag" "$text" >> $FILE } f1_help() { cat <strftime("%H:%M") if /_____/; $count++; ($sh, $sm, $eh, $em) = split /:/, "$F[1]:$F[2]"; $diff = $eh*60+$em - $sh*60-$sm; $sum+=$diff; $sum{$F[3]}+=$diff; sub hhmm { $mm=shift; return sprintf "%02d:%02d", int($mm/60), $mm%60; } END { say "$_\t" . hhmm($sum{$_}) for sort keys %sum; printf "TOTAL:\t%s from %d entries\n\n", hhmm($sum), $count; }' "$@" | less -c } f7_new() { stop_task cat <&3 > /dev/null # flush rest of output from fzf if [[ "$*" =~ " " ]]; then tag="${*%% *}" text="${*#* }" add_task else echo "need a TAG word and some TEXT, separated by at least one space" | less return 0 fi } enter_stop_start() { # read line. If line is a running task (i.e., contains "_____"), just stop it. # otherwise it's a different line (task), so stop the *running* task, then restart the selected task # (i.e., take fields 5 and 6 into tag and text and start it) IFS= read -r -u3 l stop_task if [[ $l =~ _____ ]] then : else tag=$(echo "$l" | cut -f4) text=$(echo "$l" | cut -f5) add_task fi } # ---------------------------------------------------------------------- FILE=time.tsv [[ -f $FILE ]] || { echo "DATE START END TAG TEXT" > $FILE f1_help } # ---------------------------------------------------------------------- export -f total # this function is called within 'preview' so we need it exported query='' while : do { IFS= read -r -u3 query IFS= read -r -u3 key case $key in f1 ) f1_help ;; f4 ) IFS= read -r -u3 line line=${line//\//\\/} ${EDITOR:-vim} $FILE "+/\\M$line" ;; f5 ) continue ;; f7 ) f7_new "$query" query='' ;; f10 ) break ;; * ) # "ENTER" enter_stop_start ;; esac } 3< <( grep -E -e ^DATE -e '^[0-9]{4}-[0-9]{2}' $FILE | fzf -d$'\t' --multi --tac \ --print-query \ --query="$query" \ --header-lines=1 \ --header="ENTER:stop/start, F1:help, F5:refresh, F7:new, F10:quit" \ --bind ctrl-a:select-all --expect=f1,f4,f5,f7,f10 \ --preview="grep ^{1} $FILE | fzf -f {q} -e +s | bash -c 'total \"totals for {1} (possibly filtered by fzf query)\"'; printf '%s\n' {+} | bash -c 'total \"totals for selected tasks or current task only\"'" \ --preview-window=top:50% ) done