➕ switch to bash-ini for config parsing
This commit is contained in:
parent
e9d125bd03
commit
60cc1357db
167
lib/ini
167
lib/ini
@ -1,34 +1,153 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# =====================================================
|
||||||
|
# bash-ini v1.0.0 | (c) 2024 DrMaxNix | www.drmaxnix.de
|
||||||
|
# =====================================================
|
||||||
|
|
||||||
|
#
|
||||||
|
# Parse a ini config file.
|
||||||
|
#
|
||||||
|
# @param $1 Path to ini file.
|
||||||
|
# @param $2 (Optional) prefix for output variable names.
|
||||||
|
#
|
||||||
ini_parse(){
|
ini_parse(){
|
||||||
local filename="$1"
|
## VALIDATE PATH ##
|
||||||
|
# get from param
|
||||||
|
local path="$1"
|
||||||
|
|
||||||
sections="$(gawk '{ if ($1 ~ /^\[/) section=tolower(gensub(/\[(.+)\]/,"\\1",1,$1)); configuration[section]=1 } END {for (key in configuration) { print key} }' $filename)"
|
# make sure it is readable
|
||||||
for section in $sections; do
|
if [[ ! -r "$path" ]]; then
|
||||||
array_name="ini_${section}"
|
ini_log_error "Unable to read config file '$path'"
|
||||||
declare -g -A ${array_name}
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
## VAR PREFIX ##
|
||||||
|
# get from param or fallback
|
||||||
|
local var_prefix="${2:-ini}"
|
||||||
|
|
||||||
|
# validate format
|
||||||
|
if [[ ! "$var_prefix" =~ ^[a-z0-9]+(_[a-z0-9]+)*$ ]]; then
|
||||||
|
ini_log_error "Invalid variable prefix '$var_prefix'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# build global var names
|
||||||
|
local -n out_section_list="${var_prefix}"
|
||||||
|
|
||||||
|
|
||||||
|
local line
|
||||||
|
local section_name
|
||||||
|
while IFS= read -r line; do
|
||||||
|
## TRIM WHITESPACES ##
|
||||||
|
line=$(echo "$line" | sed -E "s/^\s*//g" | sed -E "s/\s*$//g")
|
||||||
|
|
||||||
|
|
||||||
|
## IGNORE LINES ##
|
||||||
|
# empty lines
|
||||||
|
if [[ "$line" == "" ]]; then
|
||||||
|
# ignore
|
||||||
|
continue; fi
|
||||||
|
|
||||||
|
# comments
|
||||||
|
if [[ "$line" =~ ^# || "$line" =~ ^\; ]]; then
|
||||||
|
# ignore
|
||||||
|
continue; fi
|
||||||
|
|
||||||
|
|
||||||
|
## MATCH SECTION HEADER ##
|
||||||
|
if [[ "$line" =~ ^\[.*\]$ ]]; then
|
||||||
|
# get section name
|
||||||
|
section_name=$(echo "$line" | sed -E "s/^\[(.*)\]$/\1/g")
|
||||||
|
|
||||||
|
# trim whitespaces
|
||||||
|
section_name=$(echo "$section_name" | sed -E "s/^\s*//g" | sed -E "s/\s*$//g")
|
||||||
|
|
||||||
|
# validate format
|
||||||
|
if [[ ! "$section_name" =~ ^[A-Za-z0-9]+([\._-][A-Za-z0-9]+)*$ ]]; then
|
||||||
|
ini_log_error "Invalid section name '$section_name'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# rewrite section name
|
||||||
|
section_name=$(echo "$section_name" | tr 'A-Z' 'a-z' | tr '-' '_' | tr '.' '_')
|
||||||
|
|
||||||
|
# maybe add to section list
|
||||||
|
local found="no"
|
||||||
|
for s in ${out_section_list[*]:-}; do
|
||||||
|
if [[ "$s" == "$section_name" ]]; then found="yes"; break; fi
|
||||||
done
|
done
|
||||||
|
if [[ "$found" != "yes" ]]; then
|
||||||
|
out_section_list=(${out_section_list[@]:-""} "$section_name")
|
||||||
|
fi
|
||||||
|
|
||||||
eval $(gawk -F= '{
|
# declare section map
|
||||||
if($1 ~ /^\[/)
|
section_map_varname="${var_prefix}__${section_name}"
|
||||||
section=tolower(gensub(/\[(.+)\]/,"\\1",1,$1))
|
declare -g -A ${section_map_varname}
|
||||||
else if($1 !~ /^$/ && $1 !~ /^;/ && $1 !~ /^#/){
|
continue; fi
|
||||||
gsub(/^[ \t]+|[ \t]+$/, "", $1);
|
|
||||||
gsub(/[\[\]]/, "", $1);
|
|
||||||
gsub(/^[ \t]+|[ \t]+$/, "", $2);
|
## MATCH ASSIGNMENT ##
|
||||||
if(configuration[section][$1] == "")
|
if [[ "$line" =~ ^([A-Za-z0-9]+([\._-][A-Za-z0-9]+)*)[[:space:]\t]*=[[:space:]\t]*(.*)$ ]]; then
|
||||||
configuration[section][$1]=$2
|
# maybe enter root section
|
||||||
else
|
if [[ ! "${section_name:+x}" ]]; then
|
||||||
configuration[section][$1]=configuration[section][$1]" "$2
|
section_name="_root"
|
||||||
|
out_section_list=(${out_section_list[@]:-""} "$section_name")
|
||||||
|
section_map_varname="${var_prefix}__${section_name}"
|
||||||
|
declare -g -A ${section_map_varname}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# get key and value
|
||||||
|
local key=$(echo "$line" | sed -E "s/^([A-Za-z0-9]+([\._-][A-Za-z0-9]+)*)[ \t]*=[ \t]*(.*)$/\1/g")
|
||||||
|
local value=$(echo "$line" | sed -E "s/^([A-Za-z0-9]+([\._-][A-Za-z0-9]+)*)[ \t]*=[ \t]*(.*)$/\3/g")
|
||||||
|
|
||||||
|
# maybe trim quote marks
|
||||||
|
if [[ "$value" =~ ^\".*\"$ ]]; then
|
||||||
|
value=$(echo "$value" | sed -E "s/^\"(.*)\"$/\1/g")
|
||||||
|
elif [[ "$value" =~ ^\'.*\'$ ]]; then
|
||||||
|
value=$(echo "$value" | sed -E "s/^'(.*)'$/\1/g")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# maybe add key to key list
|
||||||
|
local -n out_section_key_list="${var_prefix}__${section_name}__key_list"
|
||||||
|
local found="no"
|
||||||
|
for k in ${out_section_key_list[*]:-}; do
|
||||||
|
if [[ "$k" == "$key" ]]; then found="yes"; break; fi
|
||||||
|
done
|
||||||
|
if [[ "$found" != "yes" ]]; then
|
||||||
|
out_section_key_list=(${out_section_key_list[@]:-""} "$key")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# set value in section map
|
||||||
|
local -n out_section_map="${var_prefix}__${section_name}"
|
||||||
|
out_section_map[$key]="$value"
|
||||||
|
continue; fi
|
||||||
|
|
||||||
|
|
||||||
|
## UNKNOWN ##
|
||||||
|
ini_log_error "Unknown config string '$line'"
|
||||||
|
done < "$path"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# HELPER: try calling external logger, else use fallback.
|
||||||
|
#
|
||||||
|
# @param $1 Message to print.
|
||||||
|
#
|
||||||
|
ini_log_debug(){
|
||||||
|
if [[ "$(type -t log_debug)" == "function" ]]; then log_debug "$1"; return; fi
|
||||||
|
echo "[DEBUG] $1" 1>&2
|
||||||
}
|
}
|
||||||
END {
|
ini_log_info(){
|
||||||
for(section in configuration)
|
if [[ "$(type -t log_info)" == "function" ]]; then log_info "$1"; return; fi
|
||||||
for(key in configuration[section]){
|
echo "[INFO ] $1" 1>&2
|
||||||
section_name = section
|
|
||||||
gsub("-", "_", section_name)
|
|
||||||
print "ini_" section_name "[\""key"\"]=\""configuration[section][key]"\";"
|
|
||||||
}
|
}
|
||||||
}' ${filename}
|
ini_log_warn(){
|
||||||
)
|
if [[ "$(type -t log_warn)" == "function" ]]; then log_warn "$1"; return; fi
|
||||||
|
echo "[WARN ] $1" 1>&2
|
||||||
|
}
|
||||||
|
ini_log_error(){
|
||||||
|
if [[ "$(type -t log_error)" == "function" ]]; then log_error "$1"; return; fi
|
||||||
|
echo "[ERROR] $1" 1>&2
|
||||||
|
exit 1
|
||||||
}
|
}
|
||||||
|
32
workplace
32
workplace
@ -76,19 +76,14 @@ workplace_set(){
|
|||||||
|
|
||||||
|
|
||||||
## RUN SET COMMANDS ##
|
## RUN SET COMMANDS ##
|
||||||
local -n workplace_section_name="ini_$workplace_name"
|
local -n workplace_section="ini__$workplace_name"
|
||||||
for k in "${!workplace_section_name[@]}"; do
|
for k in "${!workplace_section[@]}"; do
|
||||||
# make sure this is a `set` command
|
# `set` command
|
||||||
if [[ ! "$k" =~ ^set\. ]]; then
|
if [[ "$k" =~ ^set\. ]]; then
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# extract command and parameter
|
|
||||||
command=$(echo "$k" | grep -oPe '(?<=^set.).*')
|
command=$(echo "$k" | grep -oPe '(?<=^set.).*')
|
||||||
param="${workplace_section_name[$k]}"
|
param="${workplace_section[$k]}"
|
||||||
|
|
||||||
# run command
|
|
||||||
workplace_setcommand_run "$command" "$param"
|
workplace_setcommand_run "$command" "$param"
|
||||||
|
continue; fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,16 +102,16 @@ workplace_update(){
|
|||||||
workplace_list_prio_0=""
|
workplace_list_prio_0=""
|
||||||
workplace_list_prio_1=""
|
workplace_list_prio_1=""
|
||||||
for n in $(workplace_available_name_list); do
|
for n in $(workplace_available_name_list); do
|
||||||
local -n workplace_section_name="ini_$n"
|
local -n workplace_section="ini__$n"
|
||||||
|
|
||||||
# default
|
# default
|
||||||
trigger_default="${workplace_section_name[trigger.default]:-""}"
|
trigger_default="${workplace_section[trigger.default]:-""}"
|
||||||
if [[ "$trigger_default" == "true" ]]; then
|
if [[ "$trigger_default" == "true" ]]; then
|
||||||
workplace_list_prio_0="${workplace_list_prio_0} $n"
|
workplace_list_prio_0="${workplace_list_prio_0} $n"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# usb-id
|
# usb-id
|
||||||
trigger_usbid="${workplace_section_name[trigger.usb-id]:-""}"
|
trigger_usbid="${workplace_section[trigger.usb-id]:-""}"
|
||||||
if [[ "$trigger_usbid" ]]; then
|
if [[ "$trigger_usbid" ]]; then
|
||||||
for i in $usb_id_list; do
|
for i in $usb_id_list; do
|
||||||
if [[ "$i" == "$trigger_usbid" ]]; then
|
if [[ "$i" == "$trigger_usbid" ]]; then
|
||||||
@ -195,7 +190,8 @@ workplace_updatedaemon(){
|
|||||||
#
|
#
|
||||||
workplace_config_load(){
|
workplace_config_load(){
|
||||||
# clear used variables
|
# clear used variables
|
||||||
for v in $(compgen -A variable | grep -Pe '^ini_'); do
|
unset ini
|
||||||
|
for v in $(compgen -A variable | grep -Pe '^ini__'); do
|
||||||
unset $v
|
unset $v
|
||||||
done
|
done
|
||||||
|
|
||||||
@ -209,7 +205,11 @@ workplace_config_load(){
|
|||||||
# HELPER: Get defined workplace names.
|
# HELPER: Get defined workplace names.
|
||||||
#
|
#
|
||||||
workplace_available_name_list(){
|
workplace_available_name_list(){
|
||||||
for v in $(compgen -A variable | grep -oPe '(?<=^ini_).*'); do
|
for v in ${ini[*]}; do
|
||||||
|
# ignore root section
|
||||||
|
[[ "$v" == "_root" ]] && continue
|
||||||
|
|
||||||
|
# include this section's name
|
||||||
echo $v
|
echo $v
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user