feat(completion): complete flag values and stop offering file names

Every value completed to file names, because no command registered a
completion. Values without a completer now complete nothing, and only
path flags (--*-file, --input, --attachment, --asset, --file, --ssh-key,
--dir, --cwd) and arguments named file or directory complete paths.

--json completes the fields of the command, also after a comma. --host,
--user, --remote and -R complete from hosts.yml, Git remotes and the
instance. enumFlag and enumValues give a flag one list of values that
validation (case-insensitive) and completion share, and instance
completers for issues, pull requests, labels, milestones, users,
branches, tags, releases, organizations, teams, workflows, runs, secrets
and variables are ready for commands to attach. They give up after two
seconds, never prompt, retry or refresh an OAuth token, and drop values
with control characters.

tea completion bash now says to use eval "$(tea completion bash)",
because bash 3.2 on macOS cannot source <(...), and names the
bash-completion package; the zsh help says to run compinit first. The
README matches.

Signed-off-by: bircni <bircni@icloud.com>
This commit is contained in:
bircni committed 2026-10-11 22:55:27 +02:00
1 parent 48c1e5b781
commit f03d0fdf54
5 files changed
+1034 -8

No files matched your search

+15
View File
@@ -118,10 +118,19 @@ func NewRoot(deps Dependencies) *cobra.Command {
flags.BoolVar(&a.options.interactive, "interactive", false, "Allow prompts with machine output")
flags.BoolVarP(&a.options.yes, "yes", "y", false, "Accept confirmations without prompting")
flags.BoolVar(&a.options.debug, "debug", false, "Log the method, URL, status, and duration of each HTTP request to stderr")
_ = root.RegisterFlagCompletionFunc("host", a.completeHosts)
_ = root.RegisterFlagCompletionFunc("user", a.completeAccounts)
_ = root.RegisterFlagCompletionFunc("repo", a.completeRepos())
_ = root.RegisterFlagCompletionFunc("remote", a.completeRemotes)
_ = root.RegisterFlagCompletionFunc("cwd", completeDirectories)
_ = root.RegisterFlagCompletionFunc("json", completeJSONFields)
root.PersistentPreRunE = func(cmd *cobra.Command, _ []string) error {
if err := a.checkOutputFlags(cmd); err != nil {
return err
}
if err := validateEnums(cmd); err != nil {
return err
}
if cmd.Flags().Changed("sudo") {
if a.options.sudo == "" || strings.IndexFunc(a.options.sudo, func(r rune) bool { return unicode.IsSpace(r) || unicode.IsControl(r) }) >= 0 {
return clierr.Wrap(clierr.Usage, errors.New("--sudo requires a username"))
@@ -151,8 +160,10 @@ func NewRoot(deps Dependencies) *cobra.Command {
root.SetHelpCommand(a.helpCommand())
root.InitDefaultHelpCmd()
root.InitDefaultCompletionCmd()
completionInstallHelp(root)
root.SetVersionTemplate("{{.Version}}\n")
root.SetHelpFunc(a.writeHelp)
root.CompletionOptions.SetDefaultShellCompDirective(cobra.ShellCompDirectiveNoFileComp)
root.AddGroup(
&cobra.Group{ID: "core", Title: "Core commands"},
&cobra.Group{ID: "actions", Title: "Actions commands"},
@@ -166,6 +177,7 @@ func NewRoot(deps Dependencies) *cobra.Command {
}
rejectUnknownSubcommands(root)
addVerbAliases(root)
completeDefaults(root)
return root
}
@@ -303,6 +315,9 @@ func Execute(ctx context.Context, deps Dependencies, args []string) error {
}
args = joinJSONFields(root, slices.Concat(args[:commandAt], expanded))
}
if completion {
args = completeJSONValue(args)
}
}
if loadErr == nil {
for name, expansion := range snapshot.Preferences.Aliases {