Merge pull request #203 from github/preview-things
Preview issues and PRs on the terminal
This commit is contained in:
commit
42f58eac4b
11 changed files with 364 additions and 14 deletions
|
|
@ -16,10 +16,17 @@ type IssuesAndTotalCount struct {
|
|||
}
|
||||
|
||||
type Issue struct {
|
||||
Number int
|
||||
Title string
|
||||
URL string
|
||||
State string
|
||||
Number int
|
||||
Title string
|
||||
URL string
|
||||
State string
|
||||
Body string
|
||||
Comments struct {
|
||||
TotalCount int
|
||||
}
|
||||
Author struct {
|
||||
Login string
|
||||
}
|
||||
|
||||
Labels struct {
|
||||
Nodes []IssueLabel
|
||||
|
|
@ -234,6 +241,19 @@ func IssueByNumber(client *Client, ghRepo Repo, number int) (*Issue, error) {
|
|||
query($owner: String!, $repo: String!, $issue_number: Int!) {
|
||||
repository(owner: $owner, name: $repo) {
|
||||
issue(number: $issue_number) {
|
||||
title
|
||||
body
|
||||
author {
|
||||
login
|
||||
}
|
||||
comments {
|
||||
totalCount
|
||||
}
|
||||
labels(first: 3) {
|
||||
nodes {
|
||||
name
|
||||
}
|
||||
}
|
||||
number
|
||||
url
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,13 @@ type PullRequest struct {
|
|||
Title string
|
||||
State string
|
||||
URL string
|
||||
BaseRefName string
|
||||
HeadRefName string
|
||||
Body string
|
||||
|
||||
Author struct {
|
||||
Login string
|
||||
}
|
||||
HeadRepositoryOwner struct {
|
||||
Login string
|
||||
}
|
||||
|
|
@ -38,7 +43,8 @@ type PullRequest struct {
|
|||
ReviewDecision string
|
||||
|
||||
Commits struct {
|
||||
Nodes []struct {
|
||||
TotalCount int
|
||||
Nodes []struct {
|
||||
Commit struct {
|
||||
StatusCheckRollup struct {
|
||||
Contexts struct {
|
||||
|
|
@ -296,6 +302,15 @@ func PullRequestByNumber(client *Client, ghRepo Repo, number int) (*PullRequest,
|
|||
pullRequest(number: $pr_number) {
|
||||
url
|
||||
number
|
||||
title
|
||||
body
|
||||
author {
|
||||
login
|
||||
}
|
||||
commits {
|
||||
totalCount
|
||||
}
|
||||
baseRefName
|
||||
headRefName
|
||||
headRepositoryOwner {
|
||||
login
|
||||
|
|
@ -343,7 +358,15 @@ func PullRequestForBranch(client *Client, ghRepo Repo, branch string) (*PullRequ
|
|||
nodes {
|
||||
number
|
||||
title
|
||||
body
|
||||
author {
|
||||
login
|
||||
}
|
||||
commits {
|
||||
totalCount
|
||||
}
|
||||
url
|
||||
baseRefName
|
||||
headRefName
|
||||
headRepositoryOwner {
|
||||
login
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ func init() {
|
|||
issueListCmd.Flags().StringSliceP("label", "l", nil, "Filter by label")
|
||||
issueListCmd.Flags().StringP("state", "s", "", "Filter by state: {open|closed|all}")
|
||||
issueListCmd.Flags().IntP("limit", "L", 30, "Maximum number of issues to fetch")
|
||||
|
||||
issueViewCmd.Flags().BoolP("preview", "p", false, "Preview PR in terminal")
|
||||
}
|
||||
|
||||
var issueCmd = &cobra.Command{
|
||||
|
|
@ -217,8 +219,39 @@ func issueView(cmd *cobra.Command, args []string) error {
|
|||
}
|
||||
openURL := issue.URL
|
||||
|
||||
fmt.Fprintf(cmd.ErrOrStderr(), "Opening %s in your browser.\n", openURL)
|
||||
return utils.OpenInBrowser(openURL)
|
||||
preview, err := cmd.Flags().GetBool("preview")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if preview {
|
||||
out := colorableOut(cmd)
|
||||
printIssuePreview(out, issue)
|
||||
return nil
|
||||
} else {
|
||||
fmt.Fprintf(cmd.ErrOrStderr(), "Opening %s in your browser.\n", openURL)
|
||||
return utils.OpenInBrowser(openURL)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func printIssuePreview(out io.Writer, issue *api.Issue) {
|
||||
coloredLabels := labelList(*issue)
|
||||
if coloredLabels != "" {
|
||||
coloredLabels = utils.Gray(fmt.Sprintf("(%s)", coloredLabels))
|
||||
}
|
||||
|
||||
fmt.Fprintln(out, utils.Bold(issue.Title))
|
||||
fmt.Fprintln(out, utils.Gray(fmt.Sprintf(
|
||||
"opened by %s. %s. %s",
|
||||
issue.Author.Login,
|
||||
utils.Pluralize(issue.Comments.TotalCount, "comment"),
|
||||
coloredLabels,
|
||||
)))
|
||||
fmt.Fprintln(out)
|
||||
fmt.Fprintln(out, utils.RenderMarkdown(issue.Body))
|
||||
fmt.Fprintln(out)
|
||||
fmt.Fprintf(out, utils.Gray("View this issue on GitHub: %s\n"), issue.URL)
|
||||
}
|
||||
|
||||
var issueURLRE = regexp.MustCompile(`^https://github\.com/([^/]+)/([^/]+)/issues/(\d+)`)
|
||||
|
|
|
|||
|
|
@ -231,6 +231,51 @@ func TestIssueView(t *testing.T) {
|
|||
eq(t, url, "https://github.com/OWNER/REPO/issues/123")
|
||||
}
|
||||
|
||||
func TestIssueView_preview(t *testing.T) {
|
||||
initBlankContext("OWNER/REPO", "master")
|
||||
http := initFakeHTTP()
|
||||
|
||||
http.StubResponse(200, bytes.NewBufferString(`
|
||||
{ "data": { "repository": { "issue": {
|
||||
"number": 123,
|
||||
"body": "**bold story**",
|
||||
"title": "ix of coins",
|
||||
"author": {
|
||||
"login": "marseilles"
|
||||
},
|
||||
"labels": {
|
||||
"nodes": [
|
||||
{"name": "tarot"}
|
||||
]
|
||||
},
|
||||
"comments": {
|
||||
"totalCount": 9
|
||||
},
|
||||
"url": "https://github.com/OWNER/REPO/issues/123"
|
||||
} } } }
|
||||
`))
|
||||
|
||||
output, err := RunCommand(issueViewCmd, "issue view -p 123")
|
||||
if err != nil {
|
||||
t.Errorf("error running command `issue view`: %v", err)
|
||||
}
|
||||
|
||||
eq(t, output.Stderr(), "")
|
||||
|
||||
expectedLines := []*regexp.Regexp{
|
||||
regexp.MustCompile(`ix of coins`),
|
||||
regexp.MustCompile(`opened by marseilles. 9 comments. \(tarot\)`),
|
||||
regexp.MustCompile(`bold story`),
|
||||
regexp.MustCompile(`View this issue on GitHub: https://github.com/OWNER/REPO/issues/123`),
|
||||
}
|
||||
for _, r := range expectedLines {
|
||||
if !r.MatchString(output.String()) {
|
||||
t.Errorf("output did not match regexp /%s/\n> output\n%s\n", r, output)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssueView_notFound(t *testing.T) {
|
||||
initBlankContext("OWNER/REPO", "master")
|
||||
http := initFakeHTTP()
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ func init() {
|
|||
prListCmd.Flags().StringP("base", "B", "", "Filter by base branch")
|
||||
prListCmd.Flags().StringSliceP("label", "l", nil, "Filter by label")
|
||||
prListCmd.Flags().StringP("assignee", "a", "", "Filter by assignee")
|
||||
|
||||
prViewCmd.Flags().BoolP("preview", "p", false, "Preview PR in terminal")
|
||||
}
|
||||
|
||||
var prCmd = &cobra.Command{
|
||||
|
|
@ -253,9 +255,15 @@ func prView(cmd *cobra.Command, args []string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
preview, err := cmd.Flags().GetBool("preview")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var openURL string
|
||||
var pr *api.PullRequest
|
||||
if len(args) > 0 {
|
||||
pr, err := prFromArg(apiClient, baseRepo, args[0])
|
||||
pr, err = prFromArg(apiClient, baseRepo, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -268,8 +276,14 @@ func prView(cmd *cobra.Command, args []string) error {
|
|||
|
||||
if prNumber > 0 {
|
||||
openURL = fmt.Sprintf("https://github.com/%s/%s/pull/%d", baseRepo.RepoOwner(), baseRepo.RepoName(), prNumber)
|
||||
if preview {
|
||||
pr, err = api.PullRequestByNumber(apiClient, baseRepo, prNumber)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pr, err := api.PullRequestForBranch(apiClient, baseRepo, branchWithOwner)
|
||||
pr, err = api.PullRequestForBranch(apiClient, baseRepo, branchWithOwner)
|
||||
if err != nil {
|
||||
var notFoundErr *api.NotFoundError
|
||||
if errors.As(err, ¬FoundErr) {
|
||||
|
|
@ -282,8 +296,29 @@ func prView(cmd *cobra.Command, args []string) error {
|
|||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(cmd.ErrOrStderr(), "Opening %s in your browser.\n", openURL)
|
||||
return utils.OpenInBrowser(openURL)
|
||||
if preview {
|
||||
out := colorableOut(cmd)
|
||||
printPrPreview(out, pr)
|
||||
return nil
|
||||
} else {
|
||||
fmt.Fprintf(cmd.ErrOrStderr(), "Opening %s in your browser.\n", openURL)
|
||||
return utils.OpenInBrowser(openURL)
|
||||
}
|
||||
}
|
||||
|
||||
func printPrPreview(out io.Writer, pr *api.PullRequest) {
|
||||
fmt.Fprintln(out, utils.Bold(pr.Title))
|
||||
fmt.Fprintln(out, utils.Gray(fmt.Sprintf(
|
||||
"%s wants to merge %s into %s from %s",
|
||||
pr.Author.Login,
|
||||
utils.Pluralize(pr.Commits.TotalCount, "commit"),
|
||||
pr.BaseRefName,
|
||||
pr.HeadRefName,
|
||||
)))
|
||||
fmt.Fprintln(out)
|
||||
fmt.Fprintln(out, utils.RenderMarkdown(pr.Body))
|
||||
fmt.Fprintln(out)
|
||||
fmt.Fprintf(out, utils.Gray("View this PR on GitHub: %s\n"), pr.URL)
|
||||
}
|
||||
|
||||
var prURLRE = regexp.MustCompile(`^https://github\.com/([^/]+)/([^/]+)/pull/(\d+)`)
|
||||
|
|
|
|||
|
|
@ -238,6 +238,69 @@ func TestPRList_filteringAssigneeLabels(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestPRView_preview(t *testing.T) {
|
||||
initBlankContext("OWNER/REPO", "master")
|
||||
http := initFakeHTTP()
|
||||
|
||||
jsonFile, _ := os.Open("../test/fixtures/prViewPreview.json")
|
||||
defer jsonFile.Close()
|
||||
http.StubResponse(200, jsonFile)
|
||||
|
||||
output, err := RunCommand(prViewCmd, "pr view -p 12")
|
||||
if err != nil {
|
||||
t.Errorf("error running command `pr view`: %v", err)
|
||||
}
|
||||
|
||||
eq(t, output.Stderr(), "")
|
||||
|
||||
expectedLines := []*regexp.Regexp{
|
||||
regexp.MustCompile(`Blueberries are from a fork`),
|
||||
regexp.MustCompile(`nobody wants to merge 12 commits into master from blueberries`),
|
||||
regexp.MustCompile(`blueberries taste good`),
|
||||
regexp.MustCompile(`View this PR on GitHub: https://github.com/OWNER/REPO/pull/12`),
|
||||
}
|
||||
for _, r := range expectedLines {
|
||||
if !r.MatchString(output.String()) {
|
||||
t.Errorf("output did not match regexp /%s/\n> output\n%s\n", r, output)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPRView_previewCurrentBranch(t *testing.T) {
|
||||
initBlankContext("OWNER/REPO", "blueberries")
|
||||
http := initFakeHTTP()
|
||||
|
||||
jsonFile, _ := os.Open("../test/fixtures/prView.json")
|
||||
defer jsonFile.Close()
|
||||
http.StubResponse(200, jsonFile)
|
||||
|
||||
restoreCmd := utils.SetPrepareCmd(func(cmd *exec.Cmd) utils.Runnable {
|
||||
return &outputStub{}
|
||||
})
|
||||
defer restoreCmd()
|
||||
|
||||
output, err := RunCommand(prViewCmd, "pr view -p")
|
||||
if err != nil {
|
||||
t.Errorf("error running command `pr view`: %v", err)
|
||||
}
|
||||
|
||||
eq(t, output.Stderr(), "")
|
||||
|
||||
expectedLines := []*regexp.Regexp{
|
||||
regexp.MustCompile(`Blueberries are a good fruit`),
|
||||
regexp.MustCompile(`nobody wants to merge 8 commits into master from blueberries`),
|
||||
regexp.MustCompile(`blueberries taste good`),
|
||||
regexp.MustCompile(`View this PR on GitHub: https://github.com/OWNER/REPO/pull/10`),
|
||||
}
|
||||
for _, r := range expectedLines {
|
||||
if !r.MatchString(output.String()) {
|
||||
t.Errorf("output did not match regexp /%s/\n> output\n%s\n", r, output)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPRView_currentBranch(t *testing.T) {
|
||||
initBlankContext("OWNER/REPO", "blueberries")
|
||||
http := initFakeHTTP()
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -14,7 +14,7 @@ require (
|
|||
github.com/pkg/errors v0.8.1
|
||||
github.com/spf13/cobra v0.0.5
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.3.0 // indirect
|
||||
github.com/vilmibm/go-termd v0.0.4
|
||||
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5
|
||||
gopkg.in/yaml.v3 v3.0.0-20191010095647-fc94e3f71652
|
||||
)
|
||||
|
|
|
|||
56
go.sum
56
go.sum
|
|
@ -2,34 +2,65 @@ github.com/AlecAivazis/survey/v2 v2.0.4 h1:qzXnJSzXEvmUllWqMBWpZndvT2YfoAUzAMvZU
|
|||
github.com/AlecAivazis/survey/v2 v2.0.4/go.mod h1:WYBhg6f0y/fNYUuesWQc0PKbJcEliGcYHB9sNT3Bg74=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
|
||||
github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0=
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
|
||||
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
|
||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
|
||||
github.com/alecthomas/chroma v0.6.8 h1:TW4JJaIdbAbMyUtGEd6BukFlOKYvVQz3vVhLBEUNwMU=
|
||||
github.com/alecthomas/chroma v0.6.8/go.mod h1:o9ohftueRi7H5be3+Q2cQCNa/YnLBFUNx40ZJfGVFKA=
|
||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=
|
||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
|
||||
github.com/alecthomas/kong v0.1.17-0.20190424132513-439c674f7ae0/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
|
||||
github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
|
||||
github.com/alecthomas/kong-hcl v0.1.8-0.20190615233001-b21fea9723c8/go.mod h1:MRgZdU3vrFd05IQ89AxUZ0aYdF39BYoNFa324SodPCA=
|
||||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY=
|
||||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo=
|
||||
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
|
||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
|
||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dlclark/regexp2 v1.1.6 h1:CqB4MjHw0MFCDj+PHHjiESmHX+N7t0tJzKvC6M97BRg=
|
||||
github.com/dlclark/regexp2 v1.1.6/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/gorilla/csrf v1.6.0/go.mod h1:7tSf8kmjNYr7IWDCYhd3U8Ck34iQ/Yw5CJu7bAkHEGI=
|
||||
github.com/gorilla/handlers v1.4.1/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
|
||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.4 h1:5Myjjh3JY/NaAi4IsUbHADytDyl1VE1Y9PXDlL+P/VQ=
|
||||
github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
|
|
@ -37,14 +68,24 @@ github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1f
|
|||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
|
||||
|
|
@ -60,7 +101,17 @@ github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
|||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/tj/assert v0.0.0-20190920132354-ee03d75cd160 h1:NSWpaDaurcAJY7PkL8Xt0PhZE7qpvbZl5ljd8r6U0bI=
|
||||
github.com/tj/assert v0.0.0-20190920132354-ee03d75cd160/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0=
|
||||
github.com/tj/go-css v0.0.0-20191108133013-220a796d1705 h1:+UA89aFRjPMqdccHd9A0HLNCRDXIoElaDoW2C1V3TzA=
|
||||
github.com/tj/go-css v0.0.0-20191108133013-220a796d1705/go.mod h1:e+JPLQ9wyQCgRnPenX2bo7MJoLphBHz5c1WUqaANSeA=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/vilmibm/go-termd v0.0.4 h1:uCmDUZ3qZUblTN/D5Hvl+g1rTJj/HW746JQFWidqAyk=
|
||||
github.com/vilmibm/go-termd v0.0.4/go.mod h1:ys+dRO6wlM3el0vPJmYBkhOPPozViBgDXHOEn1x5Vsc=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
|
|
@ -68,6 +119,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5 h1:8dUaAV7K4uHsF56JQWkprecIQKdPHtR9jCHF5nB8uzc=
|
||||
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
|
|
|||
16
test/fixtures/prView.json
vendored
16
test/fixtures/prView.json
vendored
|
|
@ -6,21 +6,37 @@
|
|||
{
|
||||
"number": 12,
|
||||
"title": "Blueberries are from a fork",
|
||||
"body": "yeah",
|
||||
"url": "https://github.com/OWNER/REPO/pull/12",
|
||||
"headRefName": "blueberries",
|
||||
"baseRefName": "master",
|
||||
"headRepositoryOwner": {
|
||||
"login": "hubot"
|
||||
},
|
||||
"commits": {
|
||||
"totalCount": 12
|
||||
},
|
||||
"author": {
|
||||
"login": "nobody"
|
||||
},
|
||||
"isCrossRepository": true
|
||||
},
|
||||
{
|
||||
"number": 10,
|
||||
"title": "Blueberries are a good fruit",
|
||||
"body": "**blueberries taste good**",
|
||||
"url": "https://github.com/OWNER/REPO/pull/10",
|
||||
"baseRefName": "master",
|
||||
"headRefName": "blueberries",
|
||||
"author": {
|
||||
"login": "nobody"
|
||||
},
|
||||
"headRepositoryOwner": {
|
||||
"login": "OWNER"
|
||||
},
|
||||
"commits": {
|
||||
"totalCount": 8
|
||||
},
|
||||
"isCrossRepository": false
|
||||
}
|
||||
]
|
||||
|
|
|
|||
24
test/fixtures/prViewPreview.json
vendored
Normal file
24
test/fixtures/prViewPreview.json
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"data": {
|
||||
"repository": {
|
||||
"pullRequest": {
|
||||
"number": 12,
|
||||
"title": "Blueberries are from a fork",
|
||||
"body": "**blueberries taste good**",
|
||||
"url": "https://github.com/OWNER/REPO/pull/12",
|
||||
"author": {
|
||||
"login": "nobody"
|
||||
},
|
||||
"commits": {
|
||||
"totalCount": 12
|
||||
},
|
||||
"baseRefName": "master",
|
||||
"headRefName": "blueberries",
|
||||
"headRepositoryOwner": {
|
||||
"login": "hubot"
|
||||
},
|
||||
"isCrossRepository": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,15 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
|
||||
"github.com/kballard/go-shellquote"
|
||||
md "github.com/vilmibm/go-termd"
|
||||
)
|
||||
|
||||
func OpenInBrowser(url string) error {
|
||||
|
|
@ -51,3 +54,39 @@ func searchBrowserLauncher(goos string) (browser string) {
|
|||
|
||||
return browser
|
||||
}
|
||||
|
||||
func normalizeNewlines(d []byte) []byte {
|
||||
d = bytes.Replace(d, []byte("\r\n"), []byte("\n"), -1)
|
||||
d = bytes.Replace(d, []byte("\r"), []byte("\n"), -1)
|
||||
return d
|
||||
}
|
||||
|
||||
func RenderMarkdown(text string) string {
|
||||
textB := []byte(text)
|
||||
textB = normalizeNewlines(textB)
|
||||
mdCompiler := md.Compiler{
|
||||
Columns: 100,
|
||||
SyntaxHighlighter: md.SyntaxTheme{
|
||||
"keyword": md.Style{Color: "#9196ed"},
|
||||
"comment": md.Style{
|
||||
Color: "#c0c0c2",
|
||||
},
|
||||
"literal": md.Style{
|
||||
Color: "#aaedf7",
|
||||
},
|
||||
"name": md.Style{
|
||||
Color: "#fe8eb5",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return mdCompiler.Compile(string(textB))
|
||||
}
|
||||
|
||||
func Pluralize(num int, thing string) string {
|
||||
if num == 1 {
|
||||
return fmt.Sprintf("%d %s", num, thing)
|
||||
} else {
|
||||
return fmt.Sprintf("%d %ss", num, thing)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue