Skip to content

Improve readability of generated CUE for text helpers with nested ranges #126

@myitcv

Description

@myitcv

Is your feature request related to a problem? Please describe.

Text helpers with nested range blocks produce deeply nested strings.Join calls embedded inside string interpolations, making the generated CUE hard to read. For example, a helper like:

{{- define "test.helper" -}}
{{- $n := int .Values.replicas -}}
{{- range $i := until $n }}
item {{ $i }}
  {{- range $i := until $n }}
  sub {{ $i }}
  {{- end }}
{{- end }}
{{- end -}}

currently produces:

_test_helper: strings.TrimSpace("\(strings.Join([for _, _range1 in list.Range(0, int & #values.replicas, 1) {
	"\nitem \(_range1)\(strings.Join([for _, _range2 in list.Range(0, int & #values.replicas, 1) {
		"\n  sub \(_range2)"
	}], \"\"))"
}], \"\"))")

Two specific problems:

  1. strings.TrimSpace("\(strings.Join(...))") wraps a function call in a needless string interpolation — should be strings.TrimSpace(strings.Join(...)).
  2. Nested strings.Join embedded inside \(...) interpolations is hard to read. Each additional nesting level makes the code progressively harder to follow.

Describe the solution you'd like

There are several possible approaches, roughly in order of increasing scope:

Option A: + concatenation. When a text helper body part is a complex expression (e.g. a strings.Join call), emit it as "text" + expr instead of "text\(expr)". Also return bare expressions when there is no surrounding text (fixing issue 1). Smallest change, fixes the worst readability issues but doesn't eliminate nesting.

Option B: let declarations. Break nested expressions into named intermediate variables inside the comprehension:

_test_helper: strings.TrimSpace(strings.Join([for _, _range1 in list.Range(0, int & #values.replicas, 1) {
	let _subs = strings.Join([for _, _range2 in list.Range(0, int & #values.replicas, 1) {
		"\n  sub \(_range2)"
	}], "")
	"\nitem \(_range1)" + _subs
}], ""))

Option C: text/template.Execute. Since the helper is Go text/template and we've already typed the values, emit the template nearly verbatim and use CUE's text/template package:

import "text/template"

_test_helper: strings.TrimSpace(text.Execute("""
	{{- range $i := until .n }}
	item {{ $i }}
	  {{- range $i := until .n }}
	  sub {{ $i }}
	  {{- end }}
	{{- end }}
	""", {n: int & #values.replicas}))

Most readable, but CUE's text/template only supports basic Go template actions — no until, no Sprig functions. Would need to pre-compute values or restrict to templates using supported functions.

Option D: List-building with list.FlattenN. Have each range produce list elements and flatten before a single top-level strings.Join.

Describe alternatives you've considered

Option A is the minimal fix and could be done independently of the others. Options B–D are more involved and could be combined (e.g. A+B).

Additional context

See testdata/noverify/text_helper_nested_range.txtar for the current output. Issue 1 (needless interpolation wrapping) affects all single-expression text helper bodies, not just nested ranges.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions