From 63a003230193541174782fc348fee37960c3f99d Mon Sep 17 00:00:00 2001 From: danmx Date: Thu, 18 Aug 2022 10:28:13 +0200 Subject: [PATCH 1/2] feat(command): adding args to use line Signed-off-by: danmx --- command.go | 17 ++++++-- command_test.go | 100 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 4 deletions(-) diff --git a/command.go b/command.go index 909d8585..df850b7d 100644 --- a/command.go +++ b/command.go @@ -242,6 +242,10 @@ type Command struct { // line of a command when printing help or generating docs DisableFlagsInUseLine bool + // DisableArgsInUseLine will disable the addition of [args] to the usage + // line of a command when printing help or generating docs + DisableArgsInUseLine bool + // DisableSuggestions disables the suggestions based on Levenshtein distance // that go along with 'unknown command' messages. DisableSuggestions bool @@ -1415,12 +1419,12 @@ func (c *Command) UseLine() string { } else { useline = c.Use } - if c.DisableFlagsInUseLine { - return useline - } - if c.HasAvailableFlags() && !strings.Contains(useline, "[flags]") { + if c.HasAvailableFlags() && !strings.Contains(useline, "[flags]") && !c.DisableFlagsInUseLine { useline += " [flags]" } + if c.HasAvailableArgs() && !strings.Contains(useline, "[args]") && !c.DisableArgsInUseLine { + useline += " [args]" + } return useline } @@ -1764,6 +1768,11 @@ func (c *Command) HasAvailableInheritedFlags() bool { return c.InheritedFlags().HasAvailableFlags() } +// HasAvailableArgs checks if the command has non-nil Args. +func (c *Command) HasAvailableArgs() bool { + return c.Args != nil +} + // Flag climbs up the command tree looking for matching flag. func (c *Command) Flag(name string) (flag *flag.Flag) { flag = c.Flags().Lookup(name) diff --git a/command_test.go b/command_test.go index 4afb7f7b..445e26a6 100644 --- a/command_test.go +++ b/command_test.go @@ -2768,3 +2768,103 @@ func TestUnknownFlagShouldReturnSameErrorRegardlessOfArgPosition(t *testing.T) { }) } } + +func TestUseLine(t *testing.T) { + var testFlagSet pflag.FlagSet + testFlagSet.AddFlag(&pflag.Flag{ + Name: "flag_0", + }) + testArgs := func(cmd *Command, args []string) error { return nil } + testCases := []struct { + Cmd *Command + UseLine string + }{ + { + &Command{ + DisableFlagsInUseLine: true, + DisableArgsInUseLine: true, + parent: &Command{ + Use: "parent_use_0", + }, + flags: &testFlagSet, + Args: testArgs, + Use: "use_0", + }, + "parent_use_0 use_0", + }, + { + &Command{ + DisableFlagsInUseLine: false, + DisableArgsInUseLine: false, + parent: &Command{ + Use: "parent_use_1", + }, + Use: "use_1", + }, + "parent_use_1 use_1", + }, + { + &Command{ + DisableFlagsInUseLine: false, + DisableArgsInUseLine: false, + Use: "use_2", + }, + "use_2", + }, + { + &Command{ + DisableFlagsInUseLine: false, + DisableArgsInUseLine: true, + parent: &Command{ + Use: "parent_use_3", + }, + flags: &testFlagSet, + Args: testArgs, + Use: "use_3", + }, + "parent_use_3 use_3 [flags]", + }, + { + &Command{ + DisableFlagsInUseLine: false, + DisableArgsInUseLine: false, + flags: &testFlagSet, + Args: testArgs, + Use: "use_4", + }, + "use_4 [flags] [args]", + }, + { + &Command{ + DisableFlagsInUseLine: false, + DisableArgsInUseLine: false, + Args: testArgs, + Use: "use_5", + }, + "use_5 [args]", + }, + { + &Command{ + DisableFlagsInUseLine: false, + DisableArgsInUseLine: false, + flags: &testFlagSet, + Use: "[flags] use_6", + }, + "[flags] use_6", + }, + { + &Command{ + DisableFlagsInUseLine: false, + DisableArgsInUseLine: false, + Args: testArgs, + Use: "[args] use_7", + }, + "[args] use_7", + }, + } + for i, tc := range testCases { + if tc.Cmd.UseLine() != tc.UseLine { + t.Errorf("test case no. %d mismatch.\nResult: %s\nExpect: %s", i, tc.Cmd.UseLine(), tc.UseLine) + } + } +} From 86e879bfa910e4b16e7d86abb3647536b79c3716 Mon Sep 17 00:00:00 2001 From: danmx Date: Sun, 24 Sep 2023 21:16:52 +0200 Subject: [PATCH 2/2] fix(command): struct to pass maligned linter check Signed-off-by: danmx --- command.go | 148 ++++++++++++++++++++++++++++------------------------- 1 file changed, 78 insertions(+), 70 deletions(-) diff --git a/command.go b/command.go index df850b7d..cd29d6c5 100644 --- a/command.go +++ b/command.go @@ -46,6 +46,36 @@ type Group struct { // you to define the usage and description as part of your command // definition to ensure usability. type Command struct { + // Aliases is an array of aliases that can be used instead of the first word in Use. + Aliases []string + + // SuggestFor is an array of command names for which this command will be suggested - + // similar to aliases but only suggests. + SuggestFor []string + + // ValidArgs is list of all valid non-flag arguments that are accepted in shell completions + ValidArgs []string + + // ArgAliases is List of aliases for ValidArgs. + // These are not suggested to the user in the shell completion, + // but accepted if entered manually. + ArgAliases []string + + // groups for subcommands + commandgroups []*Group + + // args is actual args parsed from flags. + args []string + + // commandCalledAs is the name or alias value used to call this command. + commandCalledAs struct { + name string + called bool + } + + // commands is the list of commands supported by this program. + commands []*Command + // Use is the one-line usage message. // Recommended syntax is as follows: // [ ] identifies an optional argument. Arguments that are not enclosed in brackets are required. @@ -57,13 +87,6 @@ type Command struct { // Example: add [-F file | -D dir]... [-f format] profile Use string - // Aliases is an array of aliases that can be used instead of the first word in Use. - Aliases []string - - // SuggestFor is an array of command names for which this command will be suggested - - // similar to aliases but only suggests. - SuggestFor []string - // Short is the short description shown in the 'help' output. Short string @@ -76,8 +99,44 @@ type Command struct { // Example is examples of how to use the command. Example string - // ValidArgs is list of all valid non-flag arguments that are accepted in shell completions - ValidArgs []string + // BashCompletionFunction is custom bash functions used by the legacy bash autocompletion generator. + // For portability with other shells, it is recommended to instead use ValidArgsFunction + BashCompletionFunction string + + // Deprecated defines, if this command is deprecated and should print this string when used. + Deprecated string + + // Version defines the version for this command. If this value is non-empty and the command does not + // define a "version" flag, a "version" boolean flag will be added to the command and, if specified, + // will print content of the "Version" variable. A shorthand "v" flag will also be added if the + // command does not define one. + Version string + + // usageTemplate is usage template defined by user. + usageTemplate string + + // helpTemplate is help template defined by user. + helpTemplate string + + // helpCommandGroupID is the group id for the helpCommand + helpCommandGroupID string + + // completionCommandGroupID is the group id for the completion command + completionCommandGroupID string + + // versionTemplate is the version template defined by user. + versionTemplate string + + // errPrefix is the error message prefix defined by user. + errPrefix string + + // inReader is a reader defined by the user that replaces stdin + inReader io.Reader + // outWriter is a writer defined by the user that replaces stdout + outWriter io.Writer + // errWriter is a writer defined by the user that replaces stderr + errWriter io.Writer + // ValidArgsFunction is an optional function that provides valid non-flag arguments for shell completion. // It is a dynamic version of using ValidArgs. // Only one of ValidArgs and ValidArgsFunction can be used for a command. @@ -86,28 +145,10 @@ type Command struct { // Expected arguments Args PositionalArgs - // ArgAliases is List of aliases for ValidArgs. - // These are not suggested to the user in the shell completion, - // but accepted if entered manually. - ArgAliases []string - - // BashCompletionFunction is custom bash functions used by the legacy bash autocompletion generator. - // For portability with other shells, it is recommended to instead use ValidArgsFunction - BashCompletionFunction string - - // Deprecated defines, if this command is deprecated and should print this string when used. - Deprecated string - // Annotations are key/value pairs that can be used by applications to identify or // group commands. Annotations map[string]string - // Version defines the version for this command. If this value is non-empty and the command does not - // define a "version" flag, a "version" boolean flag will be added to the command and, if specified, - // will print content of the "Version" variable. A shorthand "v" flag will also be added if the - // command does not define one. - Version string - // The *Run functions are executed in the following order: // * PersistentPreRun() // * PreRun() @@ -139,11 +180,6 @@ type Command struct { // PersistentPostRunE: PersistentPostRun but returns an error. PersistentPostRunE func(cmd *Command, args []string) error - // groups for subcommands - commandgroups []*Group - - // args is actual args parsed from flags. - args []string // flagErrorBuf contains all error messages from pflag. flagErrorBuf *bytes.Buffer // flags is full set of flags. @@ -162,36 +198,28 @@ type Command struct { // usageFunc is usage func defined by user. usageFunc func(*Command) error - // usageTemplate is usage template defined by user. - usageTemplate string // flagErrorFunc is func defined by user and it's called when the parsing of // flags returns an error. flagErrorFunc func(*Command, error) error - // helpTemplate is help template defined by user. - helpTemplate string // helpFunc is help func defined by user. helpFunc func(*Command, []string) // helpCommand is command with usage 'help'. If it's not defined by user, // cobra uses default help command. helpCommand *Command - // helpCommandGroupID is the group id for the helpCommand - helpCommandGroupID string - // completionCommandGroupID is the group id for the completion command - completionCommandGroupID string + // parent is a parent command for this command. + parent *Command - // versionTemplate is the version template defined by user. - versionTemplate string + ctx context.Context - // errPrefix is the error message prefix defined by user. - errPrefix string + // Max lengths of commands' string lengths for use in padding. + commandsMaxUseLen int + commandsMaxCommandPathLen int + commandsMaxNameLen int - // inReader is a reader defined by the user that replaces stdin - inReader io.Reader - // outWriter is a writer defined by the user that replaces stdout - outWriter io.Writer - // errWriter is a writer defined by the user that replaces stderr - errWriter io.Writer + // SuggestionsMinimumDistance defines minimum levenshtein distance to display suggestions. + // Must be > 0. + SuggestionsMinimumDistance int // FParseErrWhitelist flag parse errors to be ignored FParseErrWhitelist FParseErrWhitelist @@ -201,22 +229,6 @@ type Command struct { // commandsAreSorted defines, if command slice are sorted or not. commandsAreSorted bool - // commandCalledAs is the name or alias value used to call this command. - commandCalledAs struct { - name string - called bool - } - - ctx context.Context - - // commands is the list of commands supported by this program. - commands []*Command - // parent is a parent command for this command. - parent *Command - // Max lengths of commands' string lengths for use in padding. - commandsMaxUseLen int - commandsMaxCommandPathLen int - commandsMaxNameLen int // TraverseChildren parses flags on all parents before executing child command. TraverseChildren bool @@ -249,10 +261,6 @@ type Command struct { // DisableSuggestions disables the suggestions based on Levenshtein distance // that go along with 'unknown command' messages. DisableSuggestions bool - - // SuggestionsMinimumDistance defines minimum levenshtein distance to display suggestions. - // Must be > 0. - SuggestionsMinimumDistance int } // Context returns underlying command context. If command was executed