10000 Merge pull request #1396 from urfave/suggestion-pluggability · urfave/cli@9de0cd3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9de0cd3

Browse files
authored
Merge pull request #1396 from urfave/suggestion-pluggability
Introduce override hooks for suggestions
2 parents 9e65b4d + 5bb9f45 commit 9de0cd3

File tree

6 files changed

+62
-36
lines changed

6 files changed

+62
-36
lines changed

app.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,19 @@ import (
1111
"time"
1212
)
1313

14+
const suggestDidYouMeanTemplate = "Did you mean %q?"
15+
1416
var (
1517
changeLogURL = "https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md"
1618
appActionDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-action-signature", changeLogURL)
1719
contactSysadmin = "This is an error in the application. Please contact the distributor of this application if this is not you."
1820
errInvalidActionType = NewExitError("ERROR invalid Action type. "+
1921
fmt.Sprintf("Must be `func(*Context`)` or `func(*Context) error). %s", contactSysadmin)+
2022
fmt.Sprintf("See %s", appActionDeprecationURL), 2)
23+
24+
SuggestFlag SuggestFlagFunc = suggestFlag
25+
SuggestCommand SuggestCommandFunc = suggestCommand
26+
SuggestDidYouMeanTemplate string = suggestDidYouMeanTemplate
2127
)
2228

2329
// App is the main structure of a cli application. It is recommended that
@@ -102,6 +108,10 @@ type App struct {
102108
didSetup bool
103109
}
104110

111+
type SuggestFlagFunc func(flags []Flag, provided string, hideHelp bool) string
112+
113+
type SuggestCommandFunc func(commands []*Command, provided string) string
114+
105115
// Tries to find out when this binary was compiled.
106116
// Returns the current time if it fails to find it.
107117
func compileTime() time.Time {
@@ -343,6 +353,29 @@ func (a *App) RunContext(ctx context.Context, arguments []string) (err error) {
343353
return err
344354
}
345355

356+
func (a *App) suggestFlagFromError(err error, command string) (string, error) {
357+
flag, parseErr := flagFromError(err)
358+
if parseErr != nil {
359+
return "", err
360+
}
361+
362+
flags := a.Flags
363+
if command != "" {
364+
cmd := a.Command(command)
365+
if cmd == nil {
366+
return "", err
367+
}
368+
flags = cmd.Flags
369+
}
370+
371+
suggestion := SuggestFlag(flags, flag, a.HideHelp)
372+
if len(suggestion) == 0 {
373+
return "", err
374+
}
375+
376+
return fmt.Sprintf(SuggestDidYouMeanTemplate+"\n\n", suggestion), nil
377+
}
378+
346379
// RunAndExitOnError calls .Run() and exits non-zero if an error was returned
347380
//
348381
// Deprecated: instead you should return an error that fulfills cli.ExitCoder

godoc-current.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ application:
2626

2727
VARIABLES
2828

29+
var (
30+
SuggestFlag SuggestFlagFunc = suggestFlag
31+
SuggestCommand SuggestCommandFunc = suggestCommand
32+
SuggestDidYouMeanTemplate string = suggestDidYouMeanTemplate
33+
)
2934
var AppHelpTemplate = `NAME:
3035
{{.Name}}{{if .Usage}} - {{.Usage}}{{end}}
3136

@@ -1622,6 +1627,10 @@ func (f *StringSliceFlag) String() string
16221627
func (f *StringSliceFlag) TakesValue() bool
16231628
TakesValue returns true of the flag takes a value, otherwise false
16241629

1630+
type SuggestCommandFunc func(commands []*Command, provided string) string
1631+
1632+
type SuggestFlagFunc func(flags []Flag, provided string, hideHelp bool) string
1633+
16251634
type Timestamp struct {
16261635
// Has unexported fields.
16271636
}

help.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ func ShowCommandHelp(ctx *Context, command string) error {
221221
if ctx.App.CommandNotFound == nil {
222222
errMsg := fmt.Sprintf("No help topic for '%v'", command)
223223
if ctx.App.Suggest {
224-
if suggestion := suggestCommand(ctx.App.Commands, command); suggestion != "" {
224+
if suggestion := SuggestCommand(ctx.App.Commands, command); suggestion != "" {
225225
errMsg += ". " + suggestion
226226
}
227227
}

suggestions.go

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,13 @@ import (
66
"github.com/antzucaro/matchr"
77
)
88

9-
const didYouMeanTemplate = "Did you mean '%s'?"
10-
11-
func (a *App) suggestFlagFromError(err error, command string) (string, error) {
12-
flag, parseErr := flagFromError(err)
13-
if parseErr != nil {
14-
return "", err
15-
}
16-
17-
flags := a.Flags
18-
if command != "" {
19-
cmd := a.Command(command)
20-
if cmd == nil {
21-
return "", err
22-
}
23-
flags = cmd.Flags
24-
}
25-
26-
suggestion := a.suggestFlag(flags, flag)
27-
if len(suggestion) == 0 {
28-
return "", err
29-
}
30-
31-
return fmt.Sprintf(didYouMeanTemplate+"\n\n", suggestion), nil
32-
}
33-
34-
func (a *App) suggestFlag(flags []Flag, provided string) (suggestion string) {
9+
func suggestFlag(flags []Flag, provided string, hideHelp bool) string {
3510
distance := 0.0
11+
suggestion := ""
3612

3713
for _, flag := range flags {
3814
flagNames := flag.Names()
39-
if !a.HideHelp {
15+
if !hideHelp {
4016
flagNames = append(flagNames, HelpFlag.Names()...)
4117
}
4218
for _, name := range flagNames {
@@ -71,5 +47,5 @@ func suggestCommand(commands []*Command, provided string) (suggestion string) {
7147
}
7248
}
7349

74-
return fmt.Sprintf(didYouMeanTemplate, suggestion)
50+
return fmt.Sprintf(SuggestDidYouMeanTemplate, suggestion)
7551
}

suggestions_test.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func TestSuggestFlag(t *testing.T) {
2020
{"s", "-s"},
2121
} {
2222
// When
23-
res := app.suggestFlag(app.Flags, testCase.provided)
23+
res := suggestFlag(app.Flags, testCase.provided, false)
2424

2525
// Then
2626
expect(t, res, testCase.expected)
@@ -30,10 +30,9 @@ func TestSuggestFlag(t *testing.T) {
3030
func TestSuggestFlagHideHelp(t *testing.T) {
3131
// Given
3232
app := testApp()
33-
app.HideHelp = true
3433

3534
// When
36-
res := app.suggestFlag(app.Flags, "hlp")
35+
res := suggestFlag(app.Flags, "hlp", true)
3736

3837
// Then
3938
expect(t, res, "--fl")
@@ -57,7 +56,7 @@ func TestSuggestFlagFromError(t *testing.T) {
5756
)
5857

5958
// Then
60-
expect(t, res, fmt.Sprintf(didYouMeanTemplate+"\n\n", testCase.expected))
59+
expect(t, res, fmt.Sprintf(SuggestDidYouMeanTemplate+"\n\n", testCase.expected))
6160
}
6261
}
6362

@@ -117,7 +116,7 @@ func TestSuggestCommand(t *testing.T) {
117116
res := suggestCommand(app.Commands, testCase.provided)
118117

119118
// Then
120-
expect(t, res, fmt.Sprintf(didYouMeanTemplate, testCase.expected))
119+
expect(t, res, fmt.Sprintf(SuggestDidYouMeanTemplate, testCase.expected))
121120
}
122121
}
123122

@@ -141,7 +140,7 @@ func ExampleApp_Suggest() {
141140
// Output:
142141
// Incorrect Usage. flag provided but not defined: -nema
143142
//
144-
// Did you mean '--name'?
143+
// Did you mean "--name"?
145144
//
146145
// (this space intentionally left blank)
147146
}
@@ -182,7 +181,7 @@ func ExampleApp_Suggest_command() {
182181
// Output:
183182
// Incorrect Usage: flag provided but not defined: -sliming
184183
//
185-
// Did you mean '--smiling'?
184+
// Did you mean "--smiling"?
186185
//
187186
// (this space intentionally left blank)
188187
}

testdata/godoc-v2.x.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ application:
2626

2727
VARIABLES
2828

29+
var (
30+
SuggestFlag SuggestFlagFunc = suggestFlag
31+
SuggestCommand SuggestCommandFunc = suggestCommand
32+
SuggestDidYouMeanTemplate string = suggestDidYouMeanTemplate
33+
)
2934
var AppHelpTemplate = `NAME:
3035
{{.Name}}{{if .Usage}} - {{.Usage}}{{end}}
3136

@@ -1622,6 +1627,10 @@ func (f *StringSliceFlag) String() string
16221627
func (f *StringSliceFlag) TakesValue() bool
16231628
TakesValue returns true of the flag takes a value, otherwise false
16241629

1630+
type SuggestCommandFunc func(commands []*Command, provided string) string
1631+
1632+
type SuggestFlagFunc func(flags []Flag, provided string, hideHelp bool) string
1633+
16251634
type Timestamp struct {
16261635
// Has unexported fields.
16271636
}

0 commit comments

Comments
 (0)
0