# Sourced, not run: organization selector options, the shell half of # packages/organization/src/selector.mjs (rename design r2, "Selector scopes and parser matrix"). A # script in the same checkout sources it; it defines functions only and runs no other program. # # --org and --business are one option family (id), and --org-file and --business-file are another # (file). A scope is one parser's own options, so the caller's own loop decides which tokens are # selectors; text after a separator or a value another option consumes is never passed here. In a # scope each spelling may appear once, and a second spelling must carry exactly the same value. # # selector_take SCOPE FAMILY REFUSE VALID FLAG [VALUE] # SCOPE [a-z0-9_]+, the scope's name; each keeps its own spellings and value # FAMILY id or file # REFUSE a function called as REFUSE KIND MESSAGE that must exit; KIND is missing, flag, # repeated, invalid or differ, so each script keeps its exit codes and wording # VALID a predicate called as VALID VALUE, or - when the caller checks the value itself # FLAG the spelling given # VALUE absent when the argument list ended there; pass "${@:2:1}" from a loop on "$@" # selector_value SCOPE prints the scope's value, nothing when none was given # # A missing or empty value, one starting with "-", one VALID refuses, a repeated spelling and two # spellings with different values all refuse. File values are compared as given, not as paths. selector__bug() { echo "selector.sh: $*" >&2; exit 70; } selector_take() { [ $# -ge 5 ] && [ $# -le 6 ] || selector__bug "selector_take takes 5 or 6 arguments, not $#" local scope="$1" family="$2" refuse="$3" valid="$4" flag="$5" [[ "$scope" =~ ^[a-z0-9_]+$ ]] || selector__bug "bad scope name $scope" case "$family:$flag" in id:--business|id:--org|file:--business-file|file:--org-file) ;; *) selector__bug "$flag is not a $family selector" ;; esac local seen_name="SELECTOR_SEEN_$scope" value_name="SELECTOR_VALUE_$scope" local seen="${!seen_name-}" current="${!value_name-}" first case " $seen " in *" $flag "*) "$refuse" repeated "$flag given twice"; selector__bug "$refuse returned" ;; esac if [ $# -lt 6 ] || [ -z "$6" ]; then "$refuse" missing "$flag needs one value"; selector__bug "$refuse returned"; fi local value="$6" case "$value" in -*) "$refuse" flag "$flag needs one value, not $value"; selector__bug "$refuse returned" ;; esac if [ "$valid" != - ] && ! "$valid" "$value"; then "$refuse" invalid "$flag $value is not valid"; selector__bug "$refuse returned"; fi first="${seen%% *}" if [ -n "$seen" ] && [ "$current" != "$value" ]; then "$refuse" differ "$first $current and $flag $value conflict"; selector__bug "$refuse returned" fi printf -v "$seen_name" '%s' "${seen:+$seen }$flag" printf -v "$value_name" '%s' "$value" } selector_value() { [[ "${1-}" =~ ^[a-z0-9_]+$ ]] || selector__bug "bad scope name ${1-}" local value_name="SELECTOR_VALUE_$1" printf '%s' "${!value_name-}" }