Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

text/template: add "else with" like "else if" #57646

Closed
willfaught opened this issue Jan 6, 2023 · 12 comments
Closed

text/template: add "else with" like "else if" #57646

willfaught opened this issue Jan 6, 2023 · 12 comments
Labels
early-in-cycle A change that should be done early in the 3 month dev cycle. FixPending Issues that have a fix which has not yet been reviewed or submitted. Proposal Proposal-Accepted
Milestone

Comments

@willfaught
Copy link
Contributor

The text/template doc says:

{{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
	To simplify the appearance of if-else chains, the else action
	of an if may include another if directly; the effect is exactly
	the same as writing
		{{if pipeline}} T1 {{else}}{{if pipeline}} T0 {{end}}{{end}}

However, no such "else with" counterpart exists:

{{with pipeline}} T1 {{else}} T0 {{end}}
	If the value of the pipeline is empty, dot is unaffected and T0
	is executed; otherwise, dot is set to the value of the pipeline
	and T1 is executed.

Which would be very useful:

{{ with .foo.bar.baz }}
  {{ . }}
{{ else with .foo.bar.bez }}
  {{ . }}
{{ else with .foo.bar.biz }}
  {{ . }}
{{ end }}

Currently, we must do the nesting that the else/if doc mentions:

{{ with .foo.bar.baz }}
  {{ . }}
{{ else }}
  {{ with .foo.bar.bez }}
    {{ . }}
  {{ else }}
    {{ with .foo.bar.biz }}
      {{ . }}
    {{ end }}
  {{ end }}
{{ end }}

This gets tiresome.

Mixing the two would also be useful:

{{ if .foo.bar.baz }}
  {{ .quux }}
{{ else with .foo.bar.bez }}
  {{ . }}
{{ else if .foo.bar.biz }}
  {{ .boz }}
{{ end }}
@gopherbot gopherbot added this to the Proposal milestone Jan 6, 2023
@ianlancetaylor
Copy link
Contributor

CC @robpike

@robpike
Copy link
Contributor

robpike commented May 11, 2023

This adds no functionality, it is just a convenience. One may argue that it should be done for consistency, and it's not difficult although every change has costs (and for templates, they are doubled because of html/template). I am not convinced it is worth doing but I am not adamant.

@willfaught
Copy link
Contributor Author

It's just a convenience for if/else too.

This is real code:

{{ with $page.Resources.GetMatch $url }}
    {{ $result = . }}
{{ else }}
    {{ with $page.Resources.Get $url }}
        {{ $result = . }}
    {{ else }}
        {{ with resources.GetMatch $url }}
            {{ $result = . }}
        {{ else }}
            {{ with resources.Get $url }}
                {{ $result = . }}
            {{ else }}
                {{ with resources.GetRemote $url }}
                    {{ $result = . }}
                {{ end }}
            {{ end }}
        {{ end }}
    {{ end }}
{{ end }}

Compare that to:

{{ with $page.Resources.GetMatch $url }}
    {{ $result = . }}
{{ else with $page.Resources.Get $url }}
    {{ $result = . }}
{{ else with resources.GetMatch $url }}
    {{ $result = . }}
{{ else with resources.Get $url }}
    {{ $result = . }}
{{ else with resources.GetRemote $url }}
    {{ $result = . }}
{{ end }}

The difference might seem trivial if you're used to only touching templates occasionally or superficially, but it's a big quality of life improvement for those who spend hours writing non-trivial programs in templates, like authors of Hugo themes/modules.

@seankhliao
Copy link
Member

or you could format your existing code like this

{{ with $page.Resources.GetMatch $url }}
    {{ $result = . }}
{{ else }}{{ with $page.Resources.Get $url }}
    {{ $result = . }}
{{ else }}{{ with resources.GetMatch $url }}
    {{ $result = . }}
{{ else }}{{ with resources.Get $url }}
    {{ $result = . }}
{{ else }}{{ with resources.GetRemote $url }}
    {{ $result = . }}
{{ end }}{{ end }}{{ end }}{{ end }}{{ end }}

@willfaught
Copy link
Contributor Author

It's not the shape of the code that's important, it's the complexity. {{ else }}{{ with is harder to read and reason about. How can you even tell if {{ end }}{{ end }}{{ end }}{{ end }}{{ end }} has enough end's without counting them?

@bep
Copy link
Contributor

bep commented May 12, 2023

@seankhliao there's no sane template formatter (e.g.: https://github.com/NiklasPor/prettier-plugin-go-template) that would format the template source the way you suggest, and throwing a way automatic template formatting is not something anyone would want to do.

I agree with proposal. It should be of tremendous value (save lots of end user time) compared to the time spent on implementing it. I suspect that the people who say "thumbs down" to this are people who really don't spend any amount of time writing Go templates.

@rsc
Copy link
Contributor

rsc commented May 17, 2023

Given the use cases presented here, this seems OK to do.

@rsc
Copy link
Contributor

rsc commented May 17, 2023

This proposal has been added to the active column of the proposals project
and will now be reviewed at the weekly proposal review meetings.
— rsc for the proposal review group

@rsc
Copy link
Contributor

rsc commented May 24, 2023

Based on the discussion above, this proposal seems like a likely accept.
— rsc for the proposal review group

@rsc
Copy link
Contributor

rsc commented May 31, 2023

No change in consensus, so accepted. 🎉
This issue now tracks the work of implementing the proposal.
— rsc for the proposal review group

@rsc rsc changed the title proposal: text/template: add "else with" like "else if" text/template: add "else with" like "else if" May 31, 2023
@rsc rsc modified the milestones: Proposal, Backlog May 31, 2023
@gopherbot
Copy link

Change https://go.dev/cl/545376 mentions this issue: text/template: add "else with" action

@dmitshur dmitshur modified the milestones: Backlog, Go1.23 Dec 4, 2023
@dmitshur dmitshur added early-in-cycle A change that should be done early in the 3 month dev cycle. FixPending Issues that have a fix which has not yet been reviewed or submitted. labels Dec 4, 2023
@gopherbot
Copy link

This issue is currently labeled as early-in-cycle for Go 1.23.
That time is now, so a friendly reminder to look at it again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
early-in-cycle A change that should be done early in the 3 month dev cycle. FixPending Issues that have a fix which has not yet been reviewed or submitted. Proposal Proposal-Accepted
Projects
Status: Accepted
Development

No branches or pull requests

8 participants