diff --git a/bash_completions.go b/bash_completions.go index 236dee67..5b3e855b 100644 --- a/bash_completions.go +++ b/bash_completions.go @@ -421,6 +421,9 @@ func writeFlags(cmd *Command, w io.Writer) error { localNonPersistentFlags := cmd.LocalNonPersistentFlags() var visitErr error cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) { + if nonCompletableFlag(flag) { + return + } if err := writeFlag(flag, w); err != nil { visitErr = err return @@ -442,6 +445,9 @@ func writeFlags(cmd *Command, w io.Writer) error { return visitErr } cmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) { + if nonCompletableFlag(flag) { + return + } if err := writeFlag(flag, w); err != nil { visitErr = err return @@ -468,6 +474,9 @@ func writeRequiredFlag(cmd *Command, w io.Writer) error { flags := cmd.NonInheritedFlags() var visitErr error flags.VisitAll(func(flag *pflag.Flag) { + if nonCompletableFlag(flag) { + return + } for key := range flag.Annotations { switch key { case BashCompOneRequiredFlag: @@ -574,6 +583,10 @@ func (cmd *Command) GenBashCompletion(w io.Writer) error { return postscript(w, cmd.Name()) } +func nonCompletableFlag(flag *pflag.Flag) bool { + return flag.Hidden || len(flag.Deprecated) > 0 +} + func (cmd *Command) GenBashCompletionFile(filename string) error { outFile, err := os.Create(filename) if err != nil { diff --git a/bash_completions_test.go b/bash_completions_test.go index 6957f8bd..5f4cb4d1 100644 --- a/bash_completions_test.go +++ b/bash_completions_test.go @@ -138,3 +138,43 @@ func TestBashCompletions(t *testing.T) { t.Fatalf("shellcheck failed: %v", err) } } + +func TestBashCompletionHiddenFlag(t *testing.T) { + var cmdTrue = &Command{ + Use: "does nothing", + Run: func(cmd *Command, args []string) {}, + } + + const flagName = "hidden-foo-bar-baz" + + var flagValue bool + cmdTrue.Flags().BoolVar(&flagValue, flagName, false, "hidden flag") + cmdTrue.Flags().MarkHidden(flagName) + + out := new(bytes.Buffer) + cmdTrue.GenBashCompletion(out) + bashCompletion := out.String() + if strings.Contains(bashCompletion, flagName) { + t.Error("expected completion to not include %q flag: Got %v", flagName, bashCompletion) + } +} + +func TestBashCompletionDeprecatedFlag(t *testing.T) { + var cmdTrue = &Command{ + Use: "does nothing", + Run: func(cmd *Command, args []string) {}, + } + + const flagName = "deprecated-foo-bar-baz" + + var flagValue bool + cmdTrue.Flags().BoolVar(&flagValue, flagName, false, "hidden flag") + cmdTrue.Flags().MarkDeprecated(flagName, "use --does-not-exist instead") + + out := new(bytes.Buffer) + cmdTrue.GenBashCompletion(out) + bashCompletion := out.String() + if strings.Contains(bashCompletion, flagName) { + t.Errorf("expected completion to not include %q flag: Got %v", flagName, bashCompletion) + } +}