#!/usr/bin/env bash
# Creates an obnoxious alert that is good for important, but
# long-running processes that you want to know if they stop early. To
# use, simply append to a command line, as in:
#
#     command-one ; beep
#
# It also works in a series:
#
#     command-one && beep && command-two && beep
#
# Of course, in this second case, you'd want to give the 'beep' the
# name of the command, as in:
#
#     command-one && beep "The first" && command-two && beep "The second"
#
# This script, along with attempting to speak the exit message, can
# also use the `terminal-notifier' program (on later Mac versions
# after the demise of Growl), so you can specify both the command and
# details about the message with options. Of course, using the script
# this way is getting into the realm where this script is part of
# another script.
#
# This program is quite Mac specific, in that it expects the sounds
# files in a particular location as well as the existence of the
# `aplay' command, etc.


# We first need to capture the status of the previous command, however,
# this feature no longer works in the latest version of Mac's OS:
ERROR=$?

unset MESSAGE

function available {
    which "$1" >/dev/null 2>&1
}

while getopts "b:c:m:" o $*
do
    case "$o" in
        b)  AUDIO=/System/Library/Sounds/$OPTARG.aiff;;
        c)  CMD_STR="$OPTARG";;
        m)  MESSAGE="$OPTARG";;
        [?])    print >&2 "Usage: $0 [-b audio] [-m message] [-c] command-name"
            exit 1;;
    esac
done
shift $((OPTIND-1))

# I would like the -c argument to be truly optional, so that if words
# are just given, they are automatically assumed to have a -c in front.

CMD_STR="$CMD_STR $*"

# If we were given the command to run as arguments, do that, and reset the ERROR
# variable to the new status code.
if [[ -n $CMD_STR ]]
then
    COMMAND=$(echo "$CMD_STR" | cut -d' ' -f1)
    $CMD_STR
    ERROR=$?
else
    COMMAND='The command'
fi

# Default value for the audio depends on the success or failure
# of the previous command... and do we have Failure wave file.
if (( ERROR == 0 ))
then
    AUDIO=/System/Library/Sounds/Ping.aiff
else
    AUDIO=/System/Library/Sounds/Glass.aiff
fi

# Craft a message based on the status of the command:
if [[ -z $MESSAGE ]]
then
    if (( ERROR == 0 ))
    then
        MESSAGE="$COMMAND has completed."
    else
        MESSAGE="$COMMAND has failed."
    fi
fi

if [[ $INSIDE_EMACS = vterm ]]
then
    vterm_cmd() {
        local vterm_elisp
        vterm_elisp=""
        while [ $# -gt 0 ]; do
            vterm_elisp="$vterm_elisp""$(printf '"%s" ' "$(printf "%s" "$1" | sed -e 's|\\|\\\\|g' -e 's|"|\\"|g')")"
            shift
        done

        printf "\e]%s\e\\" "51;E$vterm_elisp"
    }

    vterm_cmd message "$MESSAGE"
fi

if available terminal-notifier
then
    terminal-notifier -message "$MESSAGE" -title "Process Complete"
fi

if available aplay
then
    aplay $AUDIO
else
    afplay $AUDIO
fi

if available say
then
    say "$MESSAGE"
fi

# In case we are still using && on the command line, we need to
# pass on the failure... and since we really can't assign $?
exit $ERROR
