From dee7077fcf80ab5675e2791f4a6bdca7d7cd629d Mon Sep 17 00:00:00 2001 From: Sam Coe Date: Wed, 9 Dec 2020 14:35:29 -0500 Subject: [PATCH] Extract shared comment and reaction group code --- pkg/cmd/issue/view/view.go | 120 +----------------------- pkg/cmd/pr/shared/comments.go | 100 ++++++++++++++++++++ pkg/cmd/pr/shared/reaction_groups.go | 32 +++++++ pkg/cmd/pr/view/view.go | 135 ++------------------------- 4 files changed, 142 insertions(+), 245 deletions(-) create mode 100644 pkg/cmd/pr/shared/comments.go create mode 100644 pkg/cmd/pr/shared/reaction_groups.go diff --git a/pkg/cmd/issue/view/view.go b/pkg/cmd/issue/view/view.go index 58883965d..76d32e032 100644 --- a/pkg/cmd/issue/view/view.go +++ b/pkg/cmd/issue/view/view.go @@ -123,7 +123,8 @@ func viewRun(opts *ViewOptions) error { } if opts.Comments { - return printRawIssueComments(opts.IO.Out, issue) + fmt.Fprint(opts.IO.Out, prShared.RawCommentList(issue.Comments)) + return nil } return printRawIssuePreview(opts.IO.Out, issue) @@ -149,26 +150,6 @@ func printRawIssuePreview(out io.Writer, issue *api.Issue) error { return nil } -func printRawIssueComments(out io.Writer, issue *api.Issue) error { - var b strings.Builder - for _, comment := range issue.Comments.Nodes { - fmt.Fprint(&b, formatRawIssueComment(comment)) - } - fmt.Fprint(out, b.String()) - return nil -} - -func formatRawIssueComment(comment api.Comment) string { - var b strings.Builder - fmt.Fprintf(&b, "author:\t%s\n", comment.Author.Login) - fmt.Fprintf(&b, "association:\t%s\n", strings.ToLower(comment.AuthorAssociation)) - fmt.Fprintf(&b, "edited:\t%t\n", comment.IncludesCreatedEdit) - fmt.Fprintln(&b, "--") - fmt.Fprintln(&b, comment.Body) - fmt.Fprintln(&b, "--") - return b.String() -} - func printHumanIssuePreview(io *iostreams.IOStreams, issue *api.Issue) error { out := io.Out now := time.Now() @@ -186,7 +167,7 @@ func printHumanIssuePreview(io *iostreams.IOStreams, issue *api.Issue) error { ) // Reactions - if reactions := reactionGroupList(issue.ReactionGroups); reactions != "" { + if reactions := prShared.ReactionGroupList(issue.ReactionGroups); reactions != "" { fmt.Fprint(out, reactions) fmt.Fprintln(out) } @@ -224,7 +205,7 @@ func printHumanIssuePreview(io *iostreams.IOStreams, issue *api.Issue) error { // Comments if issue.Comments.TotalCount > 0 { - comments, err := issueCommentList(io, issue.Comments) + comments, err := prShared.CommentList(io, issue.Comments) if err != nil { return err } @@ -237,75 +218,6 @@ func printHumanIssuePreview(io *iostreams.IOStreams, issue *api.Issue) error { return nil } -func issueCommentList(io *iostreams.IOStreams, comments api.Comments) (string, error) { - var b strings.Builder - cs := io.ColorScheme() - retrievedCount := len(comments.Nodes) - hiddenCount := comments.TotalCount - retrievedCount - - if hiddenCount > 0 { - fmt.Fprint(&b, cs.Gray(fmt.Sprintf("———————— Not showing %s ————————", utils.Pluralize(hiddenCount, "comment")))) - fmt.Fprintf(&b, "\n\n\n") - } - - for i, comment := range comments.Nodes { - last := i+1 == retrievedCount - cmt, err := formatIssueComment(io, comment, last) - if err != nil { - return "", err - } - fmt.Fprint(&b, cmt) - if last { - fmt.Fprintln(&b) - } - } - - if hiddenCount > 0 { - fmt.Fprint(&b, cs.Gray("Use --comments to view the full conversation")) - fmt.Fprintln(&b) - } - - return b.String(), nil -} - -func formatIssueComment(io *iostreams.IOStreams, comment api.Comment, newest bool) (string, error) { - var b strings.Builder - cs := io.ColorScheme() - - // Header - fmt.Fprint(&b, cs.Bold(comment.Author.Login)) - if comment.AuthorAssociation != "NONE" { - fmt.Fprint(&b, cs.Bold(fmt.Sprintf(" (%s)", strings.ToLower(comment.AuthorAssociation)))) - } - fmt.Fprint(&b, cs.Bold(fmt.Sprintf(" • %s", utils.FuzzyAgoAbbr(time.Now(), comment.CreatedAt)))) - if comment.IncludesCreatedEdit { - fmt.Fprint(&b, cs.Bold(" • edited")) - } - if newest { - fmt.Fprint(&b, cs.Bold(" • ")) - fmt.Fprint(&b, cs.CyanBold("Newest comment")) - } - fmt.Fprintln(&b) - - // Reactions - if reactions := reactionGroupList(comment.ReactionGroups); reactions != "" { - fmt.Fprint(&b, reactions) - fmt.Fprintln(&b) - } - - // Body - if comment.Body != "" { - style := markdown.GetStyle(io.TerminalTheme()) - md, err := markdown.Render(comment.Body, style, "") - if err != nil { - return "", err - } - fmt.Fprint(&b, md) - } - - return b.String(), nil -} - func issueStateTitleWithColor(cs *iostreams.ColorScheme, state string) string { colorFunc := cs.ColorFromString(prShared.ColorForState(state)) return colorFunc(strings.Title(strings.ToLower(state))) @@ -348,27 +260,3 @@ func issueProjectList(issue api.Issue) string { } return list } - -func reactionGroupList(rgs api.ReactionGroups) string { - var rs []string - - for _, rg := range rgs { - if r := formatReactionGroup(rg); r != "" { - rs = append(rs, r) - } - } - - return strings.Join(rs, " • ") -} - -func formatReactionGroup(rg api.ReactionGroup) string { - c := rg.Count() - if c == 0 { - return "" - } - e := rg.Emoji() - if e == "" { - return "" - } - return fmt.Sprintf("%v %s", c, e) -} diff --git a/pkg/cmd/pr/shared/comments.go b/pkg/cmd/pr/shared/comments.go new file mode 100644 index 000000000..f0d820c1f --- /dev/null +++ b/pkg/cmd/pr/shared/comments.go @@ -0,0 +1,100 @@ +package shared + +import ( + "fmt" + "strings" + "time" + + "github.com/cli/cli/api" + "github.com/cli/cli/pkg/iostreams" + "github.com/cli/cli/pkg/markdown" + "github.com/cli/cli/utils" +) + +func RawCommentList(comments api.Comments) string { + var b strings.Builder + for _, comment := range comments.Nodes { + fmt.Fprint(&b, formatRawComment(comment)) + } + return b.String() +} + +func formatRawComment(comment api.Comment) string { + var b strings.Builder + fmt.Fprintf(&b, "author:\t%s\n", comment.Author.Login) + fmt.Fprintf(&b, "association:\t%s\n", strings.ToLower(comment.AuthorAssociation)) + fmt.Fprintf(&b, "edited:\t%t\n", comment.IncludesCreatedEdit) + fmt.Fprintln(&b, "--") + fmt.Fprintln(&b, comment.Body) + fmt.Fprintln(&b, "--") + return b.String() +} + +func CommentList(io *iostreams.IOStreams, comments api.Comments) (string, error) { + var b strings.Builder + cs := io.ColorScheme() + retrievedCount := len(comments.Nodes) + hiddenCount := comments.TotalCount - retrievedCount + + if hiddenCount > 0 { + fmt.Fprint(&b, cs.Gray(fmt.Sprintf("———————— Not showing %s ————————", utils.Pluralize(hiddenCount, "comment")))) + fmt.Fprintf(&b, "\n\n\n") + } + + for i, comment := range comments.Nodes { + last := i+1 == retrievedCount + cmt, err := formatComment(io, comment, last) + if err != nil { + return "", err + } + fmt.Fprint(&b, cmt) + if last { + fmt.Fprintln(&b) + } + } + + if hiddenCount > 0 { + fmt.Fprint(&b, cs.Gray("Use --comments to view the full conversation")) + fmt.Fprintln(&b) + } + + return b.String(), nil +} + +func formatComment(io *iostreams.IOStreams, comment api.Comment, newest bool) (string, error) { + var b strings.Builder + cs := io.ColorScheme() + + // Header + fmt.Fprint(&b, cs.Bold(comment.Author.Login)) + if comment.AuthorAssociation != "NONE" { + fmt.Fprint(&b, cs.Bold(fmt.Sprintf(" (%s)", strings.ToLower(comment.AuthorAssociation)))) + } + fmt.Fprint(&b, cs.Bold(fmt.Sprintf(" • %s", utils.FuzzyAgoAbbr(time.Now(), comment.CreatedAt)))) + if comment.IncludesCreatedEdit { + fmt.Fprint(&b, cs.Bold(" • edited")) + } + if newest { + fmt.Fprint(&b, cs.Bold(" • ")) + fmt.Fprint(&b, cs.CyanBold("Newest comment")) + } + fmt.Fprintln(&b) + + // Reactions + if reactions := ReactionGroupList(comment.ReactionGroups); reactions != "" { + fmt.Fprint(&b, reactions) + fmt.Fprintln(&b) + } + + // Body + if comment.Body != "" { + style := markdown.GetStyle(io.TerminalTheme()) + md, err := markdown.Render(comment.Body, style, "") + if err != nil { + return "", err + } + fmt.Fprint(&b, md) + } + + return b.String(), nil +} diff --git a/pkg/cmd/pr/shared/reaction_groups.go b/pkg/cmd/pr/shared/reaction_groups.go new file mode 100644 index 000000000..caf972672 --- /dev/null +++ b/pkg/cmd/pr/shared/reaction_groups.go @@ -0,0 +1,32 @@ +package shared + +import ( + "fmt" + "strings" + + "github.com/cli/cli/api" +) + +func ReactionGroupList(rgs api.ReactionGroups) string { + var rs []string + + for _, rg := range rgs { + if r := formatReactionGroup(rg); r != "" { + rs = append(rs, r) + } + } + + return strings.Join(rs, " • ") +} + +func formatReactionGroup(rg api.ReactionGroup) string { + c := rg.Count() + if c == 0 { + return "" + } + e := rg.Emoji() + if e == "" { + return "" + } + return fmt.Sprintf("%v %s", c, e) +} diff --git a/pkg/cmd/pr/view/view.go b/pkg/cmd/pr/view/view.go index df1b1590a..8384d7af3 100644 --- a/pkg/cmd/pr/view/view.go +++ b/pkg/cmd/pr/view/view.go @@ -3,14 +3,11 @@ package view import ( "errors" "fmt" - "io" "net/http" "sort" "strings" - "time" "github.com/MakeNowJust/heredoc" - "github.com/briandowns/spinner" "github.com/cli/cli/api" "github.com/cli/cli/context" "github.com/cli/cli/internal/config" @@ -105,21 +102,13 @@ func viewRun(opts *ViewOptions) error { } if opts.Comments { - var s *spinner.Spinner - if connectedToTerminal { - s = utils.Spinner(opts.IO.ErrOut) - utils.StartSpinner(s) - } - + opts.IO.StartProgressIndicator() comments, err := api.CommentsForPullRequest(apiClient, repo, pr) + opts.IO.StopProgressIndicator() if err != nil { return err } pr.Comments = *comments - - if connectedToTerminal { - utils.StopSpinner(s) - } } opts.IO.DetectTerminalTheme() @@ -135,7 +124,8 @@ func viewRun(opts *ViewOptions) error { } if opts.Comments { - return printRawPrComments(opts.IO.Out, pr) + fmt.Fprint(opts.IO.Out, shared.RawCommentList(pr.Comments)) + return nil } return printRawPrPreview(opts.IO, pr) @@ -167,26 +157,6 @@ func printRawPrPreview(io *iostreams.IOStreams, pr *api.PullRequest) error { return nil } -func printRawPrComments(out io.Writer, pr *api.PullRequest) error { - var b strings.Builder - for _, comment := range pr.Comments.Nodes { - fmt.Fprint(&b, formatRawPrComment(comment)) - } - fmt.Fprint(out, b.String()) - return nil -} - -func formatRawPrComment(comment api.Comment) string { - var b strings.Builder - fmt.Fprintf(&b, "author:\t%s\n", comment.Author.Login) - fmt.Fprintf(&b, "association:\t%s\n", strings.ToLower(comment.AuthorAssociation)) - fmt.Fprintf(&b, "edited:\t%t\n", comment.IncludesCreatedEdit) - fmt.Fprintln(&b, "--") - fmt.Fprintln(&b, comment.Body) - fmt.Fprintln(&b, "--") - return b.String() -} - func printHumanPrPreview(io *iostreams.IOStreams, pr *api.PullRequest) error { out := io.Out cs := io.ColorScheme() @@ -203,7 +173,7 @@ func printHumanPrPreview(io *iostreams.IOStreams, pr *api.PullRequest) error { ) // Reactions - if reactions := reactionGroupList(pr.ReactionGroups); reactions != "" { + if reactions := shared.ReactionGroupList(pr.ReactionGroups); reactions != "" { fmt.Fprint(out, reactions) fmt.Fprintln(out) } @@ -245,7 +215,7 @@ func printHumanPrPreview(io *iostreams.IOStreams, pr *api.PullRequest) error { // Comments if pr.Comments.TotalCount > 0 { - comments, err := prCommentList(io, pr.Comments) + comments, err := shared.CommentList(io, pr.Comments) if err != nil { return err } @@ -258,75 +228,6 @@ func printHumanPrPreview(io *iostreams.IOStreams, pr *api.PullRequest) error { return nil } -func prCommentList(io *iostreams.IOStreams, comments api.Comments) (string, error) { - var b strings.Builder - cs := io.ColorScheme() - retrievedCount := len(comments.Nodes) - hiddenCount := comments.TotalCount - retrievedCount - - if hiddenCount > 0 { - fmt.Fprint(&b, cs.Gray(fmt.Sprintf("———————— Not showing %s ————————", utils.Pluralize(hiddenCount, "comment")))) - fmt.Fprintf(&b, "\n\n\n") - } - - for i, comment := range comments.Nodes { - last := i+1 == retrievedCount - cmt, err := formatPrComment(io, comment, last) - if err != nil { - return "", err - } - fmt.Fprint(&b, cmt) - if last { - fmt.Fprintln(&b) - } - } - - if hiddenCount > 0 { - fmt.Fprint(&b, cs.Gray("Use --comments to view the full conversation")) - fmt.Fprintln(&b) - } - - return b.String(), nil -} - -func formatPrComment(io *iostreams.IOStreams, comment api.Comment, newest bool) (string, error) { - var b strings.Builder - cs := io.ColorScheme() - - // Header - fmt.Fprint(&b, cs.Bold(comment.Author.Login)) - if comment.AuthorAssociation != "NONE" { - fmt.Fprint(&b, cs.Bold(fmt.Sprintf(" (%s)", strings.ToLower(comment.AuthorAssociation)))) - } - fmt.Fprint(&b, cs.Bold(fmt.Sprintf(" • %s", utils.FuzzyAgoAbbr(time.Now(), comment.CreatedAt)))) - if comment.IncludesCreatedEdit { - fmt.Fprint(&b, cs.Bold(" • edited")) - } - if newest { - fmt.Fprint(&b, cs.Bold(" • ")) - fmt.Fprint(&b, cs.CyanBold("Newest comment")) - } - fmt.Fprintln(&b) - - // Reactions - if reactions := reactionGroupList(comment.ReactionGroups); reactions != "" { - fmt.Fprint(&b, reactions) - fmt.Fprintln(&b) - } - - // Body - if comment.Body != "" { - style := markdown.GetStyle(io.TerminalTheme()) - md, err := markdown.Render(comment.Body, style, "") - if err != nil { - return "", err - } - fmt.Fprint(&b, md) - } - - return b.String(), nil -} - const ( requestedReviewState = "REQUESTED" // This is our own state for review request approvedReviewState = "APPROVED" @@ -504,27 +405,3 @@ func prStateWithDraft(pr *api.PullRequest) string { return pr.State } - -func reactionGroupList(rgs api.ReactionGroups) string { - var rs []string - - for _, rg := range rgs { - if r := formatReactionGroup(rg); r != "" { - rs = append(rs, r) - } - } - - return strings.Join(rs, " • ") -} - -func formatReactionGroup(rg api.ReactionGroup) string { - c := rg.Count() - if c == 0 { - return "" - } - e := rg.Emoji() - if e == "" { - return "" - } - return fmt.Sprintf("%v %s", c, e) -}