There are 5 expression options at the moment:

The option values are all full expressions, which can include references to templates, anonymous templates, and so on. For example here is a separator that invokes another template:

<ul>$name; separator=bulletSeparator(foo=" ")+"&nbsp;"$</ul>

The wrap and anchor options are implemented via the Output Filters. The others are handled during interpretation by ST. Well, the filters also are notified that a separator vs regular string is coming out to prevent newlines between real elements and separators.

Java examples

Here is an example use of the format option.

public void testRendererWithFormatAndList() throws Exception {
    StringTemplate st =new StringTemplate(
                    "The names: <names; format=\"upper\">",
                    AngleBracketTemplateLexer.class);
    st.setAttribute("names", "ter");
    st.setAttribute("names", "tom");
    st.setAttribute("names", "sriram");
    st.registerRenderer(String.class, new StringRenderer());
    String expecting = "The names: TERTOMSRIRAM";
    String result = st.toString();
    assertEquals(expecting, result);
}

The code registers a renderer for the String class. Without the format option, the toString(Object) method is used to convert strings to the emitted text. With the option, the toString(Object, String) method is invoked. Here is the renderer used in the example:

public class StringRenderer implements AttributeRenderer {
    public String toString(Object o) {
            return (String)o;
    }
    public String toString(Object o, String formatString) {
            if ( formatString.equals("upper") ) {
                    return ((String)o).toUpperCase();
            }
            return toString(o);
    }
}

The following code snippet is the same as the previous example except for the introduction of the separator option, which cleans up the output as you can see by the expecting string:

public void testRendererWithFormatAndSeparator() throws Exception {
    StringTemplate st =new StringTemplate(
                    "The names: <names; separator=\" and \", format=\"upper\">",
                    AngleBracketTemplateLexer.class);
    st.setAttribute("names", "ter");
    st.setAttribute("names", "tom");
    st.setAttribute("names", "sriram");
    st.registerRenderer(String.class, new StringRenderer());
    String expecting = "The names: TER and TOM and SRIRAM";
    String result = st.toString();
    assertEquals(expecting, result);
}

If there are null elements in the list of names, you can specify a string to replace all of the null values using the null option:

public void testRendererWithFormatAndSeparatorAndNull() throws Exception {
    StringTemplate st =new StringTemplate(
        "The names: <names; separator=\" and \", null=\"n/a\", format=\"upper\">",
        AngleBracketTemplateLexer.class);
    List names = new ArrayList();
    names.add("ter");
    names.add(null);
    names.add("sriram");
    st.setAttribute("names", names);
    st.registerRenderer(String.class, new StringRenderer());
    String expecting = "The names: TER and N/A and SRIRAM";
    String result = st.toString();
    assertEquals(expecting, result);
}

Python examples

If you are constructing HTML documents you have to escape plain text strings so that < or & characters appear as literal text and do not act as HTML delimiters (thus opening a wide range of possible attacks if the text originated from user input).

import cgi
import stringtemplate3

group = stringtemplate3.StringTemplateGroup(
    name="default", rootDir="path/to/templates/"
    )

class EscapeRenderer(stringtemplate3.AttributeRenderer):
    def toString(self, o, formatName=None):
        if formatName is None:
            # no formatting specified
            return str(o)

        if formatName == "escape":
            return cgi.escape(str(o))
        else:
            raise ValueError("Unsupported format name")

group.registerRenderer(str, EscapeRenderer())

st = group.getInstanceOf("blogEntry")
st['comment'] = database.loadComment() # an instance with username, text, url, ... attributes

Then you can use $comment.text; format="escape"$ in your templates whenever an attribute is not known to be save.