#!/bin/bash
### bash 'strict mode' boilerplate
set -x                                              # Print commands and their arguments as they are executed.
set -e                                              # Exit immediately if a command exits with a non-zero status.
set -u                                              # Treat unset variables as an error when interpolated
set +H                                              # Disable !-style history substitution
set -o pipefail                                     # the last command in a pipeline to return non-0 sets the whole pipe's exit
IFS=$'\n\t'                                         # Remove space from word-splitting behavior

### utility functions
function fail! {
  set +x                                            # disable tracing for readability
  set -e                                            # make sure the program exits when we throw this error
  set +u                                            # allow interpolation of unset variables
  local runner="${BASH_SOURCE[-1]}"                 # set the runner to the originating script
  local msg="${1:-"(no failure message provided)"}" # default to announcing we don't have an error
  local code=${2-1}                                 # default to exit code 1
  set -u                                            # disallow interpolation of unset variables
  msg=$'\t'"${msg//$'\n'/$'\n\t'}"                  # indent the message for readability
  (
    >&2 printf '%s:\n%s\n' "${runner}" "${msg}";    # Send message to stderr.
    exit "${code}"                                  # exit with the designated code
  )
}

function is_int? {
  set +u                                            # allow interpolation of unset variables
    local chk=${1#[+-]};                            # deletes any existing sign in the front
  set -u                                            # disallow interpolation of unset variables
    [ -n "${chk}" ] && [ -z "${chk//[0-9]}" ]       # removes all pattern matched characters, and checks the resulting string is blank
}

function is_float? { 
  set +u                                            # allow interpolation of unset variables
    local chk=${1#[+-]};                            # deletes any existing sign in the front
  set -u                                            # disallow interpolation of unset variables
    chk=${chk/.}                                    # removes the first period in a string
    [ -n "${chk}" ] && [ -z "${chk//[0-9]}" ]       # removes all pattern matched characters, and checks the resulting string is blank
}
