6 Commits
1.0.0 ... 2.0.0

Author SHA1 Message Date
Tyler Akins
ad98577c42 Changing how functions are called
Old way:

    functionName CONTENT argument1 argument2

New way:

    echo -n "$CONTENT" | functionName argument1 argument2

This follow the Unix style more closely.
2017-11-13 10:13:56 -06:00
Tyler Akins
e78b15d95b Updating test to enable the flag 2017-11-03 19:38:34 -05:00
Tyler Akins
f20e4ae83a Making a bit more safe and disabling an eval by default 2017-11-03 16:45:51 -05:00
Tyler Akins
a5ec7dd740 I think this finally implements arguments to functions
This closes #18.
2017-11-03 16:34:08 -05:00
Tyler Akins
ab5dfee519 Fixing install directions 2017-10-24 07:47:50 -05:00
Tyler Akins
81fd601ebd Shortening URL 2017-10-23 15:11:23 -05:00
9 changed files with 103 additions and 16 deletions

View File

@@ -41,7 +41,7 @@ There are a few ways you can install this tool. How you install it depends on h
You can install this file in `/usr/local/bin/` or `/usr/bin/` by simply downloading it, changing the permissions, then moving it to the right location. Double check that your system's PATH includes the destination folder, otherwise users may have a hard time starting the command.
# Download
curl -sSO https://raw.githubusercontent.com/tests-always-included/mo/master/mo
curl -sS https://git.io/get-mo -o mo
# Make executable
chmod +x mo
@@ -58,7 +58,7 @@ You can install this file in `/usr/local/bin/` or `/usr/bin/` by simply download
This is very similar to installing it globally but it does not require root privileges. It is very important that your PATH includes the destination folder otherwise it won't work. Some local folders that are typically used are `~/bin/` and `~/.local/bin/`.
# Download
curl -sSO https://raw.githubusercontent.com/tests-always-included/mo/master/mo
curl -sS https://git.io/get-mo -o mo
# Make executable
chmod +x mo
@@ -78,7 +78,7 @@ This is very similar to installing it globally but it does not require root priv
Bash scripts can source `mo` to include the functionality in their own routines. This usage typically would have `mo` saved to a `lib/` folder in an application and your other scripts would use `. lib/mo` to bring it into your project.
# Download
curl -sSO https://raw.githubusercontent.com/tests-always-included/mo/master/mo
curl -sS https://git.io/get-mo -o mo
# Move into your project folder
mv mo ~/projects/amazing-things/lib/
@@ -115,6 +115,8 @@ The result? You get a list of the five elements in the array. It is vital that
There are more scripts available in the [demos directory](demo/) that could help illustrate how you would use this program.
There are additional features that the program supports. Try using `mo --help` to see what is available.
Concessions
-----------

View File

@@ -3,6 +3,9 @@
cd "$(dirname "$0")" # Go to the script's directory
EVERY_REPO() {
# The block contents come in through standard input. Capture it here.
content=$(cat)
echo "# Starting EVERY_REPO"
# Get list of repos
@@ -14,7 +17,7 @@ EVERY_REPO() {
# It rewrites {{__REPO__.name}} into {{resque.name}}, for instance.
# You can prefix your environment variables and do other things as well.
echo -n "$1" | sed "s/__REPO__/${REPO}/"
echo "$content" | sed "s/__REPO__/${REPO}/"
echo "## Looped one time for repo: $REPO"
done

View File

@@ -2,13 +2,17 @@
cd "$(dirname "$0")"/..
date-string() { date; }
wrapper() { echo -n "*** $1 ***"; }
date-string() {
date
}
wrapper() {
echo -n "*** $(cat) ***"
}
export IP=127.0.0.1
export ALLOWED_HOSTS=( 192.168.0.1 192.168.0.2 192.168.0.3 )
. mo # Keep in mind this script is executing in the parent directory
. ./mo # Keep in mind this script is executing in the parent directory
cat <<EOF | mo
# {{#wrapper}}OH SO IMPORTANT{{/wrapper}}
# This file automatically generated at {{date-string}}

68
mo
View File

@@ -29,6 +29,10 @@
# Public: Template parser function. Writes templates to stdout.
#
# $0 - Name of the mo file, used for getting the help message.
# --allow-function-arguments
# - Permit functions in templates to be called with additional
# arguments. This puts template data directly in to the path
# of an eval statement. Use with caution.
# --fail-not-set - Fail upon expansion of an unset variable. Default behavior
# is to silently ignore and expand into empty string.
# --false - Treat "false" as an empty value. You may set the
@@ -43,6 +47,12 @@
#
# Mo uses the following environment variables:
#
# MO_ALLOW_FUNCTION_ARGUMENTS
# - When set to a non-empty value, this allows functions
# referenced in templates to receive additional
# options and arguments. This puts the content from the
# template directly into an eval statement. Use with
# extreme care.
# MO_FAIL_ON_UNSET - When set to a non-empty value, expansion of an unset
# env variable will be aborted with an error.
# MO_FALSE_IS_EMPTY - When set to a non-empty value, the string "false"
@@ -74,6 +84,11 @@ mo() (
exit 0
;;
--allow-function-arguments)
# shellcheck disable=SC2030
MO_ALLOW_FUNCTION_ARGUMENTS=true
;;
--fail-not-set)
# shellcheck disable=SC2030
MO_FAIL_ON_UNSET=true
@@ -115,6 +130,30 @@ mo() (
)
# Internal: Call a function.
#
# $1 - Function to call
# $2 - Content to pass
# $3 - Additional arguments as a single string
#
# This can be dangerous, especially if you are using tags like
# {{someFunction ; rm -rf / }}
#
# Returns nothing.
moCallFunction() {
local moArgs
moArgs=()
# shellcheck disable=SC2031
if [[ -n "$MO_ALLOW_FUNCTION_ARGUMENTS" ]]; then
moArgs=$3
fi
echo -n "$2" | eval "$1" "$moArgs"
}
# Internal: Scan content until the right end tag is found. Creates an array
# with the following members:
#
@@ -567,7 +606,7 @@ moLoop() {
moParse() {
# Keep naming variables mo* here to not overwrite needed variables
# used in the string replacements
local moBlock moContent moCurrent moIsBeginning moNextIsBeginning moTag
local moArgs moBlock moContent moCurrent moIsBeginning moNextIsBeginning moTag
moCurrent=$2
moIsBeginning=$3
@@ -585,6 +624,13 @@ moParse() {
# Sets context
moStandaloneAllowed moContent "${moContent[@]}" "$moIsBeginning"
moTrimWhitespace moTag "${moTag:1}"
# Split arguments from the tag name. Arguments are passed to
# functions.
moArgs=$moTag
moTag=${moTag%% *}
moTag=${moTag%%$'\t'*}
moArgs=${moArgs:${#moTag}}
moFindEndTag moBlock "$moContent" "$moTag"
moFullTagName moTag "$moCurrent" "$moTag"
@@ -593,7 +639,7 @@ moParse() {
if moIsFunction "$moTag"; then
#: Consider piping the output to moGetContent
#: so the lambda does not execute in a subshell?
moContent=$($moTag "${moBlock[0]}")
moContent=$(moCallFunction "$moTag" "${moBlock[0]}" "$moArgs")
moParse "$moContent" "$moCurrent" false
moContent="${moBlock[2]}"
elif moIsArray "$moTag"; then
@@ -658,11 +704,16 @@ moParse() {
moContent="${moTag:1}"'}}'"$moContent"
moSplit moContent "$moContent" '}}}'
moTrimWhitespace moTag "${moContent[0]}"
moArgs=$moTag
moTag=${moTag%% *}
moTag=${moTag%%$'\t'*}
moArgs=${moArgs:${#moTag}}
moFullTagName moTag "$moCurrent" "$moTag"
moContent=${moContent[1]}
# Now show the value
moShow "$moTag" "$moCurrent"
# Quote moArgs here, do not quote it later.
moShow "$moTag" "$moCurrent" "$moArgs"
;;
'&'*)
@@ -676,8 +727,14 @@ moParse() {
*)
# Normal environment variable or function call
moStandaloneDenied moContent "${moContent[@]}"
moArgs=$moTag
moTag=${moTag%% *}
moTag=${moTag%%$'\t'*}
moArgs=${moArgs:${#moTag}}
moFullTagName moTag "$moCurrent" "$moTag"
moShow "$moTag" "$moCurrent"
# Quote moArgs here, do not quote it later.
moShow "$moTag" "$moCurrent" "$moArgs"
;;
esac
@@ -763,6 +820,7 @@ moPartial() {
#
# $1 - Name of environment variable or function
# $2 - Current context
# $3 - Arguments string if $1 is a function
#
# Returns nothing.
moShow() {
@@ -770,7 +828,7 @@ moShow() {
local moJoined moNameParts
if moIsFunction "$1"; then
CONTENT=$($1 "")
CONTENT=$(moCallFunction "$1" "" "$3")
moParse "$CONTENT" "$2" false
return 0
fi

13
tests/function-args.env Normal file
View File

@@ -0,0 +1,13 @@
name=Willy
MO_ALLOW_FUNCTION_ARGUMENTS=true
pipeTo() {
cat | "$1"
}
testArgs() {
printf "%d" "$#"
# Display all arguments
printf " %q" ${@+"$@"}
}

View File

@@ -0,0 +1,4 @@
No args: 0 '' - done
One arg: 1 one - done
Getting name in a string: 1 The\ name\ is\ Willy - done
Reverse this: edcba

View File

@@ -0,0 +1,4 @@
No args: {{testArgs}} - done
One arg: {{testArgs one}} - done
Getting name in a string: {{testArgs "The name is $name"}} - done
Reverse this: {{#pipeTo rev}}abcde{{/pipeTo}}

View File

@@ -1,5 +1,5 @@
name=Willy
wrapped() {
# The final newline is eaten by mo
echo "<b>$1</b>"
# This eats the newline in the content
echo "<b>$(cat)</b>"
}

View File

@@ -1,2 +1 @@
<b> Willy is awesome.
</b>... this is the last line.
<b> Willy is awesome.</b>... this is the last line.