fix: interpolate ${env} in help text for positional arguments#595
fix: interpolate ${env} in help text for positional arguments#595lawrence3699 wants to merge 1 commit intoalecthomas:masterfrom
Conversation
Positional arguments with an env tag could not use ${env} in their help
text, causing a panic: "undefined variable ${env}". This happened because
the env variable was only populated for flags (value.Flag != nil), not
for positional arguments.
Populate the env variable from value.Tag.Envs for positional arguments
and merge updatedVars into vars explicitly to work around an optimization
in interpolate() that skips merging when values equal missing map keys.
Fixes alecthomas#556
There was a problem hiding this comment.
Pull request overview
Fixes a construction-time panic when ${env} is used in the help text for positional arguments by ensuring the env interpolation variable is populated for non-flag values and that updated interpolation variables are reliably visible during help interpolation.
Changes:
- Populate
updatedVars["env"]for positional arguments usingvalue.Tag.Envs. - Explicitly merge
updatedVarsintovarsbefore interpolatingvalue.Helpto avoid the “missing key + empty string” merge edge case. - Add regression tests covering positional args with env set, env unset, and multiple envs.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
kong.go |
Updates interpolation logic for positional-argument help to define ${env} and avoid merge-skipping edge cases. |
issue556_test.go |
Adds regression tests ensuring ${env} in positional help interpolates correctly across key scenarios. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } else { | ||
| updatedVars["env"] = "" | ||
| if len(value.Tag.Envs) != 0 { | ||
| updatedVars["env"] = value.Tag.Envs[0] | ||
| } |
There was a problem hiding this comment.
In the positional-argument branch, updatedVars["env"] is derived from value.Tag.Envs without interpolating the env tag values first. For flags, env tag values are interpolated (value.Flag.Envs[i] = interpolate(...)) and then copied into value.Tag.Envs, so env:"${someVar}" works there. For positional arguments, env:"${someVar}" would currently leave ${someVar} unexpanded (both for ${env} in help and for later env lookup in Value.Reset). Consider interpolating value.Tag.Envs in the value.Flag == nil branch (similar to the flag path) before selecting the first env name.
| // Merge updatedVars into vars explicitly because interpolate() skips | ||
| // the merge when all updatedVars values equal the zero value of missing | ||
| // map keys (e.g. env=""). | ||
| vars = vars.CloneWith(updatedVars) | ||
| value.Help, err = interpolate(value.Help, vars, nil) |
There was a problem hiding this comment.
This fix works around interpolate() skipping the updatedVars merge when keys are missing and the updated value is "" by explicitly cloning vars before interpolating help. However, the same interpolate() behavior can still affect other calls in this function that pass updatedVars directly (eg env name interpolation and placeholder interpolation) whenever any of the updated vars are "" and the corresponding key is absent from vars. A more robust fix would be to adjust interpolate() to merge when a key is missing (not only when vars[key] != val), which would remove the need for special-case merges here and prevent similar edge cases elsewhere.
Fixes #556.
Problem: Using
${env}in the help text of a positional argument (arg:"") panics with "undefined variable ${env}", while it works fine for flags.Cause:
interpolateValue()only populated theenvvariable inupdatedVarswhenvalue.Flag != nil. Positional arguments havevalue.Flag == nil, soenvwas never set.Fix: Populate
envfromvalue.Tag.Envsfor positional arguments. Also mergeupdatedVarsintovarsexplicitly before interpolating help, sinceinterpolate()skips the merge when values equal missing map keys (both"").After:
${env}resolves to the first env var name for positional args (or""if no env tag), matching flag behavior.All existing tests pass; added regression tests for the three cases (env set, env unset, multiple envs).