cli/command/completion: change EnvVarNames to return a cobra.CompletionFunc

It's adding a slight indirection by constructing a function when called,
but makes the completion functions more consistent, the signature easier
to read, and making the return type a [cobra.CompletionFunc] makes it
more transparent what it's intended for, and helps discovery of functions
that provide completion.

[cobra.CompletionFunc]: https://pkg.go.dev/github.com/spf13/cobra#CompletionFunc

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn
2025-09-10 12:06:39 +02:00
parent c5467b5556
commit d18af47d0f
6 changed files with 14 additions and 12 deletions
+9 -7
View File
@@ -116,14 +116,16 @@ func NetworkNames(dockerCLI APIClientProvider) cobra.CompletionFunc {
// export MY_VAR=hello
// docker run --rm --env MY_VAR alpine printenv MY_VAR
// hello
func EnvVarNames(_ *cobra.Command, _ []string, _ string) (names []string, _ cobra.ShellCompDirective) {
envs := os.Environ()
names = make([]string, 0, len(envs))
for _, env := range envs {
name, _, _ := strings.Cut(env, "=")
names = append(names, name)
func EnvVarNames() cobra.CompletionFunc {
return func(_ *cobra.Command, _ []string, _ string) (names []string, _ cobra.ShellCompDirective) {
envs := os.Environ()
names = make([]string, 0, len(envs))
for _, env := range envs {
name, _, _ := strings.Cut(env, "=")
names = append(names, name)
}
return names, cobra.ShellCompDirectiveNoFileComp
}
return names, cobra.ShellCompDirectiveNoFileComp
}
// FromList offers completion for the given list of options.
+1 -1
View File
@@ -176,7 +176,7 @@ func TestCompleteEnvVarNames(t *testing.T) {
"ENV_A": "hello-a",
"ENV_B": "hello-b",
})
values, directives := EnvVarNames(nil, nil, "")
values, directives := EnvVarNames()(nil, nil, "")
assert.Check(t, is.Equal(directives&cobra.ShellCompDirectiveNoFileComp, cobra.ShellCompDirectiveNoFileComp), "Should not perform file completion")
sort.Strings(values)
+1 -1
View File
@@ -122,7 +122,7 @@ func addCompletions(cmd *cobra.Command, dockerCLI completion.APIClientProvider)
_ = cmd.RegisterFlagCompletionFunc("cap-add", completeLinuxCapabilityNames)
_ = cmd.RegisterFlagCompletionFunc("cap-drop", completeLinuxCapabilityNames)
_ = cmd.RegisterFlagCompletionFunc("cgroupns", completeCgroupns())
_ = cmd.RegisterFlagCompletionFunc("env", completion.EnvVarNames)
_ = cmd.RegisterFlagCompletionFunc("env", completion.EnvVarNames())
_ = cmd.RegisterFlagCompletionFunc("env-file", completion.FileNames)
_ = cmd.RegisterFlagCompletionFunc("ipc", completeIpc(dockerCLI))
_ = cmd.RegisterFlagCompletionFunc("link", completeLink(dockerCLI))
+1 -1
View File
@@ -78,7 +78,7 @@ func newExecCommand(dockerCLI command.Cli) *cobra.Command {
flags.StringVarP(&options.Workdir, "workdir", "w", "", "Working directory inside the container")
flags.SetAnnotation("workdir", "version", []string{"1.35"})
_ = cmd.RegisterFlagCompletionFunc("env", completion.EnvVarNames)
_ = cmd.RegisterFlagCompletionFunc("env", completion.EnvVarNames())
_ = cmd.RegisterFlagCompletionFunc("env-file", completion.FileNames)
return cmd
+1 -1
View File
@@ -82,7 +82,7 @@ func newCreateCommand(dockerCLI command.Cli) *cobra.Command {
// _ = cmd.RegisterFlagCompletionFunc(flagStopSignal, completeSignals)
_ = cmd.RegisterFlagCompletionFunc(flagMode, completion.FromList("replicated", "global", "replicated-job", "global-job"))
_ = cmd.RegisterFlagCompletionFunc(flagEnv, completion.EnvVarNames) // TODO(thaJeztah): flagEnvRemove (needs to read current env-vars on the service)
_ = cmd.RegisterFlagCompletionFunc(flagEnv, completion.EnvVarNames()) // TODO(thaJeztah): flagEnvRemove (needs to read current env-vars on the service)
_ = cmd.RegisterFlagCompletionFunc(flagEnvFile, completion.FileNames)
_ = cmd.RegisterFlagCompletionFunc(flagNetwork, completion.NetworkNames(dockerCLI))
_ = cmd.RegisterFlagCompletionFunc(flagRestartCondition, completion.FromList("none", "on-failure", "any"))
+1 -1
View File
@@ -121,7 +121,7 @@ func newUpdateCommand(dockerCLI command.Cli) *cobra.Command {
// _ = cmd.RegisterFlagCompletionFunc(flagCapDrop, completeLinuxCapabilityNames)
// _ = cmd.RegisterFlagCompletionFunc(flagStopSignal, completeSignals)
_ = cmd.RegisterFlagCompletionFunc(flagEnvAdd, completion.EnvVarNames)
_ = cmd.RegisterFlagCompletionFunc(flagEnvAdd, completion.EnvVarNames())
// TODO(thaJeztah): flagEnvRemove (needs to read current env-vars on the service)
_ = cmd.RegisterFlagCompletionFunc("image", completion.ImageNames(dockerCLI, -1))
_ = cmd.RegisterFlagCompletionFunc(flagNetworkAdd, completion.NetworkNames(dockerCLI))