Closed Swivelgames closed 4 months ago
UPDATE Just tested this with Bash 3.1 and Bash 3.2 and mo
executed successfully!
Just like the other Associative Array features already in mo
, these features are compatible with Bash 4.0-5.1.
This was implemented successfully in #59
The issue I have is that navItems
and stringArray
are both simply arrays of strings and there's no way to really tell that one's values are names of other arrays and the other is just normal strings.
Sample environment variables - add these two lines to the bottom
title="This is a title"
url="URL"
Add these lines to the bottom of your template
# Standard list again but now I can't reference `$title` nor `$url` that I defined.
{{#stringArray}}
- [{{title}}]({{url}})
{{/stringArray}}
mo
does not really have scoping of variables because Bash itself doesn't natively support data structures this complex. What I think you want is a way to do an indirect lookup of a variable. Something like how bash uses ${!variable}
, you might want the equivalent of Mustache's lookup, which I would be very interested in seeing.
If I merge this pull request as-is, it will be breaking change because the current behavior doesn't allow for looking up values automatically and could easily cause problems with people feeding in lots of data to their templates and iterating across arrays whose values match variable names.
I'd like to propose some use cases to use as examples. For both of these I included {{INDIRECT variableName [key]}}
indicating I wanted to get a variable or I wanted to get a specific key from a variable. Syntax here isn't important - just the idea that the information is needed.
. ./mo
# Use case 1: look up values in an associative array
declare -A employee
employee[123]="Tyler"
employee[456]="Joseph"
employees=(123 456)
cat <<EOF | mo
Employee list:
{{#employees}}
- {{INDIRECT employee .}}
{{/employees}}
EOF
# Use case 2: look up another variable for internationalization
welcomeMessage="Gruß dich!"
farewellMessage="Bis spater"
messages=(welcomeMessage farewellMessage)
cat <<EOF | mo
List of messages:
{{#messages}}
* {{INDIRECT .}}
{{/messages}}
EOF
# Use case 3, getting related information
declare -A pages urls
pages["home"]="Home page"
urls["home"]="http://localhost/"
pages["search"]="Search for content"
urls["search"]="http://localhost/search/"
cat <<EOF | mo
Pages on the site:
{{#pages}}
* [{{.}}]({{INDIRECT urls @key}})
{{/pages}}
EOF
Hopefully this explains some of the ways I've seen the templating system get used. Normally a function is created to do the work, but having a general purpose mechanism in place would be ideal. Getting function arguments parsed and supporting some sort of generic indirect syntax (perhaps steal from C's use of *variable
or PHP's use of $$variable
.
I think that #62 solved this problem, though in a different way. Would you concur?
Feature
In order to bring parity with
mo
and traditionalmustache
implementations, this feature will extract the keys of an associative array when looping. This feature alone will enablemo
to work with meaningful data structures and elevates it to a proper Mustache implementation.Specifically, derived from the official documentation (See "Non-Empty Lists"):
Template:
Output:
Justificaton
mo
or another implementation?mo
currently supports iterating over traditional List arrays, as well as associative Arrays. And, Bash officially supports Lists of Associative Arrays. Additionally,mo
already extracts variables into upper scopes, which can be leveraged to elevate keys of Associative Arrays into loop scopes.Implementation Considerations
Bash has supported nested arrays since Bash 4.3. Because of the way that
Bash
is implemented, this addition can leverage built-in loops to iterate over Lists and extract fields from their Associative Array members.