Posted to tcl by msiism at Tue Jun 12 23:18:11 GMT 2018view raw
- #!/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