Splitting parse function, fixing variable bug

This commit is contained in:
Tyler Akins 2023-04-09 09:51:11 -05:00
parent a237d23a2d
commit 47e10012ee
No known key found for this signature in database
GPG Key ID: 8F3B8C432F4393BD
2 changed files with 192 additions and 77 deletions

160
mo
View File

@ -541,7 +541,7 @@ mo::parse() {
# #
# Returns nothing # Returns nothing
mo::parseBlock() { mo::parseBlock() {
local moContent moCurrent moOpenDelimiter moCloseDelimiter moInvertBlock moTag moArgs moTemp moParseResult moResult moPrevious moStandaloneContent moArrayName moArrayIndexes moArrayIndex local moContent moCurrent moOpenDelimiter moCloseDelimiter moInvertBlock moArgs moParseResult moPrevious moStandaloneContent
moPrevious=$2 moPrevious=$2
mo::trim moContent "${3:1}" mo::trim moContent "${3:1}"
@ -555,7 +555,6 @@ mo::parseBlock() {
moArgs=("${moArgs[@]:1}") moArgs=("${moArgs[@]:1}")
mo::debug "Parsing block: ${moArgs[*]}" mo::debug "Parsing block: ${moArgs[*]}"
if [[ "${moArgs[0]}" == "NAME" ]] && mo::isFunction "${moArgs[1]}"; then
if mo::standaloneCheck "$moStandaloneContent" "$moContent"; then if mo::standaloneCheck "$moStandaloneContent" "$moContent"; then
mo::standaloneProcessBefore moPrevious "$moPrevious" mo::standaloneProcessBefore moPrevious "$moPrevious"
mo::standaloneProcessAfter moContent "$moContent" mo::standaloneProcessAfter moContent "$moContent"
@ -564,22 +563,101 @@ mo::parseBlock() {
moStandaloneContent="" moStandaloneContent=""
fi fi
if [[ "${moArgs[0]}" == "NAME" ]] && mo::isFunction "${moArgs[1]}"; then
mo::parseBlockFunction moParseResult "$moContent" "$moCurrent" "$moOpenDelimiter" "$moCloseDelimiter" "$moInvertBlock" "$moStandaloneContent" "${moArgs[@]}"
elif [[ "${moArgs[0]}" == "NAME" ]] && mo::isArray "${moArgs[1]}"; then
mo::parseBlockArray moParseResult "$moContent" "$moCurrent" "$moOpenDelimiter" "$moCloseDelimiter" "$moInvertBlock" "$moStandaloneContent" "${moArgs[@]}"
else
mo::parseBlockValue moParseResult "$moContent" "$moCurrent" "$moOpenDelimiter" "$moCloseDelimiter" "$moInvertBlock" "$moStandaloneContent" "${moArgs[@]}"
fi
local "$1" && mo::indirectArray "$1" "$moPrevious${moParseResult[0]}" "${moParseResult[1]}" "${moParseResult[2]}"
}
# Internal: Handle parsing a block whose first argument is a function
#
# $1 - Destination variable name, will be set to an array
# $2 - Content
# $3 - Current name (the variable NAME for what {{.}} means)
# $4 - Open delimiter
# $5 - Close delimiter
# $6 - Invert condition ("true" or "false")
# $7 - Standalone content
# $8-$* - The parsed arguments from inside the block tags
#
# The destination value will be an array
# [0] = the result text
# [1] = remaining content to parse, excluding the closing delimiter
# [2] = standalone content trick
#
# Returns nothing
mo::parseBlockFunction() {
local moTarget moContent moCurrent moOpenDelimiter moCloseDelimiter moInvertBlock moArgs moParseResult moResult moStandaloneContent
moTarget=$1
moContent=$2
moCurrent=$3
moOpenDelimiter=$4
moCloseDelimiter=$5
moInvertBlock=$6
moStandaloneContent=$7
shift 7
moArgs=(${@+"$@"})
mo::debug "Parsing block function: ${moArgs[*]}"
if [[ "$moInvertBlock" == "true" ]]; then
# The function exists and we're inverting the section, so skip the
# block content.
mo::parse moParseResult "$moContent" "$moCurrent" "${moArgs[1]}" "$moOpenDelimiter" "$moCloseDelimiter" "FAST-FUNCTION" "$moStandaloneContent"
moResult=""
moContent="${moParseResult[1]}"
else
# Get contents of block after parsing # Get contents of block after parsing
mo::parse moParseResult "$moContent" "$moCurrent" "${moArgs[1]}" "$moOpenDelimiter" "$moCloseDelimiter" "" "$moStandaloneContent" mo::parse moParseResult "$moContent" "$moCurrent" "${moArgs[1]}" "$moOpenDelimiter" "$moCloseDelimiter" "" "$moStandaloneContent"
# Pass contents to function # Pass contents to function
mo::evaluateFunction moResult "${moParseResult[0]}" "${moArgs[@]:1}" mo::evaluateFunction moResult "${moParseResult[0]}" "${moArgs[@]:1}"
moContent=${moParseResult[1]}
elif [[ "${moArgs[0]}" == "NAME" ]] && mo::isArray "${moArgs[1]}"; then
# Need to interate across array for each element in the array.
if mo::standaloneCheck "$moStandaloneContent" "$moContent"; then
mo::standaloneProcessBefore moPrevious "$moPrevious"
mo::standaloneProcessAfter moContent "$moContent"
moStandaloneContent=$'\n'
else
moStandaloneContent=""
fi fi
moContent=${moParseResult[1]}
moStandaloneContent=${moParseResult[2]}
mo::debug "Done parsing block array: ${moArgs[*]}"
local "$moTarget" && mo::indirectArray "$moTarget" "$moResult" "$moContent" "$moStandaloneContent"
}
# Internal: Handle parsing a block whose first argument is an array
#
# $1 - Destination variable name, will be set to an array
# $2 - Content
# $3 - Current name (the variable NAME for what {{.}} means)
# $4 - Open delimiter
# $5 - Close delimiter
# $6 - Invert condition ("true" or "false")
# $7 - Standalone content
# $8-$* - The parsed arguments from inside the block tags
#
# The destination value will be an array
# [0] = the result text
# [1] = remaining content to parse, excluding the closing delimiter
# [2] = standalone content trick
#
# Returns nothing
mo::parseBlockArray() {
local moTarget moContent moCurrent moOpenDelimiter moCloseDelimiter moInvertBlock moArgs moParseResult moResult moStandaloneContent moArrayName moArrayIndexes moArrayIndex
moTarget=$1
moContent=$2
moCurrent=$3
moOpenDelimiter=$4
moCloseDelimiter=$5
moInvertBlock=$6
moStandaloneContent=$7
shift 7
moArgs=(${@+"$@"})
mo::debug "Parsing block array: ${moArgs[*]}"
moArrayName=${moArgs[1]} moArrayName=${moArgs[1]}
eval "moArrayIndexes=(\"\${!${moArrayName}[@]}\")" eval "moArrayIndexes=(\"\${!${moArrayName}[@]}\")"
@ -591,13 +669,13 @@ mo::parseBlock() {
moResult=${moParseResult[0]} moResult=${moParseResult[0]}
else else
# Skip the block processing # Skip the block processing
mo::parse moParseResult "$moContent" "$moCurrent" "$moArrayName" "$moOpenDelimiter" "$moCloseDelimiter" "FAST-EMPTY" "$moStandaloneContent" mo::parse moParseResult "$moContent" "$moArrayName" "$moArrayName" "$moOpenDelimiter" "$moCloseDelimiter" "FAST-EMPTY" "$moStandaloneContent"
moResult="" moResult=""
fi fi
else else
if [[ "$moInvertBlock" == "true" ]]; then if [[ "$moInvertBlock" == "true" ]]; then
# Skip the block processing # Skip the block processing
mo::parse moParseResult "$moContent" "$moCurrent" "$moArrayName" "$moOpenDelimiter" "$moCloseDelimiter" "FAST-EMPTY" "$moStandaloneContent" mo::parse moParseResult "$moContent" "$moArrayName" "$moArrayName" "$moOpenDelimiter" "$moCloseDelimiter" "FAST-EMPTY" "$moStandaloneContent"
moResult="" moResult=""
else else
moResult="" moResult=""
@ -612,33 +690,61 @@ mo::parseBlock() {
moContent=${moParseResult[1]} moContent=${moParseResult[1]}
moStandaloneContent=${moParseResult[2]} moStandaloneContent=${moParseResult[2]}
else mo::debug "Done parsing block array: ${moArgs[*]}"
if mo::standaloneCheck "$moStandaloneContent" "$moContent"; then
mo::standaloneProcessBefore moPrevious "$moPrevious" local "$moTarget" && mo::indirectArray "$moTarget" "$moResult" "$moContent" "$moStandaloneContent"
mo::standaloneProcessAfter moContent "$moContent" }
moStandaloneContent=$'\n'
else
moStandaloneContent="" # Internal: Handle parsing a block whose first argument is a value
fi #
# $1 - Destination variable name, will be set to an array
# $2 - Content
# $3 - Current name (the variable NAME for what {{.}} means)
# $4 - Open delimiter
# $5 - Close delimiter
# $6 - Invert condition ("true" or "false")
# $7 - Standalone content
# $8-$* - The parsed arguments from inside the block tags
#
# The destination value will be an array
# [0] = the result text
# [1] = remaining content to parse, excluding the closing delimiter
# [2] = standalone content trick
#
# Returns nothing
mo::parseBlockValue() {
local moTarget moContent moCurrent moOpenDelimiter moCloseDelimiter moInvertBlock moArgs moParseResult moResult moStandaloneContent
moTarget=$1
moContent=$2
moCurrent=$3
moOpenDelimiter=$4
moCloseDelimiter=$5
moInvertBlock=$6
moStandaloneContent=$7
shift 7
moArgs=(${@+"$@"})
mo::debug "Parsing block value: ${moArgs[*]}"
# Variable, value, or list of mixed things # Variable, value, or list of mixed things
mo::evaluateListOfSingles moResult "$moCurrent" "${moArgs[@]}" mo::evaluateListOfSingles moResult "$moCurrent" "${moArgs[@]}"
if mo::isTruthy "$moResult" "$moInvertBlock"; then if mo::isTruthy "$moResult" "$moInvertBlock"; then
mo::debug "Block is truthy: $moResult" mo::debug "Block is truthy: $moResult"
mo::parse moParseResult "$moContent" "$moCurrent" "${moArgs[1]}" "$moOpenDelimiter" "$moCloseDelimiter" "" "$moStandaloneContent" mo::parse moParseResult "$moContent" "${moArgs[1]}" "${moArgs[1]}" "$moOpenDelimiter" "$moCloseDelimiter" "" "$moStandaloneContent"
moResult="${moParseResult[0]}"
else else
mo::debug "Block is falsy: $moResult" mo::debug "Block is falsy: $moResult"
mo::parse moParseResult "$moContent" "$moCurrent" "${moArgs[1]}" "$moOpenDelimiter" "$moCloseDelimiter" "FAST-FALSY" "$moStandaloneContent" mo::parse moParseResult "$moContent" "${moArgs[1]}" "${moArgs[1]}" "$moOpenDelimiter" "$moCloseDelimiter" "FAST-FALSY" "$moStandaloneContent"
moParseResult[0]="" moResult=""
fi fi
moResult=${moParseResult[0]}
moContent=${moParseResult[1]} moContent=${moParseResult[1]}
moStandaloneContent=${moParseResult[2]} moStandaloneContent=${moParseResult[2]}
fi mo::debug "Done parsing block value: ${moArgs[*]}"
local "$1" && mo::indirectArray "$1" "$moPrevious$moResult" "$moContent" "$moStandaloneContent" local "$moTarget" && mo::indirectArray "$moTarget" "$moResult" "$moContent" "$moStandaloneContent"
} }

9
tests/variable Executable file
View File

@ -0,0 +1,9 @@
#!/usr/bin/env bash
cd "${0%/*}" || exit 1
. ../run-tests
foo=bar
template="{{#foo}}{{.}} is {{foo}}{{/foo}}"
expected="bar is bar"
runTest