Migrate to tableprinter from go-gh (#6346)
This commit is contained in:
parent
4265b5b804
commit
3fe5026d39
26 changed files with 115 additions and 238 deletions
52
internal/tableprinter/table_printer.go
Normal file
52
internal/tableprinter/table_printer.go
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
package tableprinter
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cli/cli/v2/internal/text"
|
||||
"github.com/cli/cli/v2/pkg/iostreams"
|
||||
"github.com/cli/go-gh/pkg/tableprinter"
|
||||
)
|
||||
|
||||
type TablePrinter struct {
|
||||
tableprinter.TablePrinter
|
||||
isTTY bool
|
||||
}
|
||||
|
||||
func (t *TablePrinter) HeaderRow(columns ...string) {
|
||||
if !t.isTTY {
|
||||
return
|
||||
}
|
||||
for _, col := range columns {
|
||||
t.AddField(strings.ToUpper(col))
|
||||
}
|
||||
t.EndRow()
|
||||
}
|
||||
|
||||
func (tp *TablePrinter) AddTimeField(t time.Time, c func(string) string) {
|
||||
tf := t.Format(time.RFC3339)
|
||||
if tp.isTTY {
|
||||
// TODO: use a static time.Now
|
||||
tf = text.FuzzyAgo(time.Now(), t)
|
||||
}
|
||||
tp.AddField(tf, tableprinter.WithColor(c))
|
||||
}
|
||||
|
||||
var (
|
||||
WithTruncate = tableprinter.WithTruncate
|
||||
WithColor = tableprinter.WithColor
|
||||
)
|
||||
|
||||
func New(ios *iostreams.IOStreams) *TablePrinter {
|
||||
maxWidth := 80
|
||||
isTTY := ios.IsStdoutTTY()
|
||||
if isTTY {
|
||||
maxWidth = ios.TerminalWidth()
|
||||
}
|
||||
tp := tableprinter.New(ios.Out, isTTY, maxWidth)
|
||||
return &TablePrinter{
|
||||
TablePrinter: tp,
|
||||
isTTY: isTTY,
|
||||
}
|
||||
}
|
||||
|
|
@ -54,6 +54,7 @@ func listRun(opts *ListOptions) error {
|
|||
return cmdutil.NewNoResultsError("no aliases configured")
|
||||
}
|
||||
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
tp := utils.NewTablePrinter(opts.IO)
|
||||
keys := []string{}
|
||||
for alias := range aliasMap {
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ func (a *App) List(ctx context.Context, opts *listOptions, exporter cmdutil.Expo
|
|||
return cmdutil.NewNoResultsError("no codespaces found")
|
||||
}
|
||||
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
tp := utils.NewTablePrinter(a.io)
|
||||
if tp.IsTTY() {
|
||||
tp.AddField("NAME", nil, nil)
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ func (a *App) ListPorts(ctx context.Context, codespaceName string, exporter cmdu
|
|||
}
|
||||
|
||||
cs := a.io.ColorScheme()
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
tp := utils.NewTablePrinter(a.io)
|
||||
|
||||
if tp.IsTTY() {
|
||||
|
|
|
|||
|
|
@ -50,6 +50,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)
|
||||
for _, c := range cmds {
|
||||
var repo string
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ func listRun(opts *ListOptions) error {
|
|||
|
||||
cs := opts.IO.ColorScheme()
|
||||
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
tp := utils.NewTablePrinter(opts.IO)
|
||||
|
||||
for _, gist := range gists {
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ func listRun(opts *ListOptions) error {
|
|||
return cmdutil.NewNoResultsError("no GPG keys present in the GitHub account")
|
||||
}
|
||||
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
t := utils.NewTablePrinter(opts.IO)
|
||||
cs := opts.IO.ColorScheme()
|
||||
now := time.Now()
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import (
|
|||
|
||||
func PrintIssues(io *iostreams.IOStreams, now time.Time, prefix string, totalCount int, issues []api.Issue) {
|
||||
cs := io.ColorScheme()
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
table := utils.NewTablePrinter(io)
|
||||
for _, issue := range issues {
|
||||
issueNum := strconv.Itoa(issue.Number)
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ func listRun(opts *listOptions) error {
|
|||
|
||||
func printLabels(io *iostreams.IOStreams, labels []label) error {
|
||||
cs := io.ColorScheme()
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
table := utils.NewTablePrinter(io)
|
||||
|
||||
for _, label := range labels {
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ func printSummary(io *iostreams.IOStreams, counts checkCounts) {
|
|||
}
|
||||
|
||||
func printTable(io *iostreams.IOStreams, checks []check) error {
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
tp := utils.NewTablePrinter(io)
|
||||
|
||||
sort.Slice(checks, func(i, j int) bool {
|
||||
|
|
|
|||
|
|
@ -198,6 +198,7 @@ func listRun(opts *ListOptions) error {
|
|||
}
|
||||
|
||||
cs := opts.IO.ColorScheme()
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
table := utils.NewTablePrinter(opts.IO)
|
||||
for _, pr := range listResult.PullRequests {
|
||||
prNum := strconv.Itoa(pr.Number)
|
||||
|
|
|
|||
|
|
@ -3,13 +3,12 @@ package list
|
|||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/cli/cli/v2/internal/ghrepo"
|
||||
"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/pkg/iostreams"
|
||||
"github.com/cli/cli/v2/utils"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
|
@ -76,14 +75,15 @@ func listRun(opts *ListOptions) error {
|
|||
fmt.Fprintf(opts.IO.ErrOut, "failed to start pager: %v\n", err)
|
||||
}
|
||||
|
||||
table := utils.NewTablePrinter(opts.IO)
|
||||
table := tableprinter.New(opts.IO)
|
||||
iofmt := opts.IO.ColorScheme()
|
||||
table.HeaderRow("Title", "Type", "Tag name", "Published")
|
||||
for _, rel := range releases {
|
||||
title := text.RemoveExcessiveWhitespace(rel.Name)
|
||||
if title == "" {
|
||||
title = rel.TagName
|
||||
}
|
||||
table.AddField(title, nil, nil)
|
||||
table.AddField(title)
|
||||
|
||||
badge := ""
|
||||
var badgeColor func(string) string
|
||||
|
|
@ -97,23 +97,15 @@ func listRun(opts *ListOptions) error {
|
|||
badge = "Pre-release"
|
||||
badgeColor = iofmt.Yellow
|
||||
}
|
||||
table.AddField(badge, nil, badgeColor)
|
||||
table.AddField(badge, tableprinter.WithColor(badgeColor))
|
||||
|
||||
tagName := rel.TagName
|
||||
if table.IsTTY() {
|
||||
tagName = fmt.Sprintf("(%s)", tagName)
|
||||
}
|
||||
table.AddField(tagName, nil, nil)
|
||||
table.AddField(rel.TagName, tableprinter.WithTruncate(nil))
|
||||
|
||||
pubDate := rel.PublishedAt
|
||||
if rel.PublishedAt.IsZero() {
|
||||
pubDate = rel.CreatedAt
|
||||
}
|
||||
publishedAt := pubDate.Format(time.RFC3339)
|
||||
if table.IsTTY() {
|
||||
publishedAt = text.FuzzyAgo(time.Now(), pubDate)
|
||||
}
|
||||
table.AddField(publishedAt, nil, iofmt.Gray)
|
||||
table.AddTimeField(pubDate, iofmt.Gray)
|
||||
table.EndRow()
|
||||
}
|
||||
err = table.Render()
|
||||
|
|
|
|||
|
|
@ -103,10 +103,11 @@ func Test_listRun(t *testing.T) {
|
|||
LimitResults: 30,
|
||||
},
|
||||
wantStdout: heredoc.Doc(`
|
||||
v1.1.0 Draft (v1.1.0) about 1 day ago
|
||||
The big 1.0 Latest (v1.0.0) about 1 day ago
|
||||
1.0 release candidate Pre-release (v1.0.0-pre.2) about 1 day ago
|
||||
New features (v0.9.2) about 1 day ago
|
||||
TITLE TYPE TAG NAME PUBLISHED
|
||||
v1.1.0 Draft v1.1.0 about 1 day ago
|
||||
The big 1.0 Latest v1.0.0 about 1 day ago
|
||||
1.0 release candidate Pre-release v1.0.0-pre.2 about 1 day ago
|
||||
New features v0.9.2 about 1 day ago
|
||||
`),
|
||||
wantStderr: ``,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ func renderReleaseTTY(io *iostreams.IOStreams, release *shared.Release) error {
|
|||
|
||||
if len(release.Assets) > 0 {
|
||||
fmt.Fprintf(w, "%s\n", iofmt.Bold("Assets"))
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
table := utils.NewTablePrinter(io)
|
||||
for _, a := range release.Assets {
|
||||
table.AddField(a.Name, nil, nil)
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ func listRun(opts *ListOptions) error {
|
|||
return cmdutil.NewNoResultsError(fmt.Sprintf("no deploy keys found in %s", ghrepo.FullName(repo)))
|
||||
}
|
||||
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
t := utils.NewTablePrinter(opts.IO)
|
||||
cs := opts.IO.ColorScheme()
|
||||
now := time.Now()
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ func listRun(opts *ListOptions) error {
|
|||
}
|
||||
|
||||
cs := opts.IO.ColorScheme()
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
tp := utils.NewTablePrinter(opts.IO)
|
||||
|
||||
for _, repo := range listResult.Repositories {
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ func listRun(opts *ListOptions) error {
|
|||
return opts.Exporter.Write(opts.IO, runs)
|
||||
}
|
||||
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
tp := utils.NewTablePrinter(opts.IO)
|
||||
|
||||
cs := opts.IO.ColorScheme()
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ func displayResults(io *iostreams.IOStreams, now time.Time, results search.Repos
|
|||
now = time.Now()
|
||||
}
|
||||
cs := io.ColorScheme()
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
tp := utils.NewTablePrinter(io)
|
||||
for _, repo := range results.Items {
|
||||
tags := []string{visibilityLabel(repo)}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ func displayIssueResults(io *iostreams.IOStreams, now time.Time, et EntityType,
|
|||
now = time.Now()
|
||||
}
|
||||
cs := io.ColorScheme()
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
tp := utils.NewTablePrinter(io)
|
||||
for _, issue := range results.Items {
|
||||
if et == Both {
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ func listRun(opts *ListOptions) error {
|
|||
fmt.Fprintf(opts.IO.ErrOut, "failed to start pager: %v\n", err)
|
||||
}
|
||||
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
tp := utils.NewTablePrinter(opts.IO)
|
||||
for _, secret := range secrets {
|
||||
tp.AddField(secret.Name, nil, nil)
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ func listRun(opts *ListOptions) error {
|
|||
return cmdutil.NewNoResultsError("no SSH keys present in the GitHub account")
|
||||
}
|
||||
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
t := utils.NewTablePrinter(opts.IO)
|
||||
cs := opts.IO.ColorScheme()
|
||||
now := time.Now()
|
||||
|
|
|
|||
|
|
@ -664,6 +664,7 @@ func statusRun(opts *StatusOptions) error {
|
|||
section := func(header string, items []StatusItem, width, rowLimit int) (string, error) {
|
||||
tableOut := &bytes.Buffer{}
|
||||
fmt.Fprintln(tableOut, cs.Bold(header))
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinterWithOptions is deprecated: use internal/tableprinter
|
||||
tp := utils.NewTablePrinterWithOptions(opts.IO, utils.TablePrinterOptions{
|
||||
IsTTY: opts.IO.IsStdoutTTY(),
|
||||
MaxWidth: width,
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ func listRun(opts *ListOptions) error {
|
|||
fmt.Fprintf(opts.IO.ErrOut, "failed to start pager: %v\n", err)
|
||||
}
|
||||
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
tp := utils.NewTablePrinter(opts.IO)
|
||||
cs := opts.IO.ColorScheme()
|
||||
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ func viewWorkflowInfo(opts *ViewOptions, client *api.Client, repo ghrepo.Interfa
|
|||
|
||||
out := opts.IO.Out
|
||||
cs := opts.IO.ColorScheme()
|
||||
//nolint:staticcheck // SA1019: utils.NewTablePrinter is deprecated: use internal/tableprinter
|
||||
tp := utils.NewTablePrinter(opts.IO)
|
||||
|
||||
// Header
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/cli/cli/v2/internal/text"
|
||||
"github.com/cli/cli/v2/pkg/iostreams"
|
||||
"github.com/cli/go-gh/pkg/tableprinter"
|
||||
)
|
||||
|
||||
type TablePrinter interface {
|
||||
|
|
@ -23,12 +21,14 @@ type TablePrinterOptions struct {
|
|||
Out io.Writer
|
||||
}
|
||||
|
||||
// Deprecated: use internal/tableprinter
|
||||
func NewTablePrinter(io *iostreams.IOStreams) TablePrinter {
|
||||
return NewTablePrinterWithOptions(io, TablePrinterOptions{
|
||||
IsTTY: io.IsStdoutTTY(),
|
||||
})
|
||||
}
|
||||
|
||||
// Deprecated: use internal/tableprinter
|
||||
func NewTablePrinterWithOptions(ios *iostreams.IOStreams, opts TablePrinterOptions) TablePrinter {
|
||||
var out io.Writer
|
||||
if opts.Out != nil {
|
||||
|
|
@ -36,8 +36,8 @@ func NewTablePrinterWithOptions(ios *iostreams.IOStreams, opts TablePrinterOptio
|
|||
} else {
|
||||
out = ios.Out
|
||||
}
|
||||
var maxWidth int
|
||||
if opts.IsTTY {
|
||||
var maxWidth int
|
||||
if opts.MaxWidth > 0 {
|
||||
maxWidth = opts.MaxWidth
|
||||
} else if ios.IsStdoutTTY() {
|
||||
|
|
@ -45,205 +45,47 @@ func NewTablePrinterWithOptions(ios *iostreams.IOStreams, opts TablePrinterOptio
|
|||
} else {
|
||||
maxWidth = ios.ProcessTerminalWidth()
|
||||
}
|
||||
return &ttyTablePrinter{
|
||||
out: out,
|
||||
maxWidth: maxWidth,
|
||||
}
|
||||
}
|
||||
return &tsvTablePrinter{
|
||||
out: out,
|
||||
tp := tableprinter.New(out, opts.IsTTY, maxWidth)
|
||||
return &printer{
|
||||
tp: tp,
|
||||
isTTY: opts.IsTTY,
|
||||
}
|
||||
}
|
||||
|
||||
type tableField struct {
|
||||
Text string
|
||||
TruncateFunc func(int, string) string
|
||||
ColorFunc func(string) string
|
||||
type printer struct {
|
||||
tp tableprinter.TablePrinter
|
||||
colIndex int
|
||||
isTTY bool
|
||||
}
|
||||
|
||||
func (f *tableField) DisplayWidth() int {
|
||||
return text.DisplayWidth(f.Text)
|
||||
func (p printer) IsTTY() bool {
|
||||
return p.isTTY
|
||||
}
|
||||
|
||||
type ttyTablePrinter struct {
|
||||
out io.Writer
|
||||
maxWidth int
|
||||
rows [][]tableField
|
||||
}
|
||||
|
||||
func (t ttyTablePrinter) IsTTY() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (t *ttyTablePrinter) AddField(s string, truncateFunc func(int, string) string, colorFunc func(string) string) {
|
||||
func (p *printer) AddField(s string, truncateFunc func(int, string) string, colorFunc func(string) string) {
|
||||
if truncateFunc == nil {
|
||||
truncateFunc = text.Truncate
|
||||
}
|
||||
if t.rows == nil {
|
||||
t.rows = make([][]tableField, 1)
|
||||
}
|
||||
rowI := len(t.rows) - 1
|
||||
field := tableField{
|
||||
Text: s,
|
||||
TruncateFunc: truncateFunc,
|
||||
ColorFunc: colorFunc,
|
||||
}
|
||||
t.rows[rowI] = append(t.rows[rowI], field)
|
||||
}
|
||||
|
||||
func (t *ttyTablePrinter) EndRow() {
|
||||
t.rows = append(t.rows, []tableField{})
|
||||
}
|
||||
|
||||
func (t *ttyTablePrinter) Render() error {
|
||||
if len(t.rows) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
delim := " "
|
||||
numCols := len(t.rows[0])
|
||||
colWidths := t.calculateColumnWidths(len(delim))
|
||||
|
||||
for _, row := range t.rows {
|
||||
for col, field := range row {
|
||||
if col > 0 {
|
||||
_, err := fmt.Fprint(t.out, delim)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
truncVal := field.TruncateFunc(colWidths[col], field.Text)
|
||||
if col < numCols-1 {
|
||||
// pad value with spaces on the right
|
||||
if padWidth := colWidths[col] - field.DisplayWidth(); padWidth > 0 {
|
||||
truncVal += strings.Repeat(" ", padWidth)
|
||||
}
|
||||
}
|
||||
if field.ColorFunc != nil {
|
||||
truncVal = field.ColorFunc(truncVal)
|
||||
}
|
||||
_, err := fmt.Fprint(t.out, truncVal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(row) > 0 {
|
||||
_, err := fmt.Fprint(t.out, "\n")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Disallow ever truncating the 1st colum or any URL value
|
||||
if p.colIndex == 0 || isURL(s) {
|
||||
p.tp.AddField(s, tableprinter.WithTruncate(nil), tableprinter.WithColor(colorFunc))
|
||||
} else {
|
||||
p.tp.AddField(s, tableprinter.WithColor(colorFunc))
|
||||
}
|
||||
} else {
|
||||
p.tp.AddField(s, tableprinter.WithTruncate(truncateFunc), tableprinter.WithColor(colorFunc))
|
||||
}
|
||||
return nil
|
||||
p.colIndex++
|
||||
}
|
||||
|
||||
func (t *ttyTablePrinter) calculateColumnWidths(delimSize int) []int {
|
||||
numCols := len(t.rows[0])
|
||||
allColWidths := make([][]int, numCols)
|
||||
for _, row := range t.rows {
|
||||
for col, field := range row {
|
||||
allColWidths[col] = append(allColWidths[col], field.DisplayWidth())
|
||||
}
|
||||
}
|
||||
|
||||
// calculate max & median content width per column
|
||||
maxColWidths := make([]int, numCols)
|
||||
// medianColWidth := make([]int, numCols)
|
||||
for col := 0; col < numCols; col++ {
|
||||
widths := allColWidths[col]
|
||||
sort.Ints(widths)
|
||||
maxColWidths[col] = widths[len(widths)-1]
|
||||
// medianColWidth[col] = widths[(len(widths)+1)/2]
|
||||
}
|
||||
|
||||
colWidths := make([]int, numCols)
|
||||
// never truncate the first column
|
||||
colWidths[0] = maxColWidths[0]
|
||||
// never truncate the last column if it contains URLs
|
||||
if strings.HasPrefix(t.rows[0][numCols-1].Text, "https://") {
|
||||
colWidths[numCols-1] = maxColWidths[numCols-1]
|
||||
}
|
||||
|
||||
availWidth := func() int {
|
||||
setWidths := 0
|
||||
for col := 0; col < numCols; col++ {
|
||||
setWidths += colWidths[col]
|
||||
}
|
||||
return t.maxWidth - delimSize*(numCols-1) - setWidths
|
||||
}
|
||||
numFixedCols := func() int {
|
||||
fixedCols := 0
|
||||
for col := 0; col < numCols; col++ {
|
||||
if colWidths[col] > 0 {
|
||||
fixedCols++
|
||||
}
|
||||
}
|
||||
return fixedCols
|
||||
}
|
||||
|
||||
// set the widths of short columns
|
||||
if w := availWidth(); w > 0 {
|
||||
if numFlexColumns := numCols - numFixedCols(); numFlexColumns > 0 {
|
||||
perColumn := w / numFlexColumns
|
||||
for col := 0; col < numCols; col++ {
|
||||
if max := maxColWidths[col]; max < perColumn {
|
||||
colWidths[col] = max
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
firstFlexCol := -1
|
||||
// truncate long columns to the remaining available width
|
||||
if numFlexColumns := numCols - numFixedCols(); numFlexColumns > 0 {
|
||||
perColumn := availWidth() / numFlexColumns
|
||||
for col := 0; col < numCols; col++ {
|
||||
if colWidths[col] == 0 {
|
||||
if firstFlexCol == -1 {
|
||||
firstFlexCol = col
|
||||
}
|
||||
if max := maxColWidths[col]; max < perColumn {
|
||||
colWidths[col] = max
|
||||
} else if perColumn > 0 {
|
||||
colWidths[col] = perColumn
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add remainder to the first flex column
|
||||
if w := availWidth(); w > 0 && firstFlexCol > -1 {
|
||||
colWidths[firstFlexCol] += w
|
||||
if max := maxColWidths[firstFlexCol]; max < colWidths[firstFlexCol] {
|
||||
colWidths[firstFlexCol] = max
|
||||
}
|
||||
}
|
||||
|
||||
return colWidths
|
||||
func (p *printer) EndRow() {
|
||||
p.tp.EndRow()
|
||||
p.colIndex = 0
|
||||
}
|
||||
|
||||
type tsvTablePrinter struct {
|
||||
out io.Writer
|
||||
currentCol int
|
||||
func (p *printer) Render() error {
|
||||
return p.tp.Render()
|
||||
}
|
||||
|
||||
func (t tsvTablePrinter) IsTTY() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *tsvTablePrinter) AddField(text string, _ func(int, string) string, _ func(string) string) {
|
||||
if t.currentCol > 0 {
|
||||
fmt.Fprint(t.out, "\t")
|
||||
}
|
||||
fmt.Fprint(t.out, text)
|
||||
t.currentCol++
|
||||
}
|
||||
|
||||
func (t *tsvTablePrinter) EndRow() {
|
||||
fmt.Fprint(t.out, "\n")
|
||||
t.currentCol = 0
|
||||
}
|
||||
|
||||
func (t *tsvTablePrinter) Render() error {
|
||||
return nil
|
||||
func isURL(s string) bool {
|
||||
return strings.HasPrefix(s, "https://") || strings.HasPrefix(s, "http://")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_ttyTablePrinter_truncate(t *testing.T) {
|
||||
buf := bytes.Buffer{}
|
||||
tp := &ttyTablePrinter{
|
||||
out: &buf,
|
||||
maxWidth: 5,
|
||||
}
|
||||
|
||||
tp.AddField("1", nil, nil)
|
||||
tp.AddField("hello", nil, nil)
|
||||
tp.EndRow()
|
||||
tp.AddField("2", nil, nil)
|
||||
tp.AddField("world", nil, nil)
|
||||
tp.EndRow()
|
||||
|
||||
err := tp.Render()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
expected := "1 he\n2 wo\n"
|
||||
if buf.String() != expected {
|
||||
t.Errorf("expected: %q, got: %q", expected, buf.String())
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue