Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.0
0.1.0
File renamed without changes.
16 changes: 8 additions & 8 deletions project.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[project]
name = structured-shell
maintainer = Kyle Smith <kyle@kmaismith.com>
description = '''
Structured Shell (STSH) is a script execution framework extending the power of
BASH Shell scripting with safer programming paradigms.
'''
name = "structured-shell"
maintainer = "Kyle Smith <kyle@kmaismith.com>"
# description = '''
# Structured Shell (STSH) is a script execution framework extending the power of
# BASH Shell scripting with safer programming paradigms.
# '''

[build]
build_root = ${PROJECT_ROOT}/build
build_root = "${PROJECT_ROOT}/build"

[hello_world]
greeting = Salutations
greeting = "Salutations"
2 changes: 1 addition & 1 deletion src/bin/autotask
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ __script_parse_opts() {

declare -g TASK_FILE

LOG_CONTEXT_BUILDER="autotask:${TASK_NAME}:"
# LOG_CONTEXT_BUILDER="autotask:${TASK_NAME}:"
[ -n "${TASK_MAIN-}" ] || \
TASK_MAIN="${TASK_NAME}"
}
Expand Down
16 changes: 9 additions & 7 deletions src/lib/libautoshell.exec.bash
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ export -f try
# 1 and exits the current process
###############################
fatal() {
local _message="${1}"

if type log &>/dev/null; then
log FATAL "${_message}" "${FUNCNAME[1]-}"
else
echo "FATAL: ${_message}"
fi
local _message="${1-}"

[ -n "${_message}" ] && {
if type log &>/dev/null; then
log FATAL "${_message}" "${FUNCNAME[1]-}"
else
echo "FATAL: ${_message}"
fi
}

exit 1
}
Expand Down
68 changes: 31 additions & 37 deletions src/lib/libautoshell.toml.bash
Original file line number Diff line number Diff line change
@@ -1,55 +1,49 @@
#!/usr/bin/env bash

export TOML_PREFIX="TOML"
export TOML_CONFIG_VAR="TOML_CONFIG"
toml.load() { # toml_file[, toml_prefix=$TOML_PREFIX]
local \
current_heading="default" \
current_key \
current_value \
global_var_name \
line \
toml_file="${1}" \
toml_prefix="${2:-"${TOML_PREFIX}"}"

while read -r line; do
case "${line}" in
\[*\])
current_heading="$(sed -e 's/\[\(.*\)\]/\1/' <<< "${line}")"
;;
*\ \=\ *)
current_key="$(sed -e 's/^\(.*\) = .*$/\1/' <<< "${line}")"
current_value="$(sed -e 's/^.* = \(.*\)$/\1/' <<< "${line}")"

if [ -n "${current_value}" ]; then
global_var_name="${toml_prefix}_${current_heading/\./_}_KEY_${current_key}"
declare -gx "${global_var_name}"
local -n ref_var="${global_var_name}"
ref_var="${current_value}"
fi
;;
esac
done < <(cat "${toml_file}"; echo)
config_var="${2:-"${TOML_CONFIG_VAR}"}"

include "$(find_lib autoshell.toml.parser)"

declare -gA "${config_var}"

tomlparser.parse "${config_var}" < "${toml_file}"
}
export -f toml.load

toml.get_value() { # toml_key, toml_section[, toml_prefix=$TOML_PREFIX]
local \
toml_key="${1}" \
toml_section="${2}" \
toml_prefix="${3:-"${TOML_PREFIX}"}"
config_var_name="${2:-"${TOML_CONFIG_VAR}"}"

toml.map_value "${toml_key}" "${toml_section}" "${toml_prefix}" TOML_VALUE
toml.map_value "${toml_key}" TOML_VALUE "${config_var_name}"

echo "${TOML_VALUE-}"
}

toml.map_value() { # toml_key, toml_section[, toml_prefix=$TOML_PREFIX, dest_var=$toml_key]
toml.map_value() { # toml_key, dest_var[, config_var=$TOML_CONFIG_VAR]
local \
toml_key="${1}" \
toml_section="${2}" \
toml_prefix="${3:-"${TOML_PREFIX}"}" \
dest_var="${4:-${1}}"

declare -gn "${dest_var}=${toml_prefix}_${toml_section}_KEY_${toml_key}"
dest_var_name="${2}" \
config_var_name="${3:-"${TOML_CONFIG_VAR}"}"
local -n config_ref="${config_var_name}"
local -n var_ref="${dest_var_name}"
declare -g "${dest_var_name}"
var_ref=""

[ -n "${config_ref[*]-}" ] || \
return 0

var_ref="${config_ref["${toml_key}"]-}"

[ -n "${var_ref-}" ] || {
[ "$(type -t map.keys)" = "function" ] || \
include "$(find_lib map)"
declare -ga "${dest_var_name}=()"
while read -r key; do var_ref+=("${config_ref[${key}]}"); done < \
<( map.keys config_ref | grep "${toml_key}\[[0-9]*\]" | sort )
}
}
export -f toml.map_value
export -f toml.map_value
217 changes: 217 additions & 0 deletions src/lib/libautoshell.toml.parser.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
#!/usr/bin/env bash

tomlparser.parse() { # config_var <<< TOML Data
declare -g \
heading="" \
key="" \
value="" \
quote="" \
array_index="" \
line_index="1" \
mode="key" \
line char
declare -gn ref=key
declare -gn config="${1}"

while read -r line; do
tomlparser.parse_line "${line}"
line_index=$(( line_index + 1 ))
done
}

tomlparser.parse_line() {
local \
line="${1}" \
last_char="" \
char_index=0

while read -rN1 char; do
tomlparser.parse_char "${char_index}" "${char-}" "${last_char-}"
char_index=$(( char_index + 1 ))
last_char="${char-}"
done <<< "${line}"
case "${mode}" in
array)
;;
*)
tomlparser.flush_key
mode=key
;;
esac
}

tomlparser.parse_char() {
local \
char_index="${1}" \
char="${2:- }" \
last_char="${3:- }"

[ "${char}" = $'\n' ] && return 0

case "${mode}" in
key)
if [ -n "${quote-}" ]; then
tomlparser.parse_char^quote key "${char}"
else
tomlparser.parse_char^key "${char}"
fi
;;
heading)
if [ -n "${quote-}" ]; then
tomlparser.parse_char^quote heading "${char}"
else
tomlparser.parse_char^heading "${char}"
fi
;;
value)
if [ -n "${quote-}" ]; then
tomlparser.parse_char^quote value "${char}"
else
tomlparser.parse_char^value "${char}"
fi
;;
array)
[ -n "${array_index-}" ] || array_index=0
if [ -n "${quote-}" ]; then
tomlparser.parse_char^quote value "${char}"
else
tomlparser.parse_char^array "${char}"
fi
;;
line_return)
tomlparser.parse_char^line_return "${char}"
;;
comment)
;;
esac
}

tomlparser.parse_char^quote() {
local -n ref="${1}"
local char="${2}"

case "${char}" in
"${quote}")
quote=""
;;
$''|$' ')
ref+=" "
;;
*)
ref+="${char}"
;;
esac
}

tomlparser.parse_char^key() {
case "${1}" in
$'[')
heading=""
mode=heading
;;
$'=')
mode=value
;;
$'"')
quote="${char}"
;;
$'#')
mode=comment
;;
$' ')
;;
*)
[ "${last_char}" = " " ] && [ "${char_index}" -gt 0 ] && \
tomlparser.parse_error "Unexpected char: ${char}: Unquoted keys cannot have spaces"
key+="${char}"
;;
esac
}

tomlparser.parse_char^heading() {
case "${1}" in
$']')
mode=line_return
;;
$'"')
quote="${char}"
;;
$' ')
;;
*)
heading+="${char}"
;;
esac
}

tomlparser.parse_char^value() {
case "${1}" in
$'[')
mode=array
;;
$'"')
quote="${char}"
;;
$' ')
;;
$'#')
mode=comment
;;
*)
tomlparser.parse_error "Unquoted string"
;;
esac
}

tomlparser.parse_char^array() {
case "${1}" in
$']')
tomlparser.flush_key
mode=line_return
;;
$',')
tomlparser.flush_value
array_index=$(( array_index + 1 ))
;;
$'"')
quote="${char}"
;;
$' ')
;;
*)
tomlparser.parse_error "Unquoted string"
;;
esac
}

tomlparser.parse_char^line_return() {
case "${1}" in
$' ')
;;
$'#')
mode[-1]="comment"
;;
*)
tomlparser.parse_error "Unexpected symbol: ${char}"
;;
esac
}

tomlparser.flush_value() {
[ -n "${key}" ] && [ -n "${value}" ] && {
local config_key="${heading:+.${heading}}.${key}${array_index:+[${array_index}]}"
local config_value="$(envsubst <<< "${value}")"
config["${config_key}"]="${config_value}"
}
value=""
}

tomlparser.flush_key() {
tomlparser.flush_value
key=""
}

tomlparser.parse_error() {
log FATAL "${1}" "tomlparser: line ${line_index}, char ${char_index}"
fatal
}
Loading