#! /bin/bash # Usage: # context 1h2m30s (Update current context with given time) # context -s 1h20m (Set current context with given time) # context (Check total time of each context) # # TODO support minus time # trap 'exit 1' SIGUSR1 trap 'which rsync_retry.sh &>/dev/null && setsid rsync_retry.sh $LOG_FILE &>/dev/null &' EXIT LOG_FILE=~/.context PLAN_FILE=~/log/plan.context.md PROC=$$ if [[ "$1" =~ ^e ]]; then $EDITOR $LOG_FILE exit 0 elif [[ "$1" =~ ^[a-zA-Z] ]]; then if [ -z "$2" ]; then echo "$1" > ~/.task/context exit 0 else context="$1" time="$2" fi else context="$(cat ~/.task/context)" time="$1" fi # The unit of time display. For example: # If it is 900(seconds), then the minimal symbol of # time display is 15min UNIT=900 #BLOCK_CHAR= BLOCK_CHAR=▮ #▊◼ # This dictionary store the valid contexts and the time I plan to spend on declare -A SPEND # Get seconds from given string _get_seconds() { # Modify input to fit the format that `date` can read hour=$(grep -o '[0-9.]\+h' <<<"$1" | tr -d '[:alpha:]') min=$(grep -o '[0-9.]\+m' <<<"$1" | tr -d '[:alpha:]') sec=$(grep -o '[0-9.]\+s' <<<"$1" | tr -d '[:alpha:]') [ -z "$hour$min$sec" ] && kill -10 $PROC [[ "$time" =~ ^- ]] && echo -n - echo "${hour:-0}*3600 + ${min:-0}*60 + ${sec:-0}" | bc | xargs printf '%.0f\n' } # Get formated string from given seconds _format_seconds() { hour=$(( $1 / 3600 )) min=$(( ($1 % 3600) / 60 )) sec=$(( $1 % 60 )) echo ${hour}h${min}m${sec}s } _save_spend_time_to_dic() { while read -r date time ctx sec; do SPEND[$ctx]=$(( SPEND[$ctx] + $sec )) done < <(sed -n "/^$(date +%Y%m%d)/p" $LOG_FILE) } _desktop_notify() { which notify-send &>/dev/null && notify-send "$context +$1" } # Update spend time on current context _update_spend_time() { # If current conetxt is not given, exit with 1 if [ -z "$context" ] || [ "$context" = none ]; then exit 1 fi given_seconds="$(_get_seconds "$time")" _desktop_notify "$(_format_seconds "${given_seconds}")" echo -e "$(date +'%Y%m%d %H:%M:%S')\t$context\t${given_seconds}" >>$LOG_FILE } # Print spend for each context _print_spend_time() { _save_spend_time_to_dic while read -r line; do [ -z "$line" ] && break ctx=$(awk '{print $1}' <<<"$line") time=$(awk '{print $2}' <<<"$line") seconds_of_plan=$(_get_seconds "$time") sec=${SPEND[$ctx]}; sec=${sec:-0} # Print context and time I spend [ "$context" = "$ctx" ] && echo -ne '\e[33;1m' echo -ne "$ctx\t\t" date -u -d @"$sec" +%H:%M | tr -d '\n' echo -n "/" date -u -d @"$seconds_of_plan" +%H:%M | tr -d '\n' number_of_spend=$(( sec / UNIT )) # Print block of time spend (green) echo -ne "\t\t\e[32m" [ ! "$number_of_spend" = 0 ] && printf "%0.s$BLOCK_CHAR" $(seq $number_of_spend) echo -en "\e[0m" if [ -n "$seconds_of_plan" ]; then number_of_plan=$(( seconds_of_plan / UNIT )) [ "$(( seconds_of_plan % UNIT ))" = 0 ] || (( number_of_plan++ )) number_of_remaining=$(( number_of_plan - number_of_spend )) # Print block of remaining time (normal) if (( "$number_of_remaining" > 0 )); then printf "%0.s$BLOCK_CHAR" $(seq $number_of_remaining) # Print block of exceed time (red) elif (( "$number_of_remaining" < 0 )); then echo -ne "\e[31m" number_of_exceed=${number_of_remaining#-} printf "%0.s\b" $(seq "$number_of_exceed") printf "%0.s$BLOCK_CHAR" $(seq "$number_of_exceed") echo -en "\e[0m" fi fi echo done <$PLAN_FILE } if [ -n "$1" ]; then _update_spend_time else _print_spend_time fi