Custom completion handle multiple shorhand flags together (#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 #1257. Fixes #1257 Signed-off-by: Paul Holzinger <paul.holzinger@web.de>
This commit is contained in:
		@ -469,7 +469,16 @@ func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*p
 | 
				
			|||||||
	if len(lastArg) > 0 && lastArg[0] == '-' {
 | 
						if len(lastArg) > 0 && lastArg[0] == '-' {
 | 
				
			||||||
		if index := strings.Index(lastArg, "="); index >= 0 {
 | 
							if index := strings.Index(lastArg, "="); index >= 0 {
 | 
				
			||||||
			// Flag with an =
 | 
								// Flag with an =
 | 
				
			||||||
			flagName = strings.TrimLeft(lastArg[:index], "-")
 | 
								if strings.HasPrefix(lastArg[:index], "--") {
 | 
				
			||||||
 | 
									// Flag has full name
 | 
				
			||||||
 | 
									flagName = lastArg[2:index]
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									// Flag is shorthand
 | 
				
			||||||
 | 
									// We have to get the last shorthand flag name
 | 
				
			||||||
 | 
									// e.g. `-asd` => d to provide the correct completion
 | 
				
			||||||
 | 
									// https://github.com/spf13/cobra/issues/1257
 | 
				
			||||||
 | 
									flagName = lastArg[index-1 : index]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			lastArg = lastArg[index+1:]
 | 
								lastArg = lastArg[index+1:]
 | 
				
			||||||
			flagWithEqual = true
 | 
								flagWithEqual = true
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
@ -486,8 +495,16 @@ func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*p
 | 
				
			|||||||
				// If the flag contains an = it means it has already been fully processed,
 | 
									// If the flag contains an = it means it has already been fully processed,
 | 
				
			||||||
				// so we don't need to deal with it here.
 | 
									// so we don't need to deal with it here.
 | 
				
			||||||
				if index := strings.Index(prevArg, "="); index < 0 {
 | 
									if index := strings.Index(prevArg, "="); index < 0 {
 | 
				
			||||||
					flagName = strings.TrimLeft(prevArg, "-")
 | 
										if strings.HasPrefix(prevArg, "--") {
 | 
				
			||||||
 | 
											// Flag has full name
 | 
				
			||||||
 | 
											flagName = prevArg[2:]
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											// Flag is shorthand
 | 
				
			||||||
 | 
											// We have to get the last shorthand flag name
 | 
				
			||||||
 | 
											// e.g. `-asd` => d to provide the correct completion
 | 
				
			||||||
 | 
											// https://github.com/spf13/cobra/issues/1257
 | 
				
			||||||
 | 
											flagName = prevArg[len(prevArg)-1:]
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
					// Remove the uncompleted flag or else there could be an error created
 | 
										// Remove the uncompleted flag or else there could be an error created
 | 
				
			||||||
					// for an invalid value for that flag
 | 
										// for an invalid value for that flag
 | 
				
			||||||
					trimmedArgs = args[:len(args)-1]
 | 
										trimmedArgs = args[:len(args)-1]
 | 
				
			||||||
 | 
				
			|||||||
@ -2201,3 +2201,96 @@ func TestCompleteCompletion(t *testing.T) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestMultipleShorthandFlagCompletion(t *testing.T) {
 | 
				
			||||||
 | 
						rootCmd := &Command{
 | 
				
			||||||
 | 
							Use:       "root",
 | 
				
			||||||
 | 
							ValidArgs: []string{"foo", "bar"},
 | 
				
			||||||
 | 
							Run:       emptyRun,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						f := rootCmd.Flags()
 | 
				
			||||||
 | 
						f.BoolP("short", "s", false, "short flag 1")
 | 
				
			||||||
 | 
						f.BoolP("short2", "d", false, "short flag 2")
 | 
				
			||||||
 | 
						f.StringP("short3", "f", "", "short flag 3")
 | 
				
			||||||
 | 
						_ = rootCmd.RegisterFlagCompletionFunc("short3", func(*Command, []string, string) ([]string, ShellCompDirective) {
 | 
				
			||||||
 | 
							return []string{"works"}, ShellCompDirectiveNoFileComp
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Test that a single shorthand flag works
 | 
				
			||||||
 | 
						output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "-s", "")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expected := strings.Join([]string{
 | 
				
			||||||
 | 
							"foo",
 | 
				
			||||||
 | 
							"bar",
 | 
				
			||||||
 | 
							":4",
 | 
				
			||||||
 | 
							"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if output != expected {
 | 
				
			||||||
 | 
							t.Errorf("expected: %q, got: %q", expected, output)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Test that multiple boolean shorthand flags work
 | 
				
			||||||
 | 
						output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "-sd", "")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expected = strings.Join([]string{
 | 
				
			||||||
 | 
							"foo",
 | 
				
			||||||
 | 
							"bar",
 | 
				
			||||||
 | 
							":4",
 | 
				
			||||||
 | 
							"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if output != expected {
 | 
				
			||||||
 | 
							t.Errorf("expected: %q, got: %q", expected, output)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Test that multiple boolean + string shorthand flags work
 | 
				
			||||||
 | 
						output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "-sdf", "")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expected = strings.Join([]string{
 | 
				
			||||||
 | 
							"works",
 | 
				
			||||||
 | 
							":4",
 | 
				
			||||||
 | 
							"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if output != expected {
 | 
				
			||||||
 | 
							t.Errorf("expected: %q, got: %q", expected, output)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Test that multiple boolean + string with equal sign shorthand flags work
 | 
				
			||||||
 | 
						output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "-sdf=")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expected = strings.Join([]string{
 | 
				
			||||||
 | 
							"works",
 | 
				
			||||||
 | 
							":4",
 | 
				
			||||||
 | 
							"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if output != expected {
 | 
				
			||||||
 | 
							t.Errorf("expected: %q, got: %q", expected, output)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Test that multiple boolean + string with equal sign with value shorthand flags work
 | 
				
			||||||
 | 
						output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "-sdf=abc", "")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expected = strings.Join([]string{
 | 
				
			||||||
 | 
							"foo",
 | 
				
			||||||
 | 
							"bar",
 | 
				
			||||||
 | 
							":4",
 | 
				
			||||||
 | 
							"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if output != expected {
 | 
				
			||||||
 | 
							t.Errorf("expected: %q, got: %q", expected, output)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user