From 447ffb9db670745d500909023f09c49bdc47b059 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Sat, 9 Oct 2021 12:39:04 -0400 Subject: [PATCH] ActiveHelp env var per program Use an environment variable containing the program name to set the ActiveHelp configuration. This is important because different programs can use different configurations, so a global variable would not work. But we also provide a global COBRA_ACTIVE_HELP environment variable which can only be set to 0 and which will disable Active Help for ALL programs based on Cobra. Signed-off-by: Marc Khouzam --- active_help.md | 15 ++++++++++----- bash_completions.go | 4 ++-- bash_completionsV2.go | 4 ++-- completions.go | 21 ++++++++++++++++++--- fish_completions.go | 4 ++-- powershell_completions.go | 4 ++-- zsh_completions.go | 4 ++-- 7 files changed, 38 insertions(+), 18 deletions(-) diff --git a/active_help.md b/active_help.md index 7a15171b17..86d23f675e 100644 --- a/active_help.md +++ b/active_help.md @@ -124,26 +124,31 @@ ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([ return comps, cobra.ShellCompDirectiveNoFileComp }, ``` -**Note**: If the string "0" is used for `cmd.Root().ActiveHelpConfig`, it will automatically be handled by Cobra and will completely disable all Active Help output (even if some output was specified by the program using the `cobra.AppendActiveHelp(...)` function). Using "0" can simplify your code in situations where you want to blindly disable Active Help. +**Note 1**: If the string "0" is used for `cmd.Root().ActiveHelpConfig`, it will automatically be handled by Cobra and will completely disable all Active Help output (even if some output was specified by the program using the `cobra.AppendActiveHelp(...)` function). Using "0" can simplify your code in situations where you want to blindly disable Active Help. -**Note**: Cobra transparently passes the `cmd.ActiveHelpConfig` string you specified back to your program when completion is invoked. You can therefore define any scheme you choose for your program; you are not limited to using integer levels for the configuration of Active Help. +**Note 2**: Cobra transparently passes the `cmd.ActiveHelpConfig` string you specified back to your program when completion is invoked. You can therefore define any scheme you choose for your program; you are not limited to using integer levels for the configuration of Active Help. However, the reserved "0" value can also be sent to you program and you should be prepared for it. ## Debugging Active Help Debugging your Active Help code is done in the same way as debugging the dynamic completion code, which is with Cobra's hidden `__complete` command. Please refer to [debugging shell completion](shell_completions.md#debugging) for details. -When debugging with the `__complete` command, if you want to specify different Active Help configurations, you should use the `COBRA_ACTIVEHELP` environment variable (as is done by the generated completion scripts). For example, we can test deactivating some Active Help as shown below: +When debugging with the `__complete` command, if you want to specify different Active Help configurations, you should use the active help environment variable (as you can find in the generated completion scripts). That variable is named `_ACTIVE_HELP` where any `-` is replaced by an `_`. For example, we can test deactivating some Active Help as shown below: ``` -$ COBRA_ACTIVEHELP=1 bin/helm __complete install wordpress bitnami/h +$ HELM_ACTIVE_HELP=1 bin/helm __complete install wordpress bitnami/h bitnami/haproxy bitnami/harbor _activeHelp_ WARNING: cannot re-use a name that is still in use :0 Completion ended with directive: ShellCompDirectiveDefault -$ COBRA_ACTIVEHELP=0 bin/helm __complete install wordpress bitnami/h +$ HELM_ACTIVE_HELP=0 bin/helm __complete install wordpress bitnami/h bitnami/haproxy bitnami/harbor :0 Completion ended with directive: ShellCompDirectiveDefault ``` + +If a user wants to disable Active Help for every single program based on Cobra, the global environment variable `COBRA_ACTIVE_HELP` can be used as follows: +``` +export COBRA_ACTIVE_HELP=0 +``` \ No newline at end of file diff --git a/bash_completions.go b/bash_completions.go index 4acfc6e58e..742dc60aec 100644 --- a/bash_completions.go +++ b/bash_completions.go @@ -74,7 +74,7 @@ __%[1]s_handle_go_custom_completion() # Calling ${words[0]} instead of directly %[1]s allows to handle aliases args=("${words[@]:1}") # Disable ActiveHelp which is not supported for bash completion v1 - requestComp="COBRA_ACTIVEHELP=0 ${words[0]} %[2]s ${args[*]}" + requestComp="%[8]s=0 ${words[0]} %[2]s ${args[*]}" lastParam=${words[$((${#words[@]}-1))]} lastChar=${lastParam:$((${#lastParam}-1)):1} @@ -378,7 +378,7 @@ __%[1]s_handle_word() `, name, ShellCompNoDescRequestCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs)) + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name))) } func writePostscript(buf io.StringWriter, name string) { diff --git a/bash_completionsV2.go b/bash_completionsV2.go index b69fd98f70..871728f65f 100644 --- a/bash_completionsV2.go +++ b/bash_completionsV2.go @@ -45,7 +45,7 @@ __%[1]s_get_completion_results() { # Prepare the command to request completions for the program. # Calling ${words[0]} instead of directly %[1]s allows to handle aliases args=("${words[@]:1}") - requestComp="COBRA_ACTIVEHELP=${COBRA_ACTIVEHELP-%[9]s} ${words[0]} %[2]s ${args[*]}" + requestComp="%[9]s=${%[9]s-%[10]s} ${words[0]} %[2]s ${args[*]}" lastParam=${words[$((${#words[@]}-1))]} lastChar=${lastParam:$((${#lastParam}-1)):1} @@ -316,7 +316,7 @@ fi `, cmd.Name(), compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, - activeHelpMarker, cmd.Root().ActiveHelpConfig)) + activeHelpMarker, activeHelpEnvVar(cmd.Name()), cmd.Root().ActiveHelpConfig)) } // GenBashCompletionFileV2 generates Bash completion version 2. diff --git a/completions.go b/completions.go index c6a46beae2..ddc049d4b0 100644 --- a/completions.go +++ b/completions.go @@ -82,7 +82,10 @@ const ( compCmdNoDescFlagDesc = "disable completion descriptions" compCmdNoDescFlagDefault = false - activeHelpMarker = "_activeHelp_ " + activeHelpMarker = "_activeHelp_ " + activeHelpEnvVarSuffix = "_ACTIVE_HELP" + activeHelpGlobalEnvVar = "COBRA_ACTIVE_HELP" + activeHelpGlobalDisable = "0" ) // CompletionOptions are the options to control shell completion @@ -97,6 +100,11 @@ type CompletionOptions struct { DisableDescriptions bool } +func activeHelpEnvVar(name string) string { + activeHelpEnvVar := strings.ToUpper(fmt.Sprintf("%s%s", name, activeHelpEnvVarSuffix)) + return strings.ReplaceAll(activeHelpEnvVar, "-", "_") +} + // NoFileCompletions can be used to disable file completion for commands that should // not trigger file completions. func NoFileCompletions(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { @@ -181,7 +189,7 @@ func (c *Command) initCompleteCmd(args []string) { noDescriptions := (cmd.CalledAs() == ShellCompNoDescRequestCmd) for _, comp := range completions { - if finalCmd.ActiveHelpConfig == "0" { + if finalCmd.ActiveHelpConfig == activeHelpGlobalDisable { // Remove all activeHelp entries in this case if strings.HasPrefix(comp, activeHelpMarker) { continue @@ -440,7 +448,14 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi // First set the ActiveHelpConfig value to make it available when // calling the completion function. We also set it on the root, // just in case users try to access it from there. - finalCmd.ActiveHelpConfig = os.Getenv("COBRA_ACTIVEHELP") + // First check the global environment variable to see if it is + // disabling active help, and if it is not, use the program-specific var. + activeHelpVar := os.Getenv(activeHelpGlobalEnvVar) + if activeHelpVar != activeHelpGlobalDisable { + activeHelpVar = os.Getenv(activeHelpEnvVar(c.Root().Name())) + } + + finalCmd.ActiveHelpConfig = activeHelpVar finalCmd.Root().ActiveHelpConfig = finalCmd.ActiveHelpConfig comps, directive = completionFn(finalCmd, finalArgs, toComplete) diff --git a/fish_completions.go b/fish_completions.go index 8a0fafc6a8..f27a01ceab 100644 --- a/fish_completions.go +++ b/fish_completions.go @@ -39,7 +39,7 @@ function __%[1]s_perform_completion __%[1]s_debug "last arg: $lastArg" # Disable ActiveHelp which is not supported for fish shell - set -l requestComp "COBRA_ACTIVEHELP=0 $args[1] %[3]s $args[2..-1] $lastArg" + set -l requestComp "%[9]s=0 $args[1] %[3]s $args[2..-1] $lastArg" __%[1]s_debug "Calling $requestComp" set -l results (eval $requestComp 2> /dev/null) @@ -197,7 +197,7 @@ complete -c %[2]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results' `, nameForVar, name, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs)) + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name))) } // GenFishCompletion generates fish completion file and writes to the passed writer. diff --git a/powershell_completions.go b/powershell_completions.go index a6f4e59982..e28920097e 100644 --- a/powershell_completions.go +++ b/powershell_completions.go @@ -92,7 +92,7 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock { __%[1]s_debug "Calling $RequestComp" # First disable ActiveHelp which is not supported for Powershell - $env:COBRA_ACTIVEHELP=0 + $env:%[8]s=0 #call the command store the output in $out and redirect stderr and stdout to null # $Out is an array contains each line per element @@ -245,7 +245,7 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock { } `, name, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs)) + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name))) } func (c *Command) genPowerShellCompletion(w io.Writer, includeDesc bool) error { diff --git a/zsh_completions.go b/zsh_completions.go index 6e124672ac..babadaaaaf 100644 --- a/zsh_completions.go +++ b/zsh_completions.go @@ -121,7 +121,7 @@ _%[1]s() fi # Prepare the command to obtain completions - requestComp="COBRA_ACTIVEHELP=${COBRA_ACTIVEHELP-%[9]s} ${words[1]} %[2]s ${words[2,-1]}" + requestComp="%[9]s=${%[9]s-%[10]s} ${words[1]} %[2]s ${words[2,-1]}" if [ "${lastChar}" = "" ]; then # If the last parameter is complete (there is a space following it) # We add an extra empty parameter so we can indicate this to the go completion code. @@ -283,5 +283,5 @@ fi `, cmd.Name(), compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, - activeHelpMarker, cmd.ActiveHelpConfig)) + activeHelpMarker, activeHelpEnvVar(cmd.Name()), cmd.ActiveHelpConfig)) }