#!/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_load_late - Set to `true` by ``config_load()``,
# signaling that all future configuration files must be loaded
# immediately (rather than being deferred). Internal use only.
# Default: ``false``
lib_setting_vars config_load_late
config_load_late=false
# $config_types[] - List of valid types of configuration files
# Default: ``sys user pkg``
lib_setting_arrays -ro config_types
config_types=( sys user pkg )
# $sys_configs[] - Lists the system configurations to load.
# Default: ``${script_name}.conf ${script_name}.local``
lib_setting_arrays sys_configs
config_sys_files_append "$script_name.conf" "$script_name.local"
# $user_configs[] - Lists the user configurations to load.
# Default: ``${script_name}.conf``
lib_setting_arrays user_configs
config_user_files_append "$script_name.conf"
# $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_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
core_config_config_check
}
######
# Library Configuration
core_config_config_check() {
config_init_check=${config_init_check:-false}
config_debug=${config_debug:-false}
}
######
# Configuration Files
# config_filename() - Prints system configuration filename
# (located in ``$confdir``)
config_sys_filename() { echo "$confdir/$script_name/$1"; }
# config_user_filename() - Prints user configuration filename
# (located in ``$user_confdir``)
config_user_filename() { echo "$user_confdir/$script_name/$1"; }
# config_pkg_filename() - Prints package configuration filename
# (located in ``$srcdir``)
config_pkg_filename() { echo "$1"; }
_config_files_add() {
local name=$1
local file
file=$($filefunc "$name" "$ext")
$addfunc $listvar "$file"
! $config_load_late || config_read "$file"
}
# config_files_add() - Inserts or appends ($2) configuration files "$@"
# to the named configuration file list ($1).
#
# The remaining functions in this section encapsulate all valid
# permutations of the first two arguments and should be used in
# preference to direct calls to this function.
# $1 - Configuration file type
# $2 - List function: `insert` or `append`
# $@ - Configuration file names
config_files_add() {
local filefunc="config_${1}_filename"
local listvar="${1}_configs"
local addfunc="list_$2"
shift 2
for_each _config_files_add "$@"
}
# config_sys_files_insert() - Inserts system configuration files ($@) to start
# of system configuration file list.
config_sys_files_insert() { config_files_add 'sys' 'insert' "$@"; }
# config_sys_files_append() - Appends system configuration files ($@) to end
# of system configuration file list.
config_sys_files_append() { config_files_add 'sys' 'append' "$@"; }
# config_user_files_insert() - Inserts user configuration files ($@) to start
# of user configuration file list.
config_user_files_insert() { config_files_add 'user' 'insert' "$@"; }
# config_user_files_append() - Appends user configuration files ($@) to end
# of user configuration file list.
config_user_files_append() { config_files_add 'user' 'append' "$@"; }
# config_pkg_files_insert() - Inserts package configuration files ($@) to start
# of package configuration file list.
config_pkg_files_insert() { config_files_add 'pkg' 'insert' "$@"; }
# config_pkg_files_append() - Appends package configuration files ($@) to end
# of package configuration file list.
config_pkg_files_append() { config_files_add 'pkg' 'append' "$@"; }
######
# 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
debug "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 by calling
# ``config_load_kind()`` for each type of configuration file.
# Sets ``$config_load_late`` to ensure all future configuration files
# are loaded immediately by ``config_files_add()``.
config_load() {
for_each config_load_kind "${config_types[@]}"
config_load_late=true
}
# config_load_kind() - Reads configuration files of the given type ($1).
# See ``$config_types[]`` for available types.
config_load_kind() {
local kind=$1
local -a files
eval "files=( \"\${${kind}_configs[@]}\" )"
[ "${files[*]}" ] || return 0
info "Loading $kind config files..."
config_read_files "${files[@]}"
}
######
# 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_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_func() { eval declare -f "\$$1"; }
Generated on Tue Jul 4 17:00:18 PDT 2017 by mcsh d14 v0.21.0.