Skip to content

Commit

Permalink
Add headers to all tables (#8157)
Browse files Browse the repository at this point in the history
  • Loading branch information
heaths committed Oct 20, 2023
1 parent 26f3601 commit 7738b61
Show file tree
Hide file tree
Showing 49 changed files with 514 additions and 426 deletions.
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/cenkalti/backoff/v4 v4.2.1
github.com/charmbracelet/glamour v0.6.0
github.com/charmbracelet/lipgloss v0.5.0
github.com/cli/go-gh/v2 v2.3.0
github.com/cli/go-gh/v2 v2.4.1-0.20231019124728-ec1e1cd3e0cb
github.com/cli/oauth v1.0.1
github.com/cli/safeexec v1.0.1
github.com/cpuguy83/go-md2man/v2 v2.0.3
Expand Down Expand Up @@ -51,8 +51,8 @@ require (
github.com/alessio/shellescape v1.4.1 // indirect
github.com/aymanbagabas/go-osc52 v1.0.3 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/cli/browser v1.2.0 // indirect
github.com/cli/shurcooL-graphql v0.0.3 // indirect
github.com/cli/browser v1.3.0 // indirect
github.com/cli/shurcooL-graphql v0.0.4 // indirect
github.com/danieljoos/wincred v1.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dlclark/regexp2 v1.4.0 // indirect
Expand Down
14 changes: 6 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ github.com/charmbracelet/glamour v0.6.0/go.mod h1:taqWV4swIMMbWALc0m7AfE9JkPSU8o
github.com/charmbracelet/lipgloss v0.5.0 h1:lulQHuVeodSgDez+3rGiuxlPVXSnhth442DATR2/8t8=
github.com/charmbracelet/lipgloss v0.5.0/go.mod h1:EZLha/HbzEt7cYqdFPovlqy5FZPj0xFhg5SaqxScmgs=
github.com/cli/browser v1.0.0/go.mod h1:IEWkHYbLjkhtjwwWlwTHW2lGxeS5gezEQBMLTwDHf5Q=
github.com/cli/browser v1.2.0 h1:yvU7e9qf97kZqGFX6n2zJPHsmSObY9ske+iCvKelvXg=
github.com/cli/browser v1.2.0/go.mod h1:xFFnXLVcAyW9ni0cuo6NnrbCP75JxJ0RO7VtCBiH/oI=
github.com/cli/go-gh/v2 v2.3.0 h1:FAQAP4PaWSAJf4VSxFEIYDQ1oBIs+bKB4GXQAiRr2sQ=
github.com/cli/go-gh/v2 v2.3.0/go.mod h1:6WBUuf7LUVAc+eXYYX/nYTYURRc6M03K9cJNwBKvwT0=
github.com/cli/browser v1.3.0 h1:LejqCrpWr+1pRqmEPDGnTZOjsMe7sehifLynZJuqJpo=
github.com/cli/browser v1.3.0/go.mod h1:HH8s+fOAxjhQoBUAsKuPCbqUuxZDhQ2/aD+SzsEfBTk=
github.com/cli/go-gh/v2 v2.4.1-0.20231019124728-ec1e1cd3e0cb h1:HeIpiv5Jf09GQA0AyABbjC7Zq55eyIxpv4/BU6ujHRk=
github.com/cli/go-gh/v2 v2.4.1-0.20231019124728-ec1e1cd3e0cb/go.mod h1:h3salfqqooVpzKmHp6aUdeNx62UmxQRpLbagFSHTJGQ=
github.com/cli/oauth v1.0.1 h1:pXnTFl/qUegXHK531Dv0LNjW4mLx626eS42gnzfXJPA=
github.com/cli/oauth v1.0.1/go.mod h1:qd/FX8ZBD6n1sVNQO3aIdRxeu5LGw9WhKnYhIIoC2A4=
github.com/cli/safeexec v1.0.0/go.mod h1:Z/D4tTN8Vs5gXYHDCbaM1S/anmEDnJb1iW0+EJ5zx3Q=
github.com/cli/safeexec v1.0.1 h1:e/C79PbXF4yYTN/wauC4tviMxEV13BwljGj0N9j+N00=
github.com/cli/safeexec v1.0.1/go.mod h1:Z/D4tTN8Vs5gXYHDCbaM1S/anmEDnJb1iW0+EJ5zx3Q=
github.com/cli/shurcooL-graphql v0.0.3 h1:CtpPxyGDs136/+ZeyAfUKYmcQBjDlq5aqnrDCW5Ghh8=
github.com/cli/shurcooL-graphql v0.0.3/go.mod h1:tlrLmw/n5Q/+4qSvosT+9/W5zc8ZMjnJeYBxSdb4nWA=
github.com/cli/shurcooL-graphql v0.0.4 h1:6MogPnQJLjKkaXPyGqPRXOI2qCsQdqNfUY1QSJu2GuY=
github.com/cli/shurcooL-graphql v0.0.4/go.mod h1:3waN4u02FiZivIV+p1y4d0Jo1jc6BViMA73C+sZo2fk=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
Expand Down Expand Up @@ -183,7 +183,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220923203811-8be639271d50/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
Expand All @@ -199,7 +198,6 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
77 changes: 62 additions & 15 deletions internal/tableprinter/table_printer.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tableprinter

import (
"io"
"strings"
"time"

Expand All @@ -12,24 +13,22 @@ import (
type TablePrinter struct {
tableprinter.TablePrinter
isTTY bool
cs *iostreams.ColorScheme
}

func (t *TablePrinter) HeaderRow(columns ...string) {
if !t.isTTY {
return
}
for _, col := range columns {
t.AddField(strings.ToUpper(col))
}
t.EndRow()
// IsTTY gets wether the TablePrinter will render to a terminal.
func (t *TablePrinter) IsTTY() bool {
return t.isTTY
}

// In tty mode display the fuzzy time difference between now and t.
// In nontty mode just display t with the time.RFC3339 format.
// AddTimeField in TTY mode displays the fuzzy time difference between now and t.
// In non-TTY mode it just displays t with the time.RFC3339 format.
func (tp *TablePrinter) AddTimeField(now, t time.Time, c func(string) string) {
tf := t.Format(time.RFC3339)
var tf string
if tp.isTTY {
tf = text.FuzzyAgo(now, t)
} else {
tf = t.Format(time.RFC3339)
}
tp.AddField(tf, tableprinter.WithColor(c))
}
Expand All @@ -39,15 +38,63 @@ var (
WithColor = tableprinter.WithColor
)

func New(ios *iostreams.IOStreams) *TablePrinter {
type headerOption struct {
columns []string
}

// New creates a TablePrinter from an IOStreams.
func New(ios *iostreams.IOStreams, headers headerOption) *TablePrinter {
maxWidth := 80
isTTY := ios.IsStdoutTTY()
if isTTY {
maxWidth = ios.TerminalWidth()
}
tp := tableprinter.New(ios.Out, isTTY, maxWidth)
return &TablePrinter{
TablePrinter: tp,

return NewWithWriter(ios.Out, isTTY, maxWidth, ios.ColorScheme(), headers)
}

// NewWithWriter creates a TablePrinter from a Writer, whether the output is a terminal, the terminal width, and more.
func NewWithWriter(w io.Writer, isTTY bool, maxWidth int, cs *iostreams.ColorScheme, headers headerOption) *TablePrinter {
tp := &TablePrinter{
TablePrinter: tableprinter.New(w, isTTY, maxWidth),
isTTY: isTTY,
cs: cs,
}

if isTTY && len(headers.columns) > 0 {
// Make sure all headers are uppercase.
for i := range headers.columns {
headers.columns[i] = strings.ToUpper(headers.columns[i])
}

// Make sure all header columns are padded - even the last one. Previously, the last header column
// was not padded. In tests cs.Enabled() is false which allows us to avoid having to fix up
// numerous tests that verify header padding.
var paddingFunc func(int, string) string
if cs.Enabled() {
paddingFunc = text.PadRight
}

tp.AddHeader(
headers.columns,
tableprinter.WithPadding(paddingFunc),
tableprinter.WithColor(cs.LightGrayUnderline),
)
}

return tp
}

// WithHeader defines the column names for a table.
// Panics if columns is nil or empty.
func WithHeader(columns ...string) headerOption {
if len(columns) == 0 {
panic("must define header columns")
}
return headerOption{columns}
}

// NoHeader disable printing or checking for a table header.
//
// Deprecated: use WithHeader unless required otherwise.
var NoHeader = headerOption{}
4 changes: 4 additions & 0 deletions internal/text/text.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,7 @@ func DisplayURL(urlStr string) string {
func RemoveDiacritics(value string) string {
return text.RemoveDiacritics(value)
}

func PadRight(maxWidth int, s string) string {
return text.PadRight(maxWidth, s)
}
3 changes: 1 addition & 2 deletions pkg/cmd/cache/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,7 @@ func listRun(opts *ListOptions) error {
opts.Now = time.Now()
}

tp := tableprinter.New(opts.IO)
tp.HeaderRow("ID", "KEY", "SIZE", "CREATED", "ACCESSED")
tp := tableprinter.New(opts.IO, tableprinter.WithHeader("ID", "KEY", "SIZE", "CREATED", "ACCESSED"))
for _, cache := range result.ActionsCaches {
tp.AddField(opts.IO.ColorScheme().Cyan(fmt.Sprintf("%d", cache.Id)))
tp.AddField(cache.Key)
Expand Down
56 changes: 27 additions & 29 deletions pkg/cmd/codespace/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import (

"github.com/MakeNowJust/heredoc"
"github.com/cli/cli/v2/internal/codespaces/api"
"github.com/cli/cli/v2/internal/tableprinter"
"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 @@ -116,25 +116,23 @@ func (a *App) List(ctx context.Context, opts *listOptions, exporter cmdutil.Expo
return a.browser.Browse(fmt.Sprintf("%s/codespaces?repository_id=%d", a.apiClient.ServerURL(), codespaces[0].Repository.ID))
}

//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
tp := utils.NewTablePrinter(a.io)
if tp.IsTTY() {
tp.AddField("NAME", nil, nil)
tp.AddField("DISPLAY NAME", nil, nil)
if opts.orgName != "" {
tp.AddField("OWNER", nil, nil)
}
tp.AddField("REPOSITORY", nil, nil)
tp.AddField("BRANCH", nil, nil)
tp.AddField("STATE", nil, nil)
tp.AddField("CREATED AT", nil, nil)

if hasNonProdVSCSTarget {
tp.AddField("VSCS TARGET", nil, nil)
}

tp.EndRow()
headers := []string{
"NAME",
"DISPLAY NAME",
}
if opts.orgName != "" {
headers = append(headers, "OWNER")
}
headers = append(headers,
"REPOSITORY",
"BRANCH",
"STATE",
"CREATED AT",
)
if hasNonProdVSCSTarget {
headers = append(headers, "VSCS TARGET")
}
tp := tableprinter.New(a.io, tableprinter.WithHeader(headers...))

cs := a.io.ColorScheme()
for _, apiCodespace := range codespaces {
Expand All @@ -158,31 +156,31 @@ func (a *App) List(ctx context.Context, opts *listOptions, exporter cmdutil.Expo
nameColor = cs.Gray
}

tp.AddField(formattedName, nil, nameColor)
tp.AddField(c.DisplayName, nil, nil)
tp.AddField(formattedName, tableprinter.WithColor(nameColor))
tp.AddField(c.DisplayName)
if opts.orgName != "" {
tp.AddField(c.Owner.Login, nil, nil)
tp.AddField(c.Owner.Login)
}
tp.AddField(c.Repository.FullName, nil, nil)
tp.AddField(c.branchWithGitStatus(), nil, cs.Cyan)
tp.AddField(c.Repository.FullName)
tp.AddField(c.branchWithGitStatus(), tableprinter.WithColor(cs.Cyan))
if c.PendingOperation {
tp.AddField(c.PendingOperationDisabledReason, nil, nameColor)
tp.AddField(c.PendingOperationDisabledReason, tableprinter.WithColor(nameColor))
} else {
tp.AddField(c.State, nil, stateColor)
tp.AddField(c.State, tableprinter.WithColor(stateColor))
}

if tp.IsTTY() {
ct, err := time.Parse(time.RFC3339, c.CreatedAt)
if err != nil {
return fmt.Errorf("error parsing date %q: %w", c.CreatedAt, err)
}
tp.AddField(text.FuzzyAgoAbbr(time.Now(), ct), nil, cs.Gray)
tp.AddField(text.FuzzyAgoAbbr(time.Now(), ct), tableprinter.WithColor(cs.Gray))
} else {
tp.AddField(c.CreatedAt, nil, nil)
tp.AddField(c.CreatedAt)
}

if hasNonProdVSCSTarget {
tp.AddField(c.VSCSTarget, nil, nil)
tp.AddField(c.VSCSTarget)
}

tp.EndRow()
Expand Down
10 changes: 1 addition & 9 deletions pkg/cmd/codespace/ports.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,7 @@ func (a *App) ListPorts(ctx context.Context, selector *CodespaceSelector, export
}

cs := a.io.ColorScheme()
tp := tableprinter.New(a.io)

if a.io.IsStdoutTTY() {
tp.AddField("LABEL")
tp.AddField("PORT")
tp.AddField("VISIBILITY")
tp.AddField("BROWSE URL")
tp.EndRow()
}
tp := tableprinter.New(a.io, tableprinter.WithHeader("LABEL", "PORT", "VISIBILITY", "BROWSE URL"))

for _, port := range portInfos {
// Convert the ACE to a friendly visibility string (private, org, public)
Expand Down
3 changes: 2 additions & 1 deletion pkg/cmd/codespace/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ func (a *App) ViewCodespace(ctx context.Context, opts *viewOptions) error {
return opts.exporter.Write(a.io, selectedCodespace)
}

tp := tableprinter.New(a.io)
//nolint:staticcheck // SA1019: Showing NAME|VALUE headers adds nothing to table.
tp := tableprinter.New(a.io, tableprinter.NoHeader)
c := codespace{selectedCodespace}
formattedName := formatNameForVSCSTarget(c.Name, c.VSCSTarget)

Expand Down
16 changes: 6 additions & 10 deletions pkg/cmd/extension/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/cli/cli/v2/pkg/extensions"
"github.com/cli/cli/v2/pkg/search"
"github.com/cli/cli/v2/utils"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -217,9 +216,7 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command {
return false
}

tp := tableprinter.New(io)
tp.HeaderRow("", "REPO", "DESCRIPTION")

tp := tableprinter.New(io, tableprinter.WithHeader("", "REPO", "DESCRIPTION"))
for _, repo := range result.Items {
if !strings.HasPrefix(repo.Name, "gh-") {
continue
Expand Down Expand Up @@ -270,8 +267,7 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command {
return cmdutil.NewNoResultsError("no installed extensions found")
}
cs := io.ColorScheme()
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
t := utils.NewTablePrinter(io)
t := tableprinter.New(io, tableprinter.WithHeader("NAME", "REPO", "VERSION"))
for _, c := range cmds {
// TODO consider a Repo() on Extension interface
var repo string
Expand All @@ -281,13 +277,13 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command {
}
}

t.AddField(fmt.Sprintf("gh %s", c.Name()), nil, nil)
t.AddField(repo, nil, nil)
t.AddField(fmt.Sprintf("gh %s", c.Name()))
t.AddField(repo)
version := displayExtensionVersion(c, c.CurrentVersion())
if c.IsPinned() {
t.AddField(version, nil, cs.Cyan)
t.AddField(version, tableprinter.WithColor(cs.Cyan))
} else {
t.AddField(version, nil, nil)
t.AddField(version)
}

t.EndRow()
Expand Down
Loading

0 comments on commit 7738b61

Please sign in to comment.