mirror of
https://github.com/tests-always-included/mo.git
synced 2026-04-08 08:50:38 +02:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e91e414cc | ||
|
|
ad98577c42 | ||
|
|
e78b15d95b | ||
|
|
f20e4ae83a | ||
|
|
a5ec7dd740 | ||
|
|
ab5dfee519 | ||
|
|
81fd601ebd |
@@ -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
|
||||
-----------
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}}
|
||||
|
||||
72
mo
72
mo
@@ -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,20 +828,20 @@ moShow() {
|
||||
local moJoined moNameParts
|
||||
|
||||
if moIsFunction "$1"; then
|
||||
CONTENT=$($1 "")
|
||||
CONTENT=$(moCallFunction "$1" "" "$3")
|
||||
moParse "$CONTENT" "$2" false
|
||||
return 0
|
||||
fi
|
||||
|
||||
moSplit moNameParts "$1" "."
|
||||
|
||||
if [[ -z "${moNameParts[1]}" ]]; then
|
||||
if [[ -z "${moNameParts[1]-}" ]]; then
|
||||
if moIsArray "$1"; then
|
||||
eval moJoin moJoined "," "\${$1[@]}"
|
||||
echo -n "$moJoined"
|
||||
else
|
||||
# shellcheck disable=SC2031
|
||||
if [[ -z "$MO_FAIL_ON_UNSET" ]] || moTestVarSet "$1"; then
|
||||
if [[ -z "${MO_FAIL_ON_UNSET-}" ]] || moTestVarSet "$1"; then
|
||||
echo -n "${!1}"
|
||||
else
|
||||
echo "Env variable not set: $1" >&2
|
||||
|
||||
13
tests/function-args.env
Normal file
13
tests/function-args.env
Normal file
@@ -0,0 +1,13 @@
|
||||
name=Willy
|
||||
MO_ALLOW_FUNCTION_ARGUMENTS=true
|
||||
|
||||
pipeTo() {
|
||||
cat | "$1"
|
||||
}
|
||||
|
||||
testArgs() {
|
||||
printf "%d" "$#"
|
||||
|
||||
# Display all arguments
|
||||
printf " %q" ${@+"$@"}
|
||||
}
|
||||
4
tests/function-args.expected
Normal file
4
tests/function-args.expected
Normal 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
|
||||
4
tests/function-args.template
Normal file
4
tests/function-args.template
Normal 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}}
|
||||
@@ -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>"
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
<b> Willy is awesome.
|
||||
</b>... this is the last line.
|
||||
<b> Willy is awesome.</b>... this is the last line.
|
||||
|
||||
Reference in New Issue
Block a user