tzselect: User input/output through one function Which can be 'overriden' in the calling process as $SHOWDIALOG With this, tzselect can be used by other scripts with a customized user dialog. Better solutions are welcome! Example call: SHOWDIALOG=$PWD/tzselect_dialog tzselect where tzselect_dialog imitates the function showdialog() of tzselect. see: https://github.com/Wuodan/tz/commit/5297b9ca06f79c334b9492713ce388b590e436e3 This file was created using: git diff 3da9649d321d9208badaf941fc59ae93b42bb4c7 54b3d917f406db7d31bfd0f4b4db8d529fa3d619 tzselect.ksh diff --git a/tzselect.ksh b/tzselect.ksh index 3acdebd..9280fb9 100644 --- a/tzselect.ksh +++ b/tzselect.ksh @@ -36,6 +36,7 @@ REPORT_BUGS_TO=tz@iana.org # Specify default values for environment variables if they are unset. : ${AWK=awk} : ${TZDIR=`pwd`} +: ${SHOWDIALOG=showdialog} # Check for awk Posix compliance. ($AWK -v x=y 'BEGIN { exit 123 }') /dev/null 2>&1 @@ -73,9 +74,10 @@ Options: Report bugs to $REPORT_BUGS_TO." # Ask the user to select from the function's arguments, -# and assign the selected argument to the variable 'select_result'. +# and print selected argument # Exit on EOF or I/O error. Use the shell's 'select' builtin if available, # falling back on a less-nice but portable substitute otherwise. +# First argument is the message preceeding the selection if case $BASH_VERSION in ?*) : ;; @@ -88,11 +90,15 @@ then # even though it is never executed. eval ' doselect() { + # print message first + echo >&2 "${1}" + shift select select_result do case $select_result in "") echo >&2 "Please enter a number in range." ;; - ?*) break + # print result + ?*) echo -n "${select_result}"; break esac done || exit } @@ -107,6 +113,9 @@ then ' else doselect() { + # print message first + echo >&2 "${1}" + shift # Field width of the prompt numbers. select_width=`expr $# : '.*'` @@ -128,6 +137,8 @@ else if test 1 -le $select_i && test $select_i -le $#; then shift `expr $select_i - 1` select_result=$1 + # print result + echo -n "${select_result}" break fi echo >&2 'Please enter a number in range.' @@ -140,6 +151,38 @@ else } fi +# showdialog() +# All normal user input/output goes through this function +# +# The user dialog of this script can be altered by setting +# the SHOWDIALOG variable as in: +# SHOWDIALOG=$PWD/tzselect_dialog tzselect +# where 'tzselect_dialog' imitates this function +# +# Arguments: +# Type: one of: menu, yesno, msgbox, inputbox +# Message: text to display +# Options: menu-options, only for types menu and yesno +# +showdialog() { + # action depends on first argument + case "${1}" in + menu|yesno) + shift + doselect "${@}" + return $? ;; + msgbox) + echo >&2 "${2}" + return 0 ;; + inputbox) + echo >&2 "${2}" + read INPUTBOX + echo -n "${INPUTBOX}" + return 0 ;; + esac + return 1 +} + while getopts c:n:t:-: opt do case $opt$OPTARG in @@ -270,8 +313,7 @@ output_distances=' # Begin the main loop. We come back here if the user wants to retry. while - echo >&2 'Please identify a location' \ - 'so that time zone rules can be set correctly.' + dialogtext='Please identify a location so that time zone rules can be set correctly.' continent= country= @@ -284,7 +326,8 @@ while # Ask the user for continent or ocean. - echo >&2 'Please select a continent, ocean, "coord", or "TZ".' + dialogtext="${dialogtext} +Please select a continent, ocean, \"coord\", or \"TZ\"." quoted_continents=` $AWK ' @@ -304,10 +347,9 @@ while ` eval ' - doselect '"$quoted_continents"' \ + continent=`"${SHOWDIALOG}" menu '\'"${dialogtext}"\'' '"$quoted_continents"' \ "coord - I want to use geographical coordinates." \ - "TZ - I want to specify the time zone using the Posix TZ format." - continent=$select_result + "TZ - I want to specify the time zone using the Posix TZ format."` || exit $? case $continent in Americas) continent=America;; *" "*) continent=`expr "$continent" : '\''\([^ ]*\)'\''` @@ -319,11 +361,9 @@ while TZ) # Ask the user for a Posix TZ string. Check that it conforms. while - echo >&2 'Please enter the desired value' \ - 'of the TZ environment variable.' - echo >&2 'For example, GST-10 is a zone named GST' \ - 'that is 10 hours ahead (east) of UTC.' - read TZ + TZ=`"${SHOWDIALOG}" inputbox \ + 'Please enter the desired value of the TZ environment variable. +For example, GST-10 is a zone named GST that is 10 hours ahead (east) of UTC.'` || exit $? $AWK -v TZ="$TZ" 'BEGIN { tzname = "[^-+,0-9][^-+,0-9][^-+,0-9]+" time = "[0-2]?[0-9](:[0-5][0-9](:[0-5][0-9])?)?" @@ -336,8 +376,8 @@ while exit 0 }' do - echo >&2 "'$TZ' is not a conforming" \ - 'Posix time zone string.' + "${SHOWDIALOG}" msgbox \ + "'$TZ' is not a conforming Posix time zone string." done TZ_for_date=$TZ;; *) @@ -345,12 +385,10 @@ while coord) case $coord in '') - echo >&2 'Please enter coordinates' \ - 'in ISO 6709 notation.' - echo >&2 'For example, +4042-07403 stands for' - echo >&2 '40 degrees 42 minutes north,' \ - '74 degrees 3 minutes west.' - read coord;; + coord=`"${SHOWDIALOG}" inputbox \ + 'Please enter coordinates in ISO 6709 notation. +For example, +4042-07403 stands for +40 degrees 42 minutes north, 74 degrees 3 minutes west.'` || exit $? esac distance_table=`$AWK \ -v coord="$coord" \ @@ -363,12 +401,10 @@ while BEGIN { FS = "\t" } { print $NF } '` - echo >&2 'Please select one of the following' \ - 'time zone regions,' - echo >&2 'listed roughly in increasing order' \ - "of distance from $coord". - doselect $regions - region=$select_result + region=`"${SHOWDIALOG}" menu \ + "Please select one of the following time zone regions, +listed roughly in increasing order of distance from $coord." \ + $regions` || exit $? TZ=`echo "$distance_table" | $AWK -v region="$region" ' BEGIN { FS="\t" } $NF == region { print $4 } @@ -405,10 +441,9 @@ while # If there's more than one country, ask the user which one. case $countries in *"$newline"*) - echo >&2 'Please select a country' \ - 'whose clocks agree with yours.' - doselect $countries - country=$select_result;; + country=`"${SHOWDIALOG}" menu \ + 'Please select a country whose clocks agree with yours.' \ + $countries` || exit $?;; *) country=$countries esac @@ -436,10 +471,9 @@ while # If there's more than one region, ask the user which one. case $regions in *"$newline"*) - echo >&2 'Please select one of the following' \ - 'time zone regions.' - doselect $regions - region=$select_result;; + region=`"${SHOWDIALOG}" menu \ + 'Please select one of the following time zone regions.' \ + $regions` || exit $?;; *) region=$regions esac @@ -495,23 +529,24 @@ Universal Time is now: $UTdate." # Output TZ info and ask the user to confirm. + infomsg=' +The following information has been given: + +' - echo >&2 "" - echo >&2 "The following information has been given:" - echo >&2 "" case $country%$region%$coord in - ?*%?*%) echo >&2 " $country$newline $region";; - ?*%%) echo >&2 " $country";; - %?*%?*) echo >&2 " coord $coord$newline $region";; - %%?*) echo >&2 " coord $coord";; - *) echo >&2 " TZ='$TZ'" + ?*%?*%) infomsg="${infomsg} $country$newline $region";; + ?*%%) infomsg="${infomsg} $country";; + %?*%?*) infomsg="${infomsg} coord $coord$newline $region";; + %%?*) infomsg="${infomsg} coord $coord";; + *) infomsg="${infomsg} TZ='$TZ'" esac - echo >&2 "" - echo >&2 "Therefore TZ='$TZ' will be used.$extra_info" - echo >&2 "Is the above information OK?" + infomsg="${infomsg} + +Therefore TZ='$TZ' will be used.$extra_info +Is the above information OK?" - doselect Yes No - ok=$select_result + ok=`"${SHOWDIALOG}" yesno "${infomsg}" Yes No` || exit $? case $ok in Yes) break esac