Posted to tcl by msiism at Tue Jun 12 23:18:11 GMT 2018view pretty
#!/bin/bash # # VHG # # A versatile virtual hourglass # # Version 1.0 # # # Copyright Michael Siegel 2018 # # <LICENSE NOTE> (GPL 3) # --- SHELL CONFIGURATION --- # --- ENVIRONMENT CHECKS --- # check for sound playing utilities? # aplay? (WAV) # mpeg # ogg # --- VARIABLE DECLARATIONS --- cmd_name="${0##*/}" # Get basename of this script version="1.0" cmd_info="A versatile virtual hourglass" use_info="" # Add usage info help_info="Run '$cmd_name -h' for help" sw_info="" # Add info on switches help="$cmd_name $version\n$cmd_info\n\n$use_info\n\n$sw_info" # An array containing all available switches sw_list=(-h --help -V --version -t --time -m --message -s --sound) sw_count="${#sw_list[@]}" # Number of elements in $sw_list t= # time value m= # alarm message (can start with - or --) # Defining a default message here and using that as an argument to f_alarm in # Main when no message was set would make more than half of the code in f_alarm # obsolete. But it's kind of illogical and bad style. s= # Will be set to 1 if -s is specified so vhg will play a sound on alarm. # Do not set this to any value. Parameter handling relies on $s being # not set at the beginning. s_file=~/.vhg/alarm.wav # Location of alarm sound file (Do not quote, or ~ # won't be expanded.) # --- FUNCTIONS --- function f_t_check { # Perform string checks on the specified time value and set 't' conditonally local t_spec="$1" if [[ "$t_spec" != +([[:digit:]])*([d|h|m|s]) ]] # Wrong... # If $1 is NOT one or more (+()) digit(s), optionally followed by one of the # letters d, h, m or s (*() is "zero or more") then printf "$cmd_name: Invalid argument\n" >&2 exit 1 else t="$t_spec" fi } function f_t_conv { # Convert the specified time value into a word expression that will be used # as the default alarm message local t_spec="$1" local t_dig= # Digit part of the specified time local t_unit= # Unit part of the specified time local t_be= # Form of be to use in the message (is or are) case "$t_spec" in *d) # Time specified in days t_dig="${t_spec%d}" # Get the digit part of the specified time if [ "$t_dig" -gt 1 ] # If the number is greater than 1 then t_unit="days" t_be="are" else t_unit="day" t_be="is" fi ;; *h) # Time specified in hours t_dig="${t_spec%h}" # Get the digit part of the specified time if [ "$t_dig" -gt 1 ] # If the number is greater than 1 then t_unit="hours" t_be="are" else t_unit="hour" t_be="is" fi ;; *m) # Time specified in minutes t_dig="${t_spec%m}" # Get the digit part of the specified time if [ "$t_dig" -gt 1 ] # If the number is greater than 1 then t_unit="minutes" t_be="are" else t_unit="minute" t_be="is" fi ;; *s|*) # Time specified in second (30s or 30, for example) t_dig="${t_spec%s}" # Get the digit part of the specified time if [ "$t_dig" -gt 1 ] # If the number is greater than 1 then t_unit="seconds" t_be="are" else t_unit="second" t_be="is" fi ;; esac printf "$t_dig $t_unit $t_be up!" } function f_alarm { # Print an alarm message on the CLI or via Xmessage, conditionally. # Also play a sound if -s is specified. local m_spec="$m" local m_default="$(f_t_conv "$t")" if [ ! "$m_spec" ] then m_spec="$m_default" fi if [ "$s" == 1 ] then aplay "$s_file" > /dev/null 2>&1 & # if you don't redirect the output, aplay will print to stdout, bringing # itself back into the foreground and block the shell until you hit enter # check for aplay up in the environment checks section fi # Select output module if [ "$DISPLAY" ] # If the script is run from X then if [ "$(type -p tkbash)" ] then ./gui/vhg-tk "$m_spec" # Use tkbash else ./gui/vhg-x "$m_spec" # Use Xmessage fi else printf "%s\n" "$cmd_name: $m_spec" fi } # --- PARAMETER PROCESSING --- # display help content on user fuck-up if [ "$#" == 0 ] # If the script is run without parameters then printf "%b\n" "$help" exit else # Process parameters in order of complexity i="$#" while [ "$#" -gt 0 ] do if [ "$#" -eq "$i" ] # Process basic switches only if they occur first and let them fall victim to # general error handling otherwise. then case "$1" in -h|--help) printf "%b\n" "$help" exit ;; -V|--version) printf "%s\n" "$cmd_name $version" exit ;; esac fi case "$1" in -s|--sound) if [ "$s" ] # If 's' has already been set then printf "$cmd_name: -s already specified\n" >&2 exit 1 else shift s=1 fi ;; -t|--time) if [ "$t" ] # If 't' has already been set then printf "$cmd_name: -t already specified\n" >&2 exit 1 else shift if [ "$#" -eq 0 ] # If there is no following parameter then printf "$cmd_name: Missing argument\n" >&2 # printf "$help_info\n" exit 1 else # Check if $1 is a known/valid switch valid=0 for((c=0; c<"$sw_count"; c++)) # Loop through the array of switches do if [ "$1" == "${sw_list[$c]}" ] # If array element matches $1 then valid=1 break fi done if [ "$valid" == 1 ] # If $1 is a known switch then printf "$cmd_name: Missing argument\n" >&2 exit 1 else f_t_check "$1" # Sets the t variable shift fi fi fi ;; -m|--message) if [ "$m" ] # If 'm' has already been set then printf "$cmd_name: -m already specified\n" >&2 exit 1 else shift if [ "$#" -eq 0 ] # If there is no following parameter then printf "$cmd_name: Missing argument\n" >&2 exit 1 else # Check if $1 is a known/valid switch valid=0 for((c=0; c<"$sw_count"; c++)) do if [ "$1" == "${sw_list[$c]}" ] # If array element matches $1 then valid=1 break fi done if [ "$valid" == 1 ] then printf "$cmd_name: Missing argument\n" >&2 exit 1 else m="$1" # Set $1 as the alarm message shift fi fi fi ;; *) printf "$cmd_name: Invalid argument\n" >&2 # like, e.g., --help sepcified at the second position exit 1 ;; esac done fi # --- MAIN --- if [ "$t" ] then # Run sleep and f_alarm as one job in the background so the shell won't be # blocked. sleep "$t" && f_alarm & # The above will print sth out, bring the job back to the foreground and # therefore block the shell until the user hits enter. else # No time value specified printf "$cmd_name: Missing argument\n" >&2 fi