From 2090e1111f2ce7262c365b5c1b0005c601679581 Mon Sep 17 00:00:00 2001 From: vilmibm Date: Tue, 13 Dec 2022 11:57:05 -0800 Subject: [PATCH] tweak UX and switch to prompter --- pkg/cmd/repo/default/default.go | 41 ++++++++++++++++++------ pkg/cmd/repo/default/default_test.go | 48 ++++++++++++++++------------ 2 files changed, 60 insertions(+), 29 deletions(-) diff --git a/pkg/cmd/repo/default/default.go b/pkg/cmd/repo/default/default.go index b3df69e21..43b13c6db 100644 --- a/pkg/cmd/repo/default/default.go +++ b/pkg/cmd/repo/default/default.go @@ -9,7 +9,6 @@ import ( ctx "context" - "github.com/AlecAivazis/survey/v2" "github.com/MakeNowJust/heredoc" "github.com/cli/cli/v2/api" "github.com/cli/cli/v2/context" @@ -17,14 +16,18 @@ import ( "github.com/cli/cli/v2/internal/ghrepo" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/iostreams" - "github.com/cli/cli/v2/pkg/prompt" "github.com/spf13/cobra" ) +type iprompter interface { + Select(string, string, []string) (int, error) +} + type DefaultOptions struct { IO *iostreams.IOStreams Remotes func() (context.Remotes, error) HttpClient func() (*http.Client, error) + Prompter iprompter Repo ghrepo.Interface ViewMode bool @@ -35,6 +38,7 @@ func NewCmdDefault(f *cmdutil.Factory, runF func(*DefaultOptions) error) *cobra. IO: f.IOStreams, HttpClient: f.HttpClient, Remotes: f.Remotes, + Prompter: f.Prompter, } cmd := &cobra.Command{ @@ -129,13 +133,21 @@ func defaultRun(opts *DefaultOptions) error { return fmt.Errorf("%s does not correspond to any git remotes", ghrepo.FullName(opts.Repo)) } } + cs := opts.IO.ColorScheme() + + hintMsg := cs.Gray("(hint: for gh to see more remote repositories, add them with `git remote`)") if selectedRepo == nil { if len(knownRepos) == 1 { selectedRepo = knownRepos[0] + + fmt.Fprintf(opts.IO.Out, "Found only one known remote repo, %s on %s.\n", + cs.Bold(ghrepo.FullName(selectedRepo)), + cs.Bold(selectedRepo.RepoHost())) + fmt.Fprintln(opts.IO.Out, hintMsg) + fmt.Fprintln(opts.IO.Out) } else { var repoNames []string - var selectedName string current := "" if currentDefaultRepo != nil { current = ghrepo.FullName(currentDefaultRepo) @@ -145,14 +157,25 @@ func defaultRun(opts *DefaultOptions) error { repoNames = append(repoNames, ghrepo.FullName(knownRepo)) } - err := prompt.SurveyAskOne(&survey.Select{ - Message: "Which should be the default repository (used for e.g. querying issues) for this directory?", - Options: repoNames, - Default: current, - }, &selectedName) + defaultExplainer := heredoc.Doc(` + gh uses the default repository for things like: + + - viewing, creating, and setting the default base for pull requests + - viewing and creating issues + - viewing and creating releases + - working with Actions + - adding secrets + `) + + fmt.Fprintln(opts.IO.Out, defaultExplainer) + fmt.Fprintln(opts.IO.Out, hintMsg) + fmt.Fprintln(opts.IO.Out) + + selected, err := opts.Prompter.Select("Which repository should be the default?", current, repoNames) if err != nil { - return err + return fmt.Errorf("could not prompt: %w", err) } + selectedName := repoNames[selected] owner, repo, _ := strings.Cut(selectedName, "/") selectedRepo = ghrepo.New(owner, repo) diff --git a/pkg/cmd/repo/default/default_test.go b/pkg/cmd/repo/default/default_test.go index a057b28c9..b8c129da8 100644 --- a/pkg/cmd/repo/default/default_test.go +++ b/pkg/cmd/repo/default/default_test.go @@ -8,11 +8,11 @@ import ( "github.com/cli/cli/v2/context" "github.com/cli/cli/v2/git" "github.com/cli/cli/v2/internal/ghrepo" + "github.com/cli/cli/v2/internal/prompter" "github.com/cli/cli/v2/internal/run" "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" ) @@ -115,16 +115,16 @@ func TestDefaultRun(t *testing.T) { repo3, _ := ghrepo.FromFullName("OWNER3/REPO3") tests := []struct { - name string - tty bool - opts DefaultOptions - remotes []*context.Remote - httpStubs func(*httpmock.Registry) - gitStubs func(*run.CommandStubber) - askStubs func(*prompt.AskStubber) - wantStdout string - wantErr bool - errMsg string + name string + tty bool + opts DefaultOptions + remotes []*context.Remote + httpStubs func(*httpmock.Registry) + gitStubs func(*run.CommandStubber) + prompterStubs func(*prompter.PrompterMock) + wantStdout string + wantErr bool + errMsg string }{ { name: "view mode no current default", @@ -318,12 +318,18 @@ func TestDefaultRun(t *testing.T) { gitStubs: func(cs *run.CommandStubber) { cs.Register(`git config --add remote.upstream.gh-resolved base`, 0, "") }, - askStubs: func(as *prompt.AskStubber) { - as.StubPrompt("Which should be the default repository (used for e.g. querying issues) for this directory?"). - AssertOptions([]string{"OWNER/REPO", "OWNER2/REPO2"}). - AnswerWith("OWNER2/REPO2") + prompterStubs: func(pm *prompter.PrompterMock) { + pm.SelectFunc = func(p, d string, opts []string) (int, error) { + switch p { + case "Which repository should be the default?": + prompter.AssertOptions(t, []string{"OWNER/REPO", "OWNER2/REPO2"}, opts) + return prompter.IndexFor(opts, "OWNER2/REPO2") + default: + return -1, prompter.NoSuchPromptErr(p) + } + } }, - wantStdout: "āœ“ Set OWNER2/REPO2 as the default repository for the current directory\n", + wantStdout: "gh uses the default repository for things like:\n\n - viewing, creating, and setting the default base for pull requests\n - viewing and creating issues\n - viewing and creating releases\n - working with Actions\n - adding secrets\n\n(hint: for gh to see more remote repositories, add them with `git remote`)\n\nāœ“ Set OWNER2/REPO2 as the default repository for the current directory\n", }, { name: "interactive mode only one known host", @@ -348,7 +354,7 @@ func TestDefaultRun(t *testing.T) { gitStubs: func(cs *run.CommandStubber) { cs.Register(`git config --add remote.upstream.gh-resolved base`, 0, "") }, - wantStdout: "āœ“ Set OWNER2/REPO2 as the default repository for the current directory\n", + wantStdout: "Found only one known remote repo, OWNER2/REPO2 on github.com.\n(hint: for gh to see more remote repositories, add them with `git remote`)\n\nāœ“ Set OWNER2/REPO2 as the default repository for the current directory\n", }, } @@ -371,11 +377,13 @@ func TestDefaultRun(t *testing.T) { return tt.remotes, nil } - as := prompt.NewAskStubber(t) - if tt.askStubs != nil { - tt.askStubs(as) + pm := &prompter.PrompterMock{} + if tt.prompterStubs != nil { + tt.prompterStubs(pm) } + tt.opts.Prompter = pm + t.Run(tt.name, func(t *testing.T) { cs, teardown := run.Stub() defer teardown(t)