/
Output Filters

Output Filters

Output Filters

Version 2.0 introduced the notion of an StringTemplateWriter/IStringTemplateWriter. All text rendered from a template goes through one of these writers before being placed in the output buffer. Terence added this primarily for auto-indentation for code generation, but it also could be used to remove whitespace (as a compression) from HTML output. Most recently, in 2.3, Terence updated the interface to support automatic line wrapping. If you don't care about indentation, you can simply subclass AutoIndentWriter and override write()/Write():

Java

public interface StringTemplateWriter {
    public static final int NO_WRAP = -1;

    void pushIndentation(String indent);

    String popIndentation();

    void pushAnchorPoint();

    void popAnchorPoint();

    void setLineWidth(int lineWidth);

    /** Write the string and return how many actual chars were written.
     *  With autoindentation and wrapping, more chars than length(str)
     *  can be emitted.  No wrapping is done.
     */
    int write(String str) throws IOException;

    /** Same as write, but wrap lines using the indicated string as the
     *  wrap character (such as "\n").
     */
    int write(String str, String wrap) throws IOException;

    /** Because we might need to wrap at a non-atomic string boundary
     *  (such as when we wrap in between template applications
     *   <data:{v|[<v>]}; wrap>) we need to expose the wrap string
     *  writing just like for the separator.
     */
    public int writeWrapSeparator(String wrap) throws IOException;

    /** Write a separator.  Same as write() except that a \n cannot
     *  be inserted before emitting a separator.
     */
    int writeSeparator(String str) throws IOException;
}

C#

public interface IStringTemplateWriter 
{
    void PushIndentation(string indent);

    string PopIndentation();

    void Write(string str);
}

Python

class StringTemplateWriter(object):
    NO_WRAP = -1
    
    def __init__(self):
        pass

    def pushIndentation(self, indent):
        raise NotImplementedError

    def popIndentation(self):
        raise NotImplementedError

    def pushAnchorPoint(self):
        raise NotImplementedError

    def popAnchorPoint(self):
        raise NotImplementedError

    def setLineWidth(self, lineWidth):
        raise NotImplementedError

    def write(self, str, wrap=None):
        raise NotImplementedError

    def writeWrapSeparator(self, wrap):
        raise NotImplementedError

    def writeSeparator(self, str):
        raise NotImplementedError

Here is a "pass through" writer that is already defined:

Java

/** Just pass through the text */
public class NoIndentWriter extends AutoIndentWriter {
    public NoIndentWriter(Writer out) {
        super(out);
    }

    public void write(String str) throws IOException {
	    out.write(str);
    }
}

C#

/** Just pass through the text */
public class NoIndentWriter : AutoIndentWriter 
{
    public NoIndentWriter(TextWriter output) :base(output) 
    {
    }

    public void Write(string str)
    {
	    output.Write(str);
    }
}

Python

class NoIndentWriter(stringtemplate3.AutoIndentWriter):
    """Just pass through the text"""
    def __init__(self, out):
        super(NoIndentWriter, self).__init__(out)

    def write(self, str):
        self.out.write(str)
        return len(str)

Use it like this:

Java

StringWriter out = new StringWriter();
StringTemplateGroup group =
                new StringTemplateGroup("test");
group.defineTemplate("bold", "<b>$x$</b>");
StringTemplate nameST = new StringTemplate(group, "$name:bold(x=name)$");
nameST.setAttribute("name", "Terence");
// write to 'out' with no indentation
nameST.write(new NoIndentWriter(out));
System.out.println("output: "+out.toString());

C#

StringWriter output = new StringWriter();
StringTemplateGroup group = new StringTemplateGroup("test");
group.DefineTemplate("bold", "<b>$x$</b>");
StringTemplate nameST = new StringTemplate(group, "$name:bold(x=name)$");
nameST.SetAttribute("name", "Terence");
// write to 'out' with no indentation
nameST.Write(new NoIndentWriter(output));
Console.Out.WriteLine("output: "+output.ToString());

Python

out = StringIO()
group = stringtemplate3.StringTemplateGroup("test")
group.defineTemplate("bold", "<b>$x$</b>")
nameST = stringtemplate3.StringTemplate("$name:bold(x=name)$", group=group)
nameST["name"] = "Terence"
# write to 'out' with no indentation
nameST.write(NoIndentWriter(out))
print "output:", str(out)

Instead of using nameST.toString(), which calls write with a string write and returns its value, manually invoke write with your writer.

If you want to always use a particular output filter, then use

Java

StringTemplateGroup.setStringTemplateWriter(Class userSpecifiedWriterClass);

C#

StringTemplateGroup.SetStringTemplateWriter(Type userSpecifiedWriterClass);

Python

stringtemplate.StringTemplateGroup.setStringTemplateWriter(userSpecifiedWriterClass)

The StringTemplate.toString() method is sensitive to the group's writer class.

Related content

Examples
Read with this
Object rendering
Object rendering
Read with this
Five minute Introduction
Five minute Introduction
Read with this
Expressions
Expressions
Read with this
Conditionally included subtemplates
Conditionally included subtemplates
Read with this
Defining Templates
Defining Templates
Read with this