mirror of
https://github.com/tests-always-included/mo.git
synced 2024-12-18 16:27:52 +00:00
Passes all of the tests
This commit is contained in:
parent
febd3467c8
commit
d997ad0e0a
203
mo
203
mo
@ -222,7 +222,7 @@ mo::usage() {
|
|||||||
if [[ "${line:0:2}" == "#/" ]]; then
|
if [[ "${line:0:2}" == "#/" ]]; then
|
||||||
echo "${line:3}"
|
echo "${line:3}"
|
||||||
fi
|
fi
|
||||||
done < <(cat "$MO_ORIGINAL_COMMAND")
|
done < "$MO_ORIGINAL_COMMAND"
|
||||||
echo ""
|
echo ""
|
||||||
echo "MO_VERSION=$MO_VERSION"
|
echo "MO_VERSION=$MO_VERSION"
|
||||||
}
|
}
|
||||||
@ -431,7 +431,7 @@ mo::chomp() {
|
|||||||
#
|
#
|
||||||
# Returns nothing.
|
# Returns nothing.
|
||||||
mo::parse() {
|
mo::parse() {
|
||||||
local moContent moCurrent moOpenDelimiter moCloseDelimieter moResult moSplit moParseChunk moFastMode moStandaloneContent
|
local moContent moCurrent moOpenDelimiter moCloseDelimieter moResult moSplit moParseChunk moFastMode moStandaloneContent moRemainder
|
||||||
moContent=$2
|
moContent=$2
|
||||||
moCurrent=$3
|
moCurrent=$3
|
||||||
moCurrentBlock=$4
|
moCurrentBlock=$4
|
||||||
@ -444,7 +444,8 @@ mo::parse() {
|
|||||||
# This is a trick to make the standalone tag detection believe it's on a
|
# This is a trick to make the standalone tag detection believe it's on a
|
||||||
# new line because there's no other way to easily tell the difference
|
# new line because there's no other way to easily tell the difference
|
||||||
# between a lone tag on a line and two tags where the first one evaluated
|
# between a lone tag on a line and two tags where the first one evaluated
|
||||||
# to an empty string.
|
# to an empty string. Whenever a standalone tag is encountered, this trick
|
||||||
|
# needs to be reset to a newline.
|
||||||
moStandaloneContent=$'\n'
|
moStandaloneContent=$'\n'
|
||||||
mo::debug "Starting parse, current: $moCurrent, ending tag: $moCurrentBlock, fast: $moFastMode"
|
mo::debug "Starting parse, current: $moCurrent, ending tag: $moCurrentBlock, fast: $moFastMode"
|
||||||
|
|
||||||
@ -471,7 +472,7 @@ mo::parse() {
|
|||||||
'/'*)
|
'/'*)
|
||||||
# Closing tag
|
# Closing tag
|
||||||
mo::parseCloseTag moParseChunk "$moResult" "$moContent" "$moCurrent" "$moCloseDelimiter" "$moCurrentBlock" "$moStandaloneContent"
|
mo::parseCloseTag moParseChunk "$moResult" "$moContent" "$moCurrent" "$moCloseDelimiter" "$moCurrentBlock" "$moStandaloneContent"
|
||||||
moRemainder=${moParseChunk[2]}
|
moRemainder=${moParseChunk[3]}
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'^'*)
|
'^'*)
|
||||||
@ -488,8 +489,8 @@ mo::parse() {
|
|||||||
# Change delimiters
|
# Change delimiters
|
||||||
# Any two non-whitespace sequences separated by whitespace.
|
# Any two non-whitespace sequences separated by whitespace.
|
||||||
mo::parseDelimiter moParseChunk "$moResult" "$moContent" "$moCloseDelimiter" "$moStandaloneContent"
|
mo::parseDelimiter moParseChunk "$moResult" "$moContent" "$moCloseDelimiter" "$moStandaloneContent"
|
||||||
moOpenDelimiter=${moParseChunk[2]}
|
moOpenDelimiter=${moParseChunk[3]}
|
||||||
moCloseDelimiter=${moParseChunk[3]}
|
moCloseDelimiter=${moParseChunk[4]}
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'&'*)
|
'&'*)
|
||||||
@ -509,8 +510,8 @@ mo::parse() {
|
|||||||
moResult=${moParseChunk[0]}
|
moResult=${moParseChunk[0]}
|
||||||
moContent=${moParseChunk[1]}
|
moContent=${moParseChunk[1]}
|
||||||
|
|
||||||
# Do not employ the trick after the first tag gets processed (see above)
|
# See above for a comment detailing this standalone trick
|
||||||
moStandaloneContent=''
|
moStandaloneContent=${moParseChunk[2]}
|
||||||
else
|
else
|
||||||
moResult="$moResult$moContent"
|
moResult="$moResult$moContent"
|
||||||
moContent=""
|
moContent=""
|
||||||
@ -535,6 +536,7 @@ mo::parse() {
|
|||||||
# The destination value will be an array
|
# The destination value will be an array
|
||||||
# [0] = the result text
|
# [0] = the result text
|
||||||
# [1] = remaining content to parse, excluding the closing delimiter
|
# [1] = remaining content to parse, excluding the closing delimiter
|
||||||
|
# [2] = standalone content trick
|
||||||
#
|
#
|
||||||
# Returns nothing
|
# Returns nothing
|
||||||
mo::parseBlock() {
|
mo::parseBlock() {
|
||||||
@ -556,6 +558,9 @@ mo::parseBlock() {
|
|||||||
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"
|
||||||
|
moStandaloneContent=$'\n'
|
||||||
|
else
|
||||||
|
moStandaloneContent=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get contents of block after parsing
|
# Get contents of block after parsing
|
||||||
@ -575,17 +580,30 @@ mo::parseBlock() {
|
|||||||
eval "moArrayIndexes=(\"\${!${moArrayName}[@]}\")"
|
eval "moArrayIndexes=(\"\${!${moArrayName}[@]}\")"
|
||||||
|
|
||||||
if [[ "${#moArrayIndexes[@]}" -lt 1 ]]; then
|
if [[ "${#moArrayIndexes[@]}" -lt 1 ]]; then
|
||||||
# No elements. Skip the block processing
|
# No elements
|
||||||
mo::parse moParseResult "$moContent" "$moCurrent" "${moArgs[1]}" "$moOpenDelimiter" "$moCloseDelimiter" "FAST-EMPTY"
|
if [[ "$moInvertBlock" == "true" ]]; then
|
||||||
moResult=""
|
# Show the block
|
||||||
|
mo::parse moParseResult "$moContent" "$moArrayName" "$moArrayName" "$moOpenDelimiter" "$moCloseDelimiter" ""
|
||||||
|
moResult=${moParseResult[0]}
|
||||||
|
else
|
||||||
|
# Skip the block processing
|
||||||
|
mo::parse moParseResult "$moContent" "$moCurrent" "$moArrayName" "$moOpenDelimiter" "$moCloseDelimiter" "FAST-EMPTY"
|
||||||
|
moResult=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
moResult=""
|
if [[ "$moInvertBlock" == "true" ]]; then
|
||||||
# Process for each element in the array
|
# Skip the block processing
|
||||||
for moArrayIndex in "${moArrayIndexes[@]}"; do
|
mo::parse moParseResult "$moContent" "$moCurrent" "$moArrayName" "$moOpenDelimiter" "$moCloseDelimiter" "FAST-EMPTY"
|
||||||
mo::debug "Iterate over array using element: $moArrayName.$moArrayIndex"
|
moResult=""
|
||||||
mo::parse moParseResult "$moContent" "$moArrayName.$moArrayIndex" "${moArgs[1]}" "$moOpenDelimiter" "$moCloseDelimiter" ""
|
else
|
||||||
moResult="$moResult${moParseResult[0]}"
|
moResult=""
|
||||||
done
|
# Process for each element in the array
|
||||||
|
for moArrayIndex in "${moArrayIndexes[@]}"; do
|
||||||
|
mo::debug "Iterate over array using element: $moArrayName.$moArrayIndex"
|
||||||
|
mo::parse moParseResult "$moContent" "$moArrayName.$moArrayIndex" "${moArgs[1]}" "$moOpenDelimiter" "$moCloseDelimiter" ""
|
||||||
|
moResult="$moResult${moParseResult[0]}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
moContent=${moParseResult[1]}
|
moContent=${moParseResult[1]}
|
||||||
@ -611,7 +629,7 @@ mo::parseBlock() {
|
|||||||
moContent=${moParseResult[1]}
|
moContent=${moParseResult[1]}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local "$1" && mo::indirectArray "$1" "$moPrevious$moResult" "$moContent"
|
local "$1" && mo::indirectArray "$1" "$moPrevious$moResult" "$moContent" "$moStandaloneContent"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -628,13 +646,15 @@ mo::parseBlock() {
|
|||||||
# The destination value will be an array
|
# The destination value will be an array
|
||||||
# [0] = the result text
|
# [0] = the result text
|
||||||
# [1] = remaining content to parse, excluding the closing delimiter
|
# [1] = remaining content to parse, excluding the closing delimiter
|
||||||
|
# [2] = standalone content trick
|
||||||
#
|
#
|
||||||
# Indentation should be applied to the entire partial's contents that are
|
# Indentation will be applied to the entire partial's contents that are
|
||||||
# returned. Adding indentation is outside the scope of this function.
|
# returned. This indentation is based on the whitespace that ends the
|
||||||
|
# previously parsed content.
|
||||||
#
|
#
|
||||||
# Returns nothing
|
# Returns nothing
|
||||||
mo::parsePartial() {
|
mo::parsePartial() {
|
||||||
local moContent moCurrent moCloseDelimiter moFilename moResult moFastMode moPrevious moStandaloneContent
|
local moContent moCurrent moCloseDelimiter moFilename moResult moFastMode moPrevious moStandaloneContent moIndentation moN moR
|
||||||
|
|
||||||
moPrevious=$2
|
moPrevious=$2
|
||||||
mo::trim moContent "${3:1}"
|
mo::trim moContent "${3:1}"
|
||||||
@ -644,10 +664,19 @@ mo::parsePartial() {
|
|||||||
moStandaloneContent=$7
|
moStandaloneContent=$7
|
||||||
mo::chomp moFilename "${moContent%%$moCloseDelimiter*}"
|
mo::chomp moFilename "${moContent%%$moCloseDelimiter*}"
|
||||||
moContent="${moContent#*$moCloseDelimiter}"
|
moContent="${moContent#*$moCloseDelimiter}"
|
||||||
|
moIndentation=""
|
||||||
|
|
||||||
if mo::standaloneCheck "$moStandaloneContent" "$moContent"; then
|
if mo::standaloneCheck "$moStandaloneContent" "$moContent"; then
|
||||||
|
moN=$'\n'
|
||||||
|
moR=$'\r'
|
||||||
|
moIndentation="$moN${moPrevious//$moR/$moN}"
|
||||||
|
moIndentation=${moIndentation##*$moN}
|
||||||
|
mo::debug "Adding indentation: '$moIndentation'"
|
||||||
mo::standaloneProcessBefore moPrevious "$moPrevious"
|
mo::standaloneProcessBefore moPrevious "$moPrevious"
|
||||||
mo::standaloneProcessAfter moContent "$moContent"
|
mo::standaloneProcessAfter moContent "$moContent"
|
||||||
|
moStandaloneContent=$'\n'
|
||||||
|
else
|
||||||
|
moStandaloneContent=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n "$moFastMode" ]]; then
|
if [[ -n "$moFastMode" ]]; then
|
||||||
@ -662,7 +691,9 @@ mo::parsePartial() {
|
|||||||
# but that is difficult when only given filenames.
|
# but that is difficult when only given filenames.
|
||||||
cd "$(dirname -- "$moFilename")" || exit 1
|
cd "$(dirname -- "$moFilename")" || exit 1
|
||||||
echo "$(
|
echo "$(
|
||||||
mo::contentFile moResult "${moFilename##*/}" || exit 1
|
if ! mo::contentFile moResult "${moFilename##*/}"; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Delimiters are reset when loading a new partial
|
# Delimiters are reset when loading a new partial
|
||||||
mo::parse moResult "$moResult" "$moCurrent" "" "{{" "}}" ""
|
mo::parse moResult "$moResult" "$moCurrent" "" "{{" "}}" ""
|
||||||
@ -671,14 +702,16 @@ mo::parsePartial() {
|
|||||||
echo -n "${moResult[0]}${moResult[1]}."
|
echo -n "${moResult[0]}${moResult[1]}."
|
||||||
)" || exit 1
|
)" || exit 1
|
||||||
) || exit 1
|
) || exit 1
|
||||||
moLen=${#moResult}
|
|
||||||
|
|
||||||
if [[ $moLen -gt 0 ]]; then
|
if [[ ${#moResult} -eq 0 ]]; then
|
||||||
moLen=$((moLen - 1))
|
mo::debug "Error detected when trying to read the file"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
mo::indentLines moResult "${moResult%.}" "$moIndentation"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local "$1" && mo::indirectArray "$1" "$moPrevious${moResult:0:moLen}" "$moContent"
|
local "$1" && mo::indirectArray "$1" "$moPrevious$moResult" "$moContent" "$moStandaloneContent"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -695,7 +728,8 @@ mo::parsePartial() {
|
|||||||
# The destination value will be an array
|
# The destination value will be an array
|
||||||
# [0] = the result text ($2)
|
# [0] = the result text ($2)
|
||||||
# [1] = remaining content to parse, excluding the closing delimiter (nothing)
|
# [1] = remaining content to parse, excluding the closing delimiter (nothing)
|
||||||
# [2] = Unparsed content outside of the block (the remainder)
|
# [2] = standalone content trick
|
||||||
|
# [3] = unparsed content outside of the block (the remainder)
|
||||||
#
|
#
|
||||||
# Returns nothing.
|
# Returns nothing.
|
||||||
mo::parseCloseTag() {
|
mo::parseCloseTag() {
|
||||||
@ -714,6 +748,9 @@ mo::parseCloseTag() {
|
|||||||
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"
|
||||||
|
moStandaloneContent=$'\n'
|
||||||
|
else
|
||||||
|
moStandaloneContent=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n "$moCurrentBlock" ]] && [[ "${moArgs[2]}" != "$moCurrentBlock" ]]; then
|
if [[ -n "$moCurrentBlock" ]] && [[ "${moArgs[2]}" != "$moCurrentBlock" ]]; then
|
||||||
@ -722,7 +759,7 @@ mo::parseCloseTag() {
|
|||||||
mo::error "Unexpected close tag: ${moArgs[2]}"
|
mo::error "Unexpected close tag: ${moArgs[2]}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local "$1" && mo::indirectArray "$1" "$moPrevious" "" "$moContent"
|
local "$1" && mo::indirectArray "$1" "$moPrevious" "" "$moStandaloneContent" "$moContent"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -737,6 +774,7 @@ mo::parseCloseTag() {
|
|||||||
# The destination value will be an array
|
# The destination value will be an array
|
||||||
# [0] = the result text
|
# [0] = the result text
|
||||||
# [1] = remaining content to parse, excluding the closing delimiter
|
# [1] = remaining content to parse, excluding the closing delimiter
|
||||||
|
# [2] = standalone content trick
|
||||||
#
|
#
|
||||||
# Returns nothing
|
# Returns nothing
|
||||||
mo::parseComment() {
|
mo::parseComment() {
|
||||||
@ -752,9 +790,12 @@ mo::parseComment() {
|
|||||||
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"
|
||||||
|
moStandaloneContent=$'\n'
|
||||||
|
else
|
||||||
|
moStandaloneContent=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local "$1" && mo::indirectArray "$1" "$moPrevious" "$moContent"
|
local "$1" && mo::indirectArray "$1" "$moPrevious" "$moContent" "$moStandaloneContent"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -769,8 +810,9 @@ mo::parseComment() {
|
|||||||
# The destination value will be an array
|
# The destination value will be an array
|
||||||
# [0] = the result text
|
# [0] = the result text
|
||||||
# [1] = remaining content to parse, excluding the closing delimiter
|
# [1] = remaining content to parse, excluding the closing delimiter
|
||||||
# [2] = new open delimiter
|
# [2] = standalone content trick
|
||||||
# [3] = new close delimiter
|
# [3] = new open delimiter
|
||||||
|
# [4] = new close delimiter
|
||||||
#
|
#
|
||||||
# Returns nothing
|
# Returns nothing
|
||||||
mo::parseDelimiter() {
|
mo::parseDelimiter() {
|
||||||
@ -790,9 +832,12 @@ mo::parseDelimiter() {
|
|||||||
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"
|
||||||
|
moStandaloneContent=$'\n'
|
||||||
|
else
|
||||||
|
moStandaloneContent=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local "$1" && mo::indirectArray "$1" "$moPrevious" "$moContent" "$moOpen" "$moClose"
|
local "$1" && mo::indirectArray "$1" "$moPrevious" "$moContent" "$moStandaloneContent" "$moOpen" "$moClose"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -809,6 +854,7 @@ mo::parseDelimiter() {
|
|||||||
# The destination value will be an array
|
# The destination value will be an array
|
||||||
# [0] = the result text
|
# [0] = the result text
|
||||||
# [1] = remaining content to parse, excluding the closing delimiter
|
# [1] = remaining content to parse, excluding the closing delimiter
|
||||||
|
# [2] = standalone content trick
|
||||||
#
|
#
|
||||||
# Returns nothing
|
# Returns nothing
|
||||||
mo::parseValue() {
|
mo::parseValue() {
|
||||||
@ -838,7 +884,7 @@ mo::parseValue() {
|
|||||||
|
|
||||||
moContent=${moContent:${#moCloseDelimiter}}
|
moContent=${moContent:${#moCloseDelimiter}}
|
||||||
|
|
||||||
local "$1" && mo::indirectArray "$1" "$moPrevious$moResult" "$moContent"
|
local "$1" && mo::indirectArray "$1" "$moPrevious$moResult" "$moContent" ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1161,9 +1207,16 @@ mo::isArray() {
|
|||||||
#
|
#
|
||||||
# $1 - Variable name to check.
|
# $1 - Variable name to check.
|
||||||
#
|
#
|
||||||
|
# Can not use logic like this in case invalid variable names are passed.
|
||||||
|
# [[ "${!1-a}" == "${!1-b}" ]]
|
||||||
|
#
|
||||||
# Returns true (0) if the variable is set, 1 if the variable is unset.
|
# Returns true (0) if the variable is set, 1 if the variable is unset.
|
||||||
mo::isVarSet() {
|
mo::isVarSet() {
|
||||||
[[ "${!1-a}" == "${!1-b}" ]]
|
if ! declare -p "$1" &> /dev/null; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1191,9 +1244,11 @@ mo::isTruthy() {
|
|||||||
# false false false
|
# false false false
|
||||||
# false true true
|
# false true true
|
||||||
if [[ "$moTruthy" == "$2" ]]; then
|
if [[ "$moTruthy" == "$2" ]]; then
|
||||||
|
mo::debug "Value is falsy, test result: $moTruthy inverse: $2"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
mo::debug "Value is truthy, test result: $moTruthy inverse: $2"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1385,7 +1440,7 @@ moJoin() {
|
|||||||
#
|
#
|
||||||
# Returns nothing.
|
# Returns nothing.
|
||||||
mo::evaluateFunction() {
|
mo::evaluateFunction() {
|
||||||
local moArgs moContent moFunctionArgs moFunctionResult moTarget moFunction moArgsSafe moTemp
|
local moArgs moContent moFunctionArgs moFunctionResult moTarget moFunction moTemp moFunctionCall
|
||||||
|
|
||||||
moTarget=$1
|
moTarget=$1
|
||||||
moContent=$2
|
moContent=$2
|
||||||
@ -1399,17 +1454,20 @@ mo::evaluateFunction() {
|
|||||||
shift 2
|
shift 2
|
||||||
done
|
done
|
||||||
|
|
||||||
|
mo::escape moFunctionCall "$moFunction"
|
||||||
|
|
||||||
# shellcheck disable=SC2031
|
# shellcheck disable=SC2031
|
||||||
if [[ -n "${MO_ALLOW_FUNCTION_ARGUMENTS-}" ]]; then
|
if [[ -n "${MO_ALLOW_FUNCTION_ARGUMENTS-}" ]]; then
|
||||||
# Intentionally remove all function arguments
|
mo::debug "Function arguments are allowed"
|
||||||
# shellcheck disable=SC2206
|
|
||||||
moArgsSafe=()
|
for moTemp in "${moArgs[@]}"; do
|
||||||
else
|
mo::escape moTemp "$moTemp"
|
||||||
moArgsSafe=(${moArgs[@]+"${moArgs[@]}"})
|
moFunctionCall="$moFunctionCall $moTemp"
|
||||||
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mo::debug "Calling function: $moFunction ${moArgs[*]}"
|
mo::debug "Calling function: $moFunctionCall"
|
||||||
moContent=$(echo -n "$moContent" | MO_FUNCTION_ARGS=(${moArgs[@]+"${moArgs[@]}"}) eval "$moFunction" ${moArgsSafe[@]+"${moArgsSafe[@]}"}) || {
|
moContent=$(export MO_FUNCTION_ARGS=("${moArgs[@]}"); echo -n "$moContent" | eval "$moFunctionCall") || {
|
||||||
moFunctionResult=$?
|
moFunctionResult=$?
|
||||||
# shellcheck disable=SC2031
|
# shellcheck disable=SC2031
|
||||||
if [[ -n "${MO_FAIL_ON_FUNCTION-}" && "$moFunctionResult" != 0 ]]; then
|
if [[ -n "${MO_FAIL_ON_FUNCTION-}" && "$moFunctionResult" != 0 ]]; then
|
||||||
@ -1418,7 +1476,7 @@ mo::evaluateFunction() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# shellcheck disable=SC2031
|
# shellcheck disable=SC2031
|
||||||
local "$1" && mo::indirect "$1" "$moContent"
|
local "$moTarget" && mo::indirect "$moTarget" "$moContent"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1524,6 +1582,63 @@ mo::standaloneProcessAfter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Internal: Apply indentation before any line that has content
|
||||||
|
#
|
||||||
|
# $1 - Destination variable
|
||||||
|
# $2 - The content to indent
|
||||||
|
# $3 - The indentation string
|
||||||
|
#
|
||||||
|
# Returns nothing.
|
||||||
|
mo::indentLines() {
|
||||||
|
local moContent moIndentation moResult moN moR moChunk
|
||||||
|
|
||||||
|
moContent=$2
|
||||||
|
moIndentation=$3
|
||||||
|
moResult=""
|
||||||
|
moN=$'\n'
|
||||||
|
moR=$'\r'
|
||||||
|
|
||||||
|
if [[ -z "$moIndentation" ]] || [[ -z "$moContent" ]]; then
|
||||||
|
mo::debug "Not applying indentation, indentation ${#moIndentation} bytes, content ${#moContent} bytes"
|
||||||
|
moResult=$moContent
|
||||||
|
else
|
||||||
|
mo::debug "Applying indentation: '${moIndentation}'"
|
||||||
|
|
||||||
|
while [[ -n "$moContent" ]]; do
|
||||||
|
moChunk=${moContent%%$moN*}
|
||||||
|
moChunk=${moChunk%%$moR*}
|
||||||
|
moContent=${moContent:${#moChunk}}
|
||||||
|
|
||||||
|
if [[ -n "$moChunk" ]]; then
|
||||||
|
moResult="$moResult$moIndentation$moChunk"
|
||||||
|
fi
|
||||||
|
|
||||||
|
moResult="$moResult${moContent:0:1}"
|
||||||
|
moContent=${moContent:1}
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
local "$1" && mo::indirect "$1" "$moResult"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Internal: Escape a value
|
||||||
|
#
|
||||||
|
# $1 - Destination variable name
|
||||||
|
# $2 - Value to escape
|
||||||
|
#
|
||||||
|
# Returns nothing
|
||||||
|
mo::escape() {
|
||||||
|
local moResult
|
||||||
|
|
||||||
|
moResult=$2
|
||||||
|
moResult=$(declare -p moResult)
|
||||||
|
moResult=${moResult#*=}
|
||||||
|
|
||||||
|
local "$1" && mo::indirect "$1" "$moResult"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# Save the original command's path for usage later
|
# Save the original command's path for usage later
|
||||||
MO_ORIGINAL_COMMAND="$(cd "${BASH_SOURCE[0]%/*}" || exit 1; pwd)/${BASH_SOURCE[0]##*/}"
|
MO_ORIGINAL_COMMAND="$(cd "${BASH_SOURCE[0]%/*}" || exit 1; pwd)/${BASH_SOURCE[0]##*/}"
|
||||||
MO_VERSION="3.0.0"
|
MO_VERSION="3.0.0"
|
||||||
|
@ -3,6 +3,7 @@ cd "${0%/*}" || exit 1
|
|||||||
. ../run-tests
|
. ../run-tests
|
||||||
|
|
||||||
arguments=(-- --help)
|
arguments=(-- --help)
|
||||||
|
returnCode=1
|
||||||
template=""
|
template=""
|
||||||
expected="cat: --help: No such file or directory"$'\n'
|
expected="cat: --help: No such file or directory"$'\n'
|
||||||
|
|
||||||
|
@ -18,9 +18,9 @@ testArgs() {
|
|||||||
template() {
|
template() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
No args: {{testArgs}} - done
|
No args: {{testArgs}} - done
|
||||||
One arg: {{testArgs one}} - done
|
One arg: {{testArgs 'one'}} - done
|
||||||
Getting name in a string: {{testArgs "The name is $name"}} - done
|
Getting name in a string: {{testArgs {"The name is " name}}} - done
|
||||||
Reverse this: {{#pipeTo rev}}abcde{{/pipeTo}}
|
Reverse this: {{#pipeTo "rev"}}abcde{{/pipeTo}}
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
expected() {
|
expected() {
|
||||||
|
@ -3,22 +3,23 @@ cd "${0%/*}" || exit 1
|
|||||||
. ../run-tests
|
. ../run-tests
|
||||||
|
|
||||||
testArgs() {
|
testArgs() {
|
||||||
echo "$MO_FUNCTION_ARGS"
|
local args=$(declare -p MO_FUNCTION_ARGS)
|
||||||
|
echo "${args#*=}"
|
||||||
}
|
}
|
||||||
template() {
|
template() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
No args: [{{testArgs}}] - done
|
No args: {{testArgs}} - done
|
||||||
One arg: [{{testArgs one}}] - done
|
One arg: {{testArgs 'one'}} - done
|
||||||
Multiple arguments: [{{testArgs aa bb cc 'x' " ! {[_.| }}] - done
|
Multiple arguments: {{testArgs 'aa' 'bb' 'cc' 'x' "" '!' '{[_.|' }} - done
|
||||||
Evil: [{{testArgs bla; cat /etc/issue}}] - done
|
Evil: {{testArgs bla; cat /etc/issue}} - done
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
expected() {
|
expected() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
No args: [] - done
|
No args: () - done
|
||||||
One arg: [one] - done
|
One arg: ([0]="one") - done
|
||||||
Multiple arguments: [aa bb cc 'x' " ! {[_.|] - done
|
Multiple arguments: ([0]="aa" [1]="bb" [2]="cc" [3]="x" [4]="" [5]="!" [6]="{[_.|") - done
|
||||||
Evil: [bla; cat /etc/issue] - done
|
Evil: ([0]="" [1]="" [2]="") - done
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,8 @@ Options:
|
|||||||
-s=FILE, --source=FILE
|
-s=FILE, --source=FILE
|
||||||
Load FILE into the environment before processing templates.
|
Load FILE into the environment before processing templates.
|
||||||
Can be used multiple times.
|
Can be used multiple times.
|
||||||
|
-d, --debug
|
||||||
|
Enable debug logging to stderr.
|
||||||
|
|
||||||
MO_VERSION=3.0.0
|
MO_VERSION=3.0.0
|
||||||
EOF
|
EOF
|
||||||
|
@ -4,6 +4,7 @@ cd "${0%/*}" || exit 1
|
|||||||
|
|
||||||
person=""
|
person=""
|
||||||
template=""
|
template=""
|
||||||
|
returnCode=1
|
||||||
arguments=(--something)
|
arguments=(--something)
|
||||||
expected() {
|
expected() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
|
@ -7,7 +7,7 @@ template() {
|
|||||||
cat <<EOF
|
cat <<EOF
|
||||||
<h2>Names</h2>
|
<h2>Names</h2>
|
||||||
{{#names}}
|
{{#names}}
|
||||||
{{> partial.partial}}
|
{{> fixtures/partial.partial}}
|
||||||
{{/names}}
|
{{/names}}
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
@ -15,7 +15,6 @@ expected() {
|
|||||||
cat <<EOF
|
cat <<EOF
|
||||||
<h2>Names</h2>
|
<h2>Names</h2>
|
||||||
<strong>Tyler</strong>
|
<strong>Tyler</strong>
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user