#!/bin/bash
#  input - Command line input helpers

set -e


######
# Config

mcui_input_config_init() {
	lib_setting_vars prompt_allow_empty
	prompt_allow_empty=true
}


######
# Value parsing functions
# These functions all have the same interface.
#
# Upon return, a valid value will be stored in the named variable;
# if the value was not valid, the function raises an error.

# parse_int - Parse a string as an integer
# $1 - raw value to parse
# $2 - variable name
parse_int() {
	has_args 2 "$@"
	case "$1" in
	[0-9]*) eval $2=$(printf "%d" "$1") ;;
	*) false ;;
	esac
}

# parse_bool - Parse a string as a boolean
# $1 - raw value to parse
# $2 - variable name
parse_bool() {
	has_args 2 "$@"
	case "$1" in
	t|T|true|True|TRUE)	eval "$2=true" ;;
	f|F|false|False|FALSE)	eval "$2=false" ;;
	*) false ;;
	esac
}

# parse_yesno - Parse a string as a yes or no answer
# $1 - raw value to parse
# $2 - variable name
parse_yesno() {
	has_args 2 "$@"
	case "$1" in
	y|yes|Y|YES)	eval "$2=true" ;;
	n|no|N|NO)	eval "$2=false" ;;
	*) false ;;
	esac
}

# parse_yesnocancel - Parse a string as a yes, no, or cancel answer
# $1 - raw value to parse
# $2 - variable name
parse_yesnocancel() {
	has_args 2 "$@"
	case "$1" in
	c|cancel|C|CANCEL)	eval "$2=" ;;
	*)			parse_yesno "$@" ;;
	esac
}

# parse_onoff - Parse a string as an on or off answer
# $1 - raw value to parse
# $2 - variable name
parse_onoff() {
	has_args 2 "$@"
	case "$1" in
	on|On|ON)	eval "$2=true" ;;
	off|Off|OFF)	eval "$2=false" ;;
	*) false ;;
	esac
}


######
# Input helpers

# read_string - Interactively reads a string into a variable
#   $1 - prompt
#   $2 - target variable
read_string() {
	has_args 2 "$@"
	run read -p "$1" -e $2
}

# read_silent - Same as read_string, but does not echo input.
read_silent() {
	has_args 2 "$@"
	run read -s -p "$1" -e $2
}

# read_and_parse - Reads a string and parses it into a typed variable
#   $1 - name of parser function
#   $2 - prompt
#   $3 - target variable
read_and_parse() {
	min_args 3 "$@"
	local parser=$1
	local prompt=$2
	local outvar=$3
	local _line
	local linevar=${4:-_line}
	read_string "$prompt" $linevar
	local -n line=$linevar
	$parser "$line" "$outvar"
}

read_int() { read_and_parse parse_int "$@"; }
read_bool() { read_and_parse parse_bool "$@"; }
read_yesno() { read_and_parse parse_yesno "$@"; }
read_yesnocancel() { read_and_parse parse_yesnocancel "$@"; }
read_onoff() { read_and_parse parse_onoff "$@"; }


######
# Prompt input

prompt_newline() { local x; read_string "Press <enter> to continue..." x; }
prompt_error() { error "$1" || prompt_newline; }
prompt_warn() { warn "$1" && prompt_newline; }
prompt_info() { app_echo "INFO: $1" && prompt_newline; }

prompt_for() {
	has_args 3 "$@"
	local raw
	while ! read_and_parse "$@" raw; do
		if [ -z "$raw" ]; then
			! $prompt_allow_empty || return 0
		else
			! error "'$raw' is not a valid response"
		fi
	done
}

prompt_int() { prompt_for parse_int "$@"; }
prompt_bool() { prompt_for parse_bool "$@"; }
prompt_yesno() { prompt_for parse_yesno "$@"; }
prompt_yesnocancel() { prompt_for parse_yesnocancel "$@"; }
prompt_onoff() { prompt_for parse_onoff "$@"; }


######
# Input validation

# assert_parse - Asserts variable ($2) is type ($1) or prints error ($3)
# $1 - parsing type, used to derive parsing function (e.g. 'parse_int')
# $2 - name of variable
# $3 - error to display if assertion fails
assert_parse() {
	has_args 3 "$@"
	local _ptype=$1
	local _var=$2
	local _error=$3

	local _pfunc="parse_$_ptype"
	local _value
	eval "_value=\"\$$_var\""
	assert "$_var: '$_value' not a $_ptype: $_error" \
		 "$_pfunc" "$_value" "$_var"
}

# assert_parse_list - Asserts values ($...) are type ($1) or prints error ($2)
assert_parse_list() {
	min_args 2 "$@"
	local _ptype=$1
	local _error=$2
	shift 2
	for_each "_assert_parse_list $_ptype $_error" "$@";
}
#   $1 - $ptype, $2 - $error, $3 - $var
_assert_parse_list() { assert_parse "$1" "$3" "$2"; }

assert_is_int() { assert_parse_list int "$@"; }
assert_is_bool() { assert_parse_list bool "$@"; }
assert_is_yesno() { assert_parse_list yesno "$@"; }
assert_is_onoff() { assert_parse_list onoff "$@"; }


######
# Library testing

check_is_input_valid() {
	has_args 2 "$@"
	local _type=$1
	local _var=$2

	local -a _cmd=( assert_is_${_type} failed $_var )
	check_for_pass "checking $_var is a $_type" "${_cmd[@]}"
}

check_is_input_invalid() {
	has_args 2 "$@"
	local _type=$1
	local _var=$2

	local -a _cmd=( assert_is_${_type} failed $_var )
	check_for_fail "checking $_var is not a $_type" "${_cmd[@]}"
}

mcui_input_lib_check() {
	check_list_start

	local testvar=123
	check_is_input_valid int testvar
	check_is_expected testvar 123

	testvar=0000
	check_is_input_valid int testvar
	check_is_expected testvar 0

	testvar=abc
	check_is_input_invalid int testvar

	check_list_finish
}

View the Developer Guide Index

View the Reference Manual Index


Generated on Thu May 4 19:00:09 PDT 2017 by mcsh i7 v0.19.0.