diff --git a/scripts/termux-dialog b/scripts/termux-dialog index d196eff..665fba6 100755 --- a/scripts/termux-dialog +++ b/scripts/termux-dialog @@ -1,55 +1,254 @@ -#!/data/data/com.termux/files/usr/bin/sh +#!/data/data/com.termux/files/usr/bin/bash set -e -u +DEFAULT_WIDGET="text" + SCRIPTNAME=termux-dialog -show_usage () { - echo "Usage: $SCRIPTNAME [-i hint] [-m] [-p] [-t title] [-w widget]" - echo "Show a text entry dialog." - echo " -i hint the input hint to show when the input is empty" - echo " -m use a textarea with multiple lines instead of a single" - echo " -p enter the input as a password" - echo " -t title the title to show for the input prompt" - echo " -w widget widget type to use: confirm, text, date, time, spinner, or speech" - echo " -v values [,,,] values to use w/ spinner widget" +show_usage() { + echo "Usage: $SCRIPTNAME widget [options]" + echo "Get user input w/ different widgets! Default Widget: $DEFAULT_WIDGET" + echo " -h, help Show this help" + echo " -l, list Full list all available widgets and their options" + echo " -t, title Set title of input dialog" exit 0 } -PARAMS="" +declare -a widgets=("confirm" "checkbox" "counter" "date" "radio" "sheet" "spinner" "text" "time") +# Descriptions for various options that multiple widgets can use +OPT_HINT_DESC="[-i hint] text hint (optional)" +OPT_MULTI_LINE_DESC="[-m multi-line] use a textarea with multiple lines instead of single (optional)" +OPT_PASS_DESC="[-p password] enter input as password (optional)" +OPT_TITLE_DESC="[-t title] dialog title (optional)" +OPT_RANGE_DESC="[-r range] min,max,start where each value is a number (optional)" +OPT_VALUES_DESC="[-v values] comma delimited string of values to use (required)" + +# Widget hints ARG_I="" OPT_I="" + +# Text widget multiline ARG_M="" + +# Counter range +ARG_R="" +OPT_R="" + +# Text widget input as password ARG_P="" + +# Dialog title (supported by all widgets) ARG_T="" OPT_T="" + +# Values for list-type widgets OPT_V="" ARG_V="" -# Use default values to preserve backwards compatibility w/ older dialog implementation -OPT_W="text" +# Widget type +ARG_W="" +WIDGET="" + +# Flags for detecting invalid option combinations +HINT_FLAG=1 +MULTI_LINE_FLAG=2 +PASS_FLAG=4 +RANGE_FLAG=8 +VALUES_FLAG=16 + +FLAGS=0 + + +# Show usage help for specific widget +widget_usage () { + echo -n -e "$1 \t" + + case "$1" in + "confirm") + echo -e "Show confirmation dialog" + echo -e "\t\t$OPT_TITLE_DESC" + echo -e "\t\t$OPT_HINT_DESC" + ;; + "checkbox") + echo -e "Select multiple values using checkboxes" + echo -e "\t\t$OPT_VALUES_DESC" + echo -e "\t\t$OPT_TITLE_DESC" + ;; + "counter") + echo -e "Pick a number in specified range" + echo -e "\t\t$OPT_TITLE_DESC" + echo -e "\t\t$OPT_RANGE_DESC" + ;; + "date") + echo -e "\tPick a date" + echo -e "\t\t$OPT_TITLE_DESC" + ;; + "radio") + echo -e "\tPick a single value from radio buttons" + echo -e "\t\t$OPT_VALUES_DESC" + echo -e "\t\t$OPT_TITLE_DESC" + ;; + "sheet") + echo -e "\tPick a value from a sliding bottom sheet interface" + echo -e "\t\t$OPT_VALUES_DESC" + echo -e "\t\t$OPT_TITLE_DESC" + ;; + "spinner") + echo -e "Pick a single value from a dropdown spinner" + echo -e "\t\t$OPT_VALUES_DESC" + echo -e "\t\t$OPT_TITLE_DESC" + ;; + "text") + echo -e "\tInput text (default if no widget specified)" + echo -e "\t\t$OPT_HINT_DESC" + echo -e "\t\t$OPT_PASS_DESC -- cannot use with -m" + echo -e "\t\t$OPT_TITLE_DESC" + echo -e "\t\t$OPT_MULTI_LINE_DESC -- cannot use with -p" + ;; + "time") + echo -e "\tPick a time value" + echo -e "\t\t[-p title] dialog title (optional)" + ;; + *) + echo -e "\tUnknown usage for '$1'" + ;; + esac +} + +# List all widgets +list_widgets() { + echo "Supported widgets:" + echo + + for w in "${widgets[@]}"; do + widget_usage $w + echo + done +} + +# Checks to see if widgets array contains specified widget +has_widget () { + for w in "${widgets[@]}"; do + [ "$w" == "$1" ] && return 0 + done + return 1 +} + +set_flag () { + FLAGS=$((FLAGS | $1)); +} + +# Convenience method to get all supported options, regardless of specified widget +# NOTE: Option combination validation doesn't occur here +parse_options() { + while getopts :hlmpr:i:t:v: option + do + case "$option" in + h) show_usage ;; + l) list_widgets; exit 0;; + i) ARG_I="--es input_hint"; OPT_I="$OPTARG"; set_flag $HINT_FLAG; ;; + m) ARG_M="--ez multiple_lines true"; set_flag $MULTI_LINE_FLAG; ;; + p) ARG_P="--es input_type password"; set_flag $PASS_FLAG; ;; + t) ARG_T="--es input_title"; OPT_T="$OPTARG" ;; + v) ARG_V="--es input_values"; OPT_V="$OPTARG"; set_flag $VALUES_FLAG; ;; + r) ARG_R="--eia input_range"; OPT_R=$OPTARG; set_flag $RANGE_FLAG; ;; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac + done +} + +options_error () { + echo -e "ERROR: Invalid option(s) detected for '$1'\n" + echo "Usage '$1'" + widget_usage $1 + exit 1 +} + +if [ $# -eq 0 ]; then + WIDGET=$DEFAULT_WIDGET +# First argument wasn't a widget +elif ! has_widget $1; then + # we didn't receive a widget as an argument, check to see if we + # at least options (even if they're illegal) + if ! [[ $1 =~ -[a-z] ]]; then + echo -e "ERROR: Illegal argument $1\n" + show_usage + fi + WIDGET=$DEFAULT_WIDGET +else + WIDGET=$1 + shift +fi + +parse_options "$@" +shift $((OPTIND - 1)) + +# Ensure proper option combinations for the specific type of widget +case "$WIDGET" in + # Text (default) if no widget specified + "text") + if [ $((FLAGS & (RANGE_FLAG | VALUES_FLAG))) -ne 0 ]; then + options_error $WIDGET + fi + + if [ $((FLAGS & MULTI_LINE_FLAG)) -ne 0 ] && [ $((FLAGS & PASS_FLAG)) -ne 0 ]; then + options_error $WIDGET + fi + ;; + + "confirm") + if [ $((FLAGS & (MULTI_LINE_FLAG | PASS_FLAG | RANGE_FLAG | VALUES_FLAG))) -ne 0 ]; then + options_error $WIDGET + fi + ;; + + "counter") + if [ $((FLAGS & (MULTI_LINE_FLAG | PASS_FLAG | VALUES_FLAG))) -ne 0 ]; then + options_error $WIDGET + fi + ;; + + "date" | "speech" | "time") + if [ $# -gt 0 ]; then + echo "ERROR: '$WIDGET' takes no arguments"; exit 1; + fi + + if [ $((FLAGS & (HINT_FLAG | MULTI_LINE_FLAG | PASS_FLAG | RANGE_FLAG | VALUES_FLAG))) -ne 0 ]; then + options_error $WIDGET + fi + ;; + + "checkbox" | "radio" | "sheet" | "spinner") + if [ "$ARG_V" == "" ]; then + echo "ERROR: '$WIDGET' must be called with $OPT_VALUES_DESC" + exit 1 + fi + + if [ $((FLAGS & (HINT_FLAG | MULTI_LINE_FLAG | PASS_FLAG | RANGE_FLAG))) -ne 0 ]; then + options_error $WIDGET + fi + ;; + + *) + echo "$SCRIPTNAME: unsupported widget '$WIDGET'"; show_usage ;; +esac + +# All valid args should be consumed by this point +if [ $# -gt 0 ]; then + echo "ERROR: Too many arguments!" + show_usage +fi + ARG_W="--es input_method" -while getopts :hi:mpt:v:w: option -do - case "$option" in - h) show_usage;; - i) ARG_I="--es input_hint"; OPT_I="$OPTARG";; - m) ARG_M="--ez multiple_lines true";; - p) ARG_P="--es input_type password";; - t) ARG_T="--es input_title"; OPT_T="$OPTARG";; - w) ARG_W="--es input_method"; OPT_W="$OPTARG";; - v) ARG_V="--es input_values"; OPT_V="$OPTARG";; - ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; - esac -done -shift $(($OPTIND-1)) - -# if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi - -set -- $ARG_M $ARG_P +# Set options, ensuring whitespace isn't lost +if [ -n "$ARG_W" ]; then set -- "$@" $ARG_W "$WIDGET"; fi if [ -n "$ARG_I" ]; then set -- "$@" $ARG_I "$OPT_I"; fi if [ -n "$ARG_T" ]; then set -- "$@" $ARG_T "$OPT_T"; fi +if [ -n "$ARG_R" ]; then set -- "$@" $ARG_R "$OPT_R"; fi if [ -n "$ARG_V" ]; then set -- "$@" $ARG_V "$OPT_V"; fi -if [ -n "$ARG_W" ]; then set -- "$@" $ARG_W "$OPT_W"; fi +if [ -n "$ARG_M" ]; then set -- "$@" $ARG_M ""; fi +if [ -n "$ARG_P" ]; then set -- "$@" $ARG_P ""; fi + /data/data/com.termux/files/usr/libexec/termux-api Dialog "$@"