mirror of
https://github.com/tests-always-included/mo.git
synced 2026-04-08 08:50:38 +02:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbefade193 | ||
|
|
57a8d41394 | ||
|
|
5739ccd705 | ||
|
|
f889c37316 | ||
|
|
4f615a0faf | ||
|
|
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.
|
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 -sSL 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
|
||||||
-----------
|
-----------
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
cd "$(dirname "$0")" # Go to the script's directory
|
cd "$(dirname "$0")" # Go to the script's directory
|
||||||
|
|
||||||
EVERY_REPO() {
|
EVERY_REPO() {
|
||||||
|
# The block contents come in through standard input. Capture it here.
|
||||||
|
content=$(cat)
|
||||||
|
|
||||||
echo "# Starting EVERY_REPO"
|
echo "# Starting EVERY_REPO"
|
||||||
|
|
||||||
# Get list of repos
|
# Get list of repos
|
||||||
@@ -14,7 +17,7 @@ EVERY_REPO() {
|
|||||||
# It rewrites {{__REPO__.name}} into {{resque.name}}, for instance.
|
# It rewrites {{__REPO__.name}} into {{resque.name}}, for instance.
|
||||||
# You can prefix your environment variables and do other things as well.
|
# 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"
|
echo "## Looped one time for repo: $REPO"
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -2,13 +2,17 @@
|
|||||||
|
|
||||||
cd "$(dirname "$0")"/..
|
cd "$(dirname "$0")"/..
|
||||||
|
|
||||||
date-string() { date; }
|
date-string() {
|
||||||
wrapper() { echo -n "*** $1 ***"; }
|
date
|
||||||
|
}
|
||||||
|
wrapper() {
|
||||||
|
echo -n "*** $(cat) ***"
|
||||||
|
}
|
||||||
|
|
||||||
export IP=127.0.0.1
|
export IP=127.0.0.1
|
||||||
export ALLOWED_HOSTS=( 192.168.0.1 192.168.0.2 192.168.0.3 )
|
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
|
cat <<EOF | mo
|
||||||
# {{#wrapper}}OH SO IMPORTANT{{/wrapper}}
|
# {{#wrapper}}OH SO IMPORTANT{{/wrapper}}
|
||||||
# This file automatically generated at {{date-string}}
|
# This file automatically generated at {{date-string}}
|
||||||
|
|||||||
77
mo
77
mo
@@ -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,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
|
# Internal: Scan content until the right end tag is found. Creates an array
|
||||||
# with the following members:
|
# with the following members:
|
||||||
#
|
#
|
||||||
@@ -567,7 +606,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 +624,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 +639,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 +704,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 +727,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 +820,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,22 +828,22 @@ 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
|
||||||
|
|
||||||
moSplit moNameParts "$1" "."
|
moSplit moNameParts "$1" "."
|
||||||
|
|
||||||
if [[ -z "${moNameParts[1]}" ]]; then
|
if [[ -z "${moNameParts[1]-}" ]]; then
|
||||||
if moIsArray "$1"; then
|
if moIsArray "$1"; then
|
||||||
eval moJoin moJoined "," "\${$1[@]}"
|
eval moJoin moJoined "," "\${$1[@]}"
|
||||||
echo -n "$moJoined"
|
echo -n "$moJoined"
|
||||||
else
|
else
|
||||||
# shellcheck disable=SC2031
|
# shellcheck disable=SC2031
|
||||||
if [[ -z "$MO_FAIL_ON_UNSET" ]] || moTestVarSet "$1"; then
|
if moTestVarSet "$1"; then
|
||||||
echo -n "${!1}"
|
echo -n "${!1}"
|
||||||
else
|
elif [[ -n "${MO_FAIL_ON_UNSET-}" ]]; then
|
||||||
echo "Env variable not set: $1" >&2
|
echo "Env variable not set: $1" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -972,11 +1030,14 @@ moTrimWhitespace() {
|
|||||||
# Returns nothing.
|
# Returns nothing.
|
||||||
moUsage() {
|
moUsage() {
|
||||||
grep '^#/' "${MO_ORIGINAL_COMMAND}" | cut -c 4-
|
grep '^#/' "${MO_ORIGINAL_COMMAND}" | cut -c 4-
|
||||||
|
echo ""
|
||||||
|
set | grep ^MO_VERSION=
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# 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="2.0.4"
|
||||||
|
|
||||||
# If sourced, load all functions.
|
# If sourced, load all functions.
|
||||||
# If executed, perform the actions as expected.
|
# If executed, perform the actions as expected.
|
||||||
|
|||||||
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
|
name=Willy
|
||||||
wrapped() {
|
wrapped() {
|
||||||
# The final newline is eaten by mo
|
# This eats the newline in the content
|
||||||
echo "<b>$1</b>"
|
echo "<b>$(cat)</b>"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
<b> Willy is awesome.
|
<b> Willy is awesome.</b>... this is the last line.
|
||||||
</b>... this is the last line.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user