5 Commits
1.0.0 ... 1.1.0

Author SHA1 Message Date
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
5 changed files with 92 additions and 8 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. 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 # Download
curl -sSO https://raw.githubusercontent.com/tests-always-included/mo/master/mo curl -sS https://git.io/get-mo -o mo
# Make executable # Make executable
chmod +x mo 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/`. 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 # Download
curl -sSO https://raw.githubusercontent.com/tests-always-included/mo/master/mo curl -sS https://git.io/get-mo -o mo
# Make executable # Make executable
chmod +x mo 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. 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 # 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 # Move into your project folder
mv mo ~/projects/amazing-things/lib/ 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 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 Concessions
----------- -----------

67
mo
View File

@@ -29,6 +29,10 @@
# Public: Template parser function. Writes templates to stdout. # Public: Template parser function. Writes templates to stdout.
# #
# $0 - Name of the mo file, used for getting the help message. # $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 # --fail-not-set - Fail upon expansion of an unset variable. Default behavior
# is to silently ignore and expand into empty string. # is to silently ignore and expand into empty string.
# --false - Treat "false" as an empty value. You may set the # --false - Treat "false" as an empty value. You may set the
@@ -43,6 +47,12 @@
# #
# Mo uses the following environment variables: # 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 # MO_FAIL_ON_UNSET - When set to a non-empty value, expansion of an unset
# env variable will be aborted with an error. # env variable will be aborted with an error.
# MO_FALSE_IS_EMPTY - When set to a non-empty value, the string "false" # MO_FALSE_IS_EMPTY - When set to a non-empty value, the string "false"
@@ -74,6 +84,11 @@ mo() (
exit 0 exit 0
;; ;;
--allow-function-arguments)
# shellcheck disable=SC2030
MO_ALLOW_FUNCTION_ARGUMENTS=true
;;
--fail-not-set) --fail-not-set)
# shellcheck disable=SC2030 # shellcheck disable=SC2030
MO_FAIL_ON_UNSET=true MO_FAIL_ON_UNSET=true
@@ -115,6 +130,29 @@ 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 moCommand
# shellcheck disable=SC2031
if [[ -n "$MO_ALLOW_FUNCTION_ARGUMENTS" ]]; then
printf -v moCommand "%q %q %s" "$1" "$2" "$3"
eval "$moCommand"
else
"$1" "$2"
fi
}
# Internal: Scan content until the right end tag is found. Creates an array # Internal: Scan content until the right end tag is found. Creates an array
# with the following members: # with the following members:
# #
@@ -567,7 +605,7 @@ moLoop() {
moParse() { moParse() {
# Keep naming variables mo* here to not overwrite needed variables # Keep naming variables mo* here to not overwrite needed variables
# used in the string replacements # used in the string replacements
local moBlock moContent moCurrent moIsBeginning moNextIsBeginning moTag local moArgs moBlock moContent moCurrent moIsBeginning moNextIsBeginning moTag
moCurrent=$2 moCurrent=$2
moIsBeginning=$3 moIsBeginning=$3
@@ -585,6 +623,13 @@ moParse() {
# Sets context # Sets context
moStandaloneAllowed moContent "${moContent[@]}" "$moIsBeginning" moStandaloneAllowed moContent "${moContent[@]}" "$moIsBeginning"
moTrimWhitespace moTag "${moTag:1}" 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" moFindEndTag moBlock "$moContent" "$moTag"
moFullTagName moTag "$moCurrent" "$moTag" moFullTagName moTag "$moCurrent" "$moTag"
@@ -593,7 +638,7 @@ moParse() {
if moIsFunction "$moTag"; then if moIsFunction "$moTag"; then
#: Consider piping the output to moGetContent #: Consider piping the output to moGetContent
#: so the lambda does not execute in a subshell? #: so the lambda does not execute in a subshell?
moContent=$($moTag "${moBlock[0]}") moContent=$(moCallFunction "$moTag" "${moBlock[0]}" "$moArgs")
moParse "$moContent" "$moCurrent" false moParse "$moContent" "$moCurrent" false
moContent="${moBlock[2]}" moContent="${moBlock[2]}"
elif moIsArray "$moTag"; then elif moIsArray "$moTag"; then
@@ -658,11 +703,16 @@ moParse() {
moContent="${moTag:1}"'}}'"$moContent" moContent="${moTag:1}"'}}'"$moContent"
moSplit moContent "$moContent" '}}}' moSplit moContent "$moContent" '}}}'
moTrimWhitespace moTag "${moContent[0]}" moTrimWhitespace moTag "${moContent[0]}"
moArgs=$moTag
moTag=${moTag%% *}
moTag=${moTag%%$'\t'*}
moArgs=${moArgs:${#moTag}}
moFullTagName moTag "$moCurrent" "$moTag" moFullTagName moTag "$moCurrent" "$moTag"
moContent=${moContent[1]} moContent=${moContent[1]}
# Now show the value # Now show the value
moShow "$moTag" "$moCurrent" # Quote moArgs here, do not quote it later.
moShow "$moTag" "$moCurrent" "$moArgs"
;; ;;
'&'*) '&'*)
@@ -676,8 +726,14 @@ moParse() {
*) *)
# Normal environment variable or function call # Normal environment variable or function call
moStandaloneDenied moContent "${moContent[@]}" moStandaloneDenied moContent "${moContent[@]}"
moArgs=$moTag
moTag=${moTag%% *}
moTag=${moTag%%$'\t'*}
moArgs=${moArgs:${#moTag}}
moFullTagName moTag "$moCurrent" "$moTag" moFullTagName moTag "$moCurrent" "$moTag"
moShow "$moTag" "$moCurrent"
# Quote moArgs here, do not quote it later.
moShow "$moTag" "$moCurrent" "$moArgs"
;; ;;
esac esac
@@ -763,6 +819,7 @@ moPartial() {
# #
# $1 - Name of environment variable or function # $1 - Name of environment variable or function
# $2 - Current context # $2 - Current context
# $3 - Arguments string if $1 is a function
# #
# Returns nothing. # Returns nothing.
moShow() { moShow() {
@@ -770,7 +827,7 @@ moShow() {
local moJoined moNameParts local moJoined moNameParts
if moIsFunction "$1"; then if moIsFunction "$1"; then
CONTENT=$($1 "") CONTENT=$(moCallFunction "$1" "" "$3")
moParse "$CONTENT" "$2" false moParse "$CONTENT" "$2" false
return 0 return 0
fi fi

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

@@ -0,0 +1,17 @@
name=Willy
MO_ALLOW_FUNCTION_ARGUMENTS=true
pipeTo() {
echo -n "$1" | "$2"
}
testArgs() {
printf "%d" "$#"
# Remove content. Note that when zero arguments are passed, this
# line does nothing and $1 will still be the content.
shift
# Display all arguments
printf " %q" "$@"
}

View File

@@ -0,0 +1,4 @@
No args: 1 '' - done
One arg: 2 one - done
Getting name in a string: 2 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}}