Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add headers to all tables #8157

Merged
merged 8 commits into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading