diff --git a/command_test.go b/command_test.go index b44ed07932..f346294339 100644 --- a/command_test.go +++ b/command_test.go @@ -98,6 +98,11 @@ func buildExtendedTestCommand() *Command { }, { Name: "hidden-command", Hidden: true, + Flags: []Flag{ + &BoolFlag{ + Name: "completable", + }, + }, }, { Aliases: []string{"u"}, Flags: []Flag{ @@ -4876,7 +4881,26 @@ func TestJSONExportCommand(t *testing.T) { "defaultCommand": "", "category": "", "commands": null, - "flags": null, + "flags": [ + { + "name": "completable", + "category": "", + "defaultText": "", + "usage": "", + "required": false, + "hidden": false, + "hideDefault": false, + "local": false, + "defaultValue": false, + "aliases": null, + "takesFileArg": false, + "config": { + "Count": null + }, + "onlyOnce": false, + "validateDefaults": false + } + ], "hideHelp": false, "hideHelpCommand": false, "hideVersion": false, diff --git a/fish.go b/fish.go index b1086ebc9e..93d4d4aab1 100644 --- a/fish.go +++ b/fish.go @@ -30,66 +30,47 @@ func (cmd *Command) writeFishCompletionTemplate(w io.Writer) error { if err != nil { return err } - allCommands := []string{} // Add global flags - completions := cmd.prepareFishFlags(cmd.VisibleFlags(), allCommands) - - // Add help flag - if !cmd.HideHelp { - completions = append( - completions, - cmd.prepareFishFlags([]Flag{HelpFlag}, allCommands)..., - ) - } - - // Add version flag - if !cmd.HideVersion { - completions = append( - completions, - cmd.prepareFishFlags([]Flag{VersionFlag}, allCommands)..., - ) - } + completions := cmd.prepareFishFlags(cmd.VisibleFlags(), []string{}) // Add commands and their flags completions = append( completions, - cmd.prepareFishCommands(cmd.VisibleCommands(), &allCommands, []string{})..., + cmd.prepareFishCommands(cmd.Commands, []string{})..., ) + toplevelCommandNames := []string{} + for _, child := range cmd.Commands { + toplevelCommandNames = append(toplevelCommandNames, child.Names()...) + } + return t.ExecuteTemplate(w, name, &fishCommandCompletionTemplate{ Command: cmd, Completions: completions, - AllCommands: allCommands, + AllCommands: toplevelCommandNames, }) } -func (cmd *Command) prepareFishCommands(commands []*Command, allCommands *[]string, previousCommands []string) []string { +func (cmd *Command) prepareFishCommands(commands []*Command, previousCommands []string) []string { completions := []string{} for _, command := range commands { - var completion strings.Builder - fmt.Fprintf(&completion, - "complete -x -c %s -n '%s' -a '%s'", - cmd.Name, - cmd.fishSubcommandHelper(previousCommands, commands), - strings.Join(command.Names(), " "), - ) - - if command.Usage != "" { + if !command.Hidden { + var completion strings.Builder fmt.Fprintf(&completion, - " -d '%s'", - escapeSingleQuotes(command.Usage)) - } - - if !command.HideHelp { - completions = append( - completions, - cmd.prepareFishFlags([]Flag{HelpFlag}, command.Names())..., + "complete -x -c %s -n '%s' -a '%s'", + cmd.Name, + cmd.fishSubcommandHelper(previousCommands, commands), + strings.Join(command.Names(), " "), ) - } - *allCommands = append(*allCommands, command.Names()...) - completions = append(completions, completion.String()) + if command.Usage != "" { + fmt.Fprintf(&completion, + " -d '%s'", + escapeSingleQuotes(command.Usage)) + } + completions = append(completions, completion.String()) + } completions = append( completions, cmd.prepareFishFlags(command.VisibleFlags(), command.Names())..., @@ -100,7 +81,7 @@ func (cmd *Command) prepareFishCommands(commands []*Command, allCommands *[]stri completions = append( completions, cmd.prepareFishCommands( - command.Commands, allCommands, command.Names(), + command.Commands, command.Names(), )..., ) } diff --git a/testdata/expected-fish-full.fish b/testdata/expected-fish-full.fish index f586c66fda..eb29d69b0d 100644 --- a/testdata/expected-fish-full.fish +++ b/testdata/expected-fish-full.fish @@ -2,7 +2,7 @@ function __fish_greet_no_subcommand --description 'Test if there has been any subcommand yet' for i in (commandline -opc) - if contains -- $i config c sub-config s ss info i in some-command usage u sub-usage su + if contains -- $i config c info i in some-command hidden-command usage u return 1 end end @@ -14,24 +14,17 @@ complete -c greet -n '__fish_greet_no_subcommand' -f -l flag -s fl -s f -r complete -c greet -n '__fish_greet_no_subcommand' -f -l another-flag -s b -d 'another usage text' complete -c greet -n '__fish_greet_no_subcommand' -l logfile -r complete -c greet -n '__fish_greet_no_subcommand' -l foofile -r -complete -c greet -n '__fish_greet_no_subcommand' -f -l help -s h -d 'show help' -complete -c greet -n '__fish_greet_no_subcommand' -f -l version -s v -d 'print the version' -complete -c greet -n '__fish_seen_subcommand_from config c' -f -l help -s h -d 'show help' complete -x -c greet -n '__fish_greet_no_subcommand' -a 'config c' -d 'another usage test' complete -c greet -n '__fish_seen_subcommand_from config c' -l flag -s fl -s f -r complete -c greet -n '__fish_seen_subcommand_from config c' -f -l another-flag -s b -d 'another usage text' -complete -c greet -n '__fish_seen_subcommand_from sub-config s ss' -f -l help -s h -d 'show help' complete -x -c greet -n '__fish_seen_subcommand_from config c; and not __fish_seen_subcommand_from sub-config s ss' -a 'sub-config s ss' -d 'another usage test' complete -c greet -n '__fish_seen_subcommand_from sub-config s ss' -f -l sub-flag -s sub-fl -s s -r complete -c greet -n '__fish_seen_subcommand_from sub-config s ss' -f -l sub-command-flag -s s -d 'some usage text' -complete -c greet -n '__fish_seen_subcommand_from info i in' -f -l help -s h -d 'show help' complete -x -c greet -n '__fish_greet_no_subcommand' -a 'info i in' -d 'retrieve generic information' -complete -c greet -n '__fish_seen_subcommand_from some-command' -f -l help -s h -d 'show help' complete -x -c greet -n '__fish_greet_no_subcommand' -a 'some-command' -complete -c greet -n '__fish_seen_subcommand_from usage u' -f -l help -s h -d 'show help' +complete -c greet -n '__fish_seen_subcommand_from hidden-command' -f -l completable complete -x -c greet -n '__fish_greet_no_subcommand' -a 'usage u' -d 'standard usage text' complete -c greet -n '__fish_seen_subcommand_from usage u' -l flag -s fl -s f -r complete -c greet -n '__fish_seen_subcommand_from usage u' -f -l another-flag -s b -d 'another usage text' -complete -c greet -n '__fish_seen_subcommand_from sub-usage su' -f -l help -s h -d 'show help' complete -x -c greet -n '__fish_seen_subcommand_from usage u; and not __fish_seen_subcommand_from sub-usage su' -a 'sub-usage su' -d 'standard usage text' complete -c greet -n '__fish_seen_subcommand_from sub-usage su' -f -l sub-command-flag -s s -d 'some usage text'