Skip to content

Commit 2d94892

Browse files
authored
Custom completion handle multiple shorhand flags together (spf13#1258)
Flag definitions like `-asd` are not handled correctly by the custom completion logic. They should be treated as multiple flags. For details refer to spf13#1257. Fixes spf13#1257 Signed-off-by: Paul Holzinger <paul.holzinger@web.de>
1 parent 6d00909 commit 2d94892

2 files changed

Lines changed: 113 additions & 3 deletions

File tree

completions.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,16 @@ func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*p
469469
if len(lastArg) > 0 && lastArg[0] == '-' {
470470
if index := strings.Index(lastArg, "="); index >= 0 {
471471
// Flag with an =
472-
flagName = strings.TrimLeft(lastArg[:index], "-")
472+
if strings.HasPrefix(lastArg[:index], "--") {
473+
// Flag has full name
474+
flagName = lastArg[2:index]
475+
} else {
476+
// Flag is shorthand
477+
// We have to get the last shorthand flag name
478+
// e.g. `-asd` => d to provide the correct completion
479+
// https://github.com/spf13/cobra/issues/1257
480+
flagName = lastArg[index-1 : index]
481+
}
473482
lastArg = lastArg[index+1:]
474483
flagWithEqual = true
475484
} else {
@@ -486,8 +495,16 @@ func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*p
486495
// If the flag contains an = it means it has already been fully processed,
487496
// so we don't need to deal with it here.
488497
if index := strings.Index(prevArg, "="); index < 0 {
489-
flagName = strings.TrimLeft(prevArg, "-")
490-
498+
if strings.HasPrefix(prevArg, "--") {
499+
// Flag has full name
500+
flagName = prevArg[2:]
501+
} else {
502+
// Flag is shorthand
503+
// We have to get the last shorthand flag name
504+
// e.g. `-asd` => d to provide the correct completion
505+
// https://github.com/spf13/cobra/issues/1257
506+
flagName = prevArg[len(prevArg)-1:]
507+
}
491508
// Remove the uncompleted flag or else there could be an error created
492509
// for an invalid value for that flag
493510
trimmedArgs = args[:len(args)-1]

completions_test.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2201,3 +2201,96 @@ func TestCompleteCompletion(t *testing.T) {
22012201
}
22022202
}
22032203
}
2204+
2205+
func TestMultipleShorthandFlagCompletion(t *testing.T) {
2206+
rootCmd := &Command{
2207+
Use: "root",
2208+
ValidArgs: []string{"foo", "bar"},
2209+
Run: emptyRun,
2210+
}
2211+
f := rootCmd.Flags()
2212+
f.BoolP("short", "s", false, "short flag 1")
2213+
f.BoolP("short2", "d", false, "short flag 2")
2214+
f.StringP("short3", "f", "", "short flag 3")
2215+
_ = rootCmd.RegisterFlagCompletionFunc("short3", func(*Command, []string, string) ([]string, ShellCompDirective) {
2216+
return []string{"works"}, ShellCompDirectiveNoFileComp
2217+
})
2218+
2219+
// Test that a single shorthand flag works
2220+
output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "-s", "")
2221+
if err != nil {
2222+
t.Errorf("Unexpected error: %v", err)
2223+
}
2224+
2225+
expected := strings.Join([]string{
2226+
"foo",
2227+
"bar",
2228+
":4",
2229+
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
2230+
2231+
if output != expected {
2232+
t.Errorf("expected: %q, got: %q", expected, output)
2233+
}
2234+
2235+
// Test that multiple boolean shorthand flags work
2236+
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "-sd", "")
2237+
if err != nil {
2238+
t.Errorf("Unexpected error: %v", err)
2239+
}
2240+
2241+
expected = strings.Join([]string{
2242+
"foo",
2243+
"bar",
2244+
":4",
2245+
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
2246+
2247+
if output != expected {
2248+
t.Errorf("expected: %q, got: %q", expected, output)
2249+
}
2250+
2251+
// Test that multiple boolean + string shorthand flags work
2252+
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "-sdf", "")
2253+
if err != nil {
2254+
t.Errorf("Unexpected error: %v", err)
2255+
}
2256+
2257+
expected = strings.Join([]string{
2258+
"works",
2259+
":4",
2260+
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
2261+
2262+
if output != expected {
2263+
t.Errorf("expected: %q, got: %q", expected, output)
2264+
}
2265+
2266+
// Test that multiple boolean + string with equal sign shorthand flags work
2267+
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "-sdf=")
2268+
if err != nil {
2269+
t.Errorf("Unexpected error: %v", err)
2270+
}
2271+
2272+
expected = strings.Join([]string{
2273+
"works",
2274+
":4",
2275+
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
2276+
2277+
if output != expected {
2278+
t.Errorf("expected: %q, got: %q", expected, output)
2279+
}
2280+
2281+
// Test that multiple boolean + string with equal sign with value shorthand flags work
2282+
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "-sdf=abc", "")
2283+
if err != nil {
2284+
t.Errorf("Unexpected error: %v", err)
2285+
}
2286+
2287+
expected = strings.Join([]string{
2288+
"foo",
2289+
"bar",
2290+
":4",
2291+
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
2292+
2293+
if output != expected {
2294+
t.Errorf("expected: %q, got: %q", expected, output)
2295+
}
2296+
}

0 commit comments

Comments
 (0)