#!/bin/sh
# curl -s http://www.mpaoli.net/~michael/bin/bclock

# display a big ASCII clock, update every second, and reasonably
# feasibly close to on the second.

# vi(1) :se tabstop=4

set -e # bail on fail

# Use temporary file for tracking sub-second accuracy
# our filesystem for that happens to support that.
t="$(mktemp)"

rc=0 # return code / exit value

# Our cleanups:
trap "trap - 0; rm $t; exit "'"$rc"' 0
for sig in 1 2 3 15
do
	trap '
		trap - 0
		rm '"$t"' || exit
		trap - '"$sig"'
		kill -'"$sig"' "$$"
	' "$sig"
done

while :
do
	{
		r="$(date +%r)" &&
		set -- $r &&
		clear && # clear screen and
		banner "$1" && # display HH:MM:SS large
		>"$t" # "touch" our temporary file
	} || {
		rc="$?"
		break
	}

	# Examine our mtime on the file, determine any fractional part
	# beyond the second
	{
		over="$(stat -c '%y' "$t")" &&
		over="$(
			sed -ne 's/^[^.]*\(\.[0-9][0-9]*\).*$/\1/p' <<- __EOT__
				$over
			__EOT__
		)"
	} || {
		rc="$?"
		break
	}

	# If we got over (above), subtract that from 1,
	# that's then the fractional part of a second we should wait to
	# almost exactly land us atop the turning over of the next second
	sleep=
	{
		[ -z "$over" ] || sleep="$(echo 1-"$over" | bc -l)"
	} || {
		rc="$?"
		break
	}
	# If we didn't get that calculated fractional bit, fallback to 1
	[ -n "$sleep" ] || sleep=1

	# Wait (sleep) our calculated (or fallback of 1) second(s) -
	# nomially a franctional part of a second.
	sleep "$sleep" || {
		rc="$?"
		break
	}

	# Alternative commented out code, that would wait until about the
	# roll-over of the 1/4 minute - essentially each 15 seconds
	# s=$(expr 15 - \( $(date +%S) % 15 \))
	# [ "$s" -ne 0 ] || s=15
	# sleep "$s"
done

# one-liner for line-by line updates on about the second:
# sh -c 'set -e; t="$(mktemp)"; rc=0; trap "trap - 0; rm $t; exit \"\$rc\"" 0; for sig in 1 2 3 15; do trap "trap - 0; rm \"\$t\" || exit; trap - $sig; kill -$sig \"\$\$\"" "$sig"; done; while :; do { date -Iseconds && >"$t" && sleep=$(stat -c \%y "$t" | sed -ne '\''s/^[^.]*\(\.[0-9][0-9]*\).*$/1-\1/p'\'' | bc -l) && [ -n "$sleep" ] && sleep "$sleep"; } || { rc="$?"; break; }; done'
