Add PAGER support to commands that produce significant output
This commit is contained in:
parent
d01355e24b
commit
ccfe38de26
10 changed files with 86 additions and 44 deletions
|
|
@ -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": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
`)
|
||||
|
|
|
|||
|
|
@ -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, "")
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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, "")
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue