#!/bin/bash
# Shows a spinner while another command is running. Randomly picks one of 12 spinner styles.
# @args command to run (with any parameters) while showing a spinner. 
#       E.g. ‹spinner sleep 10›

function shutdown() {
  tput cnorm # reset cursor
}
trap shutdown EXIT

function cursorBack() {
  echo -en "\033[$1D"
}

function spinner() {
  # make sure we use non-unicode character type locale 
  # (that way it works for any locale as long as the font supports the characters)
  local LC_CTYPE=C

  local pid=$1 # Process Id of the previous running command

  case $(($RANDOM % 12)) in
  0)
    local spin='⠁⠂⠄⡀⢀⠠⠐⠈'
    local charwidth=1
    ;;
  1)
    local spin='-\|/'
    local charwidth=1
    ;;
  2)
    local spin="▁▂▃▄▅▆▇█▇▆▅▄▃▂▁"
    local charwidth=1
    ;;
  3)
    local spin="▉▊▋▌▍▎▏▎▍▌▋▊▉"
    local charwidth=1
    ;;
  4)
    local spin='←↖↑↗→↘↓↙'
    local charwidth=1
    ;;
  5)
    local spin='▖▘▝▗'
    local charwidth=1
    ;;
  6)
    local spin='┤┘┴└├┌┬┐'
    local charwidth=1
    ;;
  7)
    local spin='◢◣◤◥'
    local charwidth=1
    ;;
  8)
    local spin='◰◳◲◱'
    local charwidth=1
    ;;
  9)
    local spin='◴◷◶◵'
    local charwidth=1
    ;;
  10)
    local spin='◐◓◑◒'
    local charwidth=1
    ;;
  11)
    local spin='⣾⣽⣻⢿⡿⣟⣯⣷'
    local charwidth=1
    ;;
  esac

  local i=0
  tput civis # cursor invisible
  while kill -0 $pid 2>/dev/null; do
    local i=$(((i + $charwidth) % ${#spin}))
    printf "%s" "${spin:$i:$charwidth}"

    cursorBack 1
    sleep .1
  done
  tput cnorm
  wait $pid # capture exit code
  return $?
}

("$@") &

tput setaf $((RANDOM % 256))
spinner $!