mirror of
https://github.com/tests-always-included/mo.git
synced 2026-04-08 08:50:38 +02:00
Compare commits
3 Commits
search-pat
...
2.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
929ffc5b88 | ||
|
|
5b8cf24068 | ||
|
|
fcedd32155 |
231
API.md
231
API.md
@@ -4,95 +4,61 @@ API / Function Documentation
|
|||||||
This documentation is generated automatically from the source of [mo] thanks to [tomdoc.sh].
|
This documentation is generated automatically from the source of [mo] thanks to [tomdoc.sh].
|
||||||
|
|
||||||
|
|
||||||
`mo()`
|
mo()
|
||||||
------
|
----
|
||||||
|
|
||||||
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. Not listed in the help because it only makes sense when mo is sourced.
|
* --fail-not-set - Fail upon expansion of an unset variable. Default behavior is to silently ignore and expand into empty string.
|
||||||
* --fail-not-set - (`-u`) 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 MO_FALSE_IS_EMPTY environment variable instead to a non-empty value to enable this behavior.
|
||||||
* --false - (`-e`) Treat "false" as an empty value. You may set the MO_FALSE_IS_EMPTY environment variable instead to a non-empty value to enable this behavior.
|
* --help - Display a help message.
|
||||||
* --help - (`-h)` Display a help message.
|
* --source=FILE - Source a file into the environment before processint template files.
|
||||||
* --source=FILE - (`-s=FILE`) Source a file into the environment before processing template files.
|
* -- - Used to indicate the end of options. You may optionally use this when filenames may start with two hyphens.
|
||||||
* --path=PATH - (`-p=PATH`) Colon-separated list of paths to search for templates. They are relative to where `mo` was executed.
|
* $@ - Filenames to parse.
|
||||||
* -- - Used to indicate the end of options. You may use this when filenames start with hyphens.
|
|
||||||
* $@ - Filenames to parse.
|
|
||||||
|
|
||||||
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 env variable will be aborted with an error.
|
||||||
|
* MO_FALSE_IS_EMPTY - When set to a non-empty value, the string "false" will be treated as an empty value for the purposes of conditionals.
|
||||||
* 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" will be treated as an empty value for the purposes of conditionals.
|
|
||||||
|
|
||||||
* MO_ORIGINAL_COMMAND - Used to find the `mo` program in order to generate a help message.
|
* MO_ORIGINAL_COMMAND - Used to find the `mo` program in order to generate a help message.
|
||||||
|
|
||||||
* MO_SEARCH_PATH - Colon-separated list of folders to search for templates. They are relative to where `mo` was executed.
|
|
||||||
|
|
||||||
Returns true (0) when there are no errors. Sometimes returns (1) when there are errors and sometimes those errors are consumed. It greatly depends on the error and your options.
|
|
||||||
|
|
||||||
|
|
||||||
`files`
|
|
||||||
-------
|
|
||||||
|
|
||||||
After we encounter two hyphens together, all the rest of the arguments are files.
|
|
||||||
|
|
||||||
|
|
||||||
`MO_ALLOW_FUNCTION_ARGUMENTS`
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
shellcheck disable=SC2030
|
|
||||||
|
|
||||||
|
|
||||||
`MO_FAIL_ON_UNSET`
|
|
||||||
------------------
|
|
||||||
|
|
||||||
shellcheck disable=SC2030
|
|
||||||
|
|
||||||
|
|
||||||
`MO_FALSE_IS_EMPTY`
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
shellcheck disable=SC2030
|
|
||||||
|
|
||||||
|
|
||||||
`doubleHyphens`
|
|
||||||
---------------
|
|
||||||
|
|
||||||
Set a flag indicating we've encountered double hyphens
|
|
||||||
|
|
||||||
|
|
||||||
`files`
|
|
||||||
-------
|
|
||||||
|
|
||||||
Every arg that is not a flag or a option should be a file
|
|
||||||
|
|
||||||
|
|
||||||
`moProcessSearchPath()`
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
Internal: Change relative paths into absolute paths
|
|
||||||
|
|
||||||
|
|
||||||
`moCallFunction()`
|
|
||||||
------------------
|
|
||||||
|
|
||||||
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.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moFindEndTag()`
|
files
|
||||||
|
-----
|
||||||
|
|
||||||
|
After we encounter two hyphens together, all the rest of the arguments are files.
|
||||||
|
|
||||||
|
|
||||||
|
MO_FAIL_ON_UNSET
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
shellcheck disable=SC2030
|
||||||
|
|
||||||
|
|
||||||
|
MO_FALSE_IS_EMPTY
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
shellcheck disable=SC2030
|
||||||
|
|
||||||
|
|
||||||
|
doubleHyphens
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Set a flag indicating we've encountered double hyphens
|
||||||
|
|
||||||
|
|
||||||
|
files
|
||||||
|
-----
|
||||||
|
|
||||||
|
Every arg that is not a flag or a option should be a file
|
||||||
|
|
||||||
|
|
||||||
|
moFindEndTag()
|
||||||
|
--------------
|
||||||
|
|
||||||
Internal: Scan content until the right end tag is found. Creates an array with the following members:
|
Internal: Scan content until the right end tag is found. Creates an array with the following members:
|
||||||
|
|
||||||
[0] = Content before end tag
|
[0] = Content before end tag
|
||||||
@@ -109,8 +75,8 @@ Everything using this function uses the "standalone tags" logic.
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moFindString()`
|
moFindString()
|
||||||
----------------
|
--------------
|
||||||
|
|
||||||
Internal: Find the first index of a substring. If not found, sets the index to -1.
|
Internal: Find the first index of a substring. If not found, sets the index to -1.
|
||||||
|
|
||||||
@@ -121,8 +87,8 @@ Internal: Find the first index of a substring. If not found, sets the index to
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moFullTagName()`
|
moFullTagName()
|
||||||
-----------------
|
---------------
|
||||||
|
|
||||||
Internal: Generate a dotted name based on current context and target name.
|
Internal: Generate a dotted name based on current context and target name.
|
||||||
|
|
||||||
@@ -133,8 +99,8 @@ Internal: Generate a dotted name based on current context and target name.
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moGetContent()`
|
moGetContent()
|
||||||
----------------
|
--------------
|
||||||
|
|
||||||
Internal: Fetches the content to parse into a variable. Can be a list of partials for files or the content from stdin.
|
Internal: Fetches the content to parse into a variable. Can be a list of partials for files or the content from stdin.
|
||||||
|
|
||||||
@@ -144,8 +110,8 @@ Internal: Fetches the content to parse into a variable. Can be a list of partia
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moIndentLines()`
|
moIndentLines()
|
||||||
-----------------
|
---------------
|
||||||
|
|
||||||
Internal: Indent a string, placing the indent at the beginning of every line that has any content.
|
Internal: Indent a string, placing the indent at the beginning of every line that has any content.
|
||||||
|
|
||||||
@@ -156,8 +122,8 @@ Internal: Indent a string, placing the indent at the beginning of every line tha
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moIndirect()`
|
moIndirect()
|
||||||
--------------
|
------------
|
||||||
|
|
||||||
Internal: Send a variable up to the parent of the caller of this function.
|
Internal: Send a variable up to the parent of the caller of this function.
|
||||||
|
|
||||||
@@ -175,8 +141,8 @@ Examples
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moIndirectArray()`
|
moIndirectArray()
|
||||||
-------------------
|
-----------------
|
||||||
|
|
||||||
Internal: Send an array as a variable up to caller of a function
|
Internal: Send an array as a variable up to caller of a function
|
||||||
|
|
||||||
@@ -195,8 +161,8 @@ Examples
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moIsArray()`
|
moIsArray()
|
||||||
-------------
|
-----------
|
||||||
|
|
||||||
Internal: Determine if a given environment variable exists and if it is an array.
|
Internal: Determine if a given environment variable exists and if it is an array.
|
||||||
|
|
||||||
@@ -207,16 +173,16 @@ Be extremely careful. Even if strict mode is enabled, it is not honored in newe
|
|||||||
Examples
|
Examples
|
||||||
|
|
||||||
var=(abc)
|
var=(abc)
|
||||||
if moIsArray var; then
|
if moIsArray var; the
|
||||||
echo "This is an array"
|
echo "This is an array"
|
||||||
echo "Make sure you don't accidentally use \$var"
|
echo "Make sure you don't accidentally use $var"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
Returns 0 if the name is not empty, 1 otherwise.
|
Returns 0 if the name is not empty, 1 otherwise.
|
||||||
|
|
||||||
|
|
||||||
`moIsFunction()`
|
moIsFunction()
|
||||||
----------------
|
--------------
|
||||||
|
|
||||||
Internal: Determine if the given name is a defined function.
|
Internal: Determine if the given name is a defined function.
|
||||||
|
|
||||||
@@ -236,8 +202,8 @@ Examples
|
|||||||
Returns 0 if the name is a function, 1 otherwise.
|
Returns 0 if the name is a function, 1 otherwise.
|
||||||
|
|
||||||
|
|
||||||
`moIsStandalone()`
|
moIsStandalone()
|
||||||
------------------
|
----------------
|
||||||
|
|
||||||
Internal: Determine if the tag is a standalone tag based on whitespace before and after the tag.
|
Internal: Determine if the tag is a standalone tag based on whitespace before and after the tag.
|
||||||
|
|
||||||
@@ -257,8 +223,8 @@ Examples
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moJoin()`
|
moJoin()
|
||||||
----------
|
--------
|
||||||
|
|
||||||
Internal: Join / implode an array
|
Internal: Join / implode an array
|
||||||
|
|
||||||
@@ -269,8 +235,8 @@ Internal: Join / implode an array
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moLoadFile()`
|
moLoadFile()
|
||||||
--------------
|
------------
|
||||||
|
|
||||||
Internal: Read a file into a variable.
|
Internal: Read a file into a variable.
|
||||||
|
|
||||||
@@ -280,8 +246,8 @@ Internal: Read a file into a variable.
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moLoop()`
|
moLoop()
|
||||||
----------
|
--------
|
||||||
|
|
||||||
Internal: Process a chunk of content some number of times. Writes output to stdout.
|
Internal: Process a chunk of content some number of times. Writes output to stdout.
|
||||||
|
|
||||||
@@ -292,8 +258,8 @@ Internal: Process a chunk of content some number of times. Writes output to std
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moParse()`
|
moParse()
|
||||||
-----------
|
---------
|
||||||
|
|
||||||
Internal: Parse a block of text, writing the result to stdout.
|
Internal: Parse a block of text, writing the result to stdout.
|
||||||
|
|
||||||
@@ -304,14 +270,8 @@ Internal: Parse a block of text, writing the result to stdout.
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moArgs`
|
moPartial()
|
||||||
--------
|
-----------
|
||||||
|
|
||||||
Split arguments from the tag name. Arguments are passed to functions.
|
|
||||||
|
|
||||||
|
|
||||||
`moPartial()`
|
|
||||||
-------------
|
|
||||||
|
|
||||||
Internal: Process a partial.
|
Internal: Process a partial.
|
||||||
|
|
||||||
@@ -331,14 +291,8 @@ Prefix all variables.
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`IFS`
|
moShow()
|
||||||
-----
|
--------
|
||||||
|
|
||||||
Search the path for the file
|
|
||||||
|
|
||||||
|
|
||||||
`moShow()`
|
|
||||||
----------
|
|
||||||
|
|
||||||
Internal: Show an environment variable or the output of a function to stdout.
|
Internal: Show an environment variable or the output of a function to stdout.
|
||||||
|
|
||||||
@@ -346,13 +300,12 @@ Limit/prefix any variables used.
|
|||||||
|
|
||||||
* $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.
|
||||||
|
|
||||||
|
|
||||||
`moSplit()`
|
moSplit()
|
||||||
-----------
|
---------
|
||||||
|
|
||||||
Internal: Split a larger string into an array.
|
Internal: Split a larger string into an array.
|
||||||
|
|
||||||
@@ -364,8 +317,8 @@ Internal: Split a larger string into an array.
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moStandaloneAllowed()`
|
moStandaloneAllowed()
|
||||||
-----------------------
|
---------------------
|
||||||
|
|
||||||
Internal: Handle the content for a standalone tag. This means removing whitespace (not newlines) before a tag and whitespace and a newline after a tag. That is, assuming, that the line is otherwise empty.
|
Internal: Handle the content for a standalone tag. This means removing whitespace (not newlines) before a tag and whitespace and a newline after a tag. That is, assuming, that the line is otherwise empty.
|
||||||
|
|
||||||
@@ -378,8 +331,8 @@ Internal: Handle the content for a standalone tag. This means removing whitespa
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moStandaloneDenied()`
|
moStandaloneDenied()
|
||||||
----------------------
|
--------------------
|
||||||
|
|
||||||
Internal: Handle the content for a tag that is never "standalone". No adjustments are made for newlines and whitespace.
|
Internal: Handle the content for a tag that is never "standalone". No adjustments are made for newlines and whitespace.
|
||||||
|
|
||||||
@@ -391,8 +344,8 @@ Internal: Handle the content for a tag that is never "standalone". No adjustmen
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moTest()`
|
moTest()
|
||||||
----------
|
--------
|
||||||
|
|
||||||
Internal: Determines if the named thing is a function or if it is a non-empty environment variable. When MO_FALSE_IS_EMPTY is set to a non-empty value, then "false" is also treated is an empty value.
|
Internal: Determines if the named thing is a function or if it is a non-empty environment variable. When MO_FALSE_IS_EMPTY is set to a non-empty value, then "false" is also treated is an empty value.
|
||||||
|
|
||||||
@@ -405,8 +358,8 @@ Do not use variables without prefixes here if possible as this needs to check if
|
|||||||
Returns 0 if the name is not empty, 1 otherwise. When MO_FALSE_IS_EMPTY is set, this returns 1 if the name is "false".
|
Returns 0 if the name is not empty, 1 otherwise. When MO_FALSE_IS_EMPTY is set, this returns 1 if the name is "false".
|
||||||
|
|
||||||
|
|
||||||
`moTestVarSet()`
|
moTestVarSet()
|
||||||
----------------
|
--------------
|
||||||
|
|
||||||
Internal: Determine if a variable is assigned, even if it is assigned an empty value.
|
Internal: Determine if a variable is assigned, even if it is assigned an empty value.
|
||||||
|
|
||||||
@@ -415,8 +368,8 @@ Internal: Determine if a variable is assigned, even if it is assigned an empty v
|
|||||||
Returns true (0) if the variable is set, 1 if the variable is unset.
|
Returns true (0) if the variable is set, 1 if the variable is unset.
|
||||||
|
|
||||||
|
|
||||||
`moTrimChars()`
|
moTrimChars()
|
||||||
---------------
|
-------------
|
||||||
|
|
||||||
Internal: Trim the leading whitespace only.
|
Internal: Trim the leading whitespace only.
|
||||||
|
|
||||||
@@ -429,8 +382,8 @@ Internal: Trim the leading whitespace only.
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moTrimWhitespace()`
|
moTrimWhitespace()
|
||||||
--------------------
|
------------------
|
||||||
|
|
||||||
Internal: Trim leading and trailing whitespace from a string.
|
Internal: Trim leading and trailing whitespace from a string.
|
||||||
|
|
||||||
@@ -440,8 +393,8 @@ Internal: Trim leading and trailing whitespace from a string.
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`moUsage()`
|
moUsage()
|
||||||
-----------
|
---------
|
||||||
|
|
||||||
Internal: Displays the usage for mo. Pulls this from the file that contained the `mo` function. Can only work when the right filename comes is the one argument, and that only happens when `mo` is called with `$0` set to this file.
|
Internal: Displays the usage for mo. Pulls this from the file that contained the `mo` function. Can only work when the right filename comes is the one argument, and that only happens when `mo` is called with `$0` set to this file.
|
||||||
|
|
||||||
@@ -450,8 +403,8 @@ Internal: Displays the usage for mo. Pulls this from the file that contained th
|
|||||||
Returns nothing.
|
Returns nothing.
|
||||||
|
|
||||||
|
|
||||||
`MO_ORIGINAL_COMMAND`
|
MO_ORIGINAL_COMMAND
|
||||||
---------------------
|
-------------------
|
||||||
|
|
||||||
Save the original command's path for usage later
|
Save the original command's path for usage later
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ Requirements
|
|||||||
* The "coreutils" package (`basename` and `cat`)
|
* The "coreutils" package (`basename` and `cat`)
|
||||||
* ... that's it. Why? Because bash **can**!
|
* ... that's it. Why? Because bash **can**!
|
||||||
|
|
||||||
If you intend to develop this and run the official specs, you also need Node.js.
|
If you intend to develop this and run the official specs, you also need node.js.
|
||||||
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
|
|||||||
29
demo/function-args
Executable file
29
demo/function-args
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# This sources a simple script with the env. variables needed for the template.
|
||||||
|
|
||||||
|
cd "$(dirname "$0")" # Go to the script's directory
|
||||||
|
source ../mo
|
||||||
|
|
||||||
|
export NAME="Alex"
|
||||||
|
export ARRAY=( AAA BBB CCC )
|
||||||
|
|
||||||
|
# Include an external template
|
||||||
|
INCLUDE() {
|
||||||
|
cat "$MO_FUNCTION_ARGS"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print section title
|
||||||
|
TITLE() {
|
||||||
|
echo "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"
|
||||||
|
echo "$MO_FUNCTION_ARGS"
|
||||||
|
echo "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"
|
||||||
|
}
|
||||||
|
|
||||||
|
cat <<EOF | mo -u
|
||||||
|
{{TITLE Part 1}}
|
||||||
|
{{INCLUDE function-args-part1}}
|
||||||
|
|
||||||
|
{{TITLE Part 2}}
|
||||||
|
{{INCLUDE function-args-part2}}
|
||||||
|
EOF
|
||||||
1
demo/function-args-part1
Normal file
1
demo/function-args-part1
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Hello, my name is {{NAME}}.
|
||||||
3
demo/function-args-part2
Normal file
3
demo/function-args-part2
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{{#ARRAY}}
|
||||||
|
* {{.}}
|
||||||
|
{{/ARRAY}}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
* Child1
|
|
||||||
{{> deeper/child2 }}
|
|
||||||
{{> ../relative-templates/deeper/child2 }}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
* Child3
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
* Child2
|
|
||||||
{{> ../child3 }}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
This is "file"
|
|
||||||
|
|
||||||
Child1 in different ways
|
|
||||||
{{> child1 }}
|
|
||||||
{{> ./child1 }}
|
|
||||||
{{> ../relative-templates/child1 }}
|
|
||||||
{{> deeper/../child1 }}
|
|
||||||
139
mo
139
mo
@@ -23,8 +23,6 @@
|
|||||||
#/ - This message.
|
#/ - This message.
|
||||||
#/ -s=FILE, --source=FILE
|
#/ -s=FILE, --source=FILE
|
||||||
#/ - Load FILE into the environment before processing templates.
|
#/ - Load FILE into the environment before processing templates.
|
||||||
#/ -p=PATH, --path=PATH
|
|
||||||
#/ - Set a colon-delimited list of folders to search for templates.
|
|
||||||
#
|
#
|
||||||
# Mo is under a MIT style licence with an additional non-advertising clause.
|
# Mo is under a MIT style licence with an additional non-advertising clause.
|
||||||
# See LICENSE.md for the full text.
|
# See LICENSE.md for the full text.
|
||||||
@@ -36,51 +34,48 @@
|
|||||||
|
|
||||||
# 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
|
# --allow-function-arguments
|
||||||
# additional arguments. This puts template data directly in to the path
|
# - Permit functions in templates to be called with additional
|
||||||
# of an eval statement. Use with caution. Not listed in the help
|
# arguments. This puts template data directly in to the path
|
||||||
# because it only makes sense when mo is sourced.
|
# of an eval statement. Use with caution. Not listed in the
|
||||||
# --fail-not-set - (`-u`) Fail upon expansion of an unset variable. Default
|
# help because it only makes sense when mo is sourced.
|
||||||
# behavior is to silently ignore and expand into empty string.
|
# -u, --fail-not-set
|
||||||
# --false - (`-e`) Treat "false" as an empty value. You may set the
|
# - Fail upon expansion of an unset variable. Default behavior
|
||||||
# MO_FALSE_IS_EMPTY environment variable instead to a non-empty value
|
# is to silently ignore and expand into empty string.
|
||||||
# to enable this behavior.
|
# -e, --false - Treat "false" as an empty value. You may set the
|
||||||
# --help - (`-h)` Display a help message.
|
# MO_FALSE_IS_EMPTY environment variable instead to a non-empty
|
||||||
# --source=FILE - (`-s=FILE`) Source a file into the environment before processing
|
# value to enable this behavior.
|
||||||
# template files.
|
# -h, --help - Display a help message.
|
||||||
# --path=PATH - (`-p=PATH`) Colon-separated list of paths to search for templates.
|
# -s=FILE, --source=FILE
|
||||||
# They are relative to where `mo` was executed.
|
# - Source a file into the environment before processint
|
||||||
# -- - Used to indicate the end of options. You may use this when filenames
|
# template files.
|
||||||
# start with hyphens.
|
# -- - Used to indicate the end of options. You may optionally
|
||||||
# $@ - Filenames to parse.
|
# use this when filenames may start with two hyphens.
|
||||||
|
# $@ - Filenames to parse.
|
||||||
#
|
#
|
||||||
# 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
|
# MO_ALLOW_FUNCTION_ARGUMENTS
|
||||||
# functions referenced in templates to receive additional options and
|
# - When set to a non-empty value, this allows functions
|
||||||
# arguments. This puts the content from the template directly into an
|
# referenced in templates to receive additional
|
||||||
# eval statement. Use with extreme care.
|
# options and arguments. This puts the content from the
|
||||||
|
# template directly into an eval statement. Use with
|
||||||
|
# extreme care.
|
||||||
|
# MO_FUNCTION_ARGS - Arguments passed to the function
|
||||||
|
# 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"
|
||||||
|
# will be treated as an empty value for the purposes
|
||||||
|
# of conditionals.
|
||||||
|
# MO_ORIGINAL_COMMAND - Used to find the `mo` program in order to generate
|
||||||
|
# a help message.
|
||||||
#
|
#
|
||||||
# MO_FAIL_ON_UNSET - When set to a non-empty value, expansion of an unset env
|
# Returns nothing.
|
||||||
# variable will be aborted with an error.
|
|
||||||
#
|
|
||||||
# MO_FALSE_IS_EMPTY - When set to a non-empty value, the string "false" will be
|
|
||||||
# treated as an empty value for the purposes of conditionals.
|
|
||||||
#
|
|
||||||
# MO_ORIGINAL_COMMAND - Used to find the `mo` program in order to generate a
|
|
||||||
# help message.
|
|
||||||
#
|
|
||||||
# MO_SEARCH_PATH - Colon-separated list of folders to search for templates.
|
|
||||||
# They are relative to where `mo` was executed.
|
|
||||||
#
|
|
||||||
# Returns true (0) when there are no errors. Sometimes returns (1) when there
|
|
||||||
# are errors and sometimes those errors are consumed. It greatly depends on the
|
|
||||||
# error and your options.
|
|
||||||
mo() (
|
mo() (
|
||||||
# This function executes in a subshell so IFS is reset.
|
# This function executes in a subshell so IFS is reset.
|
||||||
# Namespace this variable so we don't conflict with desired values.
|
# Namespace this variable so we don't conflict with desired values.
|
||||||
local moContent f2source files doubleHyphens paths
|
local moContent f2source files doubleHyphens
|
||||||
|
|
||||||
IFS=$' \n\t'
|
IFS=$' \n\t'
|
||||||
files=()
|
files=()
|
||||||
@@ -115,7 +110,11 @@ mo() (
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
-s=* | --source=*)
|
-s=* | --source=*)
|
||||||
f2source="${arg#*=}"
|
if [[ "$arg" == --source=* ]]; then
|
||||||
|
f2source="${arg#--source=}"
|
||||||
|
else
|
||||||
|
f2source="${arg#-s=}"
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ -f "$f2source" ]]; then
|
if [[ -f "$f2source" ]]; then
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
@@ -126,10 +125,6 @@ mo() (
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
||||||
-p=* | --path=*)
|
|
||||||
MO_SEARCH_PATH="$(moProcessSearchPath "${arg#*=}")"
|
|
||||||
;;
|
|
||||||
|
|
||||||
--)
|
--)
|
||||||
# Set a flag indicating we've encountered double hyphens
|
# Set a flag indicating we've encountered double hyphens
|
||||||
doubleHyphens=true
|
doubleHyphens=true
|
||||||
@@ -149,21 +144,6 @@ mo() (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Internal: Change relative paths into absolute paths
|
|
||||||
moProcessSearchPath() {
|
|
||||||
local in out path startingPwd IFS
|
|
||||||
|
|
||||||
IFS=:
|
|
||||||
startingPwd=$PWD
|
|
||||||
|
|
||||||
for path in $1; do
|
|
||||||
cd "$startingPwd" && cd "$path" 2>/dev/null && out="$out:$PWD"
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "${out:1}"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Internal: Call a function.
|
# Internal: Call a function.
|
||||||
#
|
#
|
||||||
# $1 - Function to call
|
# $1 - Function to call
|
||||||
@@ -175,16 +155,17 @@ moProcessSearchPath() {
|
|||||||
#
|
#
|
||||||
# Returns nothing.
|
# Returns nothing.
|
||||||
moCallFunction() {
|
moCallFunction() {
|
||||||
local moArgs
|
local moArgs moFunctionArgs
|
||||||
|
|
||||||
moArgs=()
|
moArgs=()
|
||||||
|
moTrimWhitespace moFunctionArgs "$3"
|
||||||
|
|
||||||
# shellcheck disable=SC2031
|
# shellcheck disable=SC2031
|
||||||
if [[ -n "${MO_ALLOW_FUNCTION_ARGUMENTS-}" ]]; then
|
if [[ -n "${MO_ALLOW_FUNCTION_ARGUMENTS-}" ]]; then
|
||||||
moArgs=$3
|
moArgs=$3
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -n "$2" | eval "$1" "$moArgs"
|
echo -n "$2" | MO_FUNCTION_ARGS="$moFunctionArgs" eval "$1" "$moArgs"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -824,39 +805,7 @@ moPartial() {
|
|||||||
(
|
(
|
||||||
# It would be nice to remove `dirname` and use a function instead,
|
# It would be nice to remove `dirname` and use a function instead,
|
||||||
# but that's difficult when you're only given filenames.
|
# but that's difficult when you're only given filenames.
|
||||||
if ! cd "$(dirname -- "$moFilename")"; then
|
cd "$(dirname -- "$moFilename")" || exit 1
|
||||||
if [[ -n "${MO_FAIL_ON_UNSET-}" ]]; then
|
|
||||||
echo "Error changing to directory: $(dirname -- "$moFilename")" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Mustache likes to be silent when there are errors.
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$moFilename" != */* ]] && [[ ! -f "$moFilename" ]] && [[ -n "$MO_SEARCH_PATH" ]]; then
|
|
||||||
# Search the path for the file
|
|
||||||
IFS=:
|
|
||||||
|
|
||||||
for moSearchPath in $MO_SEARCH_PATH; do
|
|
||||||
if [[ ! -f "$moFilename" ]]; then
|
|
||||||
cd "$moSearchPath"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
IFS=$' \n\t'
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -f "${moFilename##*/}" ]]; then
|
|
||||||
if [[ -n "${MO_FAIL_ON_UNSET-}" ]]; then
|
|
||||||
echo "File does not exist: $PWD/${moFilename##*/}" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Mustache likes to be silent when there are errors.
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
moUnindented="$(
|
moUnindented="$(
|
||||||
moLoadFile moPartial "${moFilename##*/}" || exit 1
|
moLoadFile moPartial "${moFilename##*/}" || exit 1
|
||||||
moParse "${moPartial}" "$6" true
|
moParse "${moPartial}" "$6" true
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
File does not exist: /home/fidian/repo/mo/tests/--help
|
cat: --help: No such file or directory
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
# This should display a message indicating that the file --help
|
# This should display a message indicating that the file --help
|
||||||
# could not be found. It should not display a help messsage.
|
# could not be found. It should not display a help messsage.
|
||||||
cd "${0%/*}"
|
cd "${0%/*}"
|
||||||
../mo -u -- --help 2>&1
|
../mo -- --help 2>&1
|
||||||
|
|||||||
3
tests/function-args-read.env
Normal file
3
tests/function-args-read.env
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
testArgs() {
|
||||||
|
echo "$MO_FUNCTION_ARGS"
|
||||||
|
}
|
||||||
4
tests/function-args-read.expected
Normal file
4
tests/function-args-read.expected
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
No args: [] - done
|
||||||
|
One arg: [one] - done
|
||||||
|
Multiple arguments: [aa bb cc 'x' " ! {[_.|] - done
|
||||||
|
Evil: [bla; cat /etc/issue] - done
|
||||||
4
tests/function-args-read.template
Normal file
4
tests/function-args-read.template
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
No args: [{{testArgs}}] - done
|
||||||
|
One arg: [{{testArgs one}}] - done
|
||||||
|
Multiple arguments: [{{testArgs aa bb cc 'x' " ! {[_.| }}] - done
|
||||||
|
Evil: [{{testArgs bla; cat /etc/issue}}] - done
|
||||||
@@ -9,19 +9,9 @@ Learn more about mustache templates at https://mustache.github.io/
|
|||||||
|
|
||||||
Simple usage:
|
Simple usage:
|
||||||
|
|
||||||
mo [OPTIONS] filenames...
|
mo [--false] [--help] [--source=FILE] filenames...
|
||||||
|
|
||||||
Options:
|
--fail-not-set - Fail upon expansion of an unset variable.
|
||||||
|
--false - Treat the string "false" as empty for conditionals.
|
||||||
-u, --fail-not-set
|
--help - This message.
|
||||||
- Fail upon expansion of an unset variable.
|
--source=FILE - Load FILE into the environment before processing templates.
|
||||||
-e, --false
|
|
||||||
- Treat the string "false" as empty for conditionals.
|
|
||||||
-h, --help
|
|
||||||
- This message.
|
|
||||||
-s=FILE, --source=FILE
|
|
||||||
- Load FILE into the environment before processing templates.
|
|
||||||
-p=PATH, --path=PATH
|
|
||||||
- Set a colon-delimited list of folders to search for templates.
|
|
||||||
|
|
||||||
MO_VERSION=2.0.4
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
cd "${0%/*}"
|
cd "${0%/*}"
|
||||||
../mo -u --help
|
../mo --help
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
cat: --something: No such file or directory
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
File does not exist: /home/fidian/repo/mo/tests/partial-missing.partial
|
cat: partial-missing.partial: No such file or directory
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
cd "${0%/*}"
|
cd "${0%/*}"
|
||||||
../mo -u partial-missing.template 2>&1
|
../mo partial-missing.template 2>&1
|
||||||
returned=$?
|
|
||||||
|
|
||||||
if [[ $returned -ne 1 ]]; then
|
if [[ $? -ne 1 ]]; then
|
||||||
echo "Did not return 1. Instead, returned $returned."
|
echo "Did not return 1"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
cd "${0%/*}"
|
cd "${0%/*}"
|
||||||
. ../mo
|
cat <<EOF | ../mo --source=source.vars
|
||||||
cat <<EOF | mo --source=source.vars
|
|
||||||
{{VAR}}
|
{{VAR}}
|
||||||
{{#ARR}}
|
{{#ARR}}
|
||||||
* {{.}}
|
* {{.}}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export VAR=value
|
export VAR=value
|
||||||
export ARR=(1 2 3)
|
export ARR=(1 2 3)
|
||||||
declare -A ASSOC_ARR
|
declare -A ASSOC_ARR
|
||||||
ASSOC_ARR=([a]=AAA [b]=BBB)
|
export ASSOC_ARR=([a]=AAA [b]=BBB)
|
||||||
Reference in New Issue
Block a user