Useful method for pattern matching values?

I’m working on a site right now and I’m trying to do basic pattern matching on data values without resorting to a mess of if/else statements. Basically, I’m creating a “Feature support” table on the basis of YAML data where some features are 100% supported, some are not supported, and some are partially supported. I want to have different emojis associated with each of these three options. Here’s some example YAML:

- name: product1
    feature1:  yes
    feature2: no
    feature3: partial

I could do something like this, but I’d prefer not to:

{{- range .Site.Data.products }}
  {{- range .features }}
    {{- if eq . "yes" }}
    {{- $emoji := ":emoji1:" }}
    {{- else if eq . "no" }}
    {{- $emoji := ":emoji2:" }}
    {{- else }}
    {{- $emoji := ":emoji3:" }}
    {{- end }}
  {{- end }}
{{- end }}

Can anyone think of a more elegant way to do that?

How about cond:

{{ $foo := "yes" }}
{{ $bar := cond (eq $foo "yes") 1 (cond (eq $foo "no") 2 3) }}

Taking your example:

{{- range .Site.Data.products }}
    {{- range .features }}
        {{ $emoji := cond (eq . "yes") ":emoji1:" (cond (eq . "no") ":emoji2:" ":emoji3:") }}
    {{- end }}
{{- end }}

Also, that won’t work. The $foo variables defined within if block live only within those blocks… You won’t be able to access $emoji in your example outside of that if .. end.

The working form of that nature would need to use $.Scratch.Set instead.

See golang # 10608, .Scratch doc.

@kaushalmodi I was hoping to avoid using cond as well but on second thought, I probably shouldn’t expect something more concise from Go templates. I think your proposed solution is as elegant as it’s gonna get :grinning: Thanks!

{{ $productEmojis := (dict "yes" "emoji1" "no" "emoji2" ) }}
{{- range .Site.Data.products }}
  {{- range .features }}
  {{ index $productEmojis . | default "emoji3" }}
  {{- end -}}
{{- end -}}

Totally untested, but something like the aboves should work.

Extending that, why not just make the emojis part of .Site.Data.products? Then $productEmojis won’t be needed.

yes/no without quotes is a boolean. Instead {{- if eq . "yes" }} , you should write {{ if . }}

But then the OP won’t get the 3rd “else” case… he needs “yes”, “no”, “partial”… i.e. non-binary choices.

I think it’s better not to use the word-booleans as strings at all. It is better to use any other words as trigger.

1 Like