From e3569dc7bde3a6812e529b64d4e2643897533742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Fri, 2 Jun 2023 13:31:02 +0200 Subject: [PATCH 1/4] Fix bash completions for extensions and aliases Now that extensions and alises are real Cobra Command instances, they will appear in completions automatically and don't need to be additionally inserted via ValidArgs. Their addition to ValidArgs have caused all extensions and aliases to be listed twice within completion results, which didn't seem to affect zsh completions at all, but in bash completions it had caused the completion description to be a part of the expansion. --- pkg/cmd/root/root.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkg/cmd/root/root.go b/pkg/cmd/root/root.go index 17e4180e3..437063d77 100644 --- a/pkg/cmd/root/root.go +++ b/pkg/cmd/root/root.go @@ -168,10 +168,8 @@ func NewCmdRoot(f *cmdutil.Factory, version, buildDate string) (*cobra.Command, // Extensions em := f.ExtensionManager for _, e := range em.List() { - extension := e extensionCmd := NewCmdExtension(io, em, e) cmd.AddCommand(extensionCmd) - cmd.ValidArgs = append(cmd.ValidArgs, fmt.Sprintf("%s\t%s", extension.Name(), extensionCmd.Short)) } // Aliases @@ -193,7 +191,6 @@ func NewCmdRoot(f *cmdutil.Factory, version, buildDate string) (*cobra.Command, if strings.HasPrefix(aliasValue, "!") { shellAliasCmd := NewCmdShellAlias(io, parentArgs[0], aliasValue) parentCmd.AddCommand(shellAliasCmd) - parentCmd.ValidArgs = append(parentCmd.ValidArgs, fmt.Sprintf("%s\tShell alias", aliasName)) } else { aliasCmd := NewCmdAlias(io, parentArgs[0], aliasValue) split, _ := shlex.Split(aliasValue) @@ -205,7 +202,6 @@ func NewCmdRoot(f *cmdutil.Factory, version, buildDate string) (*cobra.Command, rootHelpFunc(f, child, args) }) parentCmd.AddCommand(aliasCmd) - parentCmd.ValidArgs = append(parentCmd.ValidArgs, fmt.Sprintf("%s\tAlias for %s", aliasName, aliasValue)) } } } From 9ccd098eb0664f80d4ea9fd2a4d400c381203531 Mon Sep 17 00:00:00 2001 From: Kousik Mitra Date: Mon, 5 Jun 2023 22:07:04 +0530 Subject: [PATCH 2/4] Add gist selector option to gist edit command --- pkg/cmd/gist/edit/edit.go | 45 ++++++++----- pkg/cmd/gist/shared/shared.go | 57 ++++++++++++++++ pkg/cmd/gist/shared/shared_test.go | 100 +++++++++++++++++++++++++++++ pkg/cmd/gist/view/view.go | 60 ++--------------- pkg/cmd/gist/view/view_test.go | 94 --------------------------- 5 files changed, 190 insertions(+), 166 deletions(-) diff --git a/pkg/cmd/gist/edit/edit.go b/pkg/cmd/gist/edit/edit.go index 773ea41df..bbe62d80b 100644 --- a/pkg/cmd/gist/edit/edit.go +++ b/pkg/cmd/gist/edit/edit.go @@ -55,16 +55,15 @@ func NewCmdEdit(f *cmdutil.Factory, runF func(*EditOptions) error) *cobra.Comman Use: "edit { | } []", Short: "Edit one of your gists", Args: func(cmd *cobra.Command, args []string) error { - if len(args) < 1 { - return cmdutil.FlagErrorf("cannot edit: gist argument required") - } if len(args) > 2 { return cmdutil.FlagErrorf("too many arguments") } return nil }, RunE: func(c *cobra.Command, args []string) error { - opts.Selector = args[0] + if len(args) > 0 { + opts.Selector = args[0] + } if len(args) > 1 { opts.SourceFile = args[1] } @@ -85,7 +84,33 @@ func NewCmdEdit(f *cmdutil.Factory, runF func(*EditOptions) error) *cobra.Comman } func editRun(opts *EditOptions) error { + client, err := opts.HttpClient() + if err != nil { + return err + } + + cfg, err := opts.Config() + if err != nil { + return err + } + + host, _ := cfg.Authentication().DefaultHost() + gistID := opts.Selector + if gistID == "" { + cs := opts.IO.ColorScheme() + if gistID == "" { + gistID, err = shared.PromptGists(client, host, cs) + if err != nil { + return err + } + + if gistID == "" { + fmt.Fprintln(opts.IO.Out, "No gists found.") + return nil + } + } + } if strings.Contains(gistID, "/") { id, err := shared.GistIDFromURL(gistID) @@ -95,20 +120,8 @@ func editRun(opts *EditOptions) error { gistID = id } - client, err := opts.HttpClient() - if err != nil { - return err - } - apiClient := api.NewClientFromHTTP(client) - cfg, err := opts.Config() - if err != nil { - return err - } - - host, _ := cfg.Authentication().DefaultHost() - gist, err := shared.GetGist(client, host, gistID) if err != nil { if errors.Is(err, shared.NotFoundErr) { diff --git a/pkg/cmd/gist/shared/shared.go b/pkg/cmd/gist/shared/shared.go index 52c86caa7..547140838 100644 --- a/pkg/cmd/gist/shared/shared.go +++ b/pkg/cmd/gist/shared/shared.go @@ -5,10 +5,15 @@ import ( "fmt" "net/http" "net/url" + "sort" "strings" "time" + "github.com/AlecAivazis/survey/v2" "github.com/cli/cli/v2/api" + "github.com/cli/cli/v2/internal/text" + "github.com/cli/cli/v2/pkg/iostreams" + "github.com/cli/cli/v2/pkg/prompt" "github.com/gabriel-vasile/mimetype" "github.com/shurcooL/githubv4" ) @@ -171,3 +176,55 @@ func IsBinaryContents(contents []byte) bool { } return isBinary } + +func PromptGists(client *http.Client, host string, cs *iostreams.ColorScheme) (gistID string, err error) { + gists, err := ListGists(client, host, 10, "all") + if err != nil { + return "", err + } + + if len(gists) == 0 { + return "", nil + } + + var opts []string + var result int + var gistIDs = make([]string, len(gists)) + + for i, gist := range gists { + gistIDs[i] = gist.ID + description := "" + gistName := "" + + if gist.Description != "" { + description = gist.Description + } + + filenames := make([]string, 0, len(gist.Files)) + for fn := range gist.Files { + filenames = append(filenames, fn) + } + sort.Strings(filenames) + gistName = filenames[0] + + gistTime := text.FuzzyAgo(time.Now(), gist.UpdatedAt) + // TODO: support dynamic maxWidth + description = text.Truncate(100, text.RemoveExcessiveWhitespace(description)) + opt := fmt.Sprintf("%s %s %s", cs.Bold(gistName), description, cs.Gray(gistTime)) + opts = append(opts, opt) + } + + questions := &survey.Select{ + Message: "Select a gist", + Options: opts, + } + + //nolint:staticcheck // SA1019: prompt.SurveyAskOne is deprecated: use Prompter + err = prompt.SurveyAskOne(questions, &result) + + if err != nil { + return "", err + } + + return gistIDs[result], nil +} diff --git a/pkg/cmd/gist/shared/shared_test.go b/pkg/cmd/gist/shared/shared_test.go index c55cbea67..0811464e5 100644 --- a/pkg/cmd/gist/shared/shared_test.go +++ b/pkg/cmd/gist/shared/shared_test.go @@ -1,8 +1,14 @@ package shared import ( + "fmt" + "net/http" "testing" + "time" + "github.com/cli/cli/v2/pkg/httpmock" + "github.com/cli/cli/v2/pkg/iostreams" + "github.com/cli/cli/v2/pkg/prompt" "github.com/stretchr/testify/assert" ) @@ -85,3 +91,97 @@ func TestIsBinaryContents(t *testing.T) { assert.Equal(t, tt.want, IsBinaryContents(tt.fileContent)) } } + +func TestPromptGists(t *testing.T) { + tests := []struct { + name string + askStubs func(as *prompt.AskStubber) + response string + wantOut string + gist *Gist + wantErr bool + }{ + { + name: "multiple files, select first gist", + askStubs: func(as *prompt.AskStubber) { + as.StubPrompt("Select a gist").AnswerWith("cool.txt about 6 hours ago") + }, + response: `{ "data": { "viewer": { "gists": { "nodes": [ + { + "name": "gistid1", + "files": [{ "name": "cool.txt" }], + "description": "", + "updatedAt": "%[1]v", + "isPublic": true + }, + { + "name": "gistid2", + "files": [{ "name": "gistfile0.txt" }], + "description": "", + "updatedAt": "%[1]v", + "isPublic": true + } + ] } } } }`, + wantOut: "gistid1", + }, + { + name: "multiple files, select second gist", + askStubs: func(as *prompt.AskStubber) { + as.StubPrompt("Select a gist").AnswerWith("gistfile0.txt about 6 hours ago") + }, + response: `{ "data": { "viewer": { "gists": { "nodes": [ + { + "name": "gistid1", + "files": [{ "name": "cool.txt" }], + "description": "", + "updatedAt": "%[1]v", + "isPublic": true + }, + { + "name": "gistid2", + "files": [{ "name": "gistfile0.txt" }], + "description": "", + "updatedAt": "%[1]v", + "isPublic": true + } + ] } } } }`, + wantOut: "gistid2", + }, + { + name: "no files", + response: `{ "data": { "viewer": { "gists": { "nodes": [] } } } }`, + wantOut: "", + }, + } + + ios, _, _, _ := iostreams.Test() + + for _, tt := range tests { + reg := &httpmock.Registry{} + + const query = `query GistList\b` + sixHours, _ := time.ParseDuration("6h") + sixHoursAgo := time.Now().Add(-sixHours) + reg.Register( + httpmock.GraphQL(query), + httpmock.StringResponse(fmt.Sprintf( + tt.response, + sixHoursAgo.Format(time.RFC3339), + )), + ) + client := &http.Client{Transport: reg} + + t.Run(tt.name, func(t *testing.T) { + //nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock + as := prompt.NewAskStubber(t) + if tt.askStubs != nil { + tt.askStubs(as) + } + + gistID, err := PromptGists(client, "github.com", ios.ColorScheme()) + assert.NoError(t, err) + assert.Equal(t, tt.wantOut, gistID) + reg.Verify(t) + }) + } +} diff --git a/pkg/cmd/gist/view/view.go b/pkg/cmd/gist/view/view.go index 545681522..ffc5d54a9 100644 --- a/pkg/cmd/gist/view/view.go +++ b/pkg/cmd/gist/view/view.go @@ -5,17 +5,15 @@ import ( "net/http" "sort" "strings" - "time" - "github.com/AlecAivazis/survey/v2" "github.com/cli/cli/v2/internal/config" "github.com/cli/cli/v2/internal/ghinstance" + "github.com/cli/cli/v2/internal/prompter" "github.com/cli/cli/v2/internal/text" "github.com/cli/cli/v2/pkg/cmd/gist/shared" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/iostreams" "github.com/cli/cli/v2/pkg/markdown" - "github.com/cli/cli/v2/pkg/prompt" "github.com/spf13/cobra" ) @@ -28,6 +26,7 @@ type ViewOptions struct { Config func() (config.Config, error) HttpClient func() (*http.Client, error) Browser browser + Prompter prompter.Prompter Selector string Filename string @@ -42,6 +41,7 @@ func NewCmdView(f *cmdutil.Factory, runF func(*ViewOptions) error) *cobra.Comman Config: f.Config, HttpClient: f.HttpClient, Browser: f.Browser, + Prompter: f.Prompter, } cmd := &cobra.Command{ @@ -89,7 +89,7 @@ func viewRun(opts *ViewOptions) error { cs := opts.IO.ColorScheme() if gistID == "" { - gistID, err = promptGists(client, hostname, cs) + gistID, err = shared.PromptGists(client, hostname, cs) if err != nil { return err } @@ -204,55 +204,3 @@ func viewRun(opts *ViewOptions) error { return nil } - -func promptGists(client *http.Client, host string, cs *iostreams.ColorScheme) (gistID string, err error) { - gists, err := shared.ListGists(client, host, 10, "all") - if err != nil { - return "", err - } - - if len(gists) == 0 { - return "", nil - } - - var opts []string - var result int - var gistIDs = make([]string, len(gists)) - - for i, gist := range gists { - gistIDs[i] = gist.ID - description := "" - gistName := "" - - if gist.Description != "" { - description = gist.Description - } - - filenames := make([]string, 0, len(gist.Files)) - for fn := range gist.Files { - filenames = append(filenames, fn) - } - sort.Strings(filenames) - gistName = filenames[0] - - gistTime := text.FuzzyAgo(time.Now(), gist.UpdatedAt) - // TODO: support dynamic maxWidth - description = text.Truncate(100, text.RemoveExcessiveWhitespace(description)) - opt := fmt.Sprintf("%s %s %s", cs.Bold(gistName), description, cs.Gray(gistTime)) - opts = append(opts, opt) - } - - questions := &survey.Select{ - Message: "Select a gist", - Options: opts, - } - - //nolint:staticcheck // SA1019: prompt.SurveyAskOne is deprecated: use Prompter - err = prompt.SurveyAskOne(questions, &result) - - if err != nil { - return "", err - } - - return gistIDs[result], nil -} diff --git a/pkg/cmd/gist/view/view_test.go b/pkg/cmd/gist/view/view_test.go index 8dbc9a748..49cf878ec 100644 --- a/pkg/cmd/gist/view/view_test.go +++ b/pkg/cmd/gist/view/view_test.go @@ -389,97 +389,3 @@ func Test_viewRun(t *testing.T) { }) } } - -func Test_promptGists(t *testing.T) { - tests := []struct { - name string - askStubs func(as *prompt.AskStubber) - response string - wantOut string - gist *shared.Gist - wantErr bool - }{ - { - name: "multiple files, select first gist", - askStubs: func(as *prompt.AskStubber) { - as.StubPrompt("Select a gist").AnswerWith("cool.txt about 6 hours ago") - }, - response: `{ "data": { "viewer": { "gists": { "nodes": [ - { - "name": "gistid1", - "files": [{ "name": "cool.txt" }], - "description": "", - "updatedAt": "%[1]v", - "isPublic": true - }, - { - "name": "gistid2", - "files": [{ "name": "gistfile0.txt" }], - "description": "", - "updatedAt": "%[1]v", - "isPublic": true - } - ] } } } }`, - wantOut: "gistid1", - }, - { - name: "multiple files, select second gist", - askStubs: func(as *prompt.AskStubber) { - as.StubPrompt("Select a gist").AnswerWith("gistfile0.txt about 6 hours ago") - }, - response: `{ "data": { "viewer": { "gists": { "nodes": [ - { - "name": "gistid1", - "files": [{ "name": "cool.txt" }], - "description": "", - "updatedAt": "%[1]v", - "isPublic": true - }, - { - "name": "gistid2", - "files": [{ "name": "gistfile0.txt" }], - "description": "", - "updatedAt": "%[1]v", - "isPublic": true - } - ] } } } }`, - wantOut: "gistid2", - }, - { - name: "no files", - response: `{ "data": { "viewer": { "gists": { "nodes": [] } } } }`, - wantOut: "", - }, - } - - ios, _, _, _ := iostreams.Test() - - for _, tt := range tests { - reg := &httpmock.Registry{} - - const query = `query GistList\b` - sixHours, _ := time.ParseDuration("6h") - sixHoursAgo := time.Now().Add(-sixHours) - reg.Register( - httpmock.GraphQL(query), - httpmock.StringResponse(fmt.Sprintf( - tt.response, - sixHoursAgo.Format(time.RFC3339), - )), - ) - client := &http.Client{Transport: reg} - - t.Run(tt.name, func(t *testing.T) { - //nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock - as := prompt.NewAskStubber(t) - if tt.askStubs != nil { - tt.askStubs(as) - } - - gistID, err := promptGists(client, "github.com", ios.ColorScheme()) - assert.NoError(t, err) - assert.Equal(t, tt.wantOut, gistID) - reg.Verify(t) - }) - } -} From 31209bcf896a029bda027d11f1102c4c463ee3e0 Mon Sep 17 00:00:00 2001 From: Kousik Mitra Date: Mon, 5 Jun 2023 22:48:21 +0530 Subject: [PATCH 3/4] Replace SurveyAskOne with Prompter --- pkg/cmd/gist/edit/edit.go | 30 ++++++---------- pkg/cmd/gist/edit/edit_test.go | 56 +++++++++++++++++++----------- pkg/cmd/gist/shared/shared.go | 14 ++------ pkg/cmd/gist/shared/shared_test.go | 39 +++++++++++++-------- pkg/cmd/gist/view/view.go | 2 +- pkg/cmd/gist/view/view_test.go | 18 +++++----- 6 files changed, 84 insertions(+), 75 deletions(-) diff --git a/pkg/cmd/gist/edit/edit.go b/pkg/cmd/gist/edit/edit.go index bbe62d80b..3ad28b6c4 100644 --- a/pkg/cmd/gist/edit/edit.go +++ b/pkg/cmd/gist/edit/edit.go @@ -12,21 +12,23 @@ import ( "sort" "strings" - "github.com/AlecAivazis/survey/v2" "github.com/cli/cli/v2/api" "github.com/cli/cli/v2/internal/config" + "github.com/cli/cli/v2/internal/prompter" "github.com/cli/cli/v2/pkg/cmd/gist/shared" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/iostreams" - "github.com/cli/cli/v2/pkg/prompt" "github.com/cli/cli/v2/pkg/surveyext" "github.com/spf13/cobra" ) +var editNextOptions = []string{"Edit another file", "Submit", "Cancel"} + type EditOptions struct { IO *iostreams.IOStreams HttpClient func() (*http.Client, error) Config func() (config.Config, error) + Prompter prompter.Prompter Edit func(string, string, string, *iostreams.IOStreams) (string, error) @@ -42,6 +44,7 @@ func NewCmdEdit(f *cmdutil.Factory, runF func(*EditOptions) error) *cobra.Comman IO: f.IOStreams, HttpClient: f.HttpClient, Config: f.Config, + Prompter: f.Prompter, Edit: func(editorCmd, filename, defaultContent string, io *iostreams.IOStreams) (string, error) { return surveyext.Edit( editorCmd, @@ -100,7 +103,7 @@ func editRun(opts *EditOptions) error { if gistID == "" { cs := opts.IO.ColorScheme() if gistID == "" { - gistID, err = shared.PromptGists(client, host, cs) + gistID, err = shared.PromptGists(opts.Prompter, client, host, cs) if err != nil { return err } @@ -202,15 +205,11 @@ func editRun(opts *EditOptions) error { if !opts.IO.CanPrompt() { return errors.New("unsure what file to edit; either specify --filename or run interactively") } - //nolint:staticcheck // SA1019: prompt.SurveyAskOne is deprecated: use Prompter - err = prompt.SurveyAskOne(&survey.Select{ - Message: "Edit which file?", - Options: candidates, - }, &filename) - + result, err := opts.Prompter.Select("Edit which file?", "", candidates) if err != nil { return fmt.Errorf("could not prompt: %w", err) } + filename = candidates[result] } } @@ -262,20 +261,11 @@ func editRun(opts *EditOptions) error { } choice := "" - - //nolint:staticcheck // SA1019: prompt.SurveyAskOne is deprecated: use Prompter - err = prompt.SurveyAskOne(&survey.Select{ - Message: "What next?", - Options: []string{ - "Edit another file", - "Submit", - "Cancel", - }, - }, &choice) - + result, err := opts.Prompter.Select("What next?", "", editNextOptions) if err != nil { return fmt.Errorf("could not prompt: %w", err) } + choice = editNextOptions[result] stop := false diff --git a/pkg/cmd/gist/edit/edit_test.go b/pkg/cmd/gist/edit/edit_test.go index 33223ddee..5e52a8ffb 100644 --- a/pkg/cmd/gist/edit/edit_test.go +++ b/pkg/cmd/gist/edit/edit_test.go @@ -10,11 +10,11 @@ import ( "testing" "github.com/cli/cli/v2/internal/config" + "github.com/cli/cli/v2/internal/prompter" "github.com/cli/cli/v2/pkg/cmd/gist/shared" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" - "github.com/cli/cli/v2/pkg/prompt" "github.com/google/shlex" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -115,15 +115,15 @@ func Test_editRun(t *testing.T) { require.NoError(t, err) tests := []struct { - name string - opts *EditOptions - gist *shared.Gist - httpStubs func(*httpmock.Registry) - askStubs func(*prompt.AskStubber) - nontty bool - stdin string - wantErr string - wantParams map[string]interface{} + name string + opts *EditOptions + gist *shared.Gist + httpStubs func(*httpmock.Registry) + prompterStubs func(*prompter.MockPrompter) + nontty bool + stdin string + wantErr string + wantParams map[string]interface{} }{ { name: "no such gist", @@ -161,9 +161,17 @@ func Test_editRun(t *testing.T) { }, { name: "multiple files, submit", - askStubs: func(as *prompt.AskStubber) { - as.StubPrompt("Edit which file?").AnswerWith("unix.md") - as.StubPrompt("What next?").AnswerWith("Submit") + prompterStubs: func(pm *prompter.MockPrompter) { + pm.RegisterSelect("Edit which file?", + []string{"cicada.txt", "unix.md"}, + func(_, _ string, opts []string) (int, error) { + return prompter.IndexFor(opts, "unix.md") + }) + pm.RegisterSelect("What next?", + editNextOptions, + func(_, _ string, opts []string) (int, error) { + return prompter.IndexFor(opts, "Submit") + }) }, gist: &shared.Gist{ ID: "1234", @@ -206,9 +214,17 @@ func Test_editRun(t *testing.T) { }, { name: "multiple files, cancel", - askStubs: func(as *prompt.AskStubber) { - as.StubPrompt("Edit which file?").AnswerWith("unix.md") - as.StubPrompt("What next?").AnswerWith("Cancel") + prompterStubs: func(pm *prompter.MockPrompter) { + pm.RegisterSelect("Edit which file?", + []string{"cicada.txt", "unix.md"}, + func(_, _ string, opts []string) (int, error) { + return prompter.IndexFor(opts, "unix.md") + }) + pm.RegisterSelect("What next?", + editNextOptions, + func(_, _ string, opts []string) (int, error) { + return prompter.IndexFor(opts, "Cancel") + }) }, wantErr: "CancelError", gist: &shared.Gist{ @@ -486,11 +502,11 @@ func Test_editRun(t *testing.T) { } t.Run(tt.name, func(t *testing.T) { - //nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock - as := prompt.NewAskStubber(t) - if tt.askStubs != nil { - tt.askStubs(as) + pm := prompter.NewMockPrompter(t) + if tt.prompterStubs != nil { + tt.prompterStubs(pm) } + tt.opts.Prompter = pm err := editRun(tt.opts) reg.Verify(t) diff --git a/pkg/cmd/gist/shared/shared.go b/pkg/cmd/gist/shared/shared.go index 547140838..66ba6fe0a 100644 --- a/pkg/cmd/gist/shared/shared.go +++ b/pkg/cmd/gist/shared/shared.go @@ -9,11 +9,10 @@ import ( "strings" "time" - "github.com/AlecAivazis/survey/v2" "github.com/cli/cli/v2/api" + "github.com/cli/cli/v2/internal/prompter" "github.com/cli/cli/v2/internal/text" "github.com/cli/cli/v2/pkg/iostreams" - "github.com/cli/cli/v2/pkg/prompt" "github.com/gabriel-vasile/mimetype" "github.com/shurcooL/githubv4" ) @@ -177,7 +176,7 @@ func IsBinaryContents(contents []byte) bool { return isBinary } -func PromptGists(client *http.Client, host string, cs *iostreams.ColorScheme) (gistID string, err error) { +func PromptGists(prompter prompter.Prompter, client *http.Client, host string, cs *iostreams.ColorScheme) (gistID string, err error) { gists, err := ListGists(client, host, 10, "all") if err != nil { return "", err @@ -188,7 +187,6 @@ func PromptGists(client *http.Client, host string, cs *iostreams.ColorScheme) (g } var opts []string - var result int var gistIDs = make([]string, len(gists)) for i, gist := range gists { @@ -214,13 +212,7 @@ func PromptGists(client *http.Client, host string, cs *iostreams.ColorScheme) (g opts = append(opts, opt) } - questions := &survey.Select{ - Message: "Select a gist", - Options: opts, - } - - //nolint:staticcheck // SA1019: prompt.SurveyAskOne is deprecated: use Prompter - err = prompt.SurveyAskOne(questions, &result) + result, err := prompter.Select("Select a gist", "", opts) if err != nil { return "", err diff --git a/pkg/cmd/gist/shared/shared_test.go b/pkg/cmd/gist/shared/shared_test.go index 0811464e5..1ec66d156 100644 --- a/pkg/cmd/gist/shared/shared_test.go +++ b/pkg/cmd/gist/shared/shared_test.go @@ -6,9 +6,9 @@ import ( "testing" "time" + "github.com/cli/cli/v2/internal/prompter" "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" - "github.com/cli/cli/v2/pkg/prompt" "github.com/stretchr/testify/assert" ) @@ -94,17 +94,21 @@ func TestIsBinaryContents(t *testing.T) { func TestPromptGists(t *testing.T) { tests := []struct { - name string - askStubs func(as *prompt.AskStubber) - response string - wantOut string - gist *Gist - wantErr bool + name string + prompterStubs func(pm *prompter.MockPrompter) + response string + wantOut string + gist *Gist + wantErr bool }{ { name: "multiple files, select first gist", - askStubs: func(as *prompt.AskStubber) { - as.StubPrompt("Select a gist").AnswerWith("cool.txt about 6 hours ago") + prompterStubs: func(pm *prompter.MockPrompter) { + pm.RegisterSelect("Select a gist", + []string{"cool.txt about 6 hours ago", "gistfile0.txt about 6 hours ago"}, + func(_, _ string, opts []string) (int, error) { + return prompter.IndexFor(opts, "cool.txt about 6 hours ago") + }) }, response: `{ "data": { "viewer": { "gists": { "nodes": [ { @@ -126,8 +130,12 @@ func TestPromptGists(t *testing.T) { }, { name: "multiple files, select second gist", - askStubs: func(as *prompt.AskStubber) { - as.StubPrompt("Select a gist").AnswerWith("gistfile0.txt about 6 hours ago") + prompterStubs: func(pm *prompter.MockPrompter) { + pm.RegisterSelect("Select a gist", + []string{"cool.txt about 6 hours ago", "gistfile0.txt about 6 hours ago"}, + func(_, _ string, opts []string) (int, error) { + return prompter.IndexFor(opts, "gistfile0.txt about 6 hours ago") + }) }, response: `{ "data": { "viewer": { "gists": { "nodes": [ { @@ -173,12 +181,13 @@ func TestPromptGists(t *testing.T) { t.Run(tt.name, func(t *testing.T) { //nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock - as := prompt.NewAskStubber(t) - if tt.askStubs != nil { - tt.askStubs(as) + + mockPrompter := prompter.NewMockPrompter(t) + if tt.prompterStubs != nil { + tt.prompterStubs(mockPrompter) } - gistID, err := PromptGists(client, "github.com", ios.ColorScheme()) + gistID, err := PromptGists(mockPrompter, client, "github.com", ios.ColorScheme()) assert.NoError(t, err) assert.Equal(t, tt.wantOut, gistID) reg.Verify(t) diff --git a/pkg/cmd/gist/view/view.go b/pkg/cmd/gist/view/view.go index ffc5d54a9..e4f5c84e1 100644 --- a/pkg/cmd/gist/view/view.go +++ b/pkg/cmd/gist/view/view.go @@ -89,7 +89,7 @@ func viewRun(opts *ViewOptions) error { cs := opts.IO.ColorScheme() if gistID == "" { - gistID, err = shared.PromptGists(client, hostname, cs) + gistID, err = shared.PromptGists(opts.Prompter, client, hostname, cs) if err != nil { return err } diff --git a/pkg/cmd/gist/view/view_test.go b/pkg/cmd/gist/view/view_test.go index 49cf878ec..c571422c5 100644 --- a/pkg/cmd/gist/view/view_test.go +++ b/pkg/cmd/gist/view/view_test.go @@ -8,11 +8,11 @@ import ( "time" "github.com/cli/cli/v2/internal/config" + "github.com/cli/cli/v2/internal/prompter" "github.com/cli/cli/v2/pkg/cmd/gist/shared" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" - "github.com/cli/cli/v2/pkg/prompt" "github.com/google/shlex" "github.com/stretchr/testify/assert" ) @@ -336,6 +336,10 @@ func Test_viewRun(t *testing.T) { httpmock.JSONResponse(tt.gist)) } + if tt.opts == nil { + tt.opts = &ViewOptions{} + } + if tt.mockGistList { sixHours, _ := time.ParseDuration("6h") sixHoursAgo := time.Now().Add(-sixHours) @@ -355,13 +359,11 @@ func Test_viewRun(t *testing.T) { )), ) - //nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock - as := prompt.NewAskStubber(t) - as.StubPrompt("Select a gist").AnswerDefault() - } - - if tt.opts == nil { - tt.opts = &ViewOptions{} + pm := prompter.NewMockPrompter(t) + pm.RegisterSelect("Select a gist", []string{"cool.txt about 6 hours ago"}, func(_, _ string, opts []string) (int, error) { + return 0, nil + }) + tt.opts.Prompter = pm } tt.opts.HttpClient = func() (*http.Client, error) { From 895487127c4f4256b9eeeea4cdf36dd899e6fea9 Mon Sep 17 00:00:00 2001 From: Kousik Mitra Date: Mon, 5 Jun 2023 22:54:35 +0530 Subject: [PATCH 4/4] Remove unused linter flag --- pkg/cmd/gist/shared/shared_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/cmd/gist/shared/shared_test.go b/pkg/cmd/gist/shared/shared_test.go index 1ec66d156..4d185ff7d 100644 --- a/pkg/cmd/gist/shared/shared_test.go +++ b/pkg/cmd/gist/shared/shared_test.go @@ -180,8 +180,6 @@ func TestPromptGists(t *testing.T) { client := &http.Client{Transport: reg} t.Run(tt.name, func(t *testing.T) { - //nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock - mockPrompter := prompter.NewMockPrompter(t) if tt.prompterStubs != nil { tt.prompterStubs(mockPrompter)