Add PAGER support to commands that produce significant output

This commit is contained in:
Mislav Marohnić 2020-09-04 23:08:09 +02:00
parent d01355e24b
commit ccfe38de26
10 changed files with 86 additions and 44 deletions

View file

@ -9,6 +9,7 @@
"number": 1,
"title": "number won",
"url": "https://wow.com",
"updatedAt": "2011-01-26T19:01:12Z",
"labels": {
"nodes": [
{
@ -22,6 +23,7 @@
"number": 2,
"title": "number too",
"url": "https://wow.com",
"updatedAt": "2011-01-26T19:01:12Z",
"labels": {
"nodes": [
{
@ -35,6 +37,7 @@
"number": 4,
"title": "number fore",
"url": "https://wow.com",
"updatedAt": "2011-01-26T19:01:12Z",
"labels": {
"nodes": [
{

View file

@ -116,10 +116,16 @@ func listRun(opts *ListOptions) error {
return err
}
err = opts.IO.StartPager()
if err != nil {
return err
}
defer opts.IO.StopPager()
if isTerminal {
hasFilters := opts.State != "open" || len(opts.Labels) > 0 || opts.Assignee != "" || opts.Author != "" || opts.Mention != "" || opts.Milestone != ""
title := prShared.ListHeader(ghrepo.FullName(baseRepo), "issue", len(listResult.Issues), listResult.TotalCount, hasFilters)
fmt.Fprintf(opts.IO.ErrOut, "\n%s\n\n", title)
fmt.Fprintf(opts.IO.Out, "\n%s\n\n", title)
}
issueShared.PrintIssues(opts.IO, "", len(listResult.Issues), listResult.Issues)

View file

@ -7,8 +7,10 @@ import (
"net/http"
"os/exec"
"reflect"
"regexp"
"testing"
"github.com/MakeNowJust/heredoc"
"github.com/cli/cli/internal/config"
"github.com/cli/cli/internal/ghrepo"
"github.com/cli/cli/internal/run"
@ -97,15 +99,19 @@ func TestIssueList_tty(t *testing.T) {
t.Errorf("error running command `issue list`: %v", err)
}
eq(t, output.Stderr(), `
Showing 3 of 3 open issues in OWNER/REPO
out := output.String()
timeRE := regexp.MustCompile(`\d+ years`)
out = timeRE.ReplaceAllString(out, "X years")
`)
assert.Equal(t, heredoc.Doc(`
test.ExpectLines(t, output.String(),
"number won",
"number too",
"number fore")
Showing 3 of 3 open issues in OWNER/REPO
#1 number won (label) about X years ago
#2 number too (label) about X years ago
#4 number fore (label) about X years ago
`), out)
assert.Equal(t, ``, output.Stderr())
}
func TestIssueList_tty_withFlags(t *testing.T) {
@ -141,8 +147,8 @@ func TestIssueList_tty_withFlags(t *testing.T) {
t.Errorf("error running command `issue list`: %v", err)
}
eq(t, output.String(), "")
eq(t, output.Stderr(), `
eq(t, output.Stderr(), "")
eq(t, output.String(), `
No issues match your search in OWNER/REPO
`)

View file

@ -68,6 +68,12 @@ func statusRun(opts *StatusOptions) error {
return err
}
err = opts.IO.StartPager()
if err != nil {
return err
}
defer opts.IO.StopPager()
out := opts.IO.Out
fmt.Fprintln(out, "")

View file

@ -86,10 +86,16 @@ func viewRun(opts *ViewOptions) error {
fmt.Fprintf(opts.IO.ErrOut, "Opening %s in your browser.\n", openURL)
return utils.OpenInBrowser(openURL)
}
err = opts.IO.StartPager()
if err != nil {
return err
}
defer opts.IO.StopPager()
if opts.IO.IsStdoutTTY() {
return printHumanIssuePreview(opts.IO.Out, issue)
}
return printRawIssuePreview(opts.IO.Out, issue)
}

View file

@ -133,10 +133,16 @@ func listRun(opts *ListOptions) error {
return err
}
err = opts.IO.StartPager()
if err != nil {
return err
}
defer opts.IO.StopPager()
if opts.IO.IsStdoutTTY() {
hasFilters := opts.State != "open" || len(opts.Labels) > 0 || opts.BaseBranch != "" || opts.Assignee != ""
title := shared.ListHeader(ghrepo.FullName(baseRepo), "pull request", len(listResult.PullRequests), listResult.TotalCount, hasFilters)
fmt.Fprintf(opts.IO.ErrOut, "\n%s\n\n", title)
fmt.Fprintf(opts.IO.Out, "\n%s\n\n", title)
}
table := utils.NewTablePrinter(opts.IO)

View file

@ -6,10 +6,10 @@ import (
"net/http"
"os/exec"
"reflect"
"regexp"
"strings"
"testing"
"github.com/MakeNowJust/heredoc"
"github.com/cli/cli/internal/ghrepo"
"github.com/cli/cli/internal/run"
"github.com/cli/cli/pkg/cmdutil"
@ -76,23 +76,15 @@ func TestPRList(t *testing.T) {
t.Fatal(err)
}
assert.Equal(t, `
Showing 3 of 3 open pull requests in OWNER/REPO
assert.Equal(t, heredoc.Doc(`
`, output.Stderr())
lines := strings.Split(output.String(), "\n")
res := []*regexp.Regexp{
regexp.MustCompile(`#32.*New feature.*feature`),
regexp.MustCompile(`#29.*Fixed bad bug.*hubot:bug-fix`),
regexp.MustCompile(`#28.*Improve documentation.*docs`),
}
for i, r := range res {
if !r.MatchString(lines[i]) {
t.Errorf("%s did not match %s", lines[i], r)
}
}
Showing 3 of 3 open pull requests in OWNER/REPO
#32 New feature feature
#29 Fixed bad bug hubot:bug-fix
#28 Improve documentation docs
`), output.String())
assert.Equal(t, ``, output.Stderr())
}
func TestPRList_nontty(t *testing.T) {
@ -130,8 +122,8 @@ func TestPRList_filtering(t *testing.T) {
t.Fatal(err)
}
eq(t, output.String(), "")
eq(t, output.Stderr(), `
eq(t, output.Stderr(), "")
eq(t, output.String(), `
No pull requests match your search in OWNER/REPO
`)
@ -150,19 +142,12 @@ func TestPRList_filteringRemoveDuplicate(t *testing.T) {
t.Fatal(err)
}
lines := strings.Split(output.String(), "\n")
res := []*regexp.Regexp{
regexp.MustCompile(`#32.*New feature.*feature`),
regexp.MustCompile(`#29.*Fixed bad bug.*hubot:bug-fix`),
regexp.MustCompile(`#28.*Improve documentation.*docs`),
}
for i, r := range res {
if !r.MatchString(lines[i]) {
t.Errorf("%s did not match %s", lines[i], r)
}
out := output.String()
idx := strings.Index(out, "New feature")
if idx < 0 {
t.Fatalf("text %q not found in %q", "New feature", out)
}
assert.Equal(t, idx, strings.LastIndex(out, "New feature"))
}
func TestPRList_filteringClosed(t *testing.T) {

View file

@ -97,6 +97,12 @@ func statusRun(opts *StatusOptions) error {
return err
}
err = opts.IO.StartPager()
if err != nil {
return err
}
defer opts.IO.StopPager()
out := opts.IO.Out
fmt.Fprintln(out, "")

View file

@ -99,6 +99,12 @@ func viewRun(opts *ViewOptions) error {
return utils.OpenInBrowser(openURL)
}
err = opts.IO.StartPager()
if err != nil {
return err
}
defer opts.IO.StopPager()
if connectedToTerminal {
return printHumanPrPreview(opts.IO.Out, pr)
}

View file

@ -1,10 +1,13 @@
package view
import (
"errors"
"fmt"
"html/template"
"net/http"
"os"
"strings"
"syscall"
"github.com/MakeNowJust/heredoc"
"github.com/cli/cli/api"
@ -107,6 +110,12 @@ func viewRun(opts *ViewOptions) error {
return err
}
err = opts.IO.StartPager()
if err != nil {
return err
}
defer opts.IO.StopPager()
stdout := opts.IO.Out
if !opts.IO.IsStdoutTTY() {
@ -167,7 +176,10 @@ func viewRun(opts *ViewOptions) error {
err = tmpl.Execute(stdout, repoData)
if err != nil {
return err
var pathError *os.PathError
if !errors.As(err, &pathError) || pathError.Op != "write" || pathError.Unwrap() != syscall.EPIPE {
return err
}
}
return nil