Created
April 17, 2020 17:22
Revisions
-
multun created this gist
Apr 17, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,155 @@ # parse --my_option into the MY_OPTION variable # also handles positional arguments __args_list=() __required_args_list=() __unexport_args_list=() normalize_argument() { # uppercase local argname="${1^^}" # replace - by _ printf '%s\n' "${argname}" | tr - _ } assign_var() { # printf can assign variables printf -v "$1" '%s' "$2" } # public arguments get forwarded through the environment public_optional_argument() { local argname="$(normalize_argument "$1")" __args_list+=( "${argname}" ) assign_var "__args_${argname}" 1 } public_required_argument() { local argname="$(normalize_argument "$1")" assign_var "__args_${argname}" 1 __args_list+=( "${argname}" ) __required_args_list+=( "${argname}" ) } optional_argument() { local argname="$(normalize_argument "$1")" assign_var "__args_${argname}" 1 __args_list+=( "${argname}" ) __unexport_args_list+=( "${argname}" ) } required_argument() { local argname="$(normalize_argument "$1")" assign_var "__args_${argname}" 1 __args_list+=( "${argname}" ) __required_args_list+=( "${argname}" ) __unexport_args_list+=( "${argname}" ) } undefined_variable() { [ "${!1+x}" == '' ] } __positional_arg_count=0 positional_argument() { assign_var "__positional_arg_$((__positional_arg_count++))" "$(normalize_argument "$1")" } __arguments_parsed=0 log_command() { if [ "${__arguments_parsed}" = 0 ]; then error "call parse_arguments before log_command" exit 1 fi local argname # print the environment variables for argname in "${__args_list[@]}"; do if ! undefined_variable "$argname"; then printf '%s=%q ' "$argname" "${!argname}" fi done # print the script path printf '%s' "$0" # print the positional arguments if [ "${#positional_arguments[@]}" != 0 ]; then printf '%s' ' --' printf ' %s' "${positional_arguments[@]}" fi printf '\n' } parse_arguments() { __arguments_parsed=1 while [ $# != 0 ]; do local argument="$1" if [ "$argument" = '--' ]; then shift positional_arguments=( "$@" ) break fi case "$argument" in --*) local argname="$(normalize_argument "${argument#--}")" local slotname="__args_${argname}" if [ "${!slotname}" != '1' ]; then error "unknown named argument: $argument ($argname)" exit 1 fi if [ $# -lt 2 ]; then error "missing value for parameter ${argname}" exit 1 fi shift assign_var "$argname" "$1" ;; *) # when meeting a non option argument, stop parsing positional_arguments=( "$@" ) break ;; esac shift done # error out when there are too many positional arguments local pos_arg_count="${#positional_arguments[@]}" if [ "${pos_arg_count}" -gt "${__positional_arg_count}" ]; then error "too many positional arguments" exit 1 fi # error out when there are too few positional arguments if [ "${pos_arg_count}" -lt "${__positional_arg_count}" ]; then for ((i=pos_arg_count; i < __positional_arg_count; i++)); do local arg_name_var="__positional_arg_$i" error "missing positional argument: ${!arg_name_var}" done exit 1 fi # assign positional argument variables for ((i=0; i < __positional_arg_count; i++)); do local arg_name_var="__positional_arg_$i" local arg_name="${!arg_name_var}" assign_var "${arg_name}" "${positional_arguments[i]}" done # detect missing mandatory arguments for arg in "${__required_args_list[@]}"; do if undefined_variable "$arg"; then error "missing required argument: $arg" exit 1 fi done # unexport arguments for arg in "${__unexport_args_list[@]}"; do export -n "$arg" done }