Skip to content

Commit

Permalink
ActiveHelp env var per program
Browse files Browse the repository at this point in the history
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 <marc.khouzam@montreal.ca>
  • Loading branch information
marckhouzam committed Oct 9, 2021
1 parent 4781d40 commit 447ffb9
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 18 deletions.
15 changes: 10 additions & 5 deletions active_help.md
Expand Up @@ -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 `<PROGRAM>_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<ENTER>
$ HELM_ACTIVE_HELP=1 bin/helm __complete install wordpress bitnami/h<ENTER>
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<ENTER>
$ HELM_ACTIVE_HELP=0 bin/helm __complete install wordpress bitnami/h<ENTER>
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
```
4 changes: 2 additions & 2 deletions bash_completions.go
Expand Up @@ -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}
Expand Down Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions bash_completionsV2.go
Expand Up @@ -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}
Expand Down Expand Up @@ -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.
Expand Down
21 changes: 18 additions & 3 deletions completions.go
Expand Up @@ -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
Expand All @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions fish_completions.go
Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions powershell_completions.go
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions zsh_completions.go
Expand Up @@ -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.
Expand Down Expand Up @@ -283,5 +283,5 @@ fi
`, cmd.Name(), compCmd,
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs,
activeHelpMarker, cmd.ActiveHelpConfig))
activeHelpMarker, activeHelpEnvVar(cmd.Name()), cmd.ActiveHelpConfig))
}

0 comments on commit 447ffb9

Please sign in to comment.