5 Commits
3.0.1 ... 3.0.5

Author SHA1 Message Date
Tyler Akins
26ca5059d8 Fix slowness with larger templates
Closes #69 and #71
Released 3.0.5
2024-03-27 21:57:11 -05:00
Tyler Akins
6e57510ba9 Making it more clear that sourced files are shell
Addresses part of the concerns from #69
2023-11-16 16:04:52 -06:00
Tyler Akins
54b2184b70 Bumping version 2023-09-10 08:11:54 -05:00
Tyler Akins
84d17268c9 Work with symbolic links 2023-09-10 08:10:51 -05:00
Tyler Akins
68306c4c6d More Bash 4.x compatibility issues found and fixed 2023-05-12 08:17:57 -05:00
5 changed files with 60 additions and 30 deletions

View File

@@ -117,9 +117,11 @@ There are more scripts available in the [demos directory](demo/) that could help
There are additional features that the program supports. Try using `mo --help` to see what is available.
Please note that this command is written in Bash and pulls data from either the environment or (when using `--source`) from a text file that will be sourced and loaded into the environment, which means you will need to have Bash-style variables defined. Please see the examples in `demo/` for different ways you can use `mo`.
Enhancements
-----------
------------
In addition to many of the features built-in to Mustache, `mo` includes a number of unique features that make it a bit more powerful.

45
mo
View File

@@ -38,7 +38,8 @@
#/ This message.
#/ -s=FILE, --source=FILE
#/ Load FILE into the environment before processing templates.
#/ Can be used multiple times.
#/ Can be used multiple times. The file must be a valid shell script
#/ and should only contain variable assignments.
#/ -o=DELIM, --open=DELIM
#/ Set the opening delimiter. Default is "{{".
#/ -c=DELIM, --close=DELIM
@@ -155,7 +156,7 @@ mo() (
moSource="${arg#-s=}"
fi
if [[ -f "$moSource" ]]; then
if [[ -e "$moSource" ]]; then
# shellcheck disable=SC1090
. "$moSource"
else
@@ -429,20 +430,30 @@ mo::indirectArray() {
#
# Returns nothing.
mo::trimUnparsed() {
local moLast moR moN moT
local moLastLen moR moN moT
moLast=""
moLastLen=0
moR=$'\r'
moN=$'\n'
moT=$'\t'
while [[ "$MO_UNPARSED" != "$moLast" ]]; do
moLast=$MO_UNPARSED
while [[ "${#MO_UNPARSED}" != "$moLastLen" ]]; do
moLastLen=${#MO_UNPARSED}
# These conditions are necessary for a significant speed increase
while [[ "${MO_UNPARSED:0:1}" == " " ]]; do
MO_UNPARSED=${MO_UNPARSED# }
done
while [[ "${MO_UNPARSED:0:1}" == "$moR" ]]; do
MO_UNPARSED=${MO_UNPARSED#"$moR"}
done
while [[ "${MO_UNPARSED:0:1}" == "$moN" ]]; do
MO_UNPARSED=${MO_UNPARSED#"$moN"}
done
while [[ "${MO_UNPARSED:0:1}" == "$moT" ]]; do
MO_UNPARSED=${MO_UNPARSED#"$moT"}
done
done
}
@@ -1061,7 +1072,7 @@ mo::evaluate() {
;;
*)
moStack=("${moStack[@]}" "$1" "$2")
moStack=(${moStack[@]+"${moStack[@]}"} "$1" "$2")
;;
esac
@@ -1077,7 +1088,7 @@ mo::evaluate() {
else
#: Concatenate
mo::debug "Concatenating ${#moStack[@]} stack items"
mo::evaluateListOfSingles moResult "${moStack[@]}"
mo::evaluateListOfSingles moResult ${moStack[@]+"${moStack[@]}"}
fi
local "$moTarget" && mo::indirect "$moTarget" "$moResult"
@@ -1310,18 +1321,20 @@ mo::evaluateFunction() {
if [[ -n "${MO_ALLOW_FUNCTION_ARGUMENTS-}" ]]; then
mo::debug "Function arguments are allowed"
if [[ ${#moArgs[@]} -gt 0 ]]; then
for moTemp in "${moArgs[@]}"; do
mo::escape moTemp "$moTemp"
moFunctionCall="$moFunctionCall $moTemp"
done
fi
fi
mo::debug "Calling function: $moFunctionCall"
#: Call the function in a subshell for safety. Employ the trick to preserve
#: whitespace at the end of the output.
moContent=$(
export MO_FUNCTION_ARGS=("${moArgs[@]}")
export MO_FUNCTION_ARGS=(${moArgs[@]+"${moArgs[@]}"})
echo -n "$moContent" | eval "$moFunctionCall ; moFunctionResult=\$? ; echo -n '.' ; exit \"\$moFunctionResult\""
) || {
moFunctionResult=$?
@@ -1767,7 +1780,7 @@ mo::tokenizeTagContents() {
"$moTerminator"*)
mo::debug "Found terminator"
local "$1" && mo::indirectArray "$1" "$moTokenCount" "${moResult[@]}"
local "$1" && mo::indirectArray "$1" "$moTokenCount" ${moResult[@]+"${moResult[@]}"}
return
;;
@@ -1775,7 +1788,7 @@ mo::tokenizeTagContents() {
#: Do not tokenize the open paren - treat this as RPL
MO_UNPARSED=${MO_UNPARSED:1}
mo::tokenizeTagContents moTemp ')'
moResult=("${moResult[@]}" "${moTemp[@]:1}" PAREN "${moTemp[0]}")
moResult=(${moResult[@]+"${moResult[@]}"} "${moTemp[@]:1}" PAREN "${moTemp[0]}")
MO_UNPARSED=${MO_UNPARSED:1}
;;
@@ -1783,7 +1796,7 @@ mo::tokenizeTagContents() {
#: Do not tokenize the open brace - treat this as RPL
MO_UNPARSED=${MO_UNPARSED:1}
mo::tokenizeTagContents moTemp '}'
moResult=("${moResult[@]}" "${moTemp[@]:1}" BRACE "${moTemp[0]}")
moResult=(${moResult[@]+"${moResult[@]}"} "${moTemp[@]:1}" BRACE "${moTemp[0]}")
MO_UNPARSED=${MO_UNPARSED:1}
;;
@@ -1793,17 +1806,17 @@ mo::tokenizeTagContents() {
"'"*)
mo::tokenizeTagContentsSingleQuote moTemp
moResult=("${moResult[@]}" "${moTemp[@]}")
moResult=(${moResult[@]+"${moResult[@]}"} "${moTemp[@]}")
;;
'"'*)
mo::tokenizeTagContentsDoubleQuote moTemp
moResult=("${moResult[@]}" "${moTemp[@]}")
moResult=(${moResult[@]+"${moResult[@]}"} "${moTemp[@]}")
;;
*)
mo::tokenizeTagContentsName moTemp
moResult=("${moResult[@]}" "${moTemp[@]}")
moResult=(${moResult[@]+"${moResult[@]}"} "${moTemp[@]}")
;;
esac
@@ -1947,7 +1960,7 @@ mo::tokenizeTagContentsSingleQuote() {
# Save the original command's path for usage later
MO_ORIGINAL_COMMAND="$(cd "${BASH_SOURCE[0]%/*}" || exit 1; pwd)/${BASH_SOURCE[0]##*/}"
MO_VERSION="3.0.1"
MO_VERSION="3.0.5"
# If sourced, load all functions.
# If executed, perform the actions as expected.

View File

@@ -3,7 +3,8 @@ cd "${0%/*}" || exit 1
. ../run-tests
declare -A repo
repo[resque]="Resque"
# The order of the array elements can be shuffled depending on the version of
# Bash. Keeping this to a minimal set and alphabetized seems to help.
repo[hub]="Hub"
repo[rip]="Rip"
export repo
@@ -18,7 +19,6 @@ expected() {
cat <<EOF
<b>hub - Hub</b>
<b>rip - Rip</b>
<b>resque - Resque</b>
EOF
}

View File

@@ -6,7 +6,21 @@ testArgs() {
local args
# shellcheck disable=SC2031
args=$(declare -p MO_FUNCTION_ARGS)
echo -n "${args#*=}"
# The output from declare -p could look like these
# declare -a MO_FUNCTION_ARGS=([0]="one")
# declare -ax MO_FUNCTION_ARGS='([0]="one")'
# Trim leading declare statement and variable name
args="${args#*=}"
# If there are any quotes, remove them. The function arguments will always
# be an array.
if [[ "${args:0:1}" == "'" ]]; then
args=${args#\'}
args=${args%\'}
fi
echo -n "$args"
}
template() {
cat <<EOF

View File

@@ -43,7 +43,8 @@ Options:
This message.
-s=FILE, --source=FILE
Load FILE into the environment before processing templates.
Can be used multiple times.
Can be used multiple times. The file must be a valid shell script
and should only contain variable assignments.
-o=DELIM, --open=DELIM
Set the opening delimiter. Default is "{{".
-c=DELIM, --close=DELIM
@@ -93,7 +94,7 @@ This is open source! Please feel free to contribute.
https://github.com/tests-always-included/mo
MO_VERSION=3.0.1
MO_VERSION=3.0.5
EOF
}