Added a few new functions for dumping config state, also added new facilities for specifying that certain config options should be an array or a hash
This commit is contained in:
186
cmdarg.sh
186
cmdarg.sh
@@ -6,8 +6,15 @@ if [ $bashversion -lt 4 ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
CMDARG_FLAG_NOARG=0
|
||||||
CMDARG_FLAG_WITHARG=1
|
CMDARG_FLAG_WITHARG=1
|
||||||
|
|
||||||
|
CMDARG_TYPE_ARRAY=1
|
||||||
|
CMDARG_TYPE_HASH=2
|
||||||
|
CMDARG_TYPE_STRING=3
|
||||||
|
CMDARG_TYPE_BOOLEAN=4
|
||||||
|
|
||||||
function cmdarg
|
function cmdarg
|
||||||
{
|
{
|
||||||
# cmdarg <option> <key> <description> [default value] [validator function]
|
# cmdarg <option> <key> <description> [default value] [validator function]
|
||||||
@@ -23,11 +30,43 @@ function cmdarg
|
|||||||
# should be the name of a function. This may be enforced in future versions
|
# should be the name of a function. This may be enforced in future versions
|
||||||
# of the library.
|
# of the library.
|
||||||
shortopt=${1:0:1}
|
shortopt=${1:0:1}
|
||||||
if [[ "${1:1:2}" == ":" ]]; then
|
key="$2"
|
||||||
CMDARG_FLAGS[$shortopt]=$CMDARG_FLAG_WITHARG
|
if [[ "$shortopt" == "h" ]]; then
|
||||||
else
|
echo "-h is reserved for cmdarg usage" >&2
|
||||||
CMDARG_FLAGS[$shortopt]=0
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
if [[ "$(type -t cmdarg_$key)" != "" ]] || \
|
||||||
|
[[ "$(eval 'echo ${cmdarg_${key}}' 2>/dev/null)" != "" ]] || \
|
||||||
|
[[ "${CMDARG_TYPES[$key]}" != "" ]]; then
|
||||||
|
echo "command line key '$key' is reserved by cmdarg or defined twice" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${1:1:1}" == ":" ]]; then
|
||||||
|
CMDARG_FLAGS[$shortopt]=$CMDARG_FLAG_WITHARG
|
||||||
|
if [[ "${1:2:4}" == "[]" ]]; then
|
||||||
|
declare -p cmdarg_${key} >/dev/null 2>&1
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
echo 'Array variable cmdarg_'"${key}"' does not exist. Array variables MUST be declared by the user!' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
CMDARG_TYPES[$key]=$CMDARG_TYPE_ARRAY
|
||||||
|
elif [[ "${1:2:4}" == "{}" ]]; then
|
||||||
|
declare -p cmdarg_${key} >/dev/null 2>&1
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
echo 'Hash variable cmdarg_'"${key}"' does not exist. Hash variables MUST be declared by the user!' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
CMDARG_TYPES[$key]=$CMDARG_TYPE_HASH
|
||||||
|
else
|
||||||
|
CMDARG_TYPES[$key]=$CMDARG_TYPE_STRING
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
CMDARG_FLAGS[$shortopt]=$CMDARG_FLAG_NOARG
|
||||||
|
CMDARG_TYPES[$key]=$CMDARG_TYPE_BOOLEAN
|
||||||
|
cmdarg_cfg[$key]=false
|
||||||
|
fi
|
||||||
|
|
||||||
CMDARG["$shortopt"]=$2
|
CMDARG["$shortopt"]=$2
|
||||||
CMDARG_REV["$2"]=$shortopt
|
CMDARG_REV["$2"]=$shortopt
|
||||||
CMDARG_DESC["$shortopt"]=$3
|
CMDARG_DESC["$shortopt"]=$3
|
||||||
@@ -58,6 +97,34 @@ function cmdarg_info
|
|||||||
CMDARG_INFO["$1"]=$2
|
CMDARG_INFO["$1"]=$2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cmdarg_describe
|
||||||
|
{
|
||||||
|
local key default
|
||||||
|
key=${CMDARG[$1]}
|
||||||
|
opt=$1
|
||||||
|
if [ "${CMDARG_DEFAULT[$key]}" != "" ]; then
|
||||||
|
default="(Default \"${CMDARG_DEFAULT[$key]}\")"
|
||||||
|
fi
|
||||||
|
case ${CMDARG_TYPES[$key]} in
|
||||||
|
$CMDARG_TYPE_STRING)
|
||||||
|
echo "-${opt} v : String. ${CMDARG_DESC[$key]} $default"
|
||||||
|
;;
|
||||||
|
$CMDARG_TYPE_BOOLEAN)
|
||||||
|
echo "-${opt} : Boolean. ${CMDARG_DESC[$key]} $default"
|
||||||
|
;;
|
||||||
|
$CMDARG_TYPE_ARRAY)
|
||||||
|
echo "-${opt} v[, ...] : Array. ${CMDARG_DESC[$key]}. Pass this argument multiple times for multiple values. $default"
|
||||||
|
;;
|
||||||
|
$CMDARG_TYPE_HASH)
|
||||||
|
echo "-${opt} k=v{, ..} : Hash. ${CMDARG_DESC[$key]}. Pass this argument multiple times for multiple key/value pairs. $default"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unable to return string description for ${key}; unknown type ${CMDARG_TYPES[$key]}" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
function cmdarg_usage
|
function cmdarg_usage
|
||||||
{
|
{
|
||||||
# cmdarg_usage
|
# cmdarg_usage
|
||||||
@@ -72,11 +139,7 @@ function cmdarg_usage
|
|||||||
echo "Required Arguments:"
|
echo "Required Arguments:"
|
||||||
for key in "${CMDARG_REQUIRED[@]}"
|
for key in "${CMDARG_REQUIRED[@]}"
|
||||||
do
|
do
|
||||||
local default=""
|
echo " $(cmdarg_describe $key)"
|
||||||
if [ "${CMDARG_DEFAULT[$key]}" != "" ]; then
|
|
||||||
default="(Default \"${CMDARG_DEFAULT[$key]}\")"
|
|
||||||
fi
|
|
||||||
echo " -${key} : ${CMDARG_DESC[$key]} $default"
|
|
||||||
done
|
done
|
||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
@@ -84,17 +147,78 @@ function cmdarg_usage
|
|||||||
echo "Optional Arguments:"
|
echo "Optional Arguments:"
|
||||||
for key in "${CMDARG_OPTIONAL[@]}"
|
for key in "${CMDARG_OPTIONAL[@]}"
|
||||||
do
|
do
|
||||||
local default=""
|
echo " $(cmdarg_describe $key)"
|
||||||
if [ "${CMDARG_DEFAULT[$key]}" != "" ]; then
|
|
||||||
default="(Default \"${CMDARG_DEFAULT[$key]}\")"
|
|
||||||
fi
|
|
||||||
echo " -${key} : ${CMDARG_DESC[$key]} $default"
|
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
echo
|
echo
|
||||||
echo "${CMDARG_INFO['footer']}"
|
echo "${CMDARG_INFO['footer']}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cmdarg_set_opt
|
||||||
|
{
|
||||||
|
local key arg
|
||||||
|
key=$1
|
||||||
|
arg="$2"
|
||||||
|
case ${CMDARG_TYPES[$key]} in
|
||||||
|
$CMDARG_TYPE_STRING)
|
||||||
|
cmdarg_cfg[$key]=$OPTARG
|
||||||
|
;;
|
||||||
|
$CMDARG_TYPE_BOOLEAN)
|
||||||
|
cmdarg_cfg[$key]=true
|
||||||
|
;;
|
||||||
|
$CMDARG_TYPE_ARRAY)
|
||||||
|
arrname="cmdarg_${key}"
|
||||||
|
str='${#'"$arrname"'[@]}'
|
||||||
|
prevlen=$(eval "echo $str")
|
||||||
|
eval "${arrname}[$((prevlen + 1))]=\"$arg\""
|
||||||
|
;;
|
||||||
|
$CMDARG_TYPE_HASH)
|
||||||
|
arrname="cmdarg_${key}"
|
||||||
|
# Want to know WTF I named this variable like this?
|
||||||
|
# http://stackoverflow.com/questions/10258686/bash-associative-array-error
|
||||||
|
# ... Apparently there is a bug in bash.
|
||||||
|
cmdarghashkeythingy31337=$(echo "$arg" | cut -d = -f 1)
|
||||||
|
v=$(echo "$arg" | cut -d = -f 2-)
|
||||||
|
lval="${arrname}['${cmdarghashkeythingy31337}']"
|
||||||
|
eval "$lval=\"$v\""
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unable to return string description for ${key}; unknown type ${CMDARG_TYPES[$key]}" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
function cmdarg_check_empty
|
||||||
|
{
|
||||||
|
local key longopt
|
||||||
|
key=$1
|
||||||
|
longopt=${CMDARG[$key]}
|
||||||
|
type=${CMDARG_TYPES[$longopt]}
|
||||||
|
|
||||||
|
case $type in
|
||||||
|
$CMDARG_TYPE_STRING)
|
||||||
|
echo ${cmdarg_cfg[$longopt]}
|
||||||
|
;;
|
||||||
|
$CMDARG_TYPE_BOOLEAN)
|
||||||
|
echo ${cmdarg_cfg[$longopt]}
|
||||||
|
;;
|
||||||
|
$CMDARG_TYPE_ARRAY)
|
||||||
|
arrname="cmdarg_${longopt}"
|
||||||
|
lval='${!'"${arrname}"'[@]}'
|
||||||
|
eval "echo $lval"
|
||||||
|
;;
|
||||||
|
$CMDARG_TYPE_HASH)
|
||||||
|
arrname="cmdarg_${longopt}"
|
||||||
|
lval='${!'"${arrname}"'[@]}'
|
||||||
|
eval "echo $lval"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "${cmdarg_cfg[$longopt]}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
function cmdarg_parse
|
function cmdarg_parse
|
||||||
{
|
{
|
||||||
# cmdarg_parse "$@"
|
# cmdarg_parse "$@"
|
||||||
@@ -102,18 +226,13 @@ function cmdarg_parse
|
|||||||
# Call it EXACTLY LIKE THAT, and it will parse your arguments for you.
|
# Call it EXACTLY LIKE THAT, and it will parse your arguments for you.
|
||||||
# This function only knows about the arguments that you previously called 'cmdarg' for.
|
# This function only knows about the arguments that you previously called 'cmdarg' for.
|
||||||
local OPTIND
|
local OPTIND
|
||||||
local ARGS="$@"
|
|
||||||
|
|
||||||
while getopts "$CMDARG_GETOPTLIST" opt $ARGS; do
|
while getopts "$CMDARG_GETOPTLIST" opt "$@"; do
|
||||||
if [ "$opt" == "h" ]; then
|
if [ "$opt" == "h" ]; then
|
||||||
cmdarg_usage
|
cmdarg_usage
|
||||||
exit 1
|
exit 1
|
||||||
elif [ ${CMDARG["${opt}"]+abc} ]; then
|
elif [ ${CMDARG["${opt}"]+abc} ]; then
|
||||||
if [ ${CMDARG_FLAGS[${opt}]} -eq 0 ]; then
|
cmdarg_set_opt "${CMDARG[$opt]}" "$OPTARG"
|
||||||
cmdarg_cfg[${CMDARG[$opt]}]=true
|
|
||||||
else
|
|
||||||
cmdarg_cfg[${CMDARG[$opt]}]=$OPTARG
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
cmdarg_usage
|
cmdarg_usage
|
||||||
exit 1
|
exit 1
|
||||||
@@ -128,7 +247,7 @@ function cmdarg_parse
|
|||||||
|
|
||||||
for key in "${CMDARG_REQUIRED[@]}"
|
for key in "${CMDARG_REQUIRED[@]}"
|
||||||
do
|
do
|
||||||
if [[ "${cmdarg_cfg[${CMDARG[$key]}]}" == "" ]]; then
|
if [[ "$(cmdarg_check_empty $key)" == "" ]]; then
|
||||||
missing="${missing} -${key}"
|
missing="${missing} -${key}"
|
||||||
failed=1
|
failed=1
|
||||||
fi
|
fi
|
||||||
@@ -177,6 +296,27 @@ function cmdarg_traceback
|
|||||||
unset FRAMES
|
unset FRAMES
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cmdarg_dump
|
||||||
|
{
|
||||||
|
for key in ${!cmdarg_cfg[@]}
|
||||||
|
do
|
||||||
|
repr="${key}:${CMDARG_TYPES[$key]}"
|
||||||
|
if [[ ${CMDARG_TYPES[$key]} == $CMDARG_TYPE_ARRAY ]] || [[ ${CMDARG_TYPES[$key]} == $CMDARG_TYPE_HASH ]] ; then
|
||||||
|
arrname="cmdarg_${key}"
|
||||||
|
echo "${repr} => "
|
||||||
|
keys='${!'"$arrname"'[@]}'
|
||||||
|
for idx in $(eval "echo $keys")
|
||||||
|
do
|
||||||
|
ref='${'"$arrname"'[$idx]}'
|
||||||
|
value=$(eval "echo $ref")
|
||||||
|
echo " ${idx} => $value"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo "${repr} => ${cmdarg_cfg[$key]}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
if [[ "${_DEFINED_CMDARG}" == "" ]]; then
|
if [[ "${_DEFINED_CMDARG}" == "" ]]; then
|
||||||
export _DEFINED_CMDARG=0
|
export _DEFINED_CMDARG=0
|
||||||
# Holds the final map of configuration options
|
# Holds the final map of configuration options
|
||||||
@@ -199,5 +339,7 @@ if [[ "${_DEFINED_CMDARG}" == "" ]]; then
|
|||||||
declare -A CMDARG_INFO
|
declare -A CMDARG_INFO
|
||||||
# Map of (short arg) -> flags
|
# Map of (short arg) -> flags
|
||||||
declare -A CMDARG_FLAGS
|
declare -A CMDARG_FLAGS
|
||||||
|
# Map of (short arg) -> type (string, array, hash)
|
||||||
|
declare -A CMDARG_TYPES
|
||||||
CMDARG_GETOPTLIST="h"
|
CMDARG_GETOPTLIST="h"
|
||||||
fi
|
fi
|
||||||
|
|||||||
15
test.sh
Normal file
15
test.sh
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/bash4
|
||||||
|
|
||||||
|
declare -a cmdarg_array
|
||||||
|
declare -A cmdarg_hash
|
||||||
|
|
||||||
|
source ./cmdarg.sh
|
||||||
|
|
||||||
|
cmdarg 'b' 'boolean' 'A boolean argument'
|
||||||
|
cmdarg 's:' 'string' 'A string argument'
|
||||||
|
cmdarg 'a:[]' 'array' 'An array argument'
|
||||||
|
cmdarg 'H:{}' 'hash' 'A hash argument'
|
||||||
|
|
||||||
|
cmdarg_parse "$@"
|
||||||
|
|
||||||
|
cmdarg_dump
|
||||||
Reference in New Issue
Block a user