diff --git a/cmd/gh/main.go b/cmd/gh/main.go index 891d4b98f..7ee00b061 100644 --- a/cmd/gh/main.go +++ b/cmd/gh/main.go @@ -93,15 +93,6 @@ func mainRun() exitCode { return exitError } - if prompt, _ := cfg.Get("", "prompt"); prompt == "disabled" { - cmdFactory.IOStreams.SetNeverPrompt(true) - } - if ghPager, ghPagerExists := os.LookupEnv("GH_PAGER"); ghPagerExists { - cmdFactory.IOStreams.SetPager(ghPager) - } else if pager, _ := cfg.Get("", "pager"); pager != "" { - cmdFactory.IOStreams.SetPager(pager) - } - // TODO: remove after FromFullName has been revisited if host, err := cfg.DefaultHost(); err == nil { ghrepo.SetDefaultHost(host) diff --git a/pkg/cmd/factory/default.go b/pkg/cmd/factory/default.go index a5a71f579..eec60bc56 100644 --- a/pkg/cmd/factory/default.go +++ b/pkg/cmd/factory/default.go @@ -17,12 +17,12 @@ import ( func New(appVersion string) *cmdutil.Factory { f := &cmdutil.Factory{ - IOStreams: iostreams.System(), // No factory dependencies - Config: configFunc(), // No factory dependencies - Branch: branchFunc(), // No factory dependencies - Executable: executable(), // No factory dependencies + Config: configFunc(), // No factory dependencies + Branch: branchFunc(), // No factory dependencies + Executable: executable(), // No factory dependencies } + f.IOStreams = ioStreams(f) // Depends on Config f.HttpClient = httpClientFunc(f, appVersion) // Depends on Config, IOStreams, and appVersion f.Remotes = remotesFunc(f) // Depends on Config f.BaseRepo = BaseRepoFunc(f) // Depends on Remotes @@ -125,3 +125,27 @@ func branchFunc() func() (string, error) { return currentBranch, nil } } + +func ioStreams(f *cmdutil.Factory) *iostreams.IOStreams { + io := iostreams.System() + cfg, err := f.Config() + if err != nil { + return io + } + + if prompt, _ := cfg.Get("", "prompt"); prompt == "disabled" { + io.SetNeverPrompt(true) + } + + // Pager precedence + // 1. GH_PAGER + // 2. pager from config + // 3. PAGER + if ghPager, ghPagerExists := os.LookupEnv("GH_PAGER"); ghPagerExists { + io.SetPager(ghPager) + } else if pager, _ := cfg.Get("", "pager"); pager != "" { + io.SetPager(pager) + } + + return io +} diff --git a/pkg/cmd/factory/default_test.go b/pkg/cmd/factory/default_test.go index 1f60b6b23..1bf8702c8 100644 --- a/pkg/cmd/factory/default_test.go +++ b/pkg/cmd/factory/default_test.go @@ -272,6 +272,108 @@ func Test_OverrideBaseRepo(t *testing.T) { } } +func Test_ioStreams_pager(t *testing.T) { + tests := []struct { + name string + env map[string]string + config config.Config + wantPager string + }{ + { + name: "GH_PAGER and PAGER set", + env: map[string]string{ + "GH_PAGER": "GH_PAGER", + "PAGER": "PAGER", + }, + wantPager: "GH_PAGER", + }, + { + name: "GH_PAGER and config pager set", + env: map[string]string{ + "GH_PAGER": "GH_PAGER", + }, + config: pagerConfig(), + wantPager: "GH_PAGER", + }, + { + name: "config pager and PAGER set", + env: map[string]string{ + "PAGER": "PAGER", + }, + config: pagerConfig(), + wantPager: "CONFIG_PAGER", + }, + { + name: "only PAGER set", + env: map[string]string{ + "PAGER": "PAGER", + }, + wantPager: "PAGER", + }, + { + name: "GH_PAGER set to blank string", + env: map[string]string{ + "GH_PAGER": "", + "PAGER": "PAGER", + }, + wantPager: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.env != nil { + for k, v := range tt.env { + old := os.Getenv(k) + os.Setenv(k, v) + if k == "GH_PAGER" { + defer os.Unsetenv(k) + } else { + defer os.Setenv(k, old) + } + } + } + f := New("1") + if tt.config != nil { + f.Config = func() (config.Config, error) { + return tt.config, nil + } + } + io := ioStreams(f) + assert.Equal(t, tt.wantPager, io.GetPager()) + }) + } +} + +func Test_ioStreams_prompt(t *testing.T) { + tests := []struct { + name string + config config.Config + promptDisabled bool + }{ + { + name: "default config", + promptDisabled: false, + }, + { + name: "config with prompt disabled", + config: disablePromptConfig(), + promptDisabled: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f := New("1") + if tt.config != nil { + f.Config = func() (config.Config, error) { + return tt.config, nil + } + } + io := ioStreams(f) + assert.Equal(t, tt.promptDisabled, io.GetNeverPrompt()) + }) + } +} + func defaultConfig() config.Config { return config.InheritEnv(config.NewFromString(heredoc.Doc(` hosts: @@ -279,3 +381,11 @@ func defaultConfig() config.Config { oauth_token: BLAH `))) } + +func pagerConfig() config.Config { + return config.NewFromString("pager: CONFIG_PAGER") +} + +func disablePromptConfig() config.Config { + return config.NewFromString("prompt: disabled") +} diff --git a/pkg/iostreams/iostreams.go b/pkg/iostreams/iostreams.go index ec2503151..7e5aa0023 100644 --- a/pkg/iostreams/iostreams.go +++ b/pkg/iostreams/iostreams.go @@ -140,6 +140,10 @@ func (s *IOStreams) SetPager(cmd string) { s.pagerCommand = cmd } +func (s *IOStreams) GetPager() string { + return s.pagerCommand +} + func (s *IOStreams) StartPager() error { if s.pagerCommand == "" || s.pagerCommand == "cat" || !s.IsStdoutTTY() { return nil @@ -202,6 +206,10 @@ func (s *IOStreams) CanPrompt() bool { return s.IsStdinTTY() && s.IsStdoutTTY() } +func (s *IOStreams) GetNeverPrompt() bool { + return s.neverPrompt +} + func (s *IOStreams) SetNeverPrompt(v bool) { s.neverPrompt = v } @@ -281,8 +289,6 @@ func System() *IOStreams { stdoutIsTTY := isTerminal(os.Stdout) stderrIsTTY := isTerminal(os.Stderr) - pagerCommand := os.Getenv("PAGER") - io := &IOStreams{ In: os.Stdin, originalOut: os.Stdout, @@ -290,7 +296,7 @@ func System() *IOStreams { ErrOut: colorable.NewColorable(os.Stderr), colorEnabled: EnvColorForced() || (!EnvColorDisabled() && stdoutIsTTY), is256enabled: Is256ColorSupported(), - pagerCommand: pagerCommand, + pagerCommand: os.Getenv("PAGER"), } if stdoutIsTTY && stderrIsTTY {