Skip to content

Commit

Permalink
Merge pull request #4028 from cli/bump-cobra
Browse files Browse the repository at this point in the history
Upgrade Cobra for improved shell completion support
  • Loading branch information
mislav committed Jul 27, 2021
2 parents fdad37e + 2801206 commit f3a7d00
Show file tree
Hide file tree
Showing 8 changed files with 426 additions and 108 deletions.
10 changes: 5 additions & 5 deletions go.mod
Expand Up @@ -13,7 +13,7 @@ require (
github.com/cpuguy83/go-md2man/v2 v2.0.0
github.com/creack/pty v1.1.13
github.com/gabriel-vasile/mimetype v1.1.2
github.com/google/go-cmp v0.5.4
github.com/google/go-cmp v0.5.5
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/hashicorp/go-version v1.2.1
github.com/henvic/httpretty v0.0.6
Expand All @@ -28,14 +28,14 @@ require (
github.com/rivo/uniseg v0.2.0
github.com/shurcooL/githubv4 v0.0.0-20200928013246-d292edc3691b
github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f
github.com/spf13/cobra v1.1.3
github.com/spf13/cobra v1.2.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.6.1
github.com/stretchr/objx v0.1.1 // indirect
github.com/stretchr/testify v1.7.0
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
golang.org/x/sync v0.0.0-20190423024810-112230192c58
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/sys v0.0.0-20210601080250-7ecdf8ef093b
golang.org/x/term v0.0.0-20210503060354-a79de5458b56
golang.org/x/text v0.3.4 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)

Expand Down
441 changes: 354 additions & 87 deletions go.sum

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions pkg/cmd/completion/completion.go
Expand Up @@ -29,7 +29,9 @@ func NewCmdCompletion(io *iostreams.IOStreams) *cobra.Command {
### bash
Add this to your %[1]s~/.bash_profile%[1]s:
First, ensure that you install %[1]sbash-completion%[1]s using your package manager.
After, add this to your %[1]s~/.bash_profile%[1]s:
eval "$(gh completion -s bash)"
Expand Down Expand Up @@ -65,7 +67,7 @@ func NewCmdCompletion(io *iostreams.IOStreams) *cobra.Command {

switch shellType {
case "bash":
return rootCmd.GenBashCompletion(w)
return rootCmd.GenBashCompletionV2(w, true)
case "zsh":
return rootCmd.GenZshCompletion(w)
case "powershell":
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/issue/list/list.go
Expand Up @@ -83,7 +83,7 @@ func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Comman
cmd.Flags().StringSliceVarP(&opts.Labels, "label", "l", nil, "Filter by labels")
cmd.Flags().StringVarP(&opts.State, "state", "s", "open", "Filter by state: {open|closed|all}")
_ = cmd.RegisterFlagCompletionFunc("state", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return []string{"open", "closed", "all"}, cobra.ShellCompDirectiveNoSpace
return []string{"open", "closed", "all"}, cobra.ShellCompDirectiveNoFileComp
})
cmd.Flags().IntVarP(&opts.LimitResults, "limit", "L", 30, "Maximum number of issues to fetch")
cmd.Flags().StringVarP(&opts.Author, "author", "A", "", "Filter by author")
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/pr/list/list.go
Expand Up @@ -85,7 +85,7 @@ func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Comman
cmd.Flags().IntVarP(&opts.LimitResults, "limit", "L", 30, "Maximum number of items to fetch")
cmd.Flags().StringVarP(&opts.State, "state", "s", "open", "Filter by state: {open|closed|merged|all}")
_ = cmd.RegisterFlagCompletionFunc("state", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return []string{"open", "closed", "merged", "all"}, cobra.ShellCompDirectiveNoSpace
return []string{"open", "closed", "merged", "all"}, cobra.ShellCompDirectiveNoFileComp
})
cmd.Flags().StringVarP(&opts.BaseBranch, "base", "B", "", "Filter by base branch")
cmd.Flags().StringSliceVarP(&opts.Labels, "label", "l", nil, "Filter by labels")
Expand Down
57 changes: 51 additions & 6 deletions pkg/cmd/repo/create/create.go
Expand Up @@ -135,6 +135,51 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co
cmd.Flags().BoolVarP(&opts.ConfirmSubmit, "confirm", "y", false, "Skip the confirmation prompt")
cmd.Flags().StringVarP(&opts.GitIgnoreTemplate, "gitignore", "g", "", "Specify a gitignore template for the repository")
cmd.Flags().StringVarP(&opts.LicenseTemplate, "license", "l", "", "Specify an Open Source License for the repository")

_ = cmd.RegisterFlagCompletionFunc("gitignore", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
httpClient, err := opts.HttpClient()
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
cfg, err := opts.Config()
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
hostname, err := cfg.DefaultHost()
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
results, err := listGitIgnoreTemplates(httpClient, hostname)
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
return results, cobra.ShellCompDirectiveNoFileComp
})

_ = cmd.RegisterFlagCompletionFunc("license", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
httpClient, err := opts.HttpClient()
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
cfg, err := opts.Config()
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
hostname, err := cfg.DefaultHost()
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
licenses, err := listLicenseTemplates(httpClient, hostname)
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
var results []string
for _, license := range licenses {
results = append(results, fmt.Sprintf("%s\t%s", license.Key, license.Name))
}
return results, cobra.ShellCompDirectiveNoFileComp
})

return cmd
}

Expand Down Expand Up @@ -225,14 +270,14 @@ func createRun(opts *CreateOptions) error {
// is passed, or when the confirm flag is set.
if opts.Template == "" && opts.IO.CanPrompt() && !opts.ConfirmSubmit {
if gitIgnoreTemplate == "" {
gt, err := interactiveGitIgnore(api.NewClientFromHTTP(httpClient), host)
gt, err := interactiveGitIgnore(httpClient, host)
if err != nil {
return err
}
gitIgnoreTemplate = gt
}
if repoLicenseTemplate == "" {
lt, err := interactiveLicense(api.NewClientFromHTTP(httpClient), host)
lt, err := interactiveLicense(httpClient, host)
if err != nil {
return err
}
Expand Down Expand Up @@ -384,7 +429,7 @@ func createRun(opts *CreateOptions) error {
return nil
}

func interactiveGitIgnore(client *api.Client, hostname string) (string, error) {
func interactiveGitIgnore(client *http.Client, hostname string) (string, error) {

var addGitIgnore bool
var addGitIgnoreSurvey []*survey.Question
Expand All @@ -408,7 +453,7 @@ func interactiveGitIgnore(client *api.Client, hostname string) (string, error) {
if addGitIgnore {
var gitIg []*survey.Question

gitIgnoretemplates, err := ListGitIgnoreTemplates(client, hostname)
gitIgnoretemplates, err := listGitIgnoreTemplates(client, hostname)
if err != nil {
return "", err
}
Expand All @@ -429,7 +474,7 @@ func interactiveGitIgnore(client *api.Client, hostname string) (string, error) {
return wantedIgnoreTemplate, nil
}

func interactiveLicense(client *api.Client, hostname string) (string, error) {
func interactiveLicense(client *http.Client, hostname string) (string, error) {
var addLicense bool
var addLicenseSurvey []*survey.Question
var wantedLicense string
Expand All @@ -451,7 +496,7 @@ func interactiveLicense(client *api.Client, hostname string) (string, error) {
licenseKey := map[string]string{}

if addLicense {
licenseTemplates, err := ListLicenseTemplates(client, hostname)
licenseTemplates, err := listLicenseTemplates(client, hostname)
if err != nil {
return "", err
}
Expand Down
10 changes: 6 additions & 4 deletions pkg/cmd/repo/create/http.go
Expand Up @@ -230,19 +230,21 @@ func resolveOrganizationTeam(client *api.Client, hostname, orgName, teamSlug str
return &response, err
}

// ListGitIgnoreTemplates uses API v3 here because gitignore template isn't supported by GraphQL yet.
func ListGitIgnoreTemplates(client *api.Client, hostname string) ([]string, error) {
// listGitIgnoreTemplates uses API v3 here because gitignore template isn't supported by GraphQL yet.
func listGitIgnoreTemplates(httpClient *http.Client, hostname string) ([]string, error) {
var gitIgnoreTemplates []string
client := api.NewClientFromHTTP(httpClient)
err := client.REST(hostname, "GET", "gitignore/templates", nil, &gitIgnoreTemplates)
if err != nil {
return []string{}, err
}
return gitIgnoreTemplates, nil
}

// ListLicenseTemplates uses API v3 here because license template isn't supported by GraphQL yet.
func ListLicenseTemplates(client *api.Client, hostname string) ([]api.License, error) {
// listLicenseTemplates uses API v3 here because license template isn't supported by GraphQL yet.
func listLicenseTemplates(httpClient *http.Client, hostname string) ([]api.License, error) {
var licenseTemplates []api.License
client := api.NewClientFromHTTP(httpClient)
err := client.REST(hostname, "GET", "licenses", nil, &licenseTemplates)
if err != nil {
return nil, err
Expand Down
6 changes: 4 additions & 2 deletions pkg/cmdutil/json_flags.go
Expand Up @@ -29,13 +29,15 @@ func AddJSONFlags(cmd *cobra.Command, exportTarget *Exporter, fields []string) {

_ = cmd.RegisterFlagCompletionFunc("json", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
var results []string
if idx := strings.IndexRune(toComplete, ','); idx >= 0 {
var prefix string
if idx := strings.LastIndexByte(toComplete, ','); idx >= 0 {
prefix = toComplete[:idx+1]
toComplete = toComplete[idx+1:]
}
toComplete = strings.ToLower(toComplete)
for _, f := range fields {
if strings.HasPrefix(strings.ToLower(f), toComplete) {
results = append(results, f)
results = append(results, prefix+f)
}
}
sort.Strings(results)
Expand Down

0 comments on commit f3a7d00

Please sign in to comment.