Skip to content

Instantly share code, notes, and snippets.

@lstellway
Last active March 2, 2022 23:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lstellway/f39a56af20115c30d6eecdb72b17afc0 to your computer and use it in GitHub Desktop.
Save lstellway/f39a56af20115c30d6eecdb72b17afc0 to your computer and use it in GitHub Desktop.
Shell-based timer for `bash` and `zsh`
# Read a message using the OSX `say` command
#
# In my opinion, the best voices for American English seem to be:
# 'Daniel', 'Karen', 'Rishi', 'Tessa'
export TIMER_COMMAND="say -v Karen --interactive=bold '%s'"
# Hide tty input while command is running
_timer_tty_off() {
[ -t 0 ] && stty -echo -icanon time 0 min 0
}
# Reset tty input settings
_timer_tty_on() {
[ -t 0 ] && stty sane
}
# Helper for `read`
_timer_read_a() {
[ -n "$ZSH_VERSION" ] && printf "A" || printf "a"
}
# Get the current system time in seconds
_timer_seconds() {
printf '%d' "$(date +%s)"
}
# Set a timer
#
# string time (HH:MM:SS - eg. 01:15:21)
# array message (Arguments sent to a configured command when timer finishes)
timer() {
trap _timer_tty_on EXIT
_timer_tty_off
TIME=${1// /}
# Ensure a time is specified
if [ -z "${TIME}" ]; then
printf "Please specify a time in 'hh:mm:ss' format\n"
_timer_tty_on
return 1
fi
# Parse time to array
local -a HMS
IFS=':' read -r"$(_timer_read_a)" HMS <<< "${TIME}"
# Calculate the size of the array
local N=${#HMS[@]}
# Get current time in seconds
local START=0
START=$(_timer_seconds)
# Get time values
local SECONDS=0
SECONDS="${HMS[@]:$N-1:1}"
local MINUTES=0
[ "${N}" -gt 1 ] && MINUTES="${HMS[@]:$N-2:1}"
local HOURS=0
[ "${N}" -gt 2 ] && HOURS="${HMS[@]:$N-3:1}"
# Calculate time in seconds
local DURATION=$(( SECONDS + (MINUTES * 60) + (HOURS * 60 * 60) ))
# Calculate end time
local END=0
END=$(printf '%d' $((START + DURATION)))
# Output
printf "Timer started at %s\n" "$(date -r "${START}" '+%D %T')"
# Show progress
CURRENT=$(_timer_seconds)
while [ "${CURRENT}" -lt "${END}" ]; do
# Calculate remaining time in seconds
REMAINING=$(( END - CURRENT ))
printf "\rRemaining %0.2d:%0.2d:%0.2d\e[K" $(( REMAINING / 60 / 60 )) $(( (REMAINING/60) % 60 )) $(( REMAINING % 60 ))
sleep 1
# Update current time
CURRENT=$(_timer_seconds)
done
printf "\nTimer finished at %s\n" "$(date -r "${END}" '+%D %T')"
if [ -n "${TIMER_COMMAND}" ] && [ -n "${2}" ]; then
eval $(printf "${TIMER_COMMAND}" "${@:2}")
fi
_timer_tty_on
}
@lstellway
Copy link
Author

lstellway commented Mar 2, 2022

Example usage:

timer 5:00 'Go make some delicious coffee!'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment