Skip to content

Commit 32a703e

Browse files
author
Paul Holzinger
committed
Custom completion handle multiple shorhand flags together
Flag definitions like `-asd` are not handled correctly by the custom completion logic. They should be treated as multiple flags. For details refer to #1257. Fixes #1257 Signed-off-by: Paul Holzinger <[email protected]>
1 parent eb3b639 commit 32a703e

File tree

2 files changed

+113
-3
lines changed

2 files changed

+113
-3
lines changed

completions.go

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

completions_test.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2158,3 +2158,96 @@ func TestCompleteCompletion(t *testing.T) {
21582158
}
21592159
}
21602160
}
2161+
2162+
func TestMultipleShorthandFlagCompletion(t *testing.T) {
2163+
rootCmd := &Command{
2164+
Use: "root",
2165+
ValidArgs: []string{"foo", "bar"},
2166+
Run: emptyRun,
2167+
}
2168+
f := rootCmd.Flags()
2169+
f.BoolP("short", "s", false, "short flag 1")
2170+
f.BoolP("short2", "d", false, "short flag 2")
2171+
f.StringP("short3", "f", "", "short flag 3")
2172+
_ = rootCmd.RegisterFlagCompletionFunc("short3", func(*Command, []string, string) ([]string, ShellCompDirective) {
2173+
return []string{"works"}, ShellCompDirectiveNoFileComp
2174+
})
2175+
2176+
// Test that a single shorthand flag works
2177+
output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "-s", "")
2178+
if err != nil {
2179+
t.Errorf("Unexpected error: %v", err)
2180+
}
2181+
2182+
expected := strings.Join([]string{
2183+
"foo",
2184+
"bar",
2185+
":4",
2186+
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
2187+
2188+
if output != expected {
2189+
t.Errorf("expected: %q, got: %q", expected, output)
2190+
}
2191+
2192+
// Test that multiple boolean shorthand flags work
2193+
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "-sd", "")
2194+
if err != nil {
2195+
t.Errorf("Unexpected error: %v", err)
2196+
}
2197+
2198+
expected = strings.Join([]string{
2199+
"foo",
2200+
"bar",
2201+
":4",
2202+
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
2203+
2204+
if output != expected {
2205+
t.Errorf("expected: %q, got: %q", expected, output)
2206+
}
2207+
2208+
// Test that multiple boolean + string shorthand flags work
2209+
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "-sdf", "")
2210+
if err != nil {
2211+
t.Errorf("Unexpected error: %v", err)
2212+
}
2213+
2214+
expected = strings.Join([]string{
2215+
"works",
2216+
":4",
2217+
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
2218+
2219+
if output != expected {
2220+
t.Errorf("expected: %q, got: %q", expected, output)
2221+
}
2222+
2223+
// Test that multiple boolean + string with equal sign shorthand flags work
2224+
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "-sdf=")
2225+
if err != nil {
2226+
t.Errorf("Unexpected error: %v", err)
2227+
}
2228+
2229+
expected = strings.Join([]string{
2230+
"works",
2231+
":4",
2232+
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
2233+
2234+
if output != expected {
2235+
t.Errorf("expected: %q, got: %q", expected, output)
2236+
}
2237+
2238+
// Test that multiple boolean + string with equal sign with value shorthand flags work
2239+
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "-sdf=abc", "")
2240+
if err != nil {
2241+
t.Errorf("Unexpected error: %v", err)
2242+
}
2243+
2244+
expected = strings.Join([]string{
2245+
"foo",
2246+
"bar",
2247+
":4",
2248+
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
2249+
2250+
if output != expected {
2251+
t.Errorf("expected: %q, got: %q", expected, output)
2252+
}
2253+
}

0 commit comments

Comments
 (0)