1*d396a58fSAndroid Build Coastguard Worker# EscapeVelocity summary 2*d396a58fSAndroid Build Coastguard Worker 3*d396a58fSAndroid Build Coastguard WorkerEscapeVelocity is a templating engine that can be used from Java. It is a reimplementation of a subset of 4*d396a58fSAndroid Build Coastguard Workerfunctionality from [Apache Velocity](http://velocity.apache.org/). 5*d396a58fSAndroid Build Coastguard Worker 6*d396a58fSAndroid Build Coastguard WorkerThis is not an official Google product. 7*d396a58fSAndroid Build Coastguard Worker 8*d396a58fSAndroid Build Coastguard WorkerFor a fuller explanation of Velocity's functioning, see its 9*d396a58fSAndroid Build Coastguard Worker[User Guide](http://velocity.apache.org/engine/releases/velocity-1.7/user-guide.html) 10*d396a58fSAndroid Build Coastguard Worker 11*d396a58fSAndroid Build Coastguard WorkerIf EscapeVelocity successfully produces a result from a template evaluation, that result should be 12*d396a58fSAndroid Build Coastguard Workerthe exact same string that Velocity produces. If not, that is a bug. 13*d396a58fSAndroid Build Coastguard Worker 14*d396a58fSAndroid Build Coastguard WorkerEscapeVelocity has no facilities for HTML escaping and it is not appropriate for producing 15*d396a58fSAndroid Build Coastguard WorkerHTML output that might include portions of untrusted input. 16*d396a58fSAndroid Build Coastguard Worker 17*d396a58fSAndroid Build Coastguard Worker 18*d396a58fSAndroid Build Coastguard Worker## Motivation 19*d396a58fSAndroid Build Coastguard Worker 20*d396a58fSAndroid Build Coastguard WorkerVelocity has a convenient templating language. It is easy to read, and it has widespread support 21*d396a58fSAndroid Build Coastguard Workerfrom tools such as editors and coding websites. However, *using* Velocity can prove difficult. 22*d396a58fSAndroid Build Coastguard WorkerIts use to generate Java code in the [AutoValue][AutoValue] annotation processor required many 23*d396a58fSAndroid Build Coastguard Worker[workarounds][VelocityHacks]. The way it dynamically loads classes as part of its standard operation 24*d396a58fSAndroid Build Coastguard Workermakes it hard to [shade](https://maven.apache.org/plugins/maven-shade-plugin/) it, which in the case 25*d396a58fSAndroid Build Coastguard Workerof AutoValue led to interference if Velocity was used elsewhere in a project. 26*d396a58fSAndroid Build Coastguard Worker 27*d396a58fSAndroid Build Coastguard WorkerEscapeVelocity has a simple API that does not involve any class-loading or other sources of 28*d396a58fSAndroid Build Coastguard Workerproblems. It and its dependencies can be shaded with no difficulty. 29*d396a58fSAndroid Build Coastguard Worker 30*d396a58fSAndroid Build Coastguard Worker## Loading a template 31*d396a58fSAndroid Build Coastguard Worker 32*d396a58fSAndroid Build Coastguard WorkerThe entry point for EscapeVelocity is the `Template` class. To obtain an instance, use 33*d396a58fSAndroid Build Coastguard Worker`Template.from(Reader)`. If a template is stored in a file, that file conventionally has the 34*d396a58fSAndroid Build Coastguard Workersuffix `.vm` (for Velocity Macros). But since the argument is a `Reader`, you can also load 35*d396a58fSAndroid Build Coastguard Workera template directly from a Java string, using `StringReader`. 36*d396a58fSAndroid Build Coastguard Worker 37*d396a58fSAndroid Build Coastguard WorkerHere's how you might make a `Template` instance from a template file that is packaged as a resource 38*d396a58fSAndroid Build Coastguard Workerin the same package as the calling class: 39*d396a58fSAndroid Build Coastguard Worker 40*d396a58fSAndroid Build Coastguard Worker```java 41*d396a58fSAndroid Build Coastguard WorkerInputStream in = getClass().getResourceAsStream("foo.vm"); 42*d396a58fSAndroid Build Coastguard Workerif (in == null) { 43*d396a58fSAndroid Build Coastguard Worker throw new IllegalArgumentException("Could not find resource foo.vm"); 44*d396a58fSAndroid Build Coastguard Worker} 45*d396a58fSAndroid Build Coastguard WorkerReader reader = new BufferedReader(new InputStreamReader(in)); 46*d396a58fSAndroid Build Coastguard WorkerTemplate template = Template.parseFrom(reader); 47*d396a58fSAndroid Build Coastguard Worker``` 48*d396a58fSAndroid Build Coastguard Worker 49*d396a58fSAndroid Build Coastguard Worker## Expanding a template 50*d396a58fSAndroid Build Coastguard Worker 51*d396a58fSAndroid Build Coastguard WorkerOnce you have a `Template` object, you can use it to produce a string where the variables in the 52*d396a58fSAndroid Build Coastguard Workertemplate are given the values you provide. You can do this any number of times, specifying the 53*d396a58fSAndroid Build Coastguard Workersame or different values each time. 54*d396a58fSAndroid Build Coastguard Worker 55*d396a58fSAndroid Build Coastguard WorkerSuppose you have this template: 56*d396a58fSAndroid Build Coastguard Worker 57*d396a58fSAndroid Build Coastguard Worker``` 58*d396a58fSAndroid Build Coastguard WorkerThe $language word for $original is $translated. 59*d396a58fSAndroid Build Coastguard Worker``` 60*d396a58fSAndroid Build Coastguard Worker 61*d396a58fSAndroid Build Coastguard WorkerYou might write this code: 62*d396a58fSAndroid Build Coastguard Worker 63*d396a58fSAndroid Build Coastguard Worker```java 64*d396a58fSAndroid Build Coastguard WorkerMap<String, String> vars = new HashMap<>(); 65*d396a58fSAndroid Build Coastguard Workervars.put("language", "French"); 66*d396a58fSAndroid Build Coastguard Workervars.put("original", "toe"); 67*d396a58fSAndroid Build Coastguard Workervars.put("translated", "orteil"); 68*d396a58fSAndroid Build Coastguard WorkerString result = template.evaluate(vars); 69*d396a58fSAndroid Build Coastguard Worker``` 70*d396a58fSAndroid Build Coastguard Worker 71*d396a58fSAndroid Build Coastguard WorkerThe `result` string would then be: `The French word for toe is orteil.` 72*d396a58fSAndroid Build Coastguard Worker 73*d396a58fSAndroid Build Coastguard Worker## Comments 74*d396a58fSAndroid Build Coastguard Worker 75*d396a58fSAndroid Build Coastguard WorkerThe characters `##` introduce a comment. Characters from `##` up to and including the following 76*d396a58fSAndroid Build Coastguard Workernewline are omitted from the template. This template has comments: 77*d396a58fSAndroid Build Coastguard Worker 78*d396a58fSAndroid Build Coastguard Worker``` 79*d396a58fSAndroid Build Coastguard WorkerLine 1 ## with a comment 80*d396a58fSAndroid Build Coastguard WorkerLine 2 81*d396a58fSAndroid Build Coastguard Worker``` 82*d396a58fSAndroid Build Coastguard Worker 83*d396a58fSAndroid Build Coastguard WorkerIt is the same as this template: 84*d396a58fSAndroid Build Coastguard Worker``` 85*d396a58fSAndroid Build Coastguard WorkerLine 1 Line 2 86*d396a58fSAndroid Build Coastguard Worker``` 87*d396a58fSAndroid Build Coastguard Worker 88*d396a58fSAndroid Build Coastguard Worker## References 89*d396a58fSAndroid Build Coastguard Worker 90*d396a58fSAndroid Build Coastguard WorkerEscapeVelocity supports most of the reference types described in the 91*d396a58fSAndroid Build Coastguard Worker[Velocity User Guide](http://velocity.apache.org/engine/releases/velocity-1.7/user-guide.html#References) 92*d396a58fSAndroid Build Coastguard Worker 93*d396a58fSAndroid Build Coastguard Worker### Variables 94*d396a58fSAndroid Build Coastguard Worker 95*d396a58fSAndroid Build Coastguard WorkerA variable has an ASCII name that starts with a letter (a-z or A-Z) and where any other characters 96*d396a58fSAndroid Build Coastguard Workerare also letters or digits or hyphens (-) or underscores (_). A variable reference can be written 97*d396a58fSAndroid Build Coastguard Workeras `$foo` or as `${foo}`. The value of a variable can be of any Java type. If the value `v` of 98*d396a58fSAndroid Build Coastguard Workervariable `foo` is not a String then the result of `$foo` in a template will be `String.valueOf(v)`. 99*d396a58fSAndroid Build Coastguard WorkerVariables must be defined before they are referenced; otherwise an `EvaluationException` will be 100*d396a58fSAndroid Build Coastguard Workerthrown. 101*d396a58fSAndroid Build Coastguard Worker 102*d396a58fSAndroid Build Coastguard WorkerVariable names are case-sensitive: `$foo` is not the same variable as `$Foo` or `$FOO`. 103*d396a58fSAndroid Build Coastguard Worker 104*d396a58fSAndroid Build Coastguard WorkerInitially the values of variables come from the Map that is passed to `Template.evaluate`. Those 105*d396a58fSAndroid Build Coastguard Workervalues can be changed, and new ones defined, using the `#set` directive in the template: 106*d396a58fSAndroid Build Coastguard Worker 107*d396a58fSAndroid Build Coastguard Worker``` 108*d396a58fSAndroid Build Coastguard Worker#set ($foo = "bar") 109*d396a58fSAndroid Build Coastguard Worker``` 110*d396a58fSAndroid Build Coastguard Worker 111*d396a58fSAndroid Build Coastguard WorkerSetting a variable affects later references to it in the template, but has no effect on the 112*d396a58fSAndroid Build Coastguard Worker`Map` that was passed in or on later template evaluations. 113*d396a58fSAndroid Build Coastguard Worker 114*d396a58fSAndroid Build Coastguard Worker### Properties 115*d396a58fSAndroid Build Coastguard Worker 116*d396a58fSAndroid Build Coastguard WorkerIf a reference looks like `$purchase.Total` then the value of the `$purchase` variable must be a 117*d396a58fSAndroid Build Coastguard WorkerJava object that has a public method `getTotal()` or `gettotal()`, or a method called `isTotal()` or 118*d396a58fSAndroid Build Coastguard Worker`istotal()` that returns `boolean`. The result of `$purchase.Total` is then the result of calling 119*d396a58fSAndroid Build Coastguard Workerthat method on the `$purchase` object. 120*d396a58fSAndroid Build Coastguard Worker 121*d396a58fSAndroid Build Coastguard WorkerIf you want to have a period (`.`) after a variable reference *without* it being a property 122*d396a58fSAndroid Build Coastguard Workerreference, you can use braces like this: `${purchase}.Total`. If, after a property reference, you 123*d396a58fSAndroid Build Coastguard Workerhave a further period, you can put braces around the reference like this: 124*d396a58fSAndroid Build Coastguard Worker`${purchase.Total}.nonProperty`. 125*d396a58fSAndroid Build Coastguard Worker 126*d396a58fSAndroid Build Coastguard Worker### Methods 127*d396a58fSAndroid Build Coastguard Worker 128*d396a58fSAndroid Build Coastguard WorkerIf a reference looks like `$purchase.addItem("scones", 23)` then the value of the `$purchase` 129*d396a58fSAndroid Build Coastguard Workervariable must be a Java object that has a public method `addItem` with two parameters that match 130*d396a58fSAndroid Build Coastguard Workerthe given values. Unlike Velocity, EscapeVelocity requires that there be exactly one such method. 131*d396a58fSAndroid Build Coastguard WorkerIt is OK if there are other `addItem` methods provided they are not compatible with the 132*d396a58fSAndroid Build Coastguard Workerarguments provided. 133*d396a58fSAndroid Build Coastguard Worker 134*d396a58fSAndroid Build Coastguard WorkerProperties are in fact a special case of methods: instead of writing `$purchase.Total` you could 135*d396a58fSAndroid Build Coastguard Workerwrite `$purchase.getTotal()`. Braces can be used to make the method invocation explicit 136*d396a58fSAndroid Build Coastguard Worker(`${purchase.getTotal()}`) or to prevent method invocation (`${purchase}.getTotal()`). 137*d396a58fSAndroid Build Coastguard Worker 138*d396a58fSAndroid Build Coastguard Worker### Indexing 139*d396a58fSAndroid Build Coastguard Worker 140*d396a58fSAndroid Build Coastguard WorkerIf a reference looks like `$indexme[$i]` then the value of the `$indexme` variable must be a Java 141*d396a58fSAndroid Build Coastguard Workerobject that has a public `get` method that takes one argument that is compatible with the index. 142*d396a58fSAndroid Build Coastguard WorkerFor example, `$indexme` might be a `List` and `$i` might be an integer. Then the reference would 143*d396a58fSAndroid Build Coastguard Workerbe the result of `List.get(int)` for that list and that integer. Or, `$indexme` might be a `Map`, 144*d396a58fSAndroid Build Coastguard Workerand the reference would be the result of `Map.get(Object)` for the object `$i`. In general, 145*d396a58fSAndroid Build Coastguard Worker`$indexme[$i]` is equivalent to `$indexme.get($i)`. 146*d396a58fSAndroid Build Coastguard Worker 147*d396a58fSAndroid Build Coastguard WorkerUnlike Velocity, EscapeVelocity does not allow `$indexme` to be a Java array. 148*d396a58fSAndroid Build Coastguard Worker 149*d396a58fSAndroid Build Coastguard Worker### Undefined references 150*d396a58fSAndroid Build Coastguard Worker 151*d396a58fSAndroid Build Coastguard WorkerIf a variable has not been given a value, either by being in the initial Map argument or by being 152*d396a58fSAndroid Build Coastguard Workerset in the template, then referencing it will provoke an `EvaluationException`. There is 153*d396a58fSAndroid Build Coastguard Workera special case for `#if`: if you write `#if ($var)` then it is allowed for `$var` not to be defined, 154*d396a58fSAndroid Build Coastguard Workerand it is treated as false. 155*d396a58fSAndroid Build Coastguard Worker 156*d396a58fSAndroid Build Coastguard Worker### Setting properties and indexes: not supported 157*d396a58fSAndroid Build Coastguard Worker 158*d396a58fSAndroid Build Coastguard WorkerUnlke Velocity, EscapeVelocity does not allow `#set` assignments with properties or indexes: 159*d396a58fSAndroid Build Coastguard Worker 160*d396a58fSAndroid Build Coastguard Worker``` 161*d396a58fSAndroid Build Coastguard Worker#set ($data.User = "jon") ## Allowed in Velocity but not in EscapeVelocity 162*d396a58fSAndroid Build Coastguard Worker#set ($map["apple"] = "orange") ## Allowed in Velocity but not in EscapeVelocity 163*d396a58fSAndroid Build Coastguard Worker``` 164*d396a58fSAndroid Build Coastguard Worker 165*d396a58fSAndroid Build Coastguard Worker## Expressions 166*d396a58fSAndroid Build Coastguard Worker 167*d396a58fSAndroid Build Coastguard WorkerIn certain contexts, such as the `#set` directive we have just seen or certain other directives, 168*d396a58fSAndroid Build Coastguard WorkerEscapeVelocity can evaluate expressions. An expression can be any of these: 169*d396a58fSAndroid Build Coastguard Worker 170*d396a58fSAndroid Build Coastguard Worker* A reference, of the kind we have just seen. The value is the value of the reference. 171*d396a58fSAndroid Build Coastguard Worker* A string literal enclosed in double quotes, like `"this"`. A string literal must appear on 172*d396a58fSAndroid Build Coastguard Worker one line. EscapeVelocity does not support the characters `$` or `\\` in a string literal. 173*d396a58fSAndroid Build Coastguard Worker* An integer literal such as `23` or `-100`. EscapeVelocity does not support floating-point 174*d396a58fSAndroid Build Coastguard Worker literals. 175*d396a58fSAndroid Build Coastguard Worker* A Boolean literal, `true` or `false`. 176*d396a58fSAndroid Build Coastguard Worker* Simpler expressions joined together with operators that have the same meaning as in Java: 177*d396a58fSAndroid Build Coastguard Worker `!`, `==`, `!=`, `<`, `<=`, `>`, `>=`, `&&`, `||`, `+`, `-`, `*`, `/`, `%`. The operators have the 178*d396a58fSAndroid Build Coastguard Worker same precedence as in Java. 179*d396a58fSAndroid Build Coastguard Worker* A simpler expression in parentheses, for example `(2 + 3)`. 180*d396a58fSAndroid Build Coastguard Worker 181*d396a58fSAndroid Build Coastguard WorkerVelocity supports string literals with single quotes, like `'this`' and also references within 182*d396a58fSAndroid Build Coastguard Workerstrings, like `"a $reference in a string"`, but EscapeVelocity does not. 183*d396a58fSAndroid Build Coastguard Worker 184*d396a58fSAndroid Build Coastguard Worker## Directives 185*d396a58fSAndroid Build Coastguard Worker 186*d396a58fSAndroid Build Coastguard WorkerA directive is introduced by a `#` character followed by a word. We have already seen the `#set` 187*d396a58fSAndroid Build Coastguard Workerdirective, which sets the value of a variable. The other directives are listed below. 188*d396a58fSAndroid Build Coastguard Worker 189*d396a58fSAndroid Build Coastguard WorkerDirectives can be spelled with or without braces, so `#set` or `#{set}`. 190*d396a58fSAndroid Build Coastguard Worker 191*d396a58fSAndroid Build Coastguard Worker### `#if`/`#elseif`/`#else` 192*d396a58fSAndroid Build Coastguard Worker 193*d396a58fSAndroid Build Coastguard WorkerThe `#if` directive selects parts of the template according as a condition is true or false. 194*d396a58fSAndroid Build Coastguard WorkerThe simplest case looks like this: 195*d396a58fSAndroid Build Coastguard Worker 196*d396a58fSAndroid Build Coastguard Worker``` 197*d396a58fSAndroid Build Coastguard Worker#if ($condition) yes #end 198*d396a58fSAndroid Build Coastguard Worker``` 199*d396a58fSAndroid Build Coastguard Worker 200*d396a58fSAndroid Build Coastguard WorkerThis evaluates to the string ` yes ` if the variable `$condition` is defined and has a true value, 201*d396a58fSAndroid Build Coastguard Workerand to the empty string otherwise. It is allowed for `$condition` not to be defined in this case, 202*d396a58fSAndroid Build Coastguard Workerand then it is treated as false. 203*d396a58fSAndroid Build Coastguard Worker 204*d396a58fSAndroid Build Coastguard WorkerThe expression in `#if` (here `$condition`) is considered true if its value is not null and not 205*d396a58fSAndroid Build Coastguard Workerequal to the Boolean value `false`. 206*d396a58fSAndroid Build Coastguard Worker 207*d396a58fSAndroid Build Coastguard WorkerAn `#if` directive can also have an `#else` part, for example: 208*d396a58fSAndroid Build Coastguard Worker 209*d396a58fSAndroid Build Coastguard Worker``` 210*d396a58fSAndroid Build Coastguard Worker#if ($condition) yes #else no #end 211*d396a58fSAndroid Build Coastguard Worker``` 212*d396a58fSAndroid Build Coastguard Worker 213*d396a58fSAndroid Build Coastguard WorkerThis evaluates to the string ` yes ` if the condition is true or the string ` no ` if it is not. 214*d396a58fSAndroid Build Coastguard Worker 215*d396a58fSAndroid Build Coastguard WorkerAn `#if` directive can have any number of `#elseif` parts. For example: 216*d396a58fSAndroid Build Coastguard Worker 217*d396a58fSAndroid Build Coastguard Worker``` 218*d396a58fSAndroid Build Coastguard Worker#if ($i == 0) zero #elseif ($i == 1) one #elseif ($i == 2) two #else many #end 219*d396a58fSAndroid Build Coastguard Worker``` 220*d396a58fSAndroid Build Coastguard Worker 221*d396a58fSAndroid Build Coastguard Worker### `#foreach` 222*d396a58fSAndroid Build Coastguard Worker 223*d396a58fSAndroid Build Coastguard WorkerThe `#foreach` directive repeats a part of the template once for each value in a list. 224*d396a58fSAndroid Build Coastguard Worker 225*d396a58fSAndroid Build Coastguard Worker``` 226*d396a58fSAndroid Build Coastguard Worker#foreach ($product in $allProducts) 227*d396a58fSAndroid Build Coastguard Worker ${product}! 228*d396a58fSAndroid Build Coastguard Worker#end 229*d396a58fSAndroid Build Coastguard Worker``` 230*d396a58fSAndroid Build Coastguard Worker 231*d396a58fSAndroid Build Coastguard WorkerThis will produce one line for each value in the `$allProducts` variable. The value of 232*d396a58fSAndroid Build Coastguard Worker`$allProducts` can be a Java `Iterable`, such as a `List` or `Set`; or it can be an object array; 233*d396a58fSAndroid Build Coastguard Workeror it can be a Java `Map`. When it is a `Map` the `#foreach` directive loops over every *value* 234*d396a58fSAndroid Build Coastguard Workerin the `Map`. 235*d396a58fSAndroid Build Coastguard Worker 236*d396a58fSAndroid Build Coastguard WorkerIf `$allProducts` is a `List` containing the strings `oranges` and `lemons` then the result of the 237*d396a58fSAndroid Build Coastguard Worker`#foreach` would be this: 238*d396a58fSAndroid Build Coastguard Worker 239*d396a58fSAndroid Build Coastguard Worker``` 240*d396a58fSAndroid Build Coastguard Worker 241*d396a58fSAndroid Build Coastguard Worker oranges! 242*d396a58fSAndroid Build Coastguard Worker 243*d396a58fSAndroid Build Coastguard Worker 244*d396a58fSAndroid Build Coastguard Worker lemons! 245*d396a58fSAndroid Build Coastguard Worker 246*d396a58fSAndroid Build Coastguard Worker``` 247*d396a58fSAndroid Build Coastguard Worker 248*d396a58fSAndroid Build Coastguard WorkerWhen the `#foreach` completes, the loop variable (`$product` in the example) goes back to whatever 249*d396a58fSAndroid Build Coastguard Workervalue it had before, or to being undefined if it was undefined before. 250*d396a58fSAndroid Build Coastguard Worker 251*d396a58fSAndroid Build Coastguard WorkerWithin the `#foreach`, a special variable `$foreach` is defined, such that you can write 252*d396a58fSAndroid Build Coastguard Worker`$foreach.hasNext`, which will be true if there are more values after this one or false if this 253*d396a58fSAndroid Build Coastguard Workeris the last value. For example: 254*d396a58fSAndroid Build Coastguard Worker 255*d396a58fSAndroid Build Coastguard Worker``` 256*d396a58fSAndroid Build Coastguard Worker#foreach ($product in $allProducts)${product}#if ($foreach.hasNext), #end#end 257*d396a58fSAndroid Build Coastguard Worker``` 258*d396a58fSAndroid Build Coastguard Worker 259*d396a58fSAndroid Build Coastguard WorkerThis would produce the output `oranges, lemons` for the list above. (The example is scrunched up 260*d396a58fSAndroid Build Coastguard Workerto avoid introducing extraneous spaces, as described in the [section](#spaces) on spaces 261*d396a58fSAndroid Build Coastguard Workerbelow.) 262*d396a58fSAndroid Build Coastguard Worker 263*d396a58fSAndroid Build Coastguard WorkerVelocity gives the `$foreach` variable other properties (`index` and `count`) but EscapeVelocity 264*d396a58fSAndroid Build Coastguard Workerdoes not. 265*d396a58fSAndroid Build Coastguard Worker 266*d396a58fSAndroid Build Coastguard Worker### Macros 267*d396a58fSAndroid Build Coastguard Worker 268*d396a58fSAndroid Build Coastguard WorkerA macro is a part of the template that can be reused in more than one place, potentially with 269*d396a58fSAndroid Build Coastguard Workerdifferent parameters each time. In the simplest case, a macro has no arguments: 270*d396a58fSAndroid Build Coastguard Worker 271*d396a58fSAndroid Build Coastguard Worker``` 272*d396a58fSAndroid Build Coastguard Worker#macro (hello) bonjour #end 273*d396a58fSAndroid Build Coastguard Worker``` 274*d396a58fSAndroid Build Coastguard Worker 275*d396a58fSAndroid Build Coastguard WorkerThen the macro can be referenced by writing `#hello()` and the result will be the string ` bonjour ` 276*d396a58fSAndroid Build Coastguard Workerinserted at that point. 277*d396a58fSAndroid Build Coastguard Worker 278*d396a58fSAndroid Build Coastguard WorkerMacros can also have parameters: 279*d396a58fSAndroid Build Coastguard Worker 280*d396a58fSAndroid Build Coastguard Worker``` 281*d396a58fSAndroid Build Coastguard Worker#macro (greet $hello $world) $hello, $world! #end 282*d396a58fSAndroid Build Coastguard Worker``` 283*d396a58fSAndroid Build Coastguard Worker 284*d396a58fSAndroid Build Coastguard WorkerThen `#greet("bonjour", "monde")` would produce ` bonjour, monde! `. The comma is optional, so 285*d396a58fSAndroid Build Coastguard Workeryou could also write `#greet("bonjour" "monde")`. 286*d396a58fSAndroid Build Coastguard Worker 287*d396a58fSAndroid Build Coastguard WorkerWhen a macro completes, the parameters (`$hello` and `$world` in the example) go back to whatever 288*d396a58fSAndroid Build Coastguard Workervalues they had before, or to being undefined if they were undefined before. 289*d396a58fSAndroid Build Coastguard Worker 290*d396a58fSAndroid Build Coastguard WorkerAll macro definitions take effect before the template is evaluated, so you can use a macro at a 291*d396a58fSAndroid Build Coastguard Workerpoint in the template that is before the point where it is defined. This also means that you can't 292*d396a58fSAndroid Build Coastguard Workerdefine a macro conditionally: 293*d396a58fSAndroid Build Coastguard Worker 294*d396a58fSAndroid Build Coastguard Worker``` 295*d396a58fSAndroid Build Coastguard Worker## This doesn't work! 296*d396a58fSAndroid Build Coastguard Worker#if ($language == "French") 297*d396a58fSAndroid Build Coastguard Worker#macro (hello) bonjour #end 298*d396a58fSAndroid Build Coastguard Worker#else 299*d396a58fSAndroid Build Coastguard Worker#macro (hello) hello #end 300*d396a58fSAndroid Build Coastguard Worker#end 301*d396a58fSAndroid Build Coastguard Worker``` 302*d396a58fSAndroid Build Coastguard Worker 303*d396a58fSAndroid Build Coastguard WorkerThere is no particular reason to define the same macro more than once, but if you do it is the 304*d396a58fSAndroid Build Coastguard Workerfirst definition that is retained. In the `#if` example just above, the `bonjour` version will 305*d396a58fSAndroid Build Coastguard Workeralways be used. 306*d396a58fSAndroid Build Coastguard Worker 307*d396a58fSAndroid Build Coastguard WorkerMacros can make templates hard to understand. You may prefer to put the logic in a Java method 308*d396a58fSAndroid Build Coastguard Workerrather than a macro, and call the method from the template using `$methods.doSomething("foo")` 309*d396a58fSAndroid Build Coastguard Workeror whatever. 310*d396a58fSAndroid Build Coastguard Worker 311*d396a58fSAndroid Build Coastguard Worker## Block quoting 312*d396a58fSAndroid Build Coastguard Worker 313*d396a58fSAndroid Build Coastguard WorkerIf you have text that should be treated verbatim, you can enclose it in `#[[...]]#`. The text 314*d396a58fSAndroid Build Coastguard Workerrepresented by `...` will be copied into the output. `#` and `$` characters will have no 315*d396a58fSAndroid Build Coastguard Workereffect in that text. 316*d396a58fSAndroid Build Coastguard Worker 317*d396a58fSAndroid Build Coastguard Worker``` 318*d396a58fSAndroid Build Coastguard Worker#[[ This is not a #directive, and this is not a $variable. ]]# 319*d396a58fSAndroid Build Coastguard Worker``` 320*d396a58fSAndroid Build Coastguard Worker 321*d396a58fSAndroid Build Coastguard Worker## Including other templates 322*d396a58fSAndroid Build Coastguard Worker 323*d396a58fSAndroid Build Coastguard WorkerIf you want to include a template from another file, you can use the `#parse` directive. 324*d396a58fSAndroid Build Coastguard WorkerThis can be useful if you have macros that are shared between templates, for example. 325*d396a58fSAndroid Build Coastguard Worker 326*d396a58fSAndroid Build Coastguard Worker``` 327*d396a58fSAndroid Build Coastguard Worker#set ($foo = "bar") 328*d396a58fSAndroid Build Coastguard Worker#parse("macros.vm") 329*d396a58fSAndroid Build Coastguard Worker#mymacro($foo) ## #mymacro defined in macros.vm 330*d396a58fSAndroid Build Coastguard Worker``` 331*d396a58fSAndroid Build Coastguard Worker 332*d396a58fSAndroid Build Coastguard WorkerFor this to work, you will need to tell EscapeVelocity how to find "resources" such as 333*d396a58fSAndroid Build Coastguard Worker`macro.vm` in the example. You might use something like this: 334*d396a58fSAndroid Build Coastguard Worker 335*d396a58fSAndroid Build Coastguard Worker``` 336*d396a58fSAndroid Build Coastguard WorkerResourceOpener resourceOpener = resourceName -> { 337*d396a58fSAndroid Build Coastguard Worker InputStream inputStream = getClass().getResource(resourceName); 338*d396a58fSAndroid Build Coastguard Worker if (inputStream == null) { 339*d396a58fSAndroid Build Coastguard Worker throw new IOException("Unknown resource: " + resourceName); 340*d396a58fSAndroid Build Coastguard Worker } 341*d396a58fSAndroid Build Coastguard Worker return new BufferedReader(InputStreamReader(inputStream, StandardCharsets.UTF_8)); 342*d396a58fSAndroid Build Coastguard Worker}; 343*d396a58fSAndroid Build Coastguard WorkerTemplate template = Template.parseFrom("foo.vm", resourceOpener); 344*d396a58fSAndroid Build Coastguard Worker``` 345*d396a58fSAndroid Build Coastguard Worker 346*d396a58fSAndroid Build Coastguard WorkerIn this case, the `resourceOpener` is used to find the main template `foo.vm`, as well as any 347*d396a58fSAndroid Build Coastguard Workertemplates it may reference in `#parse` directives. 348*d396a58fSAndroid Build Coastguard Worker 349*d396a58fSAndroid Build Coastguard Worker## <a name="spaces"></a> Spaces 350*d396a58fSAndroid Build Coastguard Worker 351*d396a58fSAndroid Build Coastguard WorkerFor the most part, spaces and newlines in the template are preserved exactly in the output. 352*d396a58fSAndroid Build Coastguard WorkerTo avoid unwanted newlines, you may end up using `##` comments. In the `#foreach` example above 353*d396a58fSAndroid Build Coastguard Workerwe had this: 354*d396a58fSAndroid Build Coastguard Worker 355*d396a58fSAndroid Build Coastguard Worker``` 356*d396a58fSAndroid Build Coastguard Worker#foreach ($product in $allProducts)${product}#if ($foreach.hasNext), #end#end 357*d396a58fSAndroid Build Coastguard Worker``` 358*d396a58fSAndroid Build Coastguard Worker 359*d396a58fSAndroid Build Coastguard WorkerThat was to avoid introducing unwanted spaces and newlines. A more readable way to achieve the same 360*d396a58fSAndroid Build Coastguard Workerresult is this: 361*d396a58fSAndroid Build Coastguard Worker 362*d396a58fSAndroid Build Coastguard Worker``` 363*d396a58fSAndroid Build Coastguard Worker#foreach ($product in $allProducts)## 364*d396a58fSAndroid Build Coastguard Worker${product}## 365*d396a58fSAndroid Build Coastguard Worker#if ($foreach.hasNext), #end## 366*d396a58fSAndroid Build Coastguard Worker#end 367*d396a58fSAndroid Build Coastguard Worker``` 368*d396a58fSAndroid Build Coastguard Worker 369*d396a58fSAndroid Build Coastguard WorkerSpaces are ignored between the `#` of a directive and the `)` that closes it, so there is no trace 370*d396a58fSAndroid Build Coastguard Workerin the output of the spaces in `#foreach ($product in $allProducts)` or `#if ($foreach.hasNext)`. 371*d396a58fSAndroid Build Coastguard WorkerSpaces are also ignored inside references, such as `$indexme[ $i ]` or `$callme( $i , $j )`. 372*d396a58fSAndroid Build Coastguard Worker 373*d396a58fSAndroid Build Coastguard WorkerIf you are concerned about the detailed formatting of the text from the template, you may want to 374*d396a58fSAndroid Build Coastguard Workerpost-process it. For example, if it is Java code, you could use a formatter such as 375*d396a58fSAndroid Build Coastguard Worker[google-java-format](https://github.com/google/google-java-format). Then you shouldn't have to 376*d396a58fSAndroid Build Coastguard Workerworry about extraneous spaces. 377*d396a58fSAndroid Build Coastguard Worker 378*d396a58fSAndroid Build Coastguard Worker[VelocityHacks]: https://github.com/google/auto/blob/ca2384d5ad15a0c761b940384083cf5c50c6e839/value/src/main/java/com/google/auto/value/processor/TemplateVars.java#L54 379*d396a58fSAndroid Build Coastguard Worker[AutoValue]: https://github.com/google/auto/tree/master/value 380