Problem
Currently, template variables declared in the prompts section (using {{ $var := ... }}) are not accessible in the args section. Each section gets its own template execution context, so computed values must be re-computed or accessed via promptValue/flagValue.
This leads to verbose and repetitive code when you want to compute a value once and use it in multiple places.
Current Workaround
'kv [bucket]':
flags:
context:
effect: "{{ .flag }}"
prompts: |
{{ $flagCtx := flagValue "context" }}
{{ $envCtx := env "NATS_CONTEXT" }}
{{ if not $flagCtx }}
{{ if $envCtx }}
{{ prompt "ctx" "NATS context:" $envCtx }}
{{ else }}
{{ $contexts := splitList "\n" (run "bash" `nats context ls`) }}
{{ prompt "ctx" "NATS context:" $contexts }}
{{ end }}
{{ end }}
{{ $ctx := or $flagCtx (promptValue "ctx") }} # Can't use this in args!
{{ prompt "search" "Search:" "" }}
{{ $keys := run "bash" (printf "nats --context=%s kv ls %s" $ctx (arg 0)) }}
{{ prompt "key" "Select key:" (splitList "\n" $keys) }}
args:
- |
# Must re-compute $ctx here because template variables don't persist
CTX="{{ or (flagValue "context") (promptValue "ctx") }}"
KEY="{{ promptValue "key" }}"
nats --context="$CTX" kv get bucket "$KEY"
Proposed Solution
Add set and get template functions that store/retrieve values in a shared context that persists across prompts, args, and cmd sections.
Example Usage
'kv [bucket]':
flags:
context:
effect: "{{ .flag }}"
prompts: |
{{ $flagCtx := flagValue "context" }}
{{ $envCtx := env "NATS_CONTEXT" }}
{{ if $flagCtx }}
{{ set "ctx" $flagCtx }}
{{ else if $envCtx }}
{{ set "ctx" (prompt "ctx" "NATS context:" $envCtx) }}
{{ else }}
{{ $contexts := splitList "\n" (run "bash" `nats context ls`) }}
{{ set "ctx" (prompt "ctx" "NATS context:" $contexts) }}
{{ end }}
{{ prompt "search" "Search:" "" }}
{{ $keys := run "bash" (printf "nats --context=%s kv ls %s" (get "ctx") (arg 0)) }}
{{ prompt "key" "Select key:" (splitList "\n" $keys) }}
args:
- |
CTX="{{ get "ctx" }}"
KEY="{{ promptValue "key" }}"
nats --context="$CTX" kv get bucket "$KEY"
Implementation Suggestion
In pkg/summon/driver.go, add a shared state map:
type Driver struct {
// ... existing fields
templateState map[string]interface{} // NEW: shared state across template renders
}
In pkg/summon/template.go, add the functions:
func summonFuncMap(d *Driver) template.FuncMap {
return template.FuncMap{
// ... existing functions
"set": func(key string, value interface{}) string {
if d.templateState == nil {
d.templateState = make(map[string]interface{})
}
d.templateState[key] = value
return "" // Return empty string so it doesn't output anything
},
"get": func(key string) interface{} {
if d.templateState == nil {
return ""
}
return d.templateState[key]
},
}
}
Benefits
- DRY: Compute values once, use everywhere
- Cleaner templates: Less repetition of
or (flagValue "x") (promptValue "x") patterns
- Preamble pattern: Could enable a
preamble section for setup logic that runs before prompts
- Backward compatible: Existing configs continue to work unchanged
Alternatives Considered
-
Merge prompts and args into single template execution: Would break existing behavior where prompts run interactively before args are rendered.
-
Use promptValue for everything: Works but requires calling prompt even when you don't want user interaction, and doesn't work when the value comes from a flag.
Related
This would complement the existing promptValue function which already provides a form of shared state (but only for prompt results).
Problem
Currently, template variables declared in the
promptssection (using{{ $var := ... }}) are not accessible in theargssection. Each section gets its own template execution context, so computed values must be re-computed or accessed viapromptValue/flagValue.This leads to verbose and repetitive code when you want to compute a value once and use it in multiple places.
Current Workaround
Proposed Solution
Add
setandgettemplate functions that store/retrieve values in a shared context that persists acrossprompts,args, andcmdsections.Example Usage
Implementation Suggestion
In
pkg/summon/driver.go, add a shared state map:In
pkg/summon/template.go, add the functions:Benefits
or (flagValue "x") (promptValue "x")patternspreamblesection for setup logic that runs before promptsAlternatives Considered
Merge prompts and args into single template execution: Would break existing behavior where prompts run interactively before args are rendered.
Use
promptValuefor everything: Works but requires callingprompteven when you don't want user interaction, and doesn't work when the value comes from a flag.Related
This would complement the existing
promptValuefunction which already provides a form of shared state (but only for prompt results).