# Simple bourne shell based stopwatch # Requires 'kvs' and the id 'stopwatch' therein # so make sure you set 'kvs' before sourcing this script if necessary. # # After loading, the following commands are available: # # Start a stopwatch: # stopwatch start # # 'Lap' a stopwatch # stopwatch lap # # Stop a stopwatch # stopwatch stop # # Reset a stopwatch # stopwatch reset if [ -z "${__stopwatch_sh_loaded}" ] then __stopwatch_sh_loaded=yes [ "${kvs}" ] || kvs="$(mktemp -t ".stopwatch.XXXXXXXX")" want kvs stopwatch_help() { echo "Usage: stopwatch " >&2 exit 1 } # Try and format a passed integer number of seconds into something more # useful (like 6m10s or something) _stopwatch_timefmt() { local secs mins hurs days [ "${1}" -a "$(echo "${1}" | tr -Cd '0-9')" = "${1}" ] || return 255 secs="${1}" mins=0 hurs=0 [ "${secs}" -lt 60 ] || { mins=$(( ${secs} / 60 )) secs=$(( ${secs} % 60 )) } [ "${secs}" -gt 0 ] || secs="" [ "${mins}" -lt 60 ] || { hurs=$(( ${mins} / 60 )) mins=$(( ${mins} % 60 )) } [ "${mins}" -gt 0 ] || mins="" [ "${hurs}" -lt 24 ] || { days=$(( ${hurs} / 24 )) hurs=$(( ${hurs} % 24 )) } [ "${hurs}" -gt 0 ] || hurs="" [ "${days}" -o "${hurs}" -o "${mins}" -o "${secs}" ] || printf "0s" printf "%s%s%s%s" "${days:+${days}d}" "${hurs:+${hurs}h}" "${mins:+${mins}m}" "${secs:+${secs}s}" } # Start a named stopwatch, but do nothing if the named stopwatch is already # running. stopwatch_start() { name="${1:-stopwatch}" [ "${nao}" ] || nao="$(date +%s)" # Is the stopwatch running? if kvs_has_key stopwatch "${name}" then printf "Stopwatch: %s is already running.\n" "${name}" else # start the stopwatch accum="$(kvs_get stopwatch "${name}_accumulator")" kvs_set stopwatch "${name}" "${nao}" [ "${accum}" ] && restart="$(printf " at %s" "$(_stopwatch_timefmt "${accum}")")" printf "Stopwatch: %s starts running%s.\n" "${name}" "${restart}" fi } # 'Lap' the named stopwatch: print out a line indicating how long the named # stopwatch has been running, but do not stop nor reset the stopwatch. stopwatch_lap() { name="${1:-stopwatch}" [ "${nao}" ] || nao="$(date +%s)" # Is the stopwatch running? if kvs_has_key stopwatch "${name}" then # emit a line indicating how long it has been running start="$(kvs_get stopwatch "${name}")" accum="$(kvs_get stopwatch "${name}_accumulator")" delta="$(( ${nao} - ${start} ))" [ "${accum}" ] && delta="$(( ${delta} + ${accum} ))" printf "Stopwatch: %s is running at %s.\n" "${name}" "$(_stopwatch_timefmt "${delta}")" else accum="$(kvs_get stopwatch "${name}_accumulator")" [ "${accum}" ] && printf "Stopwatch: %s is stopped at %s.\n" "${name}" "$(_stopwatch_timefmt "${accum}")" fi } # Stop the named stopwatch and print out a line indicating how long it had # been running up until that point; do not reset the stopwatch. stopwatch_stop() { name="${1:-stopwatch}" [ "${nao}" ] || nao="$(date +%s)" if kvs_has_key stopwatch "${name}" then start="$(kvs_get stopwatch "${name}")" accum="$(kvs_get stopwatch "${name}_accumulator")" delta="$(( ${nao} - ${start} ))" [ "${accum}" ] && delta="$(( ${delta} + ${accum} ))" kvs_set stopwatch "${name}_accumulator" "${delta}" kvs_unset stopwatch "${name}" printf "Stopwatch: %s stops running at %s.\n" "${name}" "$(_stopwatch_timefmt "${delta}")" else accum="$(kvs_get stopwatch "${name}_accumulator")" [ "${accum}" ] && printf "Stopwatch: %s is already stopped at %s.\n" "${name}" "$(_stopwatch_timefmt "${accum}")" fi } # Reset the named stopwatch back to zero. stopwatch_reset() { name="${1:-stopwatch}" [ "${nao}" ] || nao="$(date +%s)" kvs_unset stopwatch "${name}" kvs_unset stopwatch "${name}_accumulator" printf "Stopwatch: %s is reset to 0s.\n" "${name}" } stopwatch() { [ "${1}" -a "${2}" ] || stopwatch_help; nao="$(date +%s)" case "${2}" in [Ss][Tt][Aa][Rr][Tt]) stopwatch_start "${1}" ;; [Ll][Aa][Pp]) stopwatch_lap "${1}" ;; [Ss][Tt][Oo][Pp]) stopwatch_stop "${1}" ;; [Rr][Ee][Ss][Ee][Tt]) stopwatch_reset "${1}" ;; *) stopwatch_help ;; esac } fi