github.com/hairyhenderson/gomplate/v4@v4.0.0-pre-2.0.20240520121557-362f058f0c93/docs/content/syntax.md (about) 1 --- 2 title: Syntax 3 weight: 13 4 menu: main 5 --- 6 7 Gomplate uses the syntax understood by the Go language's [`text/template`][] 8 package. This page documents some of that syntax, but see [the language docs][`text/template`] 9 for full details. 10 11 ## The basics 12 13 Templates are just regular text, with special actions delimited by `{{` and `}}` markers. Consider the following template: 14 15 ``` 16 Hello, {{ print "World" }}! 17 ``` 18 19 If you render this template, it will produce the following output: 20 21 ``` 22 Hello, World! 23 ``` 24 25 This is obviously a contrived example, and you would likely never see this in 26 _real life_, but this conveys the basics, which is that _actions_ are delimited 27 by `{{` and `}}`, and are replaced with their output (if any) when the template 28 is rendered. 29 30 ## Multi-line templates 31 32 By default, every line containing an action will render a newline. For example, the action block below: 33 34 ``` 35 {{ range coll.Slice "Foo" "bar" "baz" }} 36 Hello, {{ . }}! 37 {{ end }} 38 ``` 39 40 will produce the output below: 41 42 ``` 43 44 Hello, Foo! 45 46 Hello, bar! 47 48 Hello, baz! 49 50 ``` 51 52 This might not be desirable. 53 54 You can use [Golang template syntax](https://golang.org/pkg/text/template/#hdr-Text_and_spaces) to fix this. Leading newlines (i.e. newlines that come before the action) can be suppressed by placing a minus sign in front of the first set of delimiters (`{{`). Putting the minus sign behind the trailing set of delimiters (`}}`) will suppress the newline _after_ the action. You can do both to suppress newlines entirely on that line. 55 56 Placing the minus sign within the context (i.e. inside of `{{.}}`) has no effect. 57 58 Here are a few examples. 59 60 ### Suppressing leading newlines 61 62 ``` 63 {{- range coll.Slice "Foo" "bar" "baz" }} 64 Hello, {{ . }}! 65 {{- end }} 66 ``` 67 68 will produce this: 69 70 ``` 71 72 Hello, Foo! 73 Hello, bar! 74 Hello, baz! 75 ``` 76 77 ### Suppressing trailling newlines 78 79 This code: 80 81 ``` 82 {{ range coll.Slice "Foo" "bar" "baz" -}} 83 Hello, {{ . }}! 84 {{ end -}} 85 ``` 86 87 yields this: 88 89 ``` 90 Hello, Foo! 91 Hello, bar! 92 Hello, baz! 93 ``` 94 95 ### Suppressing newlines altogether 96 97 This code: 98 99 ``` 100 {{- range coll.Slice "Foo" "bar" "baz" -}} 101 Hello, {{ . }}! 102 {{- end -}} 103 ``` 104 105 Produces: 106 107 ``` 108 Hello, Foo!Hello, bar!Hello, baz! 109 ``` 110 111 ## Variables 112 113 The result of an action can be assigned to a _variable_, which is denoted by a 114 leading `$` character, followed by an alphanumeric string. For example: 115 116 ``` 117 {{ $w := "world" }} 118 Hello, {{ print $w }}! 119 Goodbye, {{ print $w }}. 120 ``` 121 122 this will render as: 123 124 ``` 125 Hello, world! 126 Goodbye, world. 127 ``` 128 129 Variables are declared with `:=`, and can be redefined with `=`: 130 131 ``` 132 {{ $w := "hello" }} 133 {{ $w = "goodbye" }} 134 ``` 135 136 ### Variable scope 137 138 A variable's scope extends to the `end` action of the control structure (`if`, 139 `with`, or `range`) in which it is declared, or to the end of the template if 140 there is no such control structure. 141 142 In other words, if a variable is initialized inside an `if` or `else` block, 143 it cannot be referenced outside that block. 144 145 This template will error with `undefined variable "$w"` since `$w` is only 146 declared within `if`/`else` blocks: 147 148 ``` 149 {{ if 1 }} 150 {{ $w := "world" }} 151 {{ else }} 152 {{ $w := "earth" }} 153 {{ end }} 154 155 Hello, {{ print $w }}! 156 Goodbye, {{ print $w }}. 157 ``` 158 159 One way to approach this is to declare the variable first to an empty value: 160 161 ``` 162 {{ $w := "" }} 163 {{ if 1 }} 164 {{ $w = "world" }} 165 {{ else }} 166 {{ $w = "earth" }} 167 {{ end -}} 168 169 Hello, {{ print $w }}! 170 Goodbye, {{ print $w }}. 171 ``` 172 173 ## Indexing arrays and maps 174 175 Occasionally, multi-dimensional data such as arrays (lists, slices) and maps 176 (dictionaries) are used in templates, sometimes through the use of 177 [data sources][]. Accessing values within these data can be done in a few ways 178 which bear clarifying. 179 180 ### Arrays 181 182 Arrays are always numerically-indexed, and individual values can be accessed with the `index` built-in function: 183 184 ``` 185 {{ index $array 0 }} 186 ``` 187 188 To visit each value, you can loop through an array with `range`: 189 190 ``` 191 {{ range $array }} 192 do something with {{ . }}... 193 {{ end }} 194 ``` 195 196 If you need to keep track of the index number, you can declare two variables, separated by a comma: 197 198 ``` 199 {{ range $index, $element := $array }} 200 do something with {{ $element }}, which is number {{ $index }} 201 {{ end }} 202 ``` 203 204 ### Maps 205 206 For maps, accessing values can be done with the `.` operator. Given a map `$map` 207 with a key `foo`, you could access it like: 208 209 ``` 210 {{ $map.foo }} 211 ``` 212 213 However, this kind of access is limited to keys which are strings and contain 214 only characters in the set (`a`-`z`,`A`-`Z`,`_`,`1`-`9`), and which do not begin 215 with a number. If the key doesn't conform to these rules, you can use the `index` 216 built-in function instead: 217 218 ``` 219 {{ index $map "foo-bar" }} 220 ``` 221 222 `index` also supports nested keys and can be combined with other functions as such: 223 224 ``` 225 {{ index $map "foo" (env.Getenv "BAR") "baz" ... }} 226 ``` 227 228 **Note:** _while `index` can be used to access awkwardly-named values in maps, 229 it behaves differently than the `.` operator. If the key doesn't exist, `index` 230 will simply not return a value, while `.` will error._ 231 232 And, similar to arrays, you can loop through a map with the `range`: 233 234 ``` 235 {{ range $map }} 236 The value is {{ . }} 237 {{ end }} 238 ``` 239 240 Or if you need keys as well: 241 242 ``` 243 {{ range $key, $value := $map }} 244 {{ $key }}'s value is: {{ $value }} 245 {{ end }} 246 ``` 247 248 ## Functions 249 250 Almost all of gomplate's utility is provided as _functions._ These are key 251 words (like `print` in the previous examples) that perform some action. 252 253 See the [functions documentation](/functions/) for more information. 254 255 ## The Context 256 257 Go templates are always executed with a _context_. You can reference the context 258 with the `.` (period) character, and you can set the context in a block with the 259 `with` action. Like so: 260 261 ``` 262 $ gomplate -i '{{ with "foo" }}The context is {{ . }}{{ end }}' 263 The context is foo 264 ``` 265 266 Templates rendered by gomplate always have a _default_ context. You can populate 267 the default context from data sources with the [`--context`/`c`](../usage/#context-c) 268 flag. The special context item [`.Env`](#env) is available for referencing the 269 system's environment variables. 270 271 _Note:_ The initial context (`.`) is always available as the variable `$`, 272 so the initial context is always available, even when shadowed with `range` 273 or `with` blocks: 274 275 ``` 276 $ echo '{"bar":"baz"}' | gomplate -c .=stdin:///in.json -i 'context is: {{ . }} 277 {{ with "foo" }}now context is {{ . }} 278 but the original context is still {{ $ }} 279 {{ end }}' 280 context is: map[bar:baz] 281 now context is foo 282 but the original context is still map[bar:baz] 283 ``` 284 285 ## Nested templates 286 287 Gomplate supports nested templates, using Go's `template` action. These can be 288 defined in-line with the `define` action, or external data can be used with the 289 [`--template`/`-t`](../usage/#template-t) flag. 290 291 Note that nested templates do _not_ have access to gomplate's default 292 [context](#the-context) (though it can be explicitly provided to the `template` 293 action). 294 295 ### In-line templates 296 297 To define a nested template in-line, you can use the `define` action. 298 299 ``` 300 {{ define "T1" -}} 301 Hello {{ . }}! 302 {{- end -}} 303 304 {{ template "T1" "World" }} 305 {{ template "T1" }} 306 {{ template "T1" "everybody" }} 307 ``` 308 309 This renders as: 310 311 ``` 312 Hello World! 313 Hello <no value>! 314 Hello everybody! 315 ``` 316 317 ### External templates 318 319 To define a nested template from an external source such as a file, use the 320 [`--template`/`-t`](../usage/#template-t) flag. 321 322 _hello.t:_ 323 ``` 324 Hello {{ . }}! 325 ``` 326 327 ``` 328 $ gomplate -t hello=hello.t -i '{{ template "hello" "World" }} {{ template "hello" .Env.USER }}" 329 Hello World! Hello hairyhenderson! 330 ``` 331 332 ## `.Env` 333 334 You can easily access environment variables with `.Env`, but there's a catch: 335 if you try to reference an environment variable that doesn't exist, parsing 336 will fail and `gomplate` will exit with an error condition. 337 338 For example: 339 340 ```console 341 $ gomplate -i 'the user is {{ .Env.USER }}' 342 the user is hairyhenderson 343 $ gomplate -i 'this will fail: {{ .Env.BOGUS }}' 344 this will fail: template: <arg>:1:23: executing "<arg>" at <.Env.BOGUS>: map has no entry for key "BOGUS" 345 ``` 346 347 Sometimes, this behaviour is desired; if the output is unusable without certain 348 strings, this is a sure way to know that variables are missing! 349 350 If you want different behaviour, try [`getenv`](../functions/env/#env-getenv). 351 352 [`text/template`]: https://golang.org/pkg/text/template/ 353 [`base64.Encode`]: ../functions/base64#base64-encode 354 [data sources]: ../datasources/