Skip to content

Commit 10f69fd

Browse files
authored
Merge pull request #2481 from INo-xious/fix/suggest-applied-flags
fix: suggest flags the parser accepts for the command Reviewed-by: Eng Zer Jun <engzerjun@gmail.com> Tested-by: Eng Zer Jun <engzerjun@gmail.com>
2 parents 3546945 + 04fdb83 commit 10f69fd

2 files changed

Lines changed: 53 additions & 1 deletion

File tree

‎command.go‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,12 @@ func (cmd *Command) suggestFlagFromError(err error, commandName string) (string,
263263
return "", err
264264
}
265265

266-
flags := cmd.Flags
266+
// suggest from the flags the parser accepted, which include flags in
267+
// mutually exclusive groups and persistent flags of ancestors
268+
flags := cmd.appliedFlags
269+
if flags == nil {
270+
flags = cmd.allFlags()
271+
}
267272
hideHelp := cmd.hideHelp()
268273

269274
if commandName != "" {

‎suggestions_test.go‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"context"
66
"errors"
77
"fmt"
8+
"io"
89
"testing"
910

1011
"github.com/stretchr/testify/assert"
@@ -130,6 +131,52 @@ func TestSuggestFlagFromError(t *testing.T) {
130131
}
131132
}
132133

134+
func TestSuggestFlagFromErrorAppliedFlags(t *testing.T) {
135+
for _, testCase := range []struct {
136+
name, provided, expected, unexpected string
137+
}{
138+
{name: "persistent flag of parent", provided: "--confg", expected: "--config"},
139+
{name: "mutually exclusive flag", provided: "--jsn", expected: "--json"},
140+
{name: "local flag of parent", provided: "--local-onli", unexpected: "--local-only"},
141+
} {
142+
t.Run(testCase.name, func(t *testing.T) {
143+
// Given
144+
var errOut bytes.Buffer
145+
cmd := &Command{
146+
Name: "app",
147+
Writer: io.Discard,
148+
ErrWriter: &errOut,
149+
Flags: []Flag{
150+
&StringFlag{Name: "config"},
151+
&StringFlag{Name: "local-only", Local: true},
152+
},
153+
Commands: []*Command{
154+
{
155+
Name: "build",
156+
Suggest: true,
157+
MutuallyExclusiveFlags: []MutuallyExclusiveFlags{
158+
{Flags: [][]Flag{{&BoolFlag{Name: "json"}}, {&BoolFlag{Name: "yaml"}}}},
159+
},
160+
Action: func(context.Context, *Command) error { return nil },
161+
},
162+
},
163+
}
164+
165+
// When
166+
err := cmd.Run(buildTestContext(t), []string{"app", "build", testCase.provided})
167+
168+
// Then
169+
assert.Error(t, err)
170+
if testCase.expected != "" {
171+
assert.Contains(t, errOut.String(), fmt.Sprintf(SuggestDidYouMeanTemplate, testCase.expected))
172+
}
173+
if testCase.unexpected != "" {
174+
assert.NotContains(t, errOut.String(), fmt.Sprintf(SuggestDidYouMeanTemplate, testCase.unexpected))
175+
}
176+
})
177+
}
178+
}
179+
133180
func TestSuggestFlagFromErrorWrongError(t *testing.T) {
134181
// Given
135182
app := buildExtendedTestCommand()

0 commit comments

Comments
 (0)