#!/bin/bash
# settings - setting variable support
set -e
######
# Settings Configuration
core_settings_config_init() {
# $settings_dump - If `true`, settings are printed using ``debug``.
# Default: ``$config_debug``
lib_setting_vars settings_dump
settings_dump=${settings_dump:-$config_debug}
$debug || debug=$settings_dump
# $settings_types[] - Lists the known types of settings:
# `vars arrays assocs funcs`.
lib_setting_arrays -ro settings_types
settings_types=( vars arrays assocs funcs )
lib_setting_arrays -ro settings_attrs
settings_attrs=( readonly null )
}
######
# Setting Lists
# settings_varname() - Prints the name of a settings list, given
# the namespace ($1) and the setting type ($2).
settings_varname() { echo "${1}_settings_${2}"; }
settings_insert() {
min_args 3 "$@"
local ext=$1
local name=$2
shift 2
# add them to the script settings array
local settings
settings=$(settings_varname "$name" "$ext")
declare -ga $settings
eval "$settings+=( \"\$@\" )"
}
# settings_add() - Adds the named settings ($@) to the given data type ($1).
# Declares the settings ($@) with the given ``declare`` options ($2) in
# the given script namespace ($3).
settings_add() {
min_args 4 "$@"
local ext=$1
local opts=$2
local name=$3
shift 3
local ro=false
local null=false
local got_opt=true
while $got_opt; do
case "$1" in
(-ro|--readonly) ro=true; shift; continue ;;
(--empty|--null) null=true; shift; continue ;;
(-*) error "$1: unknown option" ;;
esac
got_opt=false
done
settings_insert "all" "$name" "$@"
! $null || settings_insert "null" "$name" "$@"
! $ro || settings_insert "readonly" "$name" "$@"
settings_insert "$ext" "$name" "$@"
# declare all of the nammed settings as globals
declare -g $opts "$@"
}
settings_add_vars() { settings_add "vars" "" "$@"; }
settings_add_funcs() { settings_add "funcs" "-f" "$@"; }
settings_add_assocs() { settings_add "assocs" "-A" "$@"; }
settings_add_arrays() { settings_add "arrays" "-a" "$@"; }
settings_list() {
has_args 2 "$@"
local settings
settings=$(settings_varname "$1" "$2")
eval "echo \${${settings}[@]}"
}
######
# Setting Attributes
# settings_list_all() - Prints list of all known settings in the given
# namespace ($1).
settings_list_all() { settings_list "$1" "all"; }
# settings_list_vars() - Prints list of known atomic settings in the
# given namespace ($1).
settings_list_vars() { settings_list "$1" "vars"; }
# settings_list_funcs() - Prints list of known functions in the given
# namespace ($1).
settings_list_funcs() { settings_list "$1" "funcs"; }
# settings_list_assocs() - Prints list of known associate arrays in the
# given namespace ($1).
settings_list_assocs() { settings_list "$1" "assocs"; }
# settings_list_arrays() - Prints list of known indexed arrays in the
# given namespace ($1).
settings_list_arrays() { settings_list "$1" "arrays"; }
# settings_list_readonly()() - Prints list of read-only settings in the
# given namespace ($1).
settings_list_readonly() { settings_list "$1" "readonly"; }
# settings_list_null()() - Prints list of settings that may be `null`
# in the given namespace ($1).
settings_list_null() { settings_list "$1" "null"; }
#; settings_list_all2 - deprecated, but useful for testing
settings_list_all2() {
echo $(for_each "settings_list $1" "${settings_types[@]}")
}
# settings_list_has_attr() - Checks if a given library ($2) setting ($1)
# exists in the given attribute list ($3).
# $1 - Setting name
# $2 - Library name
# $3 - Attribute list to check
settings_list_has_attr() { in_list "$1" $(settings_list "$2" "$3"); }
# is_setting_readonly() - Checks if a setting ($1) in the given
# namespace ($2) is read-only.
is_setting_readonly() {
has_args 2 "$@"
settings_list_has_attr "$1" "$2" "readonly"
}
# is_setting_nullable() - Checks if a setting ($1) in the given
# namespace ($2) may be configured with a `null` value.
is_setting_nullable() {
has_args 2 "$@"
settings_list_has_attr "$1" "$2" "null"
}
######
# Setting Attribute Display
# settings_dump() - Dumps configuration settings for debugging
settings_dump() {
$debug || return 0
debug "Active Configuration:"
for_each_lib_loaded settings_dump_lib
settings_dump_tool
}
# settings_dump_lib() - Dumps configuration settings for a library script ($1).
settings_dump_lib() { settings_dump_script "$1" "$(lib_symbol "$1")"; }
# settings_dump_tool() - Dumps configuration settings for a tool script ($1).
settings_dump_tool() { settings_dump_script "$1" "$(script_symbol "$1")"; }
settings_dump_script() {
local name=$1
local sym=$2
if [ -z "$(settings_list_all "$sym")" ]; then
return
fi
local s
debug "$name settings:"
for s in $(settings_list_vars "$sym"); do
local v
eval "v=\"\$$s\""
local ro=" (ro)"
is_setting_readonly "$s" "$sym" || ro=""
null=" (null)"
is_setting_nullable "$s" "$sym" || null=""
local attr="$ro$null"
debug "\t$s='$v'$attr"
done
for s in $(settings_list_arrays "$sym"); do
local v
eval "v=\"( \${$s[*]} )\""
debug "\t$s=$v"
done
for s in $(settings_list_assocs "$sym"); do
debug "\t$s=("
local -a sk
eval "sk=( \"\${!${s}[@]}\" )"
local k
for k in "${sk[@]}"; do
local v
eval "v=\${$s[\$k]}"
debug "\t\t$k=$v"
done
debug "\t\t)"
done
}
######
# Setting Attribute Verification
# settings_check() - Verifies that all configuration settings are valid.
settings_check() {
! $settings_dump || settings_dump
info "checking configuration settings..."
local -a settings_check_failures=()
for_each_lib_loaded settings_check_lib
settings_check_tool
local failures="${settings_check_failures[*]}"
[ "$failures" ] || return 0
error "some scripts have configuration errors:\n\t$failures"
}
# settings_check_lib() - Verifies that configuration settings are valid
# for a library script ($1).
settings_check_lib() { settings_check_script "$1" "$(lib_symbol "$1")"; }
# settings_check_tool() - Verifies that configuration settings are valid
# for a tool script ($1).
settings_check_tool() { settings_check_script "$1" "$(script_symbol "$1")"; }
settings_check_script() {
local name=$1
local sym=$2
if [ -z "$(settings_list_all "$sym")" ]; then
return
fi
debug "$name: checking settings..."
local -a vars
vars=( $(settings_list_vars "$sym") )
list_filter settings_check_invalid vars
[ "${vars[*]}" ] || return 0
for_each settings_check_report "${vars[@]}"
settings_check_failures+=( "$name" )
}
settings_check_invalid() {
local var=$1
local -n value=$var
! is_setting_nullable "$var" "$sym" && [ -z "$value" ]
}
settings_check_report() { warn "\$$1 is not set"; }
######
# Settings Attribute Finalization
# settings_final() - Finalizes all library and script settings.
settings_final() {
for_each_lib_loaded settings_final_lib
}
# settings_final_lib() - Finalizes settings for a library script ($1)
# by applying or checking their configured variable attributes (e.g.
# `readonly` and `nullable`).
settings_final_lib() {
local lib=$1
local ext
for ext in "${settings_types[@]}"; do
local -a names
names=( $(settings_list "$lib" "$ext") )
list_filter "is_setting_readonly $lib" names
[ "${names[*]}" ] || continue
info "$lib: $ext: readonly: ${names[*]}"
case "$ext" in
(vars) typeset -gr "${names[@]}" ;;
(arrays) typeset -gar "${names[@]}" ;;
(assocs) typeset -gAr "${names[@]}" ;;
(*) warn "$lib: $ext: readonly: ignoring ${names[*]}" ;;
esac
done
}
Generated on Fri Jul 28 14:35:04 PDT 2017 by mcsh d14 v0.23.0.