Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions internal/cmd/browse/browse.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ Use flags to open specific sections like issues, pull requests, or settings.`,
cmd.Flags().BoolVar(&downloads, "downloads", false, "Open downloads page")

_ = cmd.RegisterFlagCompletionFunc("repo", cmdutil.CompleteRepoNames)
_ = cmd.RegisterFlagCompletionFunc("branch", cmdutil.CompleteBranchNames)

return cmd
}
Expand Down
4 changes: 4 additions & 0 deletions internal/cmd/issue/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ priority, or assignee.`,
cmd.Flags().BoolVar(&opts.JSON, "json", false, "Output in JSON format")
cmd.Flags().StringVar(&opts.Repo, "repo", "", "Repository in WORKSPACE/REPO format")

// NOTE: "on hold" contains a space, which is the canonical Bitbucket API value
// (confirmed in the OpenAPI spec enum). Cobra handles quoting automatically for
// zsh, fish, and PowerShell. Bash completion may require the user to quote the
// value (e.g. --state "on hold" or --state 'on hold').
_ = cmd.RegisterFlagCompletionFunc("state", cmdutil.StaticFlagCompletion([]string{
"new", "open", "resolved", "on hold", "invalid", "duplicate", "wontfix", "closed",
}))
Expand Down
4 changes: 4 additions & 0 deletions internal/cmd/pipeline/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ by pipeline status (PENDING, IN_PROGRESS, COMPLETED, FAILED, etc.).`,
cmd.Flags().BoolVar(&opts.JSON, "json", false, "Output in JSON format")
cmd.Flags().StringVarP(&opts.Repo, "repo", "R", "", "Repository in WORKSPACE/REPO format")

_ = cmd.RegisterFlagCompletionFunc("status", cmdutil.StaticFlagCompletion([]string{
"PENDING", "IN_PROGRESS", "COMPLETED", "FAILED", "STOPPED", "EXPIRED", "SUCCESSFUL",
}))
_ = cmd.RegisterFlagCompletionFunc("branch", cmdutil.CompleteBranchNames)
_ = cmd.RegisterFlagCompletionFunc("repo", cmdutil.CompleteRepoNames)

return cmd
Expand Down
4 changes: 2 additions & 2 deletions internal/cmd/repo/clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ to change this preference.`,
cmd.Flags().IntVar(&opts.depth, "depth", 0, "Create a shallow clone with a limited number of commits")
cmd.Flags().StringVarP(&opts.branch, "branch", "b", "", "Clone a specific branch")

cmd.ValidArgsFunction = cmdutil.CompleteRepoNames

return cmd
}

Expand Down Expand Up @@ -208,5 +210,3 @@ func extractRepoNameFromURL(url string) string {
}
return ""
}


2 changes: 2 additions & 0 deletions internal/cmd/repo/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ unless the --yes flag is provided.`,

cmd.Flags().BoolVarP(&opts.yes, "yes", "y", false, "Skip confirmation prompt")

cmd.ValidArgsFunction = cmdutil.CompleteRepoNames

return cmd
}

Expand Down
1 change: 1 addition & 0 deletions internal/cmd/repo/fork.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ as a new remote (default name: "fork").`,
cmd.Flags().BoolVarP(&opts.clone, "clone", "c", false, "Clone the fork after creation")
cmd.Flags().StringVar(&opts.remoteName, "remote-name", "fork", "Name for the new remote when in an existing clone")

cmd.ValidArgsFunction = cmdutil.CompleteRepoNames
_ = cmd.RegisterFlagCompletionFunc("workspace", cmdutil.CompleteWorkspaceNames)

return cmd
Expand Down
2 changes: 2 additions & 0 deletions internal/cmd/repo/setdefault.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ require a repository context.`,
cmd.Flags().BoolVar(&opts.View, "view", false, "Show the current default repository")
cmd.Flags().BoolVar(&opts.Unset, "unset", false, "Remove the default repository")

cmd.ValidArgsFunction = cmdutil.CompleteRepoNames

return cmd
}

Expand Down
2 changes: 2 additions & 0 deletions internal/cmd/repo/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ By default, the main branch is synced. Use --branch to specify a different branc
cmd.Flags().StringVarP(&opts.branch, "branch", "b", "", "Branch to sync (default: main branch)")
cmd.Flags().BoolVarP(&opts.force, "force", "f", false, "Force update (reset to upstream, discarding local changes)")

_ = cmd.RegisterFlagCompletionFunc("branch", cmdutil.CompleteBranchNames)

return cmd
}

Expand Down
2 changes: 2 additions & 0 deletions internal/cmd/repo/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ You can specify a repository using the workspace/repo format.`,
cmd.Flags().BoolVarP(&opts.web, "web", "w", false, "Open the repository in a web browser")
cmd.Flags().BoolVar(&opts.jsonOut, "json", false, "Output in JSON format")

cmd.ValidArgsFunction = cmdutil.CompleteRepoNames

return cmd
}

Expand Down
4 changes: 4 additions & 0 deletions internal/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/rbansal42/bitbucket-cli/internal/cmd/repo"
"github.com/rbansal42/bitbucket-cli/internal/cmd/snippet"
"github.com/rbansal42/bitbucket-cli/internal/cmd/workspace"
"github.com/rbansal42/bitbucket-cli/internal/cmdutil"
"github.com/rbansal42/bitbucket-cli/internal/iostreams"
)

Expand Down Expand Up @@ -66,6 +67,9 @@ func Execute() error {
func init() {
// Global flags
rootCmd.PersistentFlags().StringP("repo", "R", "", "Select a repository using the WORKSPACE/REPO format")
// Register completion for the persistent --repo flag. Subcommands that define
// their own local --repo flag will shadow this with their own registration.
_ = rootCmd.RegisterFlagCompletionFunc("repo", cmdutil.CompleteRepoNames)

// Version command
rootCmd.AddCommand(&cobra.Command{
Expand Down
3 changes: 3 additions & 0 deletions internal/cmd/snippet/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ Snippets are workspace-scoped and can be filtered by your role.`,
cmd.Flags().BoolVar(&opts.JSON, "json", false, "Output in JSON format")

_ = cmd.RegisterFlagCompletionFunc("workspace", cmdutil.CompleteWorkspaceNames)
_ = cmd.RegisterFlagCompletionFunc("role", cmdutil.StaticFlagCompletion([]string{
"owner", "contributor", "member",
}))

return cmd
}
Expand Down
26 changes: 20 additions & 6 deletions internal/cmdutil/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ import (
// completionTimeout is the maximum time allowed for completion API calls.
const completionTimeout = 5 * time.Second

// completionListPageSize is the page size for list-type API calls during completion.
const completionListPageSize = 50

// completionDetailPageSize is the page size for PR/issue API calls during completion.
// Smaller because these include more data per item.
const completionDetailPageSize = 30

// StaticFlagCompletion returns a completion function compatible with
// cobra.RegisterFlagCompletionFunc. It filters values by the toComplete
// prefix (case-insensitive) and always returns ShellCompDirectiveNoFileComp.
Expand Down Expand Up @@ -91,7 +98,7 @@ func CompleteWorkspaceNames(cmd *cobra.Command, args []string, toComplete string
ctx, cancel := completionCtx()
defer cancel()

result, err := client.ListWorkspaces(ctx, &api.WorkspaceListOptions{Limit: 50})
result, err := client.ListWorkspaces(ctx, &api.WorkspaceListOptions{Limit: completionListPageSize})
if err != nil {
return nil, cobra.ShellCompDirectiveNoFileComp
}
Expand Down Expand Up @@ -121,7 +128,7 @@ func CompleteRepoNames(cmd *cobra.Command, args []string, toComplete string) ([]
ctx, cancel := completionCtx()
defer cancel()

result, err := client.ListRepositories(ctx, ws, &api.RepositoryListOptions{Limit: 50})
result, err := client.ListRepositories(ctx, ws, &api.RepositoryListOptions{Limit: completionListPageSize})
if err != nil {
return nil, cobra.ShellCompDirectiveNoFileComp
}
Expand Down Expand Up @@ -149,7 +156,7 @@ func CompleteBranchNames(cmd *cobra.Command, args []string, toComplete string) (
ctx, cancel := completionCtx()
defer cancel()

result, err := client.ListBranches(ctx, ws, slug, &api.BranchListOptions{Limit: 50})
result, err := client.ListBranches(ctx, ws, slug, &api.BranchListOptions{Limit: completionListPageSize})
if err != nil {
return nil, cobra.ShellCompDirectiveNoFileComp
}
Expand Down Expand Up @@ -177,7 +184,7 @@ func CompletePRNumbers(cmd *cobra.Command, args []string, toComplete string) ([]
ctx, cancel := completionCtx()
defer cancel()

result, err := client.ListPullRequests(ctx, ws, slug, &api.PRListOptions{State: api.PRStateOpen, Limit: 30})
result, err := client.ListPullRequests(ctx, ws, slug, &api.PRListOptions{State: api.PRStateOpen, Limit: completionDetailPageSize})
if err != nil {
return nil, cobra.ShellCompDirectiveNoFileComp
}
Expand Down Expand Up @@ -205,7 +212,7 @@ func CompleteIssueIDs(cmd *cobra.Command, args []string, toComplete string) ([]s
ctx, cancel := completionCtx()
defer cancel()

result, err := client.ListIssues(ctx, ws, slug, &api.IssueListOptions{Limit: 30})
result, err := client.ListIssues(ctx, ws, slug, &api.IssueListOptions{Limit: completionDetailPageSize})
if err != nil {
return nil, cobra.ShellCompDirectiveNoFileComp
}
Expand Down Expand Up @@ -233,7 +240,7 @@ func CompleteWorkspaceMembers(cmd *cobra.Command, args []string, toComplete stri
ctx, cancel := completionCtx()
defer cancel()

result, err := client.ListWorkspaceMembers(ctx, ws, &api.WorkspaceMemberListOptions{Limit: 50})
result, err := client.ListWorkspaceMembers(ctx, ws, &api.WorkspaceMemberListOptions{Limit: completionListPageSize})
if err != nil {
return nil, cobra.ShellCompDirectiveNoFileComp
}
Expand All @@ -242,6 +249,9 @@ func CompleteWorkspaceMembers(cmd *cobra.Command, args []string, toComplete stri
for _, m := range result.Values {
if m.User != nil {
name := m.User.Nickname
if name == "" {
name = m.User.Username
}
if name == "" {
name = m.User.DisplayName
}
Expand All @@ -256,6 +266,10 @@ func CompleteWorkspaceMembers(cmd *cobra.Command, args []string, toComplete stri

// filterPrefix filters values by the toComplete prefix (case-insensitive).
// For tab-separated values ("id\tdescription"), only the part before the tab is matched.
//
// NOTE: Cobra's completion framework also performs its own prefix filtering. This
// function provides a safety net to reduce API response data before passing to Cobra,
// and handles the tab-separated value format correctly. The redundancy is intentional.
func filterPrefix(values []string, toComplete string) []string {
if toComplete == "" {
return values
Expand Down
Loading