]> CyberLeo.Net >> Repos - CDN/shlib.git/blob - lib/sh/stopwatch.sh
sh/stopwatch: simple stopwatch for timing things
[CDN/shlib.git] / lib / sh / stopwatch.sh
1 # Simple bourne shell based stopwatch
2 # Requires 'kvs' and the id 'stopwatch' therein
3 # so make sure you set 'kvs' before sourcing this script if necessary.
4 #
5 # After loading, the following commands are available:
6 #
7 # Start a stopwatch:
8 #   stopwatch <tag> start
9 #
10 # 'Lap' a stopwatch
11 #   stopwatch <tag> lap
12 #
13 # Stop a stopwatch
14 #   stopwatch <tag> stop
15 #
16 # Reset a stopwatch
17 #   stopwatch <tag> reset
18
19
20 if [ -z "${__stopwatch_sh_loaded}" ]
21 then
22   __stopwatch_sh_loaded=yes
23
24   [ "${kvs}" ] || kvs="$(mktemp -t ".stopwatch.XXXXXXXX")"
25   want kvs
26
27   stopwatch_help() {
28     echo "Usage: stopwatch <tag> <start|lap|stop|reset>" >&2
29     exit 1
30   }
31
32   # Try and format a passed integer number of seconds into something more
33   # useful (like 6m10s or something)
34   _stopwatch_timefmt() {
35     local secs mins hurs days
36     [ "${1}" -a "$(echo "${1}" | tr -Cd '0-9')" = "${1}" ] || return 255
37     secs="${1}"
38     mins=0
39     hurs=0
40     [ "${secs}" -lt 60 ] || {
41       mins=$(( ${secs} / 60 ))
42       secs=$(( ${secs} % 60 ))
43     }
44     [ "${secs}" -gt 0 ] || secs=""
45     [ "${mins}" -lt 60 ] || {
46       hurs=$(( ${mins} / 60 ))
47       mins=$(( ${mins} % 60 ))
48     }
49     [ "${mins}" -gt 0 ] || mins=""
50     [ "${hurs}" -lt 24 ] || {
51       days=$(( ${hurs} / 24 ))
52       hurs=$(( ${hurs} % 24 ))
53     }
54     [ "${hurs}" -gt 0 ] || hurs=""
55
56     [ "${days}" -o "${hurs}" -o "${mins}" -o "${secs}" ] || printf "0s"
57     printf "%s%s%s%s" "${days:+${days}d}" "${hurs:+${hurs}h}" "${mins:+${mins}m}" "${secs:+${secs}s}"
58   }
59
60   # Start a named stopwatch, but do nothing if the named stopwatch is already
61   # running.
62   stopwatch_start() {
63     name="${1:-stopwatch}"
64     [ "${nao}" ] || nao="$(date +%s)"
65     # Is the stopwatch running?
66     if kvs_has_key stopwatch "${name}"
67     then
68       printf "Stopwatch: %s is already running.\n" "${name}"
69     else
70       # start the stopwatch
71       accum="$(kvs_get stopwatch "${name}_accumulator")"
72       kvs_set stopwatch "${name}" "${nao}"
73       [ "${accum}" ] && restart="$(printf " at %s." "$(_stopwatch_timefmt "${accum}")")"
74       printf "Stopwatch: %s starts running%s.\n" "${name}" "${restart}"
75     fi
76   }
77
78   # 'Lap' the named stopwatch: print out a line indicating how long the named
79   # stopwatch has been running, but do not stop nor reset the stopwatch.
80   stopwatch_lap() {
81     name="${1:-stopwatch}"
82     [ "${nao}" ] || nao="$(date +%s)"
83     # Is the stopwatch running?
84     if kvs_has_key stopwatch "${name}"
85     then
86       # emit a line indicating how long it has been running
87       start="$(kvs_get stopwatch "${name}")"
88       accum="$(kvs_get stopwatch "${name}_accumulator")"
89       delta="$(( ${nao} - ${start} ))"
90       [ "${accum}" ] && delta="$(( ${delta} + ${accum} ))"
91       printf "Stopwatch: %s is running at %s.\n" "${name}" "$(_stopwatch_timefmt "${delta}")"
92     else
93       accum="$(kvs_get stopwatch "${name}_accumulator")"
94       [ "${accum}" ] && printf "Stopwatch: %s is stopped at %s.\n" "${name}" "$(_stopwatch_timefmt "${accum}")"
95     fi
96   }
97
98   # Stop the named stopwatch and print out a line indicating how long it had
99   # been running up until that point; do not reset the stopwatch.
100   stopwatch_stop() {
101     name="${1:-stopwatch}"
102     [ "${nao}" ] || nao="$(date +%s)"
103     if kvs_has_key stopwatch "${name}"
104     then
105       start="$(kvs_get stopwatch "${name}")"
106       accum="$(kvs_get stopwatch "${name}_accumulator")"
107       delta="$(( ${nao} - ${start} ))"
108       [ "${accum}" ] && delta="$(( ${delta} + ${accum} ))"
109       kvs_set stopwatch "${name}_accumulator" "${delta}"
110       kvs_unset stopwatch "${name}"
111       printf "Stopwatch: %s stops running at %s.\n" "${name}" "$(_stopwatch_timefmt "${delta}")"
112     else
113       accum="$(kvs_get stopwatch "${name}_accumulator")"
114       [ "${accum}" ] && printf "Stopwatch: %s is already stopped at %s.\n" "${name}" "$(_stopwatch_timefmt "${accum}")"
115     fi
116   }
117
118   # Reset the named stopwatch back to zero.
119   stopwatch_reset() {
120     name="${1:-stopwatch}"
121     [ "${nao}" ] || nao="$(date +%s)"
122     kvs_unset stopwatch "${name}"
123     kvs_unset stopwatch "${name}_accumulator"
124     printf "Stopwatch: %s is reset to 0s.\n" "${name}"
125   }
126
127   stopwatch() {
128     [ "${1}" -a "${2}" ] || stopwatch_help;
129     nao="$(date +%s)"
130     case "${2}" in
131     [Ss][Tt][Aa][Rr][Tt])  stopwatch_start "${1}"  ;;
132     [Ll][Aa][Pp])          stopwatch_lap "${1}"    ;;
133     [Ss][Tt][Oo][Pp])      stopwatch_stop "${1}"   ;;
134     [Rr][Ee][Ss][Ee][Tt])  stopwatch_reset "${1}"  ;;
135     *)                     stopwatch_help          ;;
136     esac
137   }
138 fi