diff --git a/fish.go b/fish.go index 5a952671e9..6c6cf0c7eb 100644 --- a/fish.go +++ b/fish.go @@ -71,7 +71,7 @@ func (cmd *Command) prepareFishCommands(commands []*Command, allCommands *[]stri fmt.Fprintf(&completion, "complete -r -c %s -n '%s' -a '%s'", cmd.Name, - cmd.fishSubcommandHelper(previousCommands), + cmd.fishSubcommandHelper(previousCommands, commands), strings.Join(command.Names(), " "), ) @@ -116,7 +116,7 @@ func (cmd *Command) prepareFishFlags(flags []Flag, previousCommands []string) [] fmt.Fprintf(completion, "complete -c %s -n '%s'", cmd.Name, - cmd.fishSubcommandHelper(previousCommands), + cmd.fishFlagHelper(previousCommands), ) fishAddFileFlag(f, completion) @@ -165,7 +165,23 @@ func fishAddFileFlag(flag Flag, completion *strings.Builder) { completion.WriteString(" -f") } -func (cmd *Command) fishSubcommandHelper(allCommands []string) string { +func (cmd *Command) fishSubcommandHelper(allCommands []string, siblings []*Command) string { + fishHelper := fmt.Sprintf("__fish_%s_no_subcommand", cmd.Name) + if len(allCommands) > 0 { + var siblingNames []string + for _, command := range siblings { + siblingNames = append(siblingNames, command.Names()...) + } + fishHelper = fmt.Sprintf( + "__fish_seen_subcommand_from %s; and not __fish_seen_subcommand_from %s", + strings.Join(allCommands, " "), + strings.Join(siblingNames, " "), + ) + } + return fishHelper +} + +func (cmd *Command) fishFlagHelper(allCommands []string) string { fishHelper := fmt.Sprintf("__fish_%s_no_subcommand", cmd.Name) if len(allCommands) > 0 { fishHelper = fmt.Sprintf( diff --git a/testdata/expected-fish-full.fish b/testdata/expected-fish-full.fish index 95f135ae72..db4b2b5e04 100644 --- a/testdata/expected-fish-full.fish +++ b/testdata/expected-fish-full.fish @@ -21,7 +21,7 @@ complete -r -c greet -n '__fish_greet_no_subcommand' -a 'config c' -d 'another u 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 -r -c greet -n '__fish_seen_subcommand_from config c' -a 'sub-config s ss' -d 'another usage test' +complete -r -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' @@ -33,5 +33,5 @@ complete -r -c greet -n '__fish_greet_no_subcommand' -a 'usage u' -d 'standard u 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 -r -c greet -n '__fish_seen_subcommand_from usage u' -a 'sub-usage su' -d 'standard usage text' +complete -r -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'