Skip to content

Commit

Permalink
Migrate to go-gh text package (cli#6236)
Browse files Browse the repository at this point in the history
  • Loading branch information
samcoe authored Sep 14, 2022
1 parent e16bf03 commit e7102f9
Show file tree
Hide file tree
Showing 60 changed files with 371 additions and 822 deletions.
9 changes: 7 additions & 2 deletions cmd/gh/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@ import (
"github.com/cli/cli/v2/internal/config"
"github.com/cli/cli/v2/internal/ghrepo"
"github.com/cli/cli/v2/internal/run"
"github.com/cli/cli/v2/internal/text"
"github.com/cli/cli/v2/internal/update"
"github.com/cli/cli/v2/pkg/cmd/alias/expand"
"github.com/cli/cli/v2/pkg/cmd/factory"
"github.com/cli/cli/v2/pkg/cmd/root"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/cli/cli/v2/pkg/iostreams"
"github.com/cli/cli/v2/pkg/text"
"github.com/cli/cli/v2/utils"
"github.com/cli/safeexec"
"github.com/mattn/go-isatty"
"github.com/mgutz/ansi"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -336,7 +337,11 @@ func shouldCheckForUpdate() bool {
if os.Getenv("CODESPACES") != "" {
return false
}
return updaterEnabled != "" && !isCI() && utils.IsTerminal(os.Stdout) && utils.IsTerminal(os.Stderr)
return updaterEnabled != "" && !isCI() && isTerminal(os.Stdout) && isTerminal(os.Stderr)
}

func isTerminal(f *os.File) bool {
return isatty.IsTerminal(f.Fd()) || isatty.IsCygwinTerminal(f.Fd())
}

// based on https://github.com/watson/ci-info/blob/HEAD/index.js
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
github.com/briandowns/spinner v1.18.1
github.com/charmbracelet/glamour v0.5.0
github.com/charmbracelet/lipgloss v0.5.0
github.com/cli/go-gh v0.1.1-0.20220817122932-3630ab390fe7
github.com/cli/go-gh v0.1.1-0.20220913125123-04019861008e
github.com/cli/oauth v0.9.0
github.com/cli/safeexec v1.0.0
github.com/cpuguy83/go-md2man/v2 v2.0.2
Expand All @@ -25,7 +25,6 @@ require (
github.com/mattn/go-colorable v0.1.13
github.com/mattn/go-isatty v0.0.16
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d
github.com/muesli/reflow v0.3.0
github.com/muesli/termenv v0.12.0
github.com/muhammadmuzzammil1998/jsonc v0.0.0-20201229145248-615b0916ca38
github.com/opentracing/opentracing-go v1.1.0
Expand Down Expand Up @@ -59,6 +58,7 @@ require (
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/microcosm-cc/bluemonday v1.0.19 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ github.com/cli/browser v1.1.0 h1:xOZBfkfY9L9vMBgqb1YwRirGu6QFaQ5dP/vXt5ENSOY=
github.com/cli/browser v1.1.0/go.mod h1:HKMQAt9t12kov91Mn7RfZxyJQQgWgyS/3SZswlZ5iTI=
github.com/cli/crypto v0.0.0-20210929142629-6be313f59b03 h1:3f4uHLfWx4/WlnMPXGai03eoWAI+oGHJwr+5OXfxCr8=
github.com/cli/crypto v0.0.0-20210929142629-6be313f59b03/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
github.com/cli/go-gh v0.1.1-0.20220817122932-3630ab390fe7 h1:yLnT5/sLlUcnr5njBRmf/d7pEKr0Cu2TpeecdlQl8AY=
github.com/cli/go-gh v0.1.1-0.20220817122932-3630ab390fe7/go.mod h1:UKRuMl3ZaitTvO4LPWj5bVw7QwZHnLu0S0lI9WWbdpc=
github.com/cli/go-gh v0.1.1-0.20220913125123-04019861008e h1:zK2hqxSk5D/Jt4o+0NVH/qdEFh7fUhgGkhbukwPMzQU=
github.com/cli/go-gh v0.1.1-0.20220913125123-04019861008e/go.mod h1:UKRuMl3ZaitTvO4LPWj5bVw7QwZHnLu0S0lI9WWbdpc=
github.com/cli/oauth v0.9.0 h1:nxBC0Df4tUzMkqffAB+uZvisOwT3/N9FpkfdTDtafxc=
github.com/cli/oauth v0.9.0/go.mod h1:qd/FX8ZBD6n1sVNQO3aIdRxeu5LGw9WhKnYhIIoC2A4=
github.com/cli/safeexec v1.0.0 h1:0VngyaIyqACHdcMNWfo6+KdUYnqEr2Sg+bSP1pdF+dI=
Expand Down
2 changes: 1 addition & 1 deletion internal/codespaces/states.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
"time"

"github.com/cli/cli/v2/internal/codespaces/api"
"github.com/cli/cli/v2/internal/text"
"github.com/cli/cli/v2/pkg/liveshare"
"github.com/cli/cli/v2/pkg/text"
)

// PostCreateStateStatus is a string value representing the different statuses a state can have.
Expand Down
74 changes: 74 additions & 0 deletions internal/text/text.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package text

import (
"fmt"
"net/url"
"regexp"
"strings"
"time"

"github.com/cli/go-gh/pkg/text"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)

var whitespaceRE = regexp.MustCompile(`\s+`)

func Indent(s, indent string) string {
return text.Indent(s, indent)
}

// Title returns a copy of the string s with all Unicode letters that begin words mapped to their Unicode title case.
func Title(s string) string {
c := cases.Title(language.English)
return c.String(s)
}

// RemoveExcessiveWhitespace returns a copy of the string s with excessive whitespace removed.
func RemoveExcessiveWhitespace(s string) string {
return whitespaceRE.ReplaceAllString(strings.TrimSpace(s), " ")
}

func DisplayWidth(s string) int {
return text.DisplayWidth(s)
}

func Truncate(maxWidth int, s string) string {
return text.Truncate(maxWidth, s)
}

func Pluralize(num int, thing string) string {
return text.Pluralize(num, thing)
}

func FuzzyAgo(a, b time.Time) string {
return text.RelativeTimeAgo(a, b)
}

// FuzzyAgoAbbr is an abbreviated version of FuzzyAgo. It returns a human readable string of the
// time duration between a and b that is estimated to the nearest unit of time.
func FuzzyAgoAbbr(a, b time.Time) string {
ago := a.Sub(b)

if ago < time.Hour {
return fmt.Sprintf("%d%s", int(ago.Minutes()), "m")
}
if ago < 24*time.Hour {
return fmt.Sprintf("%d%s", int(ago.Hours()), "h")
}
if ago < 30*24*time.Hour {
return fmt.Sprintf("%d%s", int(ago.Hours())/24, "d")
}

return b.Format("Jan _2, 2006")
}

// DisplayURL returns a copy of the string urlStr removing everything except the hostname and path.
// If there is an error parsing urlStr then urlStr is returned without modification.
func DisplayURL(urlStr string) string {
u, err := url.Parse(urlStr)
if err != nil {
return urlStr
}
return u.Hostname() + u.Path
}
56 changes: 56 additions & 0 deletions internal/text/text_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package text

import (
"testing"
"time"

"github.com/stretchr/testify/assert"
)

func TestRemoveExcessiveWhitespace(t *testing.T) {
tests := []struct {
name string
input string
want string
}{
{
name: "nothing to remove",
input: "one two three",
want: "one two three",
},
{
name: "whitespace b-gone",
input: "\n one\n\t two three\r\n ",
want: "one two three",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := RemoveExcessiveWhitespace(tt.input)
assert.Equal(t, tt.want, got)
})
}
}

func TestFuzzyAgoAbbr(t *testing.T) {
const form = "2006-Jan-02 15:04:05"
now, _ := time.Parse(form, "2020-Nov-22 14:00:00")
cases := map[string]string{
"2020-Nov-22 14:00:00": "0m",
"2020-Nov-22 13:59:00": "1m",
"2020-Nov-22 13:30:00": "30m",
"2020-Nov-22 13:00:00": "1h",
"2020-Nov-22 02:00:00": "12h",
"2020-Nov-21 14:00:00": "1d",
"2020-Nov-07 14:00:00": "15d",
"2020-Oct-24 14:00:00": "29d",
"2020-Oct-23 14:00:00": "Oct 23, 2020",
"2019-Nov-22 14:00:00": "Nov 22, 2019",
}
for createdAt, expected := range cases {
d, err := time.Parse(form, createdAt)
assert.NoError(t, err)
fuzzy := FuzzyAgoAbbr(now, d)
assert.Equal(t, expected, fuzzy)
}
}
4 changes: 2 additions & 2 deletions pkg/cmd/browse/browse.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import (
"github.com/cli/cli/v2/git"
"github.com/cli/cli/v2/internal/browser"
"github.com/cli/cli/v2/internal/ghrepo"
"github.com/cli/cli/v2/internal/text"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/cli/cli/v2/pkg/iostreams"
"github.com/cli/cli/v2/utils"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -148,7 +148,7 @@ func runBrowse(opts *BrowseOptions) error {
}

if opts.IO.IsStdoutTTY() {
fmt.Fprintf(opts.IO.Out, "Opening %s in your browser.\n", utils.DisplayURL(url))
fmt.Fprintf(opts.IO.Out, "Opening %s in your browser.\n", text.DisplayURL(url))
}
return opts.Browser.Browse(url)
}
Expand Down
17 changes: 13 additions & 4 deletions pkg/cmd/codespace/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (
"github.com/AlecAivazis/survey/v2"
"github.com/cli/cli/v2/internal/codespaces"
"github.com/cli/cli/v2/internal/codespaces/api"
"github.com/cli/cli/v2/internal/text"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/cli/cli/v2/utils"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -192,12 +192,12 @@ func (a *App) Create(ctx context.Context, opts createOptions) error {
if len(devcontainers) > 0 {

// if there is only one devcontainer.json file and it is one of the default paths we can auto-select it
if len(devcontainers) == 1 && utils.StringInSlice(devcontainers[0].Path, DEFAULT_DEVCONTAINER_DEFINITIONS) {
if len(devcontainers) == 1 && stringInSlice(devcontainers[0].Path, DEFAULT_DEVCONTAINER_DEFINITIONS) {
devContainerPath = devcontainers[0].Path
} else {
promptOptions := []string{}

if !utils.StringInSlice(devcontainers[0].Path, DEFAULT_DEVCONTAINER_DEFINITIONS) {
if !stringInSlice(devcontainers[0].Path, DEFAULT_DEVCONTAINER_DEFINITIONS) {
promptOptions = []string{DEVCONTAINER_PROMPT_DEFAULT}
}

Expand Down Expand Up @@ -284,7 +284,7 @@ func (a *App) handleAdditionalPermissions(ctx context.Context, createParams *api
var (
isInteractive = a.io.CanPrompt()
cs = a.io.ColorScheme()
displayURL = utils.DisplayURL(allowPermissionsURL)
displayURL = text.DisplayURL(allowPermissionsURL)
)

fmt.Fprintf(a.io.ErrOut, "You must authorize or deny additional permissions requested by this codespace before continuing.\n")
Expand Down Expand Up @@ -498,3 +498,12 @@ func buildDisplayName(displayName string, prebuildAvailability string) string {
return displayName
}
}

func stringInSlice(a string, slice []string) bool {
for _, b := range slice {
if b == a {
return true
}
}
return false
}
3 changes: 2 additions & 1 deletion pkg/cmd/codespace/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/MakeNowJust/heredoc"
"github.com/cli/cli/v2/internal/codespaces/api"
"github.com/cli/cli/v2/internal/text"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/cli/cli/v2/utils"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -144,7 +145,7 @@ func (a *App) List(ctx context.Context, opts *listOptions, exporter cmdutil.Expo
if err != nil {
return fmt.Errorf("error parsing date %q: %w", c.CreatedAt, err)
}
tp.AddField(utils.FuzzyAgoAbbr(time.Now(), ct), nil, cs.Gray)
tp.AddField(text.FuzzyAgoAbbr(time.Now(), ct), nil, cs.Gray)
} else {
tp.AddField(c.CreatedAt, nil, nil)
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/cmd/gist/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ import (
"github.com/cli/cli/v2/internal/browser"
"github.com/cli/cli/v2/internal/config"
"github.com/cli/cli/v2/internal/ghinstance"
"github.com/cli/cli/v2/internal/text"
"github.com/cli/cli/v2/pkg/cmd/gist/shared"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/cli/cli/v2/pkg/iostreams"
"github.com/cli/cli/v2/utils"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -164,7 +164,7 @@ func createRun(opts *CreateOptions) error {
fmt.Fprintf(errOut, "%s %s\n", cs.SuccessIconWithColor(cs.Green), completionMessage)

if opts.WebMode {
fmt.Fprintf(opts.IO.Out, "Opening %s in your browser.\n", utils.DisplayURL(gist.HTMLURL))
fmt.Fprintf(opts.IO.Out, "Opening %s in your browser.\n", text.DisplayURL(gist.HTMLURL))

return opts.Browser.Browse(gist.HTMLURL)
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/cmd/gist/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import (
"time"

"github.com/cli/cli/v2/internal/config"
"github.com/cli/cli/v2/internal/text"
"github.com/cli/cli/v2/pkg/cmd/gist/shared"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/cli/cli/v2/pkg/iostreams"
"github.com/cli/cli/v2/pkg/text"
"github.com/cli/cli/v2/utils"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -119,12 +119,12 @@ func listRun(opts *ListOptions) error {

gistTime := gist.UpdatedAt.Format(time.RFC3339)
if tp.IsTTY() {
gistTime = utils.FuzzyAgo(time.Since(gist.UpdatedAt))
gistTime = text.FuzzyAgo(time.Now(), gist.UpdatedAt)
}

tp.AddField(gist.ID, nil, nil)
tp.AddField(text.ReplaceExcessiveWhitespace(description), nil, cs.Bold)
tp.AddField(utils.Pluralize(fileCount, "file"), nil, nil)
tp.AddField(text.RemoveExcessiveWhitespace(description), nil, cs.Bold)
tp.AddField(text.Pluralize(fileCount, "file"), nil, nil)
tp.AddField(visibility, nil, visColor)
tp.AddField(gistTime, nil, cs.Gray)
tp.EndRow()
Expand Down
9 changes: 4 additions & 5 deletions pkg/cmd/gist/view/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ import (
"github.com/AlecAivazis/survey/v2"
"github.com/cli/cli/v2/internal/config"
"github.com/cli/cli/v2/internal/ghinstance"
"github.com/cli/cli/v2/internal/text"
"github.com/cli/cli/v2/pkg/cmd/gist/shared"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/cli/cli/v2/pkg/iostreams"
"github.com/cli/cli/v2/pkg/markdown"
"github.com/cli/cli/v2/pkg/prompt"
"github.com/cli/cli/v2/pkg/text"
"github.com/cli/cli/v2/utils"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -107,7 +106,7 @@ func viewRun(opts *ViewOptions) error {
gistURL = ghinstance.GistPrefix(hostname) + gistID
}
if opts.IO.IsStderrTTY() {
fmt.Fprintf(opts.IO.ErrOut, "Opening %s in your browser.\n", utils.DisplayURL(gistURL))
fmt.Fprintf(opts.IO.ErrOut, "Opening %s in your browser.\n", text.DisplayURL(gistURL))
}
return opts.Browser.Browse(gistURL)
}
Expand Down Expand Up @@ -236,9 +235,9 @@ func promptGists(client *http.Client, host string, cs *iostreams.ColorScheme) (g
sort.Strings(filenames)
gistName = filenames[0]

gistTime := utils.FuzzyAgo(time.Since(gist.UpdatedAt))
gistTime := text.FuzzyAgo(time.Now(), gist.UpdatedAt)
// TODO: support dynamic maxWidth
description = text.Truncate(100, text.ReplaceExcessiveWhitespace(description))
description = text.Truncate(100, text.RemoveExcessiveWhitespace(description))
opt := fmt.Sprintf("%s %s %s", cs.Bold(gistName), description, cs.Gray(gistTime))
opts = append(opts, opt)
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/cmd/gpg-key/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"time"

"github.com/cli/cli/v2/internal/config"
"github.com/cli/cli/v2/internal/text"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/cli/cli/v2/pkg/iostreams"
"github.com/cli/cli/v2/utils"
Expand Down Expand Up @@ -81,7 +82,7 @@ func listRun(opts *ListOptions) error {

createdAt := gpgKey.CreatedAt.Format(time.RFC3339)
if t.IsTTY() {
createdAt = "Created " + utils.FuzzyAgoAbbr(now, gpgKey.CreatedAt)
createdAt = "Created " + text.FuzzyAgoAbbr(now, gpgKey.CreatedAt)
}
t.AddField(createdAt, nil, cs.Gray)

Expand Down
Loading

0 comments on commit e7102f9

Please sign in to comment.