#!/bin/bash
# config - configuration file support library
set -e
lib_load 'core/script'
######
# Library Initialization
# core_config_lib_init() - Other libs use config_init, so use lib_init.
core_config_lib_init() {
# $config_types[] - List of valid types of configuration files
# Default: ``sys user pkg``
lib_setting_arrays -ro config_types
config_types=( sys tool user usertool pkg )
# $sys_configs[] - Lists the system library configurations to load.
lib_setting_arrays sys_configs
# $tool_configs[] - Lists the system tool configurations to load.
lib_setting_arrays tool_configs
# $user_configs[] - Lists the user library configurations to load.
lib_setting_arrays user_configs
# $usertool_configs[] - Lists the user tool configurations to load.
lib_setting_arrays usertool_configs
# $pkg_configs[] - Lists the package configurations to load.
# Default: `none`
lib_setting_arrays pkg_configs
# $config_debug - If set to true `true`, permits errors in the
# configuration to allow debugging.
# Default: ``false``
lib_setting_vars config_debug
config_debug=${config_debug:-false}
$debug || debug=$config_debug
# $config_init_check - Set to `true` to in order to perform
# early checking of configuration settings, after initialization
# but prior to loading any configuration files.
# Default: ``false``
lib_setting_vars config_init_check
config_init_check=${config_init_check:-false}
}
######
# Configuration Filenames
# config_sys_filename() - Prints system configuration filename
# (located in ``$confdir``)
config_sys_filename() { echo "$confdir/$1"; }
# config_sys_tool_filename() - Prints system tool configuration filename
# (located in ``$confdir/$script_group/$script_name``)
config_tool_filename() {
config_sys_filename "$script_group/$script_name/$1"
}
# config_user_filename() - Prints user configuration filename
# (located in ``$user_confdir``)
config_user_filename() { echo "$user_confdir/$1"; }
# config_usertool_filename() - Prints user configuration filename
# (located in ``$user_confdir/$script_group/$script_name``)
config_usertool_filename() {
config_user_filename "$script_group/$script_name/$1"
}
# config_pkg_filename() - Prints package configuration filename
# (located in ``$srcdir``)
config_pkg_filename() { echo "$1"; }
######
# Configuration Files
# config_script_filenames() - Prints name of script configuration filenames
config_script_filenames() {
local kind=$1
case "$kind" in
(tool) echo "$script_name.conf"; echo "$script_name.local" ;;
(usertool) echo "$script_name.conf" ;;
esac
}
# config_lib_filenames() - Prints name of library configuration filenames
config_lib_filenames() {
local kind=$1
local name=$2
case "$kind" in
(sys|tool) echo "$name.conf"; echo "$name.local" ;;
(user|usertool) echo "$name.conf" ;;
esac
}
######
# Public Functions
# config_error() - Generates a warning or error, depending on whether
# ``$config_debug`` is true or false respectively.
config_error() {
local level
$config_debug && level=warn || level=error
$level "$@"
}
######
# Configuration Initialization
# config_init() - Initializes all library and tool settings, prior to
# loading any configuration files.
config_init() {
for_each_lib config_init_lib
script_cmd_exec config_init
# TODO: fix config_check callbacks to permit checking here
if ! $config_init_check || config_check true; then
info "configuration settings initialized"
else
config_dump
config_error "configuration initialization failed"
fi
}
# config_init_lib() - Initializes configuration settings for the named
# library ($1).
config_init_lib() { lib_cmd_exec "$1" config_init; }
######
# Configuration Validation
# config_check() - Ensures all configuration settings are valid
config_check() {
info "checking configuration settings"
for_each_lib config_check_lib
script_cmd_exec config_check
}
# config_check_lib() - Ensures configuration settings are valid for the
# name library ($1).
config_check_lib() { lib_cmd_exec "$1" config_check; }
######
# Configuration File Reading
# config_read() - Reads a single configuration file ($1)
# $1 - filename
config_read() {
local cfg=$1
if [ ! -f "$cfg" ]; then
! $config_debug || info "missing: $cfg"
return
fi
debug "reading: $cfg ..."
if [ -r "$cfg" ]; then
eval "$(<"$cfg")"
else
eval "$(sudo cat "$cfg")"
fi
}
# config_read_files() - Reads a list of configuration files ($@)
config_read_files() { for_each config_read "$@"; }
######
# Configuration File Loading
# config_load() - Reads all known configuration files.
config_load() { for_each config_load_kind "${config_types[@]}"; }
# config_load_kind() - Reads configuration files of the given type ($1).
# See ``$config_types[]`` for available types.
config_load_kind() {
local kind=$1
info "Loading $kind config files..."
local -a files=(
$(for_each_lib config_lib_files $kind)
$(script_cmd_exec config_files $kind)
$(config_script_filenames $kind)
)
files=( $(for_each "config_${kind}_filename" "${files[@]}") )
eval "${kind}_configs=( \"\${files[@]}\" )"
config_read_files "${files[@]}"
}
config_lib_files() {
local kind=$1
local name=$2
config_lib_filenames $kind $name
lib_cmd_exec $name config_files $kind
}
config_load_lib_kind() {
local name=$1
local kind=$2
local -a files=( $(config_lib_files "$kind" "$name") )
files=( $(for_each "config_${kind}_filename" "${files[@]}") )
eval "${kind}_configs+=( \"\${files[@]}\" )"
config_read_files "${files[@]}"
}
# config_load_lib() - Loads configuration files for the named library ($1)
config_load_lib() {
local name=$1
for_each "config_load_lib_kind $name" "${config_types[@]}"
}
######
# Config CLI
# config_usage() - Prints usage for the ``config`` command namespace.
config_usage() {
cat <<USAGE
<cmd> [<var>]
Configuration Commands:
files [(all|sys|user|pkg)] Prints the list of config files
names Prints the list of setting names
values <name>+ Prints the values of the named settings
show [all|<lib>+] Prints library settings
load <library>+ Loads the named libraries
USAGE
}
# config_files() - Prints the named list ($1) of configuration files.
# $1 - Type of configuration files: ``all``, ``sys``, ``user``, or ``pkg``.
config_files() {
case "$1" in
(sys|user|pkg) _config_files "$1" ;;
(''|all) config_files_all ;;
*) error_usage "$1: unknown type, must be ${config_types[*]}" ;;
esac
echo
}
# config_files_all() - Prints a list of all configuration files.
config_files_all() {
local -a _files
for_each _config_files "${config_types[@]}"
}
_config_files() { eval "list_insert _files \"\${${1}_configs[*]}\""; }
# config_names() - Prints list of active configuration settings.
config_names() {
local -a opts
local class
for class in "${package_libs[@]}" $(script_symbol); do
local sym
sym=$(lib_symbol $class)
list_append opts $(settings_list_all "$sym")
done
echo "${opts[*]}"
}
# config_values() - Prints list of configuration settings name/value pairs
# for the given list of setting names ($@).
config_values() {
min_args 1 "$@"
for_each _config_value "$@"
}
_config_value() {
local name=$1
local class
for class in "${package_libs[@]}" $(script_symbol); do
local sym
sym=$(lib_symbol $class)
if in_list "$name" $(settings_list_all "$sym"); then
_config_show "$sym" "$name"
fi
done
}
# config_show() - Prints active configuration settings for a given
# library ($1) or all active scripts (if none given).
# $1 - Library name (optional). If `null`, prints all script settings.
config_show() {
max_args 1 "$@"
local class=${1:-all}
local -a libs
if [ "$class" = all ]; then
libs=( "${lib_loaded[@]}" "$(script_symbol)" )
else
libs=( $class )
fi
if [ ${#libs[*]} -gt 1 ]; then
for_each config_show "${libs[@]}"
return
fi
local sym
sym=$(lib_symbol "$class")
! is_tool "$class" || sym="$(script_symbol)"
local -a settings
settings=( $(settings_list_all $sym) )
if [ -z "${settings[*]}" ]; then
return
fi
echo "######"
echo "# '$class' settings"
for_each "_config_show $sym" "${settings[@]}"
}
_config_show() {
local sym=$1
local var=$2
if in_list "$var" $(settings_list_vars "$sym"); then
_config_show_var "$var"
elif in_list "$var" $(settings_list_arrays "$sym"); then
_config_show_array "$var"
elif in_list "$var" $(settings_list_assocs "$sym"); then
_config_show_assoc "$var"
elif in_list "$var" $(settings_list_funcs "$sym"); then
_config_show_func "$var"
else
error "$sym: $var: not a valid variable name"
fi
}
_config_show_var() {
local var=$1
local -n value=$var
echo "$var=$(arg_quote "$value")"
}
_config_show_array() {
local name=$1
local -a list
eval "list=( \"\${${name}[@]}\" )"
list_quote list
echo "$name=( ${list[*]} )"
}
_config_show_assoc() {
local name=$1
local -a keys
eval "keys=( \"\${!${name}[@]}\" )"
echo "$name=("
for_each "_config_show_assoc_item $name" "${keys[@]}"
echo -e "\t)"
}
_config_show_assoc_item() {
local name=$1
local key=$2
local value
eval "value=\${$name[\$key]}"
key=$(arg_quote "$key")
value=$(arg_quote "$value")
echo -e "\t\t[$key]=$value"
}
_config_show_func() { eval declare -f "\$$1"; }
Generated on Fri Jul 28 14:34:53 PDT 2017 by mcsh d14 v0.23.0.