Skip to content

Latest commit

 

History

History
177 lines (139 loc) · 8.48 KB

3to4.md

File metadata and controls

177 lines (139 loc) · 8.48 KB

Differences between v3 and v4

Speed and memory

ST v4 seems to be about 2x faster than v3 when there's no memory pressure / GC thrashing. With memory constraints, ST v4 is much faster because it seems to use less memory. This data comes from upgrading ANTLR to use ST v4.

Migrating to v4 from v3

In general, migrating to v4 is straightforward. The biggest difference is that the names of the types have changed (I got tired of typing StringTemplateGroup all the way out) as well as the package. Instead of base package org.stringtemplate, we use org.stringtemplate.v4.

  • StringTemplate -> ST
  • StringTemplateGroup -> STGroup, STGroupFile, or STGroupDir. References to new StringTemplateGroup(directory) should become new STGroupDir(directory). References to new StringTemplateGroup(new FileReader("file.stg")) should become new STGroupFile("file.stg").
  • We pass in delimiter start and stop characters to the constructor of groups rather than passing in AngleBracketTemplateLexer.class. The default delimiters are angle brackets <...> instead of dollar signs $...$.
  • setAttribute() -> add(). This makes it clear that we are adding rather than resetting attribute values. The semantics of the same except that we can add null values.
  • There is no group header in group files but they're ignored for backward compatibility. Instead, use (possibly multiple) import "filename.stg" or import "dirname" or import "template.st".
  • All explicit and implicit references to ST.toString() become calls to render(). It was difficult to debug templates because the debugger keeps calling toString to display objects. Also, it's better to be explicit that we are rendering a template string. There are a lot of implicit conversions of templates to strings. For example,
System.out.println(st);

should be

System.out.println(st.render());
  • All templates require formal arguments unless you use constructor new ST("a template"). So, a template file looks like
bracket(x) ::= "[<x>]"

instead of just [].

  • The syntax inside templates is the same except that there is no need for ... argument that said ``pass through outer arguments.''
  • There is no implicit it or attr attribute during generation now. convert <names:{<it>}> to <names:{n | <n>}>. If you use <names:foo()> and foo looks like:
foo() ::= "<it>"

then convert it:

foo(x) ::= "<x>"

ST will automatically pass in iterated value as the first argument (as it would do in v3).

  • The functionality of existing templates should be the same except that iterating across a Map is on the keys not values for v4. In v3, it iterated across the values. We had to use <aMap.keys:{...}> to iterate across the keys. This is the only change that could be painful because of the dynamic typing nature of ST. There's no static tool to find these occurrences.
  • The only other thing is that you might notice some differences in the whitespace handling.

New Functionality

  • STViz template visualizer; setting STGroup.debug creates DebugST objects not ST and tracks which Java code sets which attributes and/or creates templates. You need to set the debug flag in order to use the visualizer.
  • multiple template group inheritance using import
  • Added ModelAdaptors, an object that knows how to convert property references to appropriate actions on a model object. Given <a.foo>, we look up foo via the M adaptor if "a instanceof(M)".
  • For <if(...)> conditionals, you can use && || conditional operators instead of nested IF statements
  • strlen, trim, and reverse functions for lists
  • predefined DateRenderer and StringRenderer (understands formats upper, lower, cap, url-encode, xml-encode) objects.
  • v4 has <%...%> template definitions that are like <<..>> except that they ignore all new lines. This is very convenient for complicated templates that need to be broken up for easy viewing but that shouldn't have newlines in the output.
  • Added ST.format methods for use in general Java code.
int[] num =
   new int[] {3,9,20,2,1,4,6,32,5,6,77,888,2,1,6,32,5,6,77,
       4,9,20,2,1,4,63,9,20,2,1,4,6,32,5,6,77,6,32,5,6,77,
       3,9,20,2,1,4,6,32,5,6,77,888,1,6,32,5};
String t =
   ST.format(30, "int <%1>[] = { <%2; wrap, anchor, separator=\", \"> };", "a", num);
System.out.println(t);

Yields:

int a[] = { 3, 9, 20, 2, 1, 4,
               6, 32, 5, 6, 77, 888,
               2, 1, 6, 32, 5, 6,
               77, 4, 9, 20, 2, 1,
               4, 63, 9, 20, 2, 1,
               4, 6, 32, 5, 6, 77,
               6, 32, 5, 6, 77, 3,
               9, 20, 2, 1, 4, 6,
               32, 5, 6, 77, 888,
               1, 6, 32, 5 };
  • \n in a template becomes \r\n or \n in output depending on platform. We can always use \n in templates. To force \r\n on unix, though, we can still create a writer:
st.write(new AutoIndentWriter(sw,"\r\n")); // force \r\n as newline
  • renderers know locale optionally; only one method in renderer now with all args
  • The default file encoding for templates and template groups is UTF-8.

Differences

Major

  • template arguments can be named or passed by position at the call site as we would in Java. For example, given a template t with two arguments, we can use <t("a","b")> to pass two strings instead of <t(first="a", last="b")>. In v3, you would get into weird situations where you would have to do <t(a=a, b=b)>. now we can say <t(a,b)>.
  • Map iteration is on keys not values for v4
  • no it iteration value
  • groups:
  • Unify groups; groups are just template files cat'd together
  • STGroup not StringTemplateGroup, STGroupDir, STGroupFile
  • no group header in group files but multiple import "filename.stg" or import "dirname"
  • render() not toString()
  • v4 does not support template interfaces

Minor

  • We can't pass arguments to the templates in map operations like this: <names:foo("hi")>.
  • default args can see other args:
t(x,y={<x:{s|<s><z>}>},z="foo") ::= <<...>>
  • allows hasXXX property method in addition to the getXXX and isXXX.
  • <a.b> for missing b is no longer an error
  • templates do not have listeners; only groups have listeners
  • renderers are per group and the group the interpreter feeds off of native group. Renderers in v4 now operate on class subtrees instead of exact types. Renderer associated with type t works for object o if
t.isAssignableFrom(o.getClass()) // would assignment t = o work?

So it works if o is subclass or implements t.

  • Can only have 65535 char in any one template (instr operands are shorts and write instruction refs back into source template pattern).
  • allows <{...}> so we can add strip/filter/format option to ignore WS
  • reset() doesn't exist anymore. Getting an instance of a template provides a "resetted" one.
  • missing vs empty; null in list and false-IF are like missing; empty is "" or <else><endif> clause
  • null values for attr allowed; st.add("name", null). same as missing. it's added to list if we add other values afterwards. same now as sending in list of null
  • arg "..." is a string (noninterpreted) and {...} is an anon template that allows full nesting etc...
  • can't do separator=names:{..} (no map ops in option expr) but can do optionname={...}
  • i, i0 don't propagate in dyn scoping
  • setting attr i or i0 has no effect; they go 1..n 0..n-1 anyway
  • <...> delimiters by default
  • "..." means string literal, {...} and <<...>> are templates; e.g., in map defs
  • change doc to say dict not map for dicts in group files.
  • for dictionaries: render any key to a string for lookup; m.(key)
  • trim just one WS char from start of multi-line templates, not all whitespace; none at end; no longer needed since we use formal args in .st files now. "..." don't get anything stripped.
  • indentation of IF stuff is ignored as is newline on end.
[
   <if(x)>
   foo
   <else>
   bar
   <endif>
]

it did two indents in STv3. result now is

[
   foo
]
  • <multi-char> is not allowed. Use <\n> instead. <\n> automatically outputs either \n or \r\n depending on the OS.
  • groups have no name other than dir name or group file name
  • \n stripped if no output on a line and literal or <...> including IF

EMPHATICALLY SAME:

  • null elements get ignored. null list elements do not get counted for <i> and <i0> indexes.
  • trim whitespace at start/end of templates; just too hard to get rid of whitespace later.

Thread safety

assume thread safe modifying access to templates, adaptors, attributes, imports, and renderer access on STGroup/ST (they are synchronized).