aboutsummaryrefslogtreecommitdiffhomepage
path: root/bin/task/context
blob: 06848d6749f90695efc9de98960165ab526d3359 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#! /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 && touch $LOG_FILE
PLAN_FILE=~/log/plan.context.md
PROC=$$

context="$(cat ~/.task/context)"
[[ "$*" =~ '-s' ]] && SET=true && shift
time="$1"

# 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
  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 ctx sec; do

    [ -z "$ctx" ] && continue
    SPEND[$ctx]=$sec
  done <$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}")"

  # Get total time of given time and current context time
  while read -r ctx sec; do
    if [ "$ctx" = "$context" ]; then
      total=$(( "$sec" + "$given_seconds" ))
      if [ "$SET" = true ]; then
        sed -i -E "/^${context}.*/d" $LOG_FILE
        break
      else
        sed -i -E "s/^${context}.*/${context}\t${total}/" $LOG_FILE
        exit 0
      fi
    fi
  # Update Log file
  done <"$LOG_FILE"

  echo -e "$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