#!/bin/bash
# config - configuration file support library
set -e
lib_load 'core/script'
######
# Library
# core_config_lib_init - Other libs use config_init, so use lib_init.
core_config_lib_init() {
lib_setting_vars config_load_late
config_load_late=false
lib_setting_arrays -ro config_types
config_types=( sys user pkg )
lib_setting_arrays sys_configs user_configs pkg_configs
config_sys_files_append "$script_name.conf" "$script_name.local"
config_user_files_append "$script_name.conf"
lib_setting_vars config_debug config_init_check
core_config_config_check
}
core_config_config_check() {
config_init_check=${config_init_check:-false}
config_debug=${config_debug:-true}
}
######
# Configuration file support
# config_filename - Prints system configuration filename (in $confdir)
config_sys_filename() { echo "$confdir/$script_name/$1"; }
# config_user_filename - Prints user configuration filename (in $user_confdir)
config_user_filename() { echo "$user_confdir/$script_name/$1"; }
# config_pkg_filename - Prints package configuration filename (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() {
local filefunc="config_${1}_filename"
local listvar="${1}_configs"
local addfunc="list_$2"
shift 2
for_each _config_files_add "$@"
}
config_sys_files_insert() { config_files_add 'sys' 'insert' "$@"; }
config_sys_files_append() { config_files_add 'sys' 'append' "$@"; }
config_user_files_insert() { config_files_add 'user' 'insert' "$@"; }
config_user_files_append() { config_files_add 'user' 'append' "$@"; }
config_pkg_files_insert() { config_files_add 'pkg' 'insert' "$@"; }
config_pkg_files_append() { config_files_add 'pkg' 'append' "$@"; }
######
# Public Functions
config_error() {
local level
$config_debug && level=warn || level=error
$level "$@"
}
# 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() { lib_cmd_exec "$1" config_init; }
# 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() { lib_cmd_exec "$1" config_check; }
# config_read() - Reads a single configuration file
# $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
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() {
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() {
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() {
local -a _files
for_each _config_files "${config_types[@]}"
}
_config_files() { eval "list_insert _files \"\${${1}_configs[*]}\""; }
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() {
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() {
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 Apr 25 21:20:05 PDT 2017 by mcsh i7 v0.18.0.