Fix cmdutil.PrintTable to handle non-simple strings
This commit is contained in:
parent
8fae881a81
commit
83e2cd7e4a
|
@ -574,6 +574,8 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z
|
|||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8=
|
||||
github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
|
|
|
@ -61,6 +61,7 @@ require (
|
|||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/spf13/pflag v1.0.3 // indirect
|
||||
github.com/src-d/gcfg v1.4.0 // indirect
|
||||
github.com/xanzy/ssh-agent v0.2.1 // indirect
|
||||
|
|
|
@ -164,6 +164,8 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
|
|||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94 h1:G04eS0JkAIVZfaJLjla9dNxkJCPiKIGZlw9AfOhzOD0=
|
||||
|
|
|
@ -17,10 +17,11 @@ package cmdutil
|
|||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/rivo/uniseg"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/util/ciutil"
|
||||
|
@ -152,6 +153,9 @@ func (table *Table) ToStringWithGap(columnGap string) string {
|
|||
|
||||
allRows = append(allRows, table.Rows...)
|
||||
|
||||
// 7-bit C1 ANSI sequences
|
||||
ansiEscape := regexp.MustCompile(`\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])`)
|
||||
|
||||
for rowIndex, row := range allRows {
|
||||
columns := row.Columns
|
||||
if len(columns) != len(preferredColumnWidths) {
|
||||
|
@ -161,36 +165,42 @@ func (table *Table) ToStringWithGap(columnGap string) string {
|
|||
}
|
||||
|
||||
for columnIndex, val := range columns {
|
||||
preferredColumnWidths[columnIndex] = max(preferredColumnWidths[columnIndex], len(val))
|
||||
// Strip ansi escape sequences
|
||||
clean := ansiEscape.ReplaceAllString(val, "")
|
||||
|
||||
// Need to count graphemes not runes or bytes
|
||||
preferredColumnWidths[columnIndex] = max(preferredColumnWidths[columnIndex], uniseg.GraphemeClusterCount(clean))
|
||||
}
|
||||
}
|
||||
|
||||
format := ""
|
||||
for i, maxWidth := range preferredColumnWidths {
|
||||
if i < len(preferredColumnWidths)-1 {
|
||||
format += "%-" + strconv.Itoa(maxWidth+len(columnGap)) + "s"
|
||||
} else {
|
||||
result := ""
|
||||
for _, row := range allRows {
|
||||
result += table.Prefix
|
||||
|
||||
for columnIndex, val := range row.Columns {
|
||||
result += val
|
||||
|
||||
if columnIndex < columnCount-1 {
|
||||
// Work out how much whitespace we need to add to this string to bring it up to the
|
||||
// preferredColumnWidth for this column. Remembering to ignore ansiEscapes
|
||||
|
||||
// Strip ansi escape sequences
|
||||
clean := ansiEscape.ReplaceAllString(val, "")
|
||||
maxWidth := preferredColumnWidths[columnIndex]
|
||||
padding := maxWidth - uniseg.GraphemeClusterCount(clean)
|
||||
result += strings.Repeat(" ", padding)
|
||||
|
||||
// Now, ensure we have the requested gap between columns as well.
|
||||
result += columnGap
|
||||
}
|
||||
// do not want whitespace appended to the last column. It would cause wrapping on lines
|
||||
// that were not actually long if some other line was very long.
|
||||
format += "%s"
|
||||
}
|
||||
}
|
||||
format += "\n"
|
||||
result := ""
|
||||
columns := make([]interface{}, columnCount)
|
||||
for _, row := range allRows {
|
||||
for columnIndex, value := range row.Columns {
|
||||
// Now, ensure we have the requested gap between columns as well.
|
||||
if columnIndex < columnCount-1 {
|
||||
value += columnGap
|
||||
}
|
||||
|
||||
columns[columnIndex] = value
|
||||
}
|
||||
|
||||
result += fmt.Sprintf(table.Prefix+format, columns...)
|
||||
result += "\n"
|
||||
|
||||
if row.AdditionalInfo != "" {
|
||||
result += fmt.Sprint(row.AdditionalInfo)
|
||||
result += row.AdditionalInfo
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
|
81
sdk/go/common/util/cmdutil/console_test.go
Normal file
81
sdk/go/common/util/cmdutil/console_test.go
Normal file
|
@ -0,0 +1,81 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cmdutil
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v3/go/common/diag/colors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTablePrinting(t *testing.T) {
|
||||
rows := []TableRow{
|
||||
{Columns: []string{"A", "B", "C"}},
|
||||
{Columns: []string{"Some A", "B", "Some C"}},
|
||||
}
|
||||
|
||||
table := &Table{
|
||||
Headers: []string{"ColumnA", "Long column B", "C"},
|
||||
Rows: rows,
|
||||
Prefix: " ",
|
||||
}
|
||||
|
||||
expected := "" +
|
||||
" ColumnA Long column B C\n" +
|
||||
" A B C\n" +
|
||||
" Some A B Some C\n"
|
||||
|
||||
assert.Equal(t, expected, table.ToStringWithGap(" "))
|
||||
}
|
||||
|
||||
func TestColorTablePrinting(t *testing.T) {
|
||||
|
||||
greenText := func(msg string) string {
|
||||
return colors.Always.Colorize(colors.Green + msg + colors.Reset)
|
||||
}
|
||||
|
||||
rows := []TableRow{
|
||||
{Columns: []string{greenText("+"), "pulumi:pulumi:Stack", "aws-cs-webserver-test", greenText("create")}},
|
||||
{Columns: []string{greenText("+"), "├─ aws:ec2/instance:Instance", "web-server-www", greenText("create")}},
|
||||
{Columns: []string{greenText("+"), "├─ aws:ec2/securityGroup:SecurityGroup", "web-secgrp", greenText("create")}},
|
||||
{Columns: []string{greenText("+"), "└─ pulumi:providers:aws", "default_4_25_0", greenText("create")}},
|
||||
}
|
||||
|
||||
columnHeader := func(msg string) string {
|
||||
return colors.Always.Colorize(colors.Underline + colors.BrightBlue + msg + colors.Reset)
|
||||
}
|
||||
|
||||
table := &Table{
|
||||
Headers: []string{"", columnHeader("Type"), columnHeader("Name"), columnHeader("Plan")},
|
||||
Rows: rows,
|
||||
Prefix: " ",
|
||||
}
|
||||
|
||||
expected := "" +
|
||||
" Type Name Plan\n" +
|
||||
" + pulumi:pulumi:Stack aws-cs-webserver-test create\n" +
|
||||
" + ├─ aws:ec2/instance:Instance web-server-www create\n" +
|
||||
" + ├─ aws:ec2/securityGroup:SecurityGroup web-secgrp create\n" +
|
||||
" + └─ pulumi:providers:aws default_4_25_0 create\n"
|
||||
|
||||
colorTable := table.ToStringWithGap(" ")
|
||||
// 7-bit C1 ANSI sequences
|
||||
ansiEscape := regexp.MustCompile(`\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])`)
|
||||
cleanTable := ansiEscape.ReplaceAllString(colorTable, "")
|
||||
|
||||
assert.Equal(t, expected, cleanTable)
|
||||
}
|
|
@ -567,6 +567,8 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z
|
|||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8=
|
||||
github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
|
|
Loading…
Reference in a new issue