Visitar URL original
fix: offer ancestors' persistent flags in the fish completion script by vidigoat · Pull Request #2506 · urfave/cli · GitHub
Skip to content

fix: offer ancestors' persistent flags in the fish completion script - #2506

Open
vidigoat wants to merge 1 commit into
urfave:mainfrom
vidigoat:fix/fish-persistent-flags
Open

vidigoat wants to merge 1 commit into
urfave:mainfrom
vidigoat:fix/fish-persistent-flags

Conversation

@vidigoat

@vidigoat vidigoat commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

What type of PR is this?

  • bug

What this PR does / why we need it:

In v3 a flag is persistent unless it is Local, so a subcommand accepts its ancestors' flags, and its help lists them under GLOBAL OPTIONS. ToFishCompletion only offered each command's own flags, and the root's flags only before any subcommand, so after a subcommand fish never suggested them:

cmd := &cli.Command{
	Name: "app",
	Flags: []cli.Flag{
		&cli.StringFlag{Name: "config", Aliases: []string{"c"}, TakesFile: true},
		&cli.BoolFlag{Name: "verbose"},
		&cli.BoolFlag{Name: "local-only", Local: true},
	},
	Commands: []*cli.Command{
		{Name: "deploy", Flags: []cli.Flag{&cli.BoolFlag{Name: "dry-run"}},
			Commands: []*cli.Command{{Name: "prod"}}},
	},
}

In fish 4.9.3 with the generated script, complete -C 'app deploy --' listed --dry-run --help, while app deploy --verbose prod runs and app deploy prod --help shows --config and --verbose under GLOBAL OPTIONS. The dynamic completion (app completion fish) already offers them, since DefaultCompleteWithFlags adds VisiblePersistentFlags.

  • fish.go: prepareFishFlags now adds the command's VisiblePersistentFlags() that it doesn't define itself, the same way DefaultCompleteWithFlags does. VisiblePersistentFlags already leaves out Local flags and flags a subcommand redefines.
  • testdata/expected-fish-full.fish and testdata/expected-help-output.txt: regenerated. Both only gain lines, the persistent flags under each subcommand, and no existing line changes.

With this change, complete -C gives the same flags with the static script as with the dynamic one at every subcommand level: app deploy -- and app deploy prod -- both list --config --dry-run --help --verbose, --local-only stays at the root, and app deploy -c completes file names.

Which issue(s) this PR fixes:

None, found while comparing the static and dynamic fish scripts.

Testing

  • New TestFishCompletionPersistentFlags: a root flag is offered after a subcommand and a nested subcommand (fails on main), while a Local root flag and a root flag the subcommand redefines are not.
  • Checked the generated script in fish 4.9.3, as above.
  • make (generate, vet, tests, binary size, gfmrun), make lint and make v3diff pass. go test -race passes, as do the tests with urfave_cli_no_template, urfave_cli_no_docs and urfave_cli_no_suggest.

The change and the test were written with Claude Code (AI).

Release Notes

The fish completion script from ToFishCompletion now offers the persistent flags of a subcommand's ancestors, such as the root's flags.

🤖 Generated with Claude Code

@vidigoat
vidigoat requested a review from a team as a code owner October 25, 2026 15:28
…cript

ToFishCompletion only offered a command's own flags, so after a
subcommand fish never suggested a root flag such as --config, although
the subcommand accepts it and its help lists it under GLOBAL OPTIONS.
Add the command's visible persistent flags, as the dynamic completion
does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vidigoat
vidigoat force-pushed the fix/fish-persistent-flags branch from d2fe51c to 7b83486 Compare October 27, 2026 02:28

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant