#!/bin/bash # monitor time in i3 workspace, via replacing i3status # save every 1/2 hour # i3status output interval = 5 (in ~/.config/i3status/config) # gives warning if total time spent >= warnifMins mins # ignores workspace 10 (ignoreWS) for time spent # show workspace time at front of status line . i3-ws-monitor.config #interval=5 warnif=$((warnifMins*60)) hour=$((saveMins*60)) runfor=0 runtotal=0 date=$(date "+%Y%m%d") saveto="$savetoDir/$date" ignorews="\"$ignoreWS\"" declare -A wstimes declare -A warnifWSSecs if ((${#warnifWSMins[@]} > 0)); then for ws in "${!warnifWSMins[@]}"; do warnifWSSecs["$ws"]=$((warnifWSMins["$ws"]*60)) done fi readData() { local total=0 while read -r key ; do read -r val wstimes["$key"]=$val total=$((total+val)) done < <(jq -r 'to_entries|.[]|select(.key!="")|.key, .value' "$saveto") runtotal=$total } save() { { echo "{" >&3 for ws in "${!wstimes[@]}"; do echo "\"$ws\": ${wstimes[$ws]}," >&3 done # json do not support trailing , echo '"":0' >&3 echo "}" >&3 } 3>$saveto } # show workspace time at front of status line # in workspace ignoreWS, show total time wsStatus() { local ws=$1 local line=$2 local aidx=$(expr index "$line" "[") if (( $aidx == 0 )); then echo "$line" || exit 1 return fi local time local wsline if [ "$ws" == "" ]; then time=$runtotal else time=wstimes["$ws"] fi local sec=$((time % 60)) local min=$((time / 60)) if (( $min >= 60 )); then local hr=$((min / 60)) min=$((min % 60)) printf -v wsline "> %d:%02d:%02d" $hr $min $sec else printf -v wsline "> %02d:%02d" $min $sec fi # "color":"#FF0000" local warn="" local tomax=$((warnif - runtotal)); local towsmax if [ "$ws" != "" ] && [ ${warnifWSMins["$ws"]} ]; then towsmax=$((warnifWSSecs["$ws"] - time)) else # workspace max is not set towsmax=$((warnStatusInSecs + time)) fi if (( $tomax <= $warnStatusInSecs )) || (( $towsmax <= $warnStatusInSecs )); then warn="\"color\":\"$warnStatusCol\"," # status is prefix with $ if total time is closer to its max if (( $tomax < $towsmax )); then wsline="\$$wsline" fi fi # [ {"name":"wstime","full_text":"> ?:??:??"}, wsline="{\"name\":\"wstime\",$warn\"full_text\":\"$wsline\"}," echo "${line:0:$aidx}${wsline}${line:$aidx}" || exit 1 } # read saved data if it exist if [ -f "$saveto" ]; then readData fi i3status | while read line; do if [ "${line: -1}" != "]" ]; then echo "$line" || exit 1 continue fi ignores=0 ws=$(i3-msg -t get_workspaces | jq '.[] | select(.visible==true).name') if [ "$ws" != "$ignorews" ]; then ws=${ws%\"} ws=${ws#\"} ((wstimes["$ws"]+=interval)) runtotal=$((runtotal+interval)) if (($runtotal >= $warnif)); then i3-msg -q "workspace $ignoreWS" notify-send -u critical "Exceeded $warnifMins mins!\nPlease stop!!" ignores=1 elif [ ${warnifWSMins["$ws"]} ]; then if ((${wstimes["$ws"]} >= ${warnifWSSecs["$ws"]})); then i3-msg -q "workspace $ignoreWS" notify-send -u critical "Exceeded workspace [$ws] ${warnifWSMins["$ws"]} mins!\nPlease stop!!" ignores=1 fi fi else ignores=1 fi if (( $ignores == 0 )); then wsStatus "$ws" "$line" runfor=$((runfor+interval)) tosave=$((runfor >= hour)) else # show total wsStatus "" "$line" #echo "$line" || exit 1 tosave=$((runfor > 0)) fi if (($tosave == 1)); then save runfor=0 fi done