Added basic lambda support.
This commit is contained in:
@@ -132,6 +132,47 @@ If you wish to make use of partials (e.g. `{{>subtmpl}}`) you must provide a
|
|||||||
The above snippet will load `new File(templateDir, "subtmpl")` when compiling
|
The above snippet will load `new File(templateDir, "subtmpl")` when compiling
|
||||||
the template.
|
the template.
|
||||||
|
|
||||||
|
Lambdas
|
||||||
|
-------
|
||||||
|
|
||||||
|
JMustache implements lambdas by passing you a `Template.Fragment` instance
|
||||||
|
which you can use to execute the fragment of the template that was passed to
|
||||||
|
the lambda. You can decorate the results of the fragment execution, as shown in
|
||||||
|
the standard Mustache documentation on lambdas:
|
||||||
|
|
||||||
|
String tmpl = "{{#bold}}{{name}} is awesome.{{/bold}}";
|
||||||
|
Mustache.compiler().compile(tmpl).execute(new Object() {
|
||||||
|
Mustache.Lambda bold = new Mustache.Lambda() {
|
||||||
|
public void execute (Template.Fragment frag, Writer out) throws IOException {
|
||||||
|
out.write("<b>");
|
||||||
|
frag.execute(out);
|
||||||
|
out.write("</b>");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
// result:
|
||||||
|
<b>Willy is awsome.</b>
|
||||||
|
|
||||||
|
You can also obtain the results of the fragment execution to do things like
|
||||||
|
internationalization or caching:
|
||||||
|
|
||||||
|
Object ctx = new Object() {
|
||||||
|
Mustache.Lambda i18n = new Mustache.Lambda() {
|
||||||
|
public void execute (Template.Fragment frag, Writer out) throws IOException {
|
||||||
|
String key = frag.execute();
|
||||||
|
String text = // look up key in i18n system
|
||||||
|
out.write(text);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// template might look something like:
|
||||||
|
<h2>{{#i18n}}title{{/i18n}</h2>
|
||||||
|
{{#i18n}}welcome_msg{{/i18n}}
|
||||||
|
|
||||||
|
Currently there is no support for "unexecuting" the template and obtaining the
|
||||||
|
original Mustache template text contained in the section. File a feature
|
||||||
|
request with a sane use case if you have one.
|
||||||
|
|
||||||
Default Values
|
Default Values
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
|||||||
@@ -150,7 +150,19 @@ public class Mustache
|
|||||||
{
|
{
|
||||||
/** Returns a reader for the template with the supplied name.
|
/** Returns a reader for the template with the supplied name.
|
||||||
* @throws Exception if the template could not be loaded for any reason. */
|
* @throws Exception if the template could not be loaded for any reason. */
|
||||||
public Reader getTemplate (String name) throws Exception;
|
Reader getTemplate (String name) throws Exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Used to handle lambdas. */
|
||||||
|
public interface Lambda
|
||||||
|
{
|
||||||
|
/** Executes this lambda on the supplied template fragment. The lambda should write its
|
||||||
|
* results to {@code out}.
|
||||||
|
*
|
||||||
|
* @param tmpl the fragment of the template that was passed to the lambda.
|
||||||
|
* @param out the writer to which the lambda should write its output.
|
||||||
|
*/
|
||||||
|
void execute (Template.Fragment frag, Writer out) throws IOException;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Used to read variables from values. */
|
/** Used to read variables from values. */
|
||||||
@@ -640,6 +652,12 @@ public class Mustache
|
|||||||
if ((Boolean)value) {
|
if ((Boolean)value) {
|
||||||
executeSegs(tmpl, ctx, out);
|
executeSegs(tmpl, ctx, out);
|
||||||
}
|
}
|
||||||
|
} else if (value instanceof Lambda) {
|
||||||
|
try {
|
||||||
|
((Lambda)value).execute(tmpl.createFragment(_segs, ctx), out);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
throw new MustacheException(ioe);
|
||||||
|
}
|
||||||
} else if (_compiler.emptyStringIsFalse && "".equals(value)) {
|
} else if (_compiler.emptyStringIsFalse && "".equals(value)) {
|
||||||
// omit the section
|
// omit the section
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -36,6 +36,22 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public class Template
|
public class Template
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Encapsulates a fragment of a template that is passed to a lambda. The fragment is bound to
|
||||||
|
* the variable context that was in effect at the time the lambda was called.
|
||||||
|
*/
|
||||||
|
public abstract class Fragment {
|
||||||
|
/** Executes this template fragment, writing its result to {@code out}. */
|
||||||
|
public abstract void execute (Writer out);
|
||||||
|
|
||||||
|
/** Executes this template fragment and returns is result as a string. */
|
||||||
|
public String execute () {
|
||||||
|
StringWriter out = new StringWriter();
|
||||||
|
execute(out);
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes this template with the given context, returning the results as a string.
|
* Executes this template with the given context, returning the results as a string.
|
||||||
* @throws MustacheException if an error occurs while executing or writing the template.
|
* @throws MustacheException if an error occurs while executing or writing the template.
|
||||||
@@ -73,7 +89,7 @@ public class Template
|
|||||||
{
|
{
|
||||||
_segs = segs;
|
_segs = segs;
|
||||||
_compiler = compiler;
|
_compiler = compiler;
|
||||||
_fcache = _compiler.collector.createFetcherCache();
|
_fcache = compiler.collector.createFetcherCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void executeSegs (Context ctx, Writer out) throws MustacheException
|
protected void executeSegs (Context ctx, Writer out) throws MustacheException
|
||||||
@@ -83,6 +99,17 @@ public class Template
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Fragment createFragment (final Segment[] segs, final Context ctx)
|
||||||
|
{
|
||||||
|
return new Fragment() {
|
||||||
|
@Override public void execute (Writer out) {
|
||||||
|
for (Segment seg : segs) {
|
||||||
|
seg.execute(Template.this, ctx, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by executing segments to obtain the value of the specified variable in the supplied
|
* Called by executing segments to obtain the value of the specified variable in the supplied
|
||||||
* context.
|
* context.
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ import static org.junit.Assert.assertEquals;
|
|||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
import java.io.Writer;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -484,6 +486,32 @@ public class MustacheTest
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test public void testLambda1 () {
|
||||||
|
test("<b>Willy is awesome.</b>", "{{#bold}}{{name}} is awesome.{{/bold}}",
|
||||||
|
context("name", "Willy", "bold", new Mustache.Lambda() {
|
||||||
|
public void execute (Template.Fragment frag, Writer out) throws IOException {
|
||||||
|
out.write("<b>");
|
||||||
|
frag.execute(out);
|
||||||
|
out.write("</b>");
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void testLambda2 () {
|
||||||
|
test("Slug bug potato!", "{{#l}}1{{/l}} {{#l}}2{{/l}} {{#l}}{{three}}{{/l}}",
|
||||||
|
context("three", "3", "l", new Mustache.Lambda() {
|
||||||
|
public void execute (Template.Fragment frag, Writer out) throws IOException {
|
||||||
|
out.write(lookup(frag.execute()));
|
||||||
|
}
|
||||||
|
protected String lookup (String contents) {
|
||||||
|
if (contents.equals("1")) return "Slug";
|
||||||
|
else if (contents.equals("2")) return "bug";
|
||||||
|
else if (contents.equals("3")) return "potato!";
|
||||||
|
else return "Who was that man?";
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
protected void test (Mustache.Compiler compiler, String expected, String template, Object ctx)
|
protected void test (Mustache.Compiler compiler, String expected, String template, Object ctx)
|
||||||
{
|
{
|
||||||
assertEquals(expected, compiler.compile(template).execute(ctx));
|
assertEquals(expected, compiler.compile(template).execute(ctx));
|
||||||
|
|||||||
Reference in New Issue
Block a user