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/