diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 643af2d..cec3024 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -58,9 +58,9 @@ jobs:
- name: Run tests
run: |
git diff --cached --exit-code
- go test ./... -v -cover -coverprofile=cover.out
+ go test ./... -v -cover -coverprofile=cover.Render
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
- files: ./cover.out
+ files: ./cover.Render
diff --git a/.gitignore b/.gitignore
index 9569a44..aca3c39 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,7 +12,7 @@
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
-*.out
+*.Render
# Dependency directories (remove the comment below to include it)
# vendor/
diff --git a/Makefile b/Makefile
index a3f3883..7e38a90 100644
--- a/Makefile
+++ b/Makefile
@@ -37,11 +37,11 @@ endif
.PHONY: test
test:
- go test ./... -v -cover -coverprofile=cover.out
+ go test ./... -v -cover -coverprofile=cover.Render
.PHONY: cover
cover:
- go tool cover -html=cover.out -o cover.html
+ go tool cover -html=cover.Render -o cover.html
.PHONY: bench
bench:
@@ -78,4 +78,4 @@ publish: deps-gobump check-git
.PHONY: clean
clean:
go clean
- rm -f cover.out cover.html cpu.prof mem.prof $(BIN).test
+ rm -f cover.Render cover.html cpu.prof mem.prof $(BIN).test
diff --git a/README.md b/README.md
index 318b1ee..9e36e74 100644
--- a/README.md
+++ b/README.md
@@ -45,6 +45,8 @@ Support
- Group rows based on previous field value
- Ignore specified columns
- Escape HTML special characters
+- Set multiple values to a field as a joined string
+- Set byte slices as a string
Notes
-----
@@ -55,7 +57,38 @@ Notes
Usage
-----
-[example](example_test.go)
+[Example](example_test.go)
+
+Benchmark
+---------
+
+[A quick benchmark](benchmark.go)
+
+This is only for reference as the functions are different, but for simple drawing, it has better performance than TableWriter.
+
+```text
+go test -run=^$ -bench=. -benchmem -count 5
+goos: darwin
+goarch: arm64
+pkg: github.com/nekrassov01/mintab
+BenchmarkMintab-8 45578 25500 ns/op 20527 B/op 399 allocs/op
+BenchmarkMintab-8 46488 25449 ns/op 20527 B/op 399 allocs/op
+BenchmarkMintab-8 44702 26457 ns/op 20528 B/op 399 allocs/op
+BenchmarkMintab-8 42699 28344 ns/op 20527 B/op 399 allocs/op
+BenchmarkMintab-8 45213 31852 ns/op 20527 B/op 399 allocs/op
+BenchmarkMintabSimple-8 55597 19234 ns/op 13033 B/op 242 allocs/op
+BenchmarkMintabSimple-8 64444 18966 ns/op 13033 B/op 242 allocs/op
+BenchmarkMintabSimple-8 53935 21939 ns/op 13034 B/op 242 allocs/op
+BenchmarkMintabSimple-8 61573 18596 ns/op 13033 B/op 242 allocs/op
+BenchmarkMintabSimple-8 64854 19147 ns/op 13033 B/op 242 allocs/op
+BenchmarkTableWriter-8 21787 47804 ns/op 25421 B/op 701 allocs/op
+BenchmarkTableWriter-8 26362 45354 ns/op 25365 B/op 701 allocs/op
+BenchmarkTableWriter-8 26691 44275 ns/op 25332 B/op 701 allocs/op
+BenchmarkTableWriter-8 26622 44199 ns/op 25360 B/op 701 allocs/op
+BenchmarkTableWriter-8 27138 44492 ns/op 25297 B/op 701 allocs/op
+PASS
+ok github.com/nekrassov01/mintab 24.097s
+```
Author
------
diff --git a/benchmark_test.go b/benchmark_test.go
index de5178a..05877e5 100644
--- a/benchmark_test.go
+++ b/benchmark_test.go
@@ -14,7 +14,7 @@ func BenchmarkMintab(b *testing.B) {
if err := table.Load(basicsample); err != nil {
b.Fatal(err)
}
- table.Out()
+ table.Render()
}
}
@@ -37,12 +37,11 @@ func BenchmarkMintabSimple(b *testing.B) {
if err := table.Load(data); err != nil {
b.Fatal(err)
}
- table.Out()
+ table.Render()
}
}
func BenchmarkTableWriter(b *testing.B) {
- header := []string{"InstanceID", "InstanceName", "InstanceState"}
data := [][]string{
{"i-1", "server-1", "running"},
{"i-2", "server-2", "stopped"},
@@ -54,10 +53,7 @@ func BenchmarkTableWriter(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
table := tablewriter.NewWriter(&bytes.Buffer{})
- table.SetHeader(header)
- for _, v := range data {
- table.Append(v)
- }
+ table.AppendBulk(data)
table.Render()
}
}
diff --git a/example_test.go b/example_test.go
index 7f4cd7c..722948d 100644
--- a/example_test.go
+++ b/example_test.go
@@ -85,7 +85,7 @@ func ExampleTable_Load_basic() {
if err := table.Load(s1); err != nil {
log.Fatal(err)
}
- table.Out()
+ table.Render()
// Output:
// +------------+--------------+------------+------------+
@@ -111,11 +111,11 @@ func ExampleTable_Load_basic() {
}
func ExampleTable_Load_markdown() {
- table := mintab.New(os.Stdout, mintab.WithFormat(mintab.FormatMarkdown))
+ table := mintab.New(os.Stdout, mintab.WithFormat(mintab.MarkdownFormat))
if err := table.Load(s1); err != nil {
log.Fatal(err)
}
- table.Out()
+ table.Render()
// Output:
// | InstanceID | InstanceName | AttachedLB | AttachedTG |
@@ -129,11 +129,11 @@ func ExampleTable_Load_markdown() {
}
func ExampleTable_Load_backlog() {
- table := mintab.New(os.Stdout, mintab.WithFormat(mintab.FormatBacklog))
+ table := mintab.New(os.Stdout, mintab.WithFormat(mintab.BacklogFormat))
if err := table.Load(s1); err != nil {
log.Fatal(err)
}
- table.Out()
+ table.Render()
// Output:
// | InstanceID | InstanceName | AttachedLB | AttachedTG |h
@@ -150,7 +150,7 @@ func ExampleTable_Load_disableheader() {
if err := table.Load(s1); err != nil {
log.Fatal(err)
}
- table.Out()
+ table.Render()
// Output:
// +------------+--------------+------------+------------+
@@ -178,7 +178,7 @@ func ExampleTable_Load_emptyfieldplaceholder() {
if err := table.Load(s1); err != nil {
log.Fatal(err)
}
- table.Out()
+ table.Render()
// Output:
// +------------+--------------+------------+------------+
@@ -208,7 +208,7 @@ func ExampleTable_Load_worddelimiter() {
if err := table.Load(s1); err != nil {
log.Fatal(err)
}
- table.Out()
+ table.Render()
// Output:
// +------------+--------------+------------+---------------------+
@@ -233,7 +233,7 @@ func ExampleTable_Load_margin() {
if err := table.Load(s1); err != nil {
log.Fatal(err)
}
- table.Out()
+ table.Render()
// Output:
// +----------------+------------------+----------------+----------------+
@@ -263,7 +263,7 @@ func ExampleTable_Load_mergefields1() {
if err := table.Load(s2); err != nil {
log.Fatal(err)
}
- table.Out()
+ table.Render()
// Output:
// +------------+--------------+-------+-----------------+---------------+------------+----------+--------+---------------+---------------+
@@ -292,7 +292,7 @@ func ExampleTable_Load_mergefields2() {
if err := table.Load(s2); err != nil {
log.Fatal(err)
}
- table.Out()
+ table.Render()
// Output:
// +------------+--------------+-------+-----------------+---------------+------------+----------+--------+---------------+---------------+
@@ -317,11 +317,11 @@ func ExampleTable_Load_mergefields2() {
}
func ExampleTable_Load_mergefields3() {
- table := mintab.New(os.Stdout, mintab.WithFormat(mintab.FormatCompressedText), mintab.WithMergeFields([]int{0, 1, 2, 3}))
+ table := mintab.New(os.Stdout, mintab.WithFormat(mintab.CompressedTextFormat), mintab.WithMergeFields([]int{0, 1, 2, 3}))
if err := table.Load(s2); err != nil {
log.Fatal(err)
}
- table.Out()
+ table.Render()
// Output:
// +------------+--------------+-------+-----------------+---------------+------------+----------+--------+---------------+---------------+
@@ -344,7 +344,7 @@ func ExampleTable_Load_ignorefields1() {
if err := table.Load(s3); err != nil {
log.Fatal(err)
}
- table.Out()
+ table.Render()
// Output:
// +---------------+---------------+
@@ -361,7 +361,7 @@ func ExampleTable_Load_ignorefields2() {
if err := table.Load(s3); err != nil {
log.Fatal(err)
}
- table.Out()
+ table.Render()
// Output:
// +---------------+
@@ -378,7 +378,7 @@ func ExampleTable_Load_escape1() {
if err := table.Load(s4); err != nil {
log.Fatal(err)
}
- table.Out()
+ table.Render()
// Output:
// +-------------------------+-----------------------------------------+
@@ -401,11 +401,11 @@ func ExampleTable_Load_escape1() {
}
func ExampleTable_Load_escape2() {
- table := mintab.New(os.Stdout, mintab.WithFormat(mintab.FormatMarkdown), mintab.WithEscape(false))
+ table := mintab.New(os.Stdout, mintab.WithFormat(mintab.MarkdownFormat), mintab.WithEscape(false))
if err := table.Load(s4); err != nil {
log.Fatal(err)
}
- table.Out()
+ table.Render()
// Output:
// | Name | EscatableValue |
@@ -417,11 +417,11 @@ func ExampleTable_Load_escape2() {
}
func ExampleTable_Load_escape3() {
- table := mintab.New(os.Stdout, mintab.WithFormat(mintab.FormatMarkdown), mintab.WithEscape(true))
+ table := mintab.New(os.Stdout, mintab.WithFormat(mintab.MarkdownFormat), mintab.WithEscape(true))
if err := table.Load(s4); err != nil {
log.Fatal(err)
}
- table.Out()
+ table.Render()
// Output:
// | Name | EscatableValue |
@@ -438,7 +438,7 @@ func ExampleTable_Load_string() {
if err := table.Load(s2); err != nil {
log.Fatal(err)
}
- table.Out()
+ table.Render()
fmt.Println(builder.String())
// Output:
diff --git a/go.mod b/go.mod
index 43a8cac..4e74411 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,7 @@ module github.com/nekrassov01/mintab
go 1.21
require (
+ github.com/google/go-cmp v0.6.0
github.com/mattn/go-runewidth v0.0.15
github.com/olekukonko/tablewriter v0.0.5
)
diff --git a/go.sum b/go.sum
index 52bd10e..de581a7 100644
--- a/go.sum
+++ b/go.sum
@@ -1,3 +1,5 @@
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
diff --git a/mintab.go b/mintab.go
index 64b46a2..8b987fa 100644
--- a/mintab.go
+++ b/mintab.go
@@ -14,26 +14,30 @@ import (
// Default values for table rendering.
const (
- DefaultEmptyFieldPlaceholder = "-"
- DefaultWordDelimiter = "\n"
- MarkdownDefaultEmptyFieldPlaceholder = "\\-"
- MarkdownDefaultWordDelimiter = "
"
- BacklogDefaultEmptyFieldPlaceholder = "-"
- BacklogDefaultWordDelimiter = "&br;"
+ TextDefaultEmptyFieldPlaceholder = "-"
+ TextDefaultWordDelimiter = textNewLine
+ MarkdownDefaultEmptyFieldPlaceholder = "\\" + TextDefaultEmptyFieldPlaceholder
+ MarkdownDefaultWordDelimiter = markdownNewLine
+ BacklogDefaultEmptyFieldPlaceholder = TextDefaultEmptyFieldPlaceholder
+ BacklogDefaultWordDelimiter = backlogNewLine
+
+ textNewLine = "\n"
+ markdownNewLine = "
"
+ backlogNewLine = "&br;"
)
-// Format defines the output format of the content.
+// A Format represents the output format.
type Format int
-// Enumeration of supported output formats.
+// Supported output formats.
const (
- FormatText Format = iota // Plain text format.
- FormatCompressedText // Compressed plain text format.
- FormatMarkdown // Markdown format.
- FormatBacklog // Backlog-specific format.
+ TextFormat Format = iota // Text table format.
+ CompressedTextFormat // Compressed text table format.
+ MarkdownFormat // Markdown table format.
+ BacklogFormat // Backlog-specific table format.
)
-// Formats holds the string representations of each format constant.
+// Formats are string representations of output format.
var Formats = []string{
"text",
"compressed",
@@ -42,7 +46,6 @@ var Formats = []string{
}
// String returns the string representation of a Format.
-// If the format is not within the predefined range, an empty string is returned.
func (o Format) String() string {
if o >= 0 && int(o) < len(Formats) {
return Formats[o]
@@ -50,33 +53,37 @@ func (o Format) String() string {
return ""
}
-// Table represents a table structure for rendering data in a matrix format.
+// Table represents a table structure for rendering data.
type Table struct {
- writer io.Writer // Destination for table output.
- data [][]string // Data holds the content of the table.
- header []string // Names of each field in the table header.
- format Format // Output format of the table.
- border string // Pre-computed border based on column widths.
- tableWidth int //
- marginWidth int //
- margin string // Margin size around cell content.
- emptyFieldPlaceholder string // Placeholder for empty fields.
- wordDelimiter string // Delimiter for words within a field.
- mergedFields []int // Indices of fields to be merged based on content.
- ignoredFields []int // Indices of fields to be ignored during rendering.
- columnWidths []int // Calculated max width of each column.
- hasHeader bool // Indicates if the header should be rendered.
- hasEscape bool // Indicates if escaping should be performed.
+ writer io.Writer // Destination for table output
+ data [][]string // Table data
+ splitedData [][][]string // Table data with strings divided by newlines
+ header []string // Names of each field in the table header
+ format Format // Output format
+ newLine string //
+ emptyFieldPlaceholder string // Placeholder for empty fields
+ wordDelimiter string // Delimiter for words within a field
+ lineHeights []int //
+ columnWidths []int // Max widths of each columns
+ border string // Border line based on column widths
+ tableWidth int //
+ marginWidth int // Margin size around field values
+ margin string // Repeating whitespace chars as margins
+ hasHeader bool // Whether header rendering
+ hasEscape bool // Whether HTML escaping
+ mergedFields []int // Indices of fields to be merged
+ ignoredFields []int // Indices of fields to be ignored
}
-// New instantiates a new Table with the specified writer and options.
+// New instantiates a new Table with the writer and options.
func New(w io.Writer, opts ...Option) *Table {
t := &Table{
writer: w,
- format: FormatText,
+ format: TextFormat,
+ newLine: textNewLine,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
marginWidth: 1,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
hasHeader: true,
}
for _, opt := range opts {
@@ -86,24 +93,24 @@ func New(w io.Writer, opts ...Option) *Table {
return t
}
-// Option defines a type for functional options used to configure a Table.
+// A Option sets an option on a Table.
type Option func(*Table)
-// WithFormat sets the output format of the table.
+// WithFormat sets the output format.
func WithFormat(format Format) Option {
return func(t *Table) {
t.format = format
}
}
-// WithHeader configures the rendering of the table header.
+// WithHeader sets the table header.
func WithHeader(has bool) Option {
return func(t *Table) {
t.hasHeader = has
}
}
-// WithMargin sets the margin size around cell content.
+// WithMargin sets the margin size around field values.
func WithMargin(width int) Option {
return func(t *Table) {
t.marginWidth = width
@@ -124,21 +131,21 @@ func WithWordDelimiter(wordDelimiter string) Option {
}
}
-// WithMergeFields specifies columns for merging based on their content.
+// WithMergeFields specifies columns for merging.
func WithMergeFields(mergeFields []int) Option {
return func(t *Table) {
t.mergedFields = mergeFields
}
}
-// WithIgnoreFields specifies columns to be ignored during rendering.
+// WithIgnoreFields specifies columns to be ignored.
func WithIgnoreFields(ignoreFields []int) Option {
return func(t *Table) {
t.ignoredFields = ignoreFields
}
}
-// WithEscape enables or disables escaping of field content.
+// WithEscape enables or disables HTML escaping.
func WithEscape(has bool) Option {
return func(t *Table) {
t.hasEscape = has
@@ -146,15 +153,14 @@ func WithEscape(has bool) Option {
}
// Load validates the input and converts it into table data.
-// Returns an error if the input is not a slice or if it's empty.
-func (t *Table) Load(input any) error {
+func (t *Table) Load(v any) error {
if t.marginWidth < 0 {
return fmt.Errorf("only unsigned integers are allowed in margin")
}
- if _, ok := input.([]interface{}); ok {
+ if _, ok := v.([]interface{}); ok {
return fmt.Errorf("elements of slice must not be empty interface")
}
- rv := reflect.ValueOf(input)
+ rv := reflect.ValueOf(v)
if rv.Kind() == reflect.Ptr {
rv = rv.Elem()
}
@@ -179,75 +185,65 @@ func (t *Table) Load(input any) error {
if err := t.setData(rv); err != nil {
return err
}
- if t.format != FormatBacklog {
+ if t.format != BacklogFormat {
t.setBorder()
}
return nil
}
-// Out renders the table to the specified writer.
+// Render renders the table to the specified writer.
// It supports markdown and backlog formats for easy copying and pasting.
-func (t *Table) Out() {
+func (t *Table) Render() {
if t.hasHeader {
switch t.format {
- case FormatText, FormatCompressedText:
+ case TextFormat, CompressedTextFormat:
t.printBorder()
}
t.printHeader()
}
- if t.format != FormatBacklog {
+ if t.format != BacklogFormat {
t.printBorder()
}
t.printData()
switch t.format {
- case FormatText, FormatCompressedText:
+ case TextFormat, CompressedTextFormat:
t.printBorder()
}
}
-// printHeader renders the table header.
func (t *Table) printHeader() {
var b strings.Builder
b.Grow(t.tableWidth)
b.WriteString("|")
for i, h := range t.header {
- t.pad(&b, h, t.columnWidths[i])
+ t.writeField(&b, h, t.columnWidths[i])
b.WriteString("|")
}
- if t.format == FormatBacklog {
+ if t.format == BacklogFormat {
b.WriteString("h")
}
fmt.Fprintln(t.writer, b.String())
}
-// printData renders the table data with dynamic conditional borders.
func (t *Table) printData() {
for i, row := range t.data {
if i > 0 {
- if t.format == FormatText {
+ if t.format == TextFormat {
t.printDataBorder(row)
}
- if t.format == FormatCompressedText && row[0] != "" {
+ if t.format == CompressedTextFormat && row[0] != "" {
t.printBorder()
}
}
- splited := make([][]string, len(row))
- n := 1
- for j, field := range row {
- splited[j] = strings.Split(field, "\n")
- if len(splited[j]) > n {
- n = len(splited[j])
- }
- }
- for k := 0; k < n; k++ {
+ for j := 0; j < t.lineHeights[i]; j++ {
var b strings.Builder
b.Grow(t.tableWidth)
b.WriteString("|")
- for l, elem := range splited {
- if k < len(elem) {
- t.pad(&b, elem[k], t.columnWidths[l])
+ for k, elem := range t.splitedData[i] {
+ if j < len(elem) {
+ t.writeField(&b, elem[j], t.columnWidths[k])
} else {
- t.pad(&b, "", t.columnWidths[l])
+ t.writeField(&b, "", t.columnWidths[k])
}
b.WriteString("|")
}
@@ -256,8 +252,6 @@ func (t *Table) printData() {
}
}
-// printDataBorder prints a conditional border based on the emptiness of fields in the current row,
-// with continuity in border characters based on the emptiness of adjacent fields.
func (t *Table) printDataBorder(row []string) {
var b strings.Builder
b.Grow(t.tableWidth)
@@ -276,36 +270,37 @@ func (t *Table) printDataBorder(row []string) {
fmt.Fprintln(t.writer, b.String())
}
-// printBorder renders the table border based on column widths.
func (t *Table) printBorder() {
fmt.Fprintln(t.writer, t.border)
}
-// setAttr configures placeholders and delimiters based on the table format.
-// It ensures consistency in the appearance and structure of table output.
func (t *Table) setAttr() {
- var p, d string
+ var p, d, n string
switch t.format {
- case FormatMarkdown:
+ case MarkdownFormat:
p = MarkdownDefaultEmptyFieldPlaceholder
d = MarkdownDefaultWordDelimiter
- case FormatBacklog:
+ n = markdownNewLine
+ case BacklogFormat:
p = BacklogDefaultEmptyFieldPlaceholder
d = BacklogDefaultWordDelimiter
+ n = backlogNewLine
default:
- p = DefaultEmptyFieldPlaceholder
- d = DefaultWordDelimiter
+ p = TextDefaultEmptyFieldPlaceholder
+ d = TextDefaultWordDelimiter
+ n = textNewLine
}
- if t.emptyFieldPlaceholder == DefaultEmptyFieldPlaceholder {
+ if t.emptyFieldPlaceholder == TextDefaultEmptyFieldPlaceholder {
t.emptyFieldPlaceholder = p
}
- if t.wordDelimiter == DefaultWordDelimiter {
+ if t.wordDelimiter == TextDefaultWordDelimiter {
t.wordDelimiter = d
}
+ if t.format != TextFormat {
+ t.newLine = n
+ }
}
-// setHeader extracts field names from the struct type to create the table header.
-// It also initializes column widths based on the header names.
func (t *Table) setHeader(typ reflect.Type) {
if len(t.header) > 0 {
return
@@ -321,55 +316,65 @@ func (t *Table) setHeader(typ reflect.Type) {
}
}
-// setData converts the input data to a matrix of strings and calculates column widths.
-// It also handles field formatting based on the table format and whether fields are merged.
func (t *Table) setData(rv reflect.Value) error {
t.data = make([][]string, rv.Len())
+ t.splitedData = make([][][]string, rv.Len())
+ t.lineHeights = make([]int, rv.Len())
prev := make([]string, len(t.header))
for i := 0; i < rv.Len(); i++ {
- row := make([]string, len(t.header))
- field := rv.Index(i)
- if field.Kind() == reflect.Ptr {
- field = field.Elem()
+ e := rv.Index(i)
+ if e.Kind() == reflect.Ptr {
+ e = e.Elem()
}
- merge := true
+ row := make([]string, len(t.header))
+ splitedRow := make([][]string, len(t.header))
+ isMerge := true
+ n := 1
for j, h := range t.header {
- field := field.FieldByName(h)
+ field := e.FieldByName(h)
if !field.IsValid() {
return fmt.Errorf("invalid field detected: %s", h)
}
- f, err := t.formatField(field)
+ v, err := t.formatField(field)
if err != nil {
return fmt.Errorf("failed to format field \"%s\": %w", h, err)
}
if slices.Contains(t.mergedFields, j) {
- if f != prev[j] {
- merge = false
- prev[j] = f
+ if v != prev[j] {
+ isMerge = false
+ prev[j] = v
}
- if merge {
- f = ""
+ if isMerge {
+ v = ""
}
}
- row[j] = f
- elems := strings.Split(f, "\n")
+ row[j] = v
+ elems := strings.Split(v, "\n")
+ splitedRow[j] = elems
for _, elem := range elems {
- lw := runewidth.StringWidth(elem)
- if lw > t.columnWidths[j] {
- t.columnWidths[j] = lw
+ width := runewidth.StringWidth(elem)
+ if width > t.columnWidths[j] {
+ t.columnWidths[j] = width
+ }
+ }
+ if t.format == TextFormat {
+ height := len(elems)
+ if height > n {
+ n = height
}
}
}
t.data[i] = row
+ t.splitedData[i] = splitedRow
+ t.lineHeights[i] = n
}
return nil
}
-// setBorder computes the table border string based on the calculated column widths.
func (t *Table) setBorder() {
var sep string
switch t.format {
- case FormatMarkdown, FormatBacklog:
+ case MarkdownFormat, BacklogFormat:
sep = "|"
default:
sep = "+"
@@ -386,8 +391,6 @@ func (t *Table) setBorder() {
t.tableWidth = len(t.border)
}
-// formatField formats a single field value based on its type and the table's configuration.
-// It applies escaping if enabled and handles various data types, including slices and primitive types.
func (t *Table) formatField(rv reflect.Value) (string, error) {
if rv.Kind() == reflect.Ptr {
if rv.IsNil() {
@@ -395,7 +398,7 @@ func (t *Table) formatField(rv reflect.Value) (string, error) {
}
rv = rv.Elem()
}
- v := getString(rv)
+ v := stringer(rv)
if v == "" {
switch rv.Kind() {
case reflect.String:
@@ -404,7 +407,9 @@ func (t *Table) formatField(rv reflect.Value) (string, error) {
v = strconv.FormatInt(rv.Int(), 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
v = strconv.FormatUint(rv.Uint(), 10)
- case reflect.Float32, reflect.Float64:
+ case reflect.Float32:
+ v = strconv.FormatFloat(rv.Float(), 'f', -1, 32)
+ case reflect.Float64:
v = strconv.FormatFloat(rv.Float(), 'f', -1, 64)
case reflect.Slice, reflect.Array:
switch {
@@ -413,72 +418,76 @@ func (t *Table) formatField(rv reflect.Value) (string, error) {
case rv.Type().Elem().Kind() == reflect.Uint8:
v = string(rv.Bytes())
default:
- ss := make([]string, rv.Len())
+ var b strings.Builder
for i := 0; i < rv.Len(); i++ {
e := rv.Index(i)
if i != 0 {
- ss[i] = t.wordDelimiter
+ b.WriteString(t.wordDelimiter)
}
if e.Kind() == reflect.Ptr {
if e.IsNil() {
- ss[i] = t.emptyFieldPlaceholder
+ b.WriteString(t.emptyFieldPlaceholder)
continue
}
e = e.Elem()
}
- if s := getString(e); s != "" {
- ss[i] = s
+ if f := stringer(e); f != "" {
+ b.WriteString(f)
continue
}
if e.Kind() == reflect.Slice && e.Type().Elem().Kind() == reflect.Uint8 {
- ss[i] = string(e.Bytes())
+ b.WriteString(string(e.Bytes()))
continue
}
if e.Kind() == reflect.Slice || e.Kind() == reflect.Array || e.Kind() == reflect.Struct {
return "", fmt.Errorf("cannot represent nested fields")
}
- f, err := t.formatField(e)
- if err != nil {
- return "", err
+ switch e.Kind() {
+ case reflect.String:
+ v = e.String()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ v = strconv.FormatInt(e.Int(), 10)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ v = strconv.FormatUint(e.Uint(), 10)
+ case reflect.Float32:
+ v = strconv.FormatFloat(e.Float(), 'f', -1, 32)
+ case reflect.Float64:
+ v = strconv.FormatFloat(e.Float(), 'f', -1, 64)
+ default:
+ v = fmt.Sprint(e.Interface())
+ }
+ if v == "" {
+ v = t.emptyFieldPlaceholder
}
- ss[i] = f
+ b.WriteString(v)
}
- v = strings.Join(ss, t.wordDelimiter)
+ v = b.String()
}
default:
v = fmt.Sprint(rv.Interface())
}
}
- if t.hasEscape {
- v = t.escape(v)
- }
- if t.format == FormatMarkdown && strings.HasPrefix(v, "*") {
- v = "\\" + v
- }
- if v == "" {
- v = t.emptyFieldPlaceholder
- }
- return strings.TrimSpace(t.replaceNL(v)), nil
+ return strings.TrimSuffix(t.sanitize(v), "\n"), nil
}
-func getString(v reflect.Value) string {
- if v.CanInterface() {
- if s, ok := v.Interface().(fmt.Stringer); ok {
- return s.String()
- }
+func (t *Table) sanitize(s string) string {
+ if s == "" {
+ return t.emptyFieldPlaceholder
}
- return ""
-}
-
-func (t *Table) replaceNL(s string) string {
- if t.wordDelimiter == "\n" {
+ if t.hasEscape {
+ s = t.escape(s)
+ }
+ if t.format == MarkdownFormat && strings.HasPrefix(s, "*") {
+ s = "\\" + s
+ }
+ if t.format == TextFormat {
return s
}
var b strings.Builder
for _, r := range s {
switch r {
case '\n':
- b.WriteString(t.wordDelimiter)
+ b.WriteString(t.newLine)
default:
b.WriteRune(r)
}
@@ -486,7 +495,6 @@ func (t *Table) replaceNL(s string) string {
return b.String()
}
-// escape applies HTML escaping to a string for safe rendering in Markdown and other formats.
func (t *Table) escape(s string) string {
var b strings.Builder
for _, r := range s {
@@ -518,8 +526,16 @@ func (t *Table) escape(s string) string {
return b.String()
}
-// pad right-aligns numeric strings and left-aligns all other strings within a field of specified width.
-func (t *Table) pad(b *strings.Builder, s string, width int) {
+func stringer(rv reflect.Value) string {
+ if rv.CanInterface() {
+ if s, ok := rv.Interface().(fmt.Stringer); ok {
+ return s.String()
+ }
+ }
+ return ""
+}
+
+func (t *Table) writeField(b *strings.Builder, s string, width int) {
b.WriteString(t.margin)
isN := isNum(s)
if !isN {
@@ -537,13 +553,12 @@ func (t *Table) pad(b *strings.Builder, s string, width int) {
b.WriteString(t.margin)
}
-// isNum checks if a string represents a numeric value.
func isNum(s string) bool {
if len(s) == 0 {
return false
}
start := 0
- if s[0] == '-' || s[0] == '+' {
+ if s[0] == '-' {
start = 1
if len(s) == 1 {
return false
diff --git a/mintab_test.go b/mintab_test.go
index 472b258..56c7ff1 100644
--- a/mintab_test.go
+++ b/mintab_test.go
@@ -8,6 +8,8 @@ import (
"strings"
"testing"
"time"
+
+ "github.com/google/go-cmp/cmp"
)
type basicSample struct {
@@ -178,22 +180,22 @@ func TestFormat_String(t *testing.T) {
}{
{
name: "text",
- o: FormatText,
+ o: TextFormat,
want: "text",
},
{
name: "compressed",
- o: FormatCompressedText,
+ o: CompressedTextFormat,
want: "compressed",
},
{
name: "markdown",
- o: FormatMarkdown,
+ o: MarkdownFormat,
want: "markdown",
},
{
name: "backlog",
- o: FormatBacklog,
+ o: BacklogFormat,
want: "backlog",
},
{
@@ -230,12 +232,13 @@ func TestNew(t *testing.T) {
writer: &bytes.Buffer{},
data: nil,
header: nil,
- format: FormatText,
+ format: TextFormat,
+ newLine: textNewLine,
border: "",
marginWidth: 1,
margin: " ",
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
mergedFields: nil,
ignoredFields: nil,
columnWidths: nil,
@@ -247,7 +250,7 @@ func TestNew(t *testing.T) {
name: "not-default",
args: args{
opts: []Option{
- WithFormat(FormatMarkdown),
+ WithFormat(MarkdownFormat),
WithHeader(false),
WithMargin(2),
WithEmptyFieldPlaceholder(MarkdownDefaultEmptyFieldPlaceholder),
@@ -261,7 +264,8 @@ func TestNew(t *testing.T) {
writer: &bytes.Buffer{},
data: nil,
header: nil,
- format: FormatMarkdown,
+ format: MarkdownFormat,
+ newLine: textNewLine, // change after setAttr()
border: "",
marginWidth: 2,
margin: " ",
@@ -417,12 +421,15 @@ func TestTable_Load(t *testing.T) {
}
}
-func TestTable_Out(t *testing.T) {
+func TestTable_Render(t *testing.T) {
type fields struct {
- format Format
- header []string
- data [][]string
+ format Format
+ header []string
+ data [][]string
+ splitedData [][][]string
+
columnWidths []int
+ lineHeights []int
}
tests := []struct {
name string
@@ -432,7 +439,7 @@ func TestTable_Out(t *testing.T) {
{
name: "text",
fields: fields{
- format: FormatText,
+ format: TextFormat,
header: []string{"InstanceID", "InstanceName", "AttachedLB", "AttachedTG"},
data: [][]string{
{"i-1", "server-1", "lb-1", "tg-1"},
@@ -442,7 +449,16 @@ func TestTable_Out(t *testing.T) {
{"i-5", "server-5", "lb-5", "-"},
{"i-6", "server-6", "-", "tg-5\ntg-6\ntg-7\ntg-8"},
},
+ splitedData: [][][]string{
+ {{"i-1"}, {"server-1"}, {"lb-1"}, {"tg-1"}},
+ {{"i-2"}, {"server-2"}, {"lb-2", "lb-3"}, {"tg-2"}},
+ {{"i-3"}, {"server-3"}, {"lb-4"}, {"tg-3", "tg-4"}},
+ {{"i-4"}, {"server-4"}, {"-"}, {"-"}},
+ {{"i-5"}, {"server-5"}, {"lb-5"}, {"-"}},
+ {{"i-6"}, {"server-6"}, {"-"}, {"tg-5", "tg-6", "tg-7", "tg-8"}},
+ },
columnWidths: []int{10, 12, 10, 10},
+ lineHeights: []int{1, 2, 2, 1, 1, 4},
},
want: `+------------+--------------+------------+------------+
| InstanceID | InstanceName | AttachedLB | AttachedTG |
@@ -469,7 +485,7 @@ func TestTable_Out(t *testing.T) {
{
name: "text_with_compressed",
fields: fields{
- format: FormatCompressedText,
+ format: CompressedTextFormat,
header: []string{"InstanceID", "InstanceName", "VPCID", "SecurityGroupID", "FlowDirection", "IPProtocol", "FromPort", "ToPort", "AddressType", "CidrBlock"},
data: [][]string{
{"i-1", "server-1", "vpc-1", "sg-1", "Ingress", "tcp", "22", "22", "SecurityGroup", "sg-10"},
@@ -481,7 +497,18 @@ func TestTable_Out(t *testing.T) {
{"", "", "", "", "Ingress", "tcp", "0", "65535", "PrefixList", "pl-id/pl-name"},
{"", "", "", "", "Egress", "-1", "0", "0", "Ipv4", "0.0.0.0/0"},
},
+ splitedData: [][][]string{
+ {{"i-1"}, {"server-1"}, {"vpc-1"}, {"sg-1"}, {"Ingress"}, {"tcp"}, {"22"}, {"22"}, {"SecurityGroup"}, {"sg-10"}},
+ {{""}, {""}, {""}, {""}, {"Egress"}, {"-1"}, {"0"}, {"0"}, {"Ipv4"}, {"0.0.0.0/0"}},
+ {{""}, {""}, {""}, {"sg-2"}, {"Ingress"}, {"tcp"}, {"443"}, {"443"}, {"Ipv4"}, {"0.0.0.0/0"}},
+ {{""}, {""}, {""}, {""}, {"Egress"}, {"-1"}, {"0"}, {"0"}, {"Ipv4"}, {"0.0.0.0/0"}},
+ {{"i-2"}, {"server-2"}, {"vpc-1"}, {"sg-3"}, {"Ingress"}, {"icmp"}, {"-1"}, {"-1"}, {"SecurityGroup"}, {"sg-11"}},
+ {{""}, {""}, {""}, {""}, {"Ingress"}, {"tcp"}, {"3389"}, {"3389"}, {"Ipv4"}, {"10.1.0.0/16"}},
+ {{""}, {""}, {""}, {""}, {"Ingress"}, {"tcp"}, {"0"}, {"65535"}, {"PrefixList"}, {"pl-id/pl-name"}},
+ {{""}, {""}, {""}, {""}, {"Egress"}, {"-1"}, {"0"}, {"0"}, {"Ipv4"}, {"0.0.0.0/0"}},
+ },
columnWidths: []int{10, 12, 5, 15, 13, 10, 8, 6, 13, 13},
+ lineHeights: []int{1, 1, 1, 1, 1, 1, 1, 1},
},
want: `+------------+--------------+-------+-----------------+---------------+------------+----------+--------+---------------+---------------+
| InstanceID | InstanceName | VPCID | SecurityGroupID | FlowDirection | IPProtocol | FromPort | ToPort | AddressType | CidrBlock |
@@ -501,7 +528,7 @@ func TestTable_Out(t *testing.T) {
{
name: "markdown",
fields: fields{
- format: FormatMarkdown,
+ format: MarkdownFormat,
header: []string{"InstanceID", "InstanceName", "AttachedLB", "AttachedTG"},
data: [][]string{
{"i-1", "server-1", "lb-1", "tg-1"},
@@ -511,7 +538,16 @@ func TestTable_Out(t *testing.T) {
{"i-5", "server-5", "lb-5", "\\-"},
{"i-6", "server-6", "\\-", "tg-5
tg-6
tg-7
tg-8"},
},
+ splitedData: [][][]string{
+ {{"i-1"}, {"server-1"}, {"lb-1"}, {"tg-1"}},
+ {{"i-2"}, {"server-2"}, {"lb-2
lb-3"}, {"tg-2"}},
+ {{"i-3"}, {"server-3"}, {"lb-4"}, {"tg-3
tg-4"}},
+ {{"i-4"}, {"server-4"}, {"\\-"}, {"\\-"}},
+ {{"i-5"}, {"server-5"}, {"lb-5"}, {"\\-"}},
+ {{"i-6"}, {"server-6"}, {"\\-"}, {"tg-5
tg-6
tg-7
tg-8"}},
+ },
columnWidths: []int{10, 12, 12, 28},
+ lineHeights: []int{1, 1, 1, 1, 1, 1},
},
want: `| InstanceID | InstanceName | AttachedLB | AttachedTG |
|------------|--------------|--------------|------------------------------|
@@ -526,7 +562,7 @@ func TestTable_Out(t *testing.T) {
{
name: "backlog",
fields: fields{
- format: FormatBacklog,
+ format: BacklogFormat,
header: []string{"InstanceID", "InstanceName", "AttachedLB", "AttachedTG"},
data: [][]string{
{"i-1", "server-1", "lb-1", "tg-1"},
@@ -536,7 +572,16 @@ func TestTable_Out(t *testing.T) {
{"i-5", "server-5", "lb-5", "-"},
{"i-6", "server-6", "-", "tg-5&br;tg-6&br;tg-7&br;tg-8"},
},
+ splitedData: [][][]string{
+ {{"i-1"}, {"server-1"}, {"lb-1"}, {"tg-1"}},
+ {{"i-2"}, {"server-2"}, {"lb-2&br;lb-3"}, {"tg-2"}},
+ {{"i-3"}, {"server-3"}, {"lb-4"}, {"tg-3&br;tg-4"}},
+ {{"i-4"}, {"server-4"}, {"-"}, {"-"}},
+ {{"i-5"}, {"server-5"}, {"lb-5"}, {"-"}},
+ {{"i-6"}, {"server-6"}, {"-"}, {"tg-5&br;tg-6&br;tg-7&br;tg-8"}},
+ },
columnWidths: []int{10, 12, 12, 28},
+ lineHeights: []int{1, 1, 1, 1, 1, 1},
},
want: `| InstanceID | InstanceName | AttachedLB | AttachedTG |h
| i-1 | server-1 | lb-1 | tg-1 |
@@ -555,12 +600,17 @@ func TestTable_Out(t *testing.T) {
tr.format = tt.fields.format
tr.header = tt.fields.header
tr.data = tt.fields.data
+ tr.splitedData = tt.fields.splitedData
tr.columnWidths = tt.fields.columnWidths
+ tr.lineHeights = tt.fields.lineHeights
tr.setBorder()
- tr.Out()
+ tr.Render()
if !reflect.DeepEqual(buf.String(), tt.want) {
t.Errorf("\ngot:\n%v\nwant:\n%v\n", buf.String(), tt.want)
}
+ if diff := cmp.Diff(buf.String(), tt.want); diff != "" {
+ t.Errorf(diff)
+ }
})
}
}
@@ -581,7 +631,7 @@ func TestTable_printHeader(t *testing.T) {
name: "text",
fields: fields{
header: []string{"a", "bb", "ccc"},
- format: FormatText,
+ format: TextFormat,
marginWidth: 1,
columnWidths: []int{1, 2, 3},
},
@@ -591,7 +641,7 @@ func TestTable_printHeader(t *testing.T) {
name: "markdown",
fields: fields{
header: []string{"a", "bb", "ccc"},
- format: FormatMarkdown,
+ format: MarkdownFormat,
marginWidth: 1,
columnWidths: []int{1, 2, 3},
},
@@ -601,7 +651,7 @@ func TestTable_printHeader(t *testing.T) {
name: "backlog",
fields: fields{
header: []string{"a", "bb", "ccc"},
- format: FormatBacklog,
+ format: BacklogFormat,
marginWidth: 1,
columnWidths: []int{1, 2, 3},
},
@@ -611,7 +661,7 @@ func TestTable_printHeader(t *testing.T) {
name: "margin",
fields: fields{
header: []string{"a", "bb", "ccc"},
- format: FormatText,
+ format: TextFormat,
marginWidth: 3,
columnWidths: []int{1, 2, 3},
},
@@ -621,7 +671,7 @@ func TestTable_printHeader(t *testing.T) {
name: "long",
fields: fields{
header: []string{"a", "bb", "ccc"},
- format: FormatText,
+ format: TextFormat,
marginWidth: 1,
columnWidths: []int{10, 2, 3},
},
@@ -631,7 +681,7 @@ func TestTable_printHeader(t *testing.T) {
name: "short",
fields: fields{
header: []string{"a", "bb", "ccc"},
- format: FormatText,
+ format: TextFormat,
marginWidth: 1,
columnWidths: []int{1, 2, 1},
},
@@ -657,8 +707,10 @@ func TestTable_printHeader(t *testing.T) {
func TestTable_printData(t *testing.T) {
type fields struct {
data [][]string
+ splitedData [][][]string
format Format
columnWidths []int
+ lineHeights []int
}
tests := []struct {
name string
@@ -676,8 +728,17 @@ func TestTable_printData(t *testing.T) {
{"i-5", "server-5", "lb-5", "-"},
{"i-6", "server-6", "-", "tg-5\ntg-6\ntg-7\ntg-8"},
},
- format: FormatText,
+ splitedData: [][][]string{
+ {{"i-1"}, {"server-1"}, {"lb-1"}, {"tg-1"}},
+ {{"i-2"}, {"server-2"}, {"lb-2", "lb-3"}, {"tg-2"}},
+ {{"i-3"}, {"server-3"}, {"lb-4"}, {"tg-3", "tg-4"}},
+ {{"i-4"}, {"server-4"}, {"-"}, {"-"}},
+ {{"i-5"}, {"server-5"}, {"lb-5"}, {"-"}},
+ {{"i-6"}, {"server-6"}, {"-"}, {"tg-5", "tg-6", "tg-7", "tg-8"}},
+ },
+ format: TextFormat,
columnWidths: []int{10, 12, 10, 10},
+ lineHeights: []int{1, 2, 2, 1, 1, 4},
},
want: `| i-1 | server-1 | lb-1 | tg-1 |
+------------+--------------+------------+------------+
@@ -695,6 +756,44 @@ func TestTable_printData(t *testing.T) {
| | | | tg-6 |
| | | | tg-7 |
| | | | tg-8 |
+`,
+ },
+ {
+ name: "text_with_compress",
+ fields: fields{
+ data: [][]string{
+ {"i-1", "server-1", "vpc-1", "sg-1", "Ingress", "tcp", "22", "22", "SecurityGroup", "sg-10"},
+ {"", "", "", "", "Egress", "-1", "0", "0", "Ipv4", "0.0.0.0/0"},
+ {"", "", "", "sg-2", "Ingress", "tcp", "443", "443", "Ipv4", "0.0.0.0/0"},
+ {"", "", "", "", "Egress", "-1", "0", "0", "Ipv4", "0.0.0.0/0"},
+ {"i-2", "server-2", "vpc-1", "sg-3", "Ingress", "icmp", "-1", "-1", "SecurityGroup", "sg-11"},
+ {"", "", "", "", "Ingress", "tcp", "3389", "3389", "Ipv4", "10.1.0.0/16"},
+ {"", "", "", "", "Ingress", "tcp", "0", "65535", "PrefixList", "pl-id/pl-name"},
+ {"", "", "", "", "Egress", "-1", "0", "0", "Ipv4", "0.0.0.0/0"},
+ },
+ splitedData: [][][]string{
+ {{"i-1"}, {"server-1"}, {"vpc-1"}, {"sg-1"}, {"Ingress"}, {"tcp"}, {"22"}, {"22"}, {"SecurityGroup"}, {"sg-10"}},
+ {{""}, {""}, {""}, {""}, {"Egress"}, {"-1"}, {"0"}, {"0"}, {"Ipv4"}, {"0.0.0.0/0"}},
+ {{""}, {""}, {""}, {"sg-2"}, {"Ingress"}, {"tcp"}, {"443"}, {"443"}, {"Ipv4"}, {"0.0.0.0/0"}},
+ {{""}, {""}, {""}, {""}, {"Egress"}, {"-1"}, {"0"}, {"0"}, {"Ipv4"}, {"0.0.0.0/0"}},
+ {{"i-2"}, {"server-2"}, {"vpc-1"}, {"sg-3"}, {"Ingress"}, {"icmp"}, {"-1"}, {"-1"}, {"SecurityGroup"}, {"sg-11"}},
+ {{""}, {""}, {""}, {""}, {"Ingress"}, {"tcp"}, {"3389"}, {"3389"}, {"Ipv4"}, {"10.1.0.0/16"}},
+ {{""}, {""}, {""}, {""}, {"Ingress"}, {"tcp"}, {"0"}, {"65535"}, {"PrefixList"}, {"pl-id/pl-name"}},
+ {{""}, {""}, {""}, {""}, {"Egress"}, {"-1"}, {"0"}, {"0"}, {"Ipv4"}, {"0.0.0.0/0"}},
+ },
+ format: CompressedTextFormat,
+ columnWidths: []int{10, 12, 5, 15, 13, 10, 8, 6, 13, 13},
+ lineHeights: []int{1, 1, 1, 1, 1, 1, 1, 1},
+ },
+ want: `| i-1 | server-1 | vpc-1 | sg-1 | Ingress | tcp | 22 | 22 | SecurityGroup | sg-10 |
+| | | | | Egress | -1 | 0 | 0 | Ipv4 | 0.0.0.0/0 |
+| | | | sg-2 | Ingress | tcp | 443 | 443 | Ipv4 | 0.0.0.0/0 |
+| | | | | Egress | -1 | 0 | 0 | Ipv4 | 0.0.0.0/0 |
++------------+--------------+-------+-----------------+---------------+------------+----------+--------+---------------+---------------+
+| i-2 | server-2 | vpc-1 | sg-3 | Ingress | icmp | -1 | -1 | SecurityGroup | sg-11 |
+| | | | | Ingress | tcp | 3389 | 3389 | Ipv4 | 10.1.0.0/16 |
+| | | | | Ingress | tcp | 0 | 65535 | PrefixList | pl-id/pl-name |
+| | | | | Egress | -1 | 0 | 0 | Ipv4 | 0.0.0.0/0 |
`,
},
{
@@ -708,8 +807,17 @@ func TestTable_printData(t *testing.T) {
{"i-5", "server-5", "lb-5", "\\-"},
{"i-6", "server-6", "\\-", "tg-5
tg-6
tg-7
tg-8"},
},
- format: FormatMarkdown,
+ splitedData: [][][]string{
+ {{"i-1"}, {"server-1"}, {"lb-1"}, {"tg-1"}},
+ {{"i-2"}, {"server-2"}, {"lb-2
lb-3"}, {"tg-2"}},
+ {{"i-3"}, {"server-3"}, {"lb-4"}, {"tg-3
tg-4"}},
+ {{"i-4"}, {"server-4"}, {"\\-"}, {"\\-"}},
+ {{"i-5"}, {"server-5"}, {"lb-5"}, {"\\-"}},
+ {{"i-6"}, {"server-6"}, {"\\-"}, {"tg-5
tg-6
tg-7
tg-8"}},
+ },
+ format: MarkdownFormat,
columnWidths: []int{10, 12, 12, 28},
+ lineHeights: []int{1, 1, 1, 1, 1, 1},
},
want: `| i-1 | server-1 | lb-1 | tg-1 |
| i-2 | server-2 | lb-2
lb-3 | tg-2 |
@@ -730,8 +838,17 @@ func TestTable_printData(t *testing.T) {
{"i-5", "server-5", "lb-5", "-"},
{"i-6", "server-6", "-", "tg-5&br;tg-6&br;tg-7&br;tg-8"},
},
- format: FormatBacklog,
+ splitedData: [][][]string{
+ {{"i-1"}, {"server-1"}, {"lb-1"}, {"tg-1"}},
+ {{"i-2"}, {"server-2"}, {"lb-2&br;lb-3"}, {"tg-2"}},
+ {{"i-3"}, {"server-3"}, {"lb-4"}, {"tg-3&br;tg-4"}},
+ {{"i-4"}, {"server-4"}, {"-"}, {"-"}},
+ {{"i-5"}, {"server-5"}, {"lb-5"}, {"-"}},
+ {{"i-6"}, {"server-6"}, {"-"}, {"tg-5&br;tg-6&br;tg-7&br;tg-8"}},
+ },
+ format: BacklogFormat,
columnWidths: []int{10, 12, 12, 28},
+ lineHeights: []int{1, 1, 1, 1, 1, 1},
},
want: `| i-1 | server-1 | lb-1 | tg-1 |
| i-2 | server-2 | lb-2&br;lb-3 | tg-2 |
@@ -739,33 +856,6 @@ func TestTable_printData(t *testing.T) {
| i-4 | server-4 | - | - |
| i-5 | server-5 | lb-5 | - |
| i-6 | server-6 | - | tg-5&br;tg-6&br;tg-7&br;tg-8 |
-`,
- },
- {
- name: "text_with_compress",
- fields: fields{
- data: [][]string{
- {"i-1", "server-1", "vpc-1", "sg-1", "Ingress", "tcp", "22", "22", "SecurityGroup", "sg-10"},
- {"", "", "", "", "Egress", "-1", "0", "0", "Ipv4", "0.0.0.0/0"},
- {"", "", "", "sg-2", "Ingress", "tcp", "443", "443", "Ipv4", "0.0.0.0/0"},
- {"", "", "", "", "Egress", "-1", "0", "0", "Ipv4", "0.0.0.0/0"},
- {"i-2", "server-2", "vpc-1", "sg-3", "Ingress", "icmp", "-1", "-1", "SecurityGroup", "sg-11"},
- {"", "", "", "", "Ingress", "tcp", "3389", "3389", "Ipv4", "10.1.0.0/16"},
- {"", "", "", "", "Ingress", "tcp", "0", "65535", "PrefixList", "pl-id/pl-name"},
- {"", "", "", "", "Egress", "-1", "0", "0", "Ipv4", "0.0.0.0/0"},
- },
- format: FormatCompressedText,
- columnWidths: []int{10, 12, 5, 15, 13, 10, 8, 6, 13, 13},
- },
- want: `| i-1 | server-1 | vpc-1 | sg-1 | Ingress | tcp | 22 | 22 | SecurityGroup | sg-10 |
-| | | | | Egress | -1 | 0 | 0 | Ipv4 | 0.0.0.0/0 |
-| | | | sg-2 | Ingress | tcp | 443 | 443 | Ipv4 | 0.0.0.0/0 |
-| | | | | Egress | -1 | 0 | 0 | Ipv4 | 0.0.0.0/0 |
-+------------+--------------+-------+-----------------+---------------+------------+----------+--------+---------------+---------------+
-| i-2 | server-2 | vpc-1 | sg-3 | Ingress | icmp | -1 | -1 | SecurityGroup | sg-11 |
-| | | | | Ingress | tcp | 3389 | 3389 | Ipv4 | 10.1.0.0/16 |
-| | | | | Ingress | tcp | 0 | 65535 | PrefixList | pl-id/pl-name |
-| | | | | Egress | -1 | 0 | 0 | Ipv4 | 0.0.0.0/0 |
`,
},
}
@@ -774,8 +864,10 @@ func TestTable_printData(t *testing.T) {
buf := new(bytes.Buffer)
tr := New(buf)
tr.data = tt.fields.data
+ tr.splitedData = tt.fields.splitedData
tr.format = tt.fields.format
tr.columnWidths = tt.fields.columnWidths
+ tr.lineHeights = tt.fields.lineHeights
tr.setBorder()
tr.printData()
if !reflect.DeepEqual(buf.String(), tt.want) {
@@ -917,7 +1009,7 @@ func TestTable_printBorder(t *testing.T) {
{
name: "text",
fields: fields{
- format: FormatText,
+ format: TextFormat,
marginWidth: 1,
columnWidths: []int{8, 12, 5},
},
@@ -926,7 +1018,7 @@ func TestTable_printBorder(t *testing.T) {
{
name: "markdown",
fields: fields{
- format: FormatMarkdown,
+ format: MarkdownFormat,
marginWidth: 1,
columnWidths: []int{8, 12, 5},
},
@@ -935,7 +1027,7 @@ func TestTable_printBorder(t *testing.T) {
{
name: "backlog",
fields: fields{
- format: FormatBacklog,
+ format: BacklogFormat,
marginWidth: 1,
columnWidths: []int{8, 12, 5},
},
@@ -944,7 +1036,7 @@ func TestTable_printBorder(t *testing.T) {
{
name: "wide-margin",
fields: fields{
- format: FormatText,
+ format: TextFormat,
marginWidth: 3,
columnWidths: []int{8, 12, 5},
},
@@ -983,17 +1075,17 @@ func TestTable_setAttr(t *testing.T) {
{
name: "text",
fields: fields{
- format: FormatText,
+ format: TextFormat,
},
want: want{
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
},
},
{
name: "markdown",
fields: fields{
- format: FormatMarkdown,
+ format: MarkdownFormat,
},
want: want{
emptyFieldPlaceholder: MarkdownDefaultEmptyFieldPlaceholder,
@@ -1003,7 +1095,7 @@ func TestTable_setAttr(t *testing.T) {
{
name: "backlog",
fields: fields{
- format: FormatBacklog,
+ format: BacklogFormat,
},
want: want{
emptyFieldPlaceholder: BacklogDefaultEmptyFieldPlaceholder,
@@ -1115,8 +1207,8 @@ func TestTable_setData(t *testing.T) {
name: "text",
fields: fields{
header: []string{"InstanceID", "InstanceName", "AttachedLB", "AttachedTG"},
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
mergedFields: nil,
ignoredFields: nil,
columnWidths: []int{0, 0, 0, 0},
@@ -1184,8 +1276,8 @@ func TestTable_setData(t *testing.T) {
name: "merge",
fields: fields{
header: []string{"InstanceID", "InstanceName", "SecurityGroupID", "FlowDirection", "IPProtocol", "FromPort", "ToPort", "AddressType", "CidrBlock"},
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
mergedFields: []int{0, 1, 2},
ignoredFields: nil,
columnWidths: []int{0, 0, 0, 0, 0, 0, 0, 0, 0},
@@ -1209,8 +1301,8 @@ func TestTable_setData(t *testing.T) {
name: "included_ptr",
fields: fields{
header: []string{"InstanceID", "InstanceName", "AttachedLB", "AttachedTG"},
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
mergedFields: nil,
ignoredFields: nil,
columnWidths: []int{0, 0, 0, 0},
@@ -1288,7 +1380,7 @@ func TestTable_setBorder(t *testing.T) {
{
name: "text",
fields: fields{
- format: FormatText,
+ format: TextFormat,
marginWidth: 1,
columnWidths: []int{8, 12, 5},
},
@@ -1297,7 +1389,7 @@ func TestTable_setBorder(t *testing.T) {
{
name: "markdown",
fields: fields{
- format: FormatMarkdown,
+ format: MarkdownFormat,
marginWidth: 1,
columnWidths: []int{8, 12, 5},
},
@@ -1306,7 +1398,7 @@ func TestTable_setBorder(t *testing.T) {
{
name: "backlog",
fields: fields{
- format: FormatBacklog,
+ format: BacklogFormat,
marginWidth: 1,
columnWidths: []int{8, 12, 5},
},
@@ -1315,7 +1407,7 @@ func TestTable_setBorder(t *testing.T) {
{
name: "wide-margin",
fields: fields{
- format: FormatText,
+ format: TextFormat,
marginWidth: 3,
columnWidths: []int{8, 12, 5},
},
@@ -1360,9 +1452,9 @@ func TestTable_formatField(t *testing.T) {
{
name: "string",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
@@ -1374,23 +1466,23 @@ func TestTable_formatField(t *testing.T) {
{
name: "string_empty",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
v: "",
},
- want: DefaultEmptyFieldPlaceholder,
+ want: TextDefaultEmptyFieldPlaceholder,
wantErr: false,
},
{
name: "byte_slice",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
@@ -1402,9 +1494,9 @@ func TestTable_formatField(t *testing.T) {
{
name: "escape",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: true,
},
args: args{
@@ -1416,7 +1508,7 @@ func TestTable_formatField(t *testing.T) {
{
name: "asterisk_prefix_at_markdown",
fields: fields{
- format: FormatMarkdown,
+ format: MarkdownFormat,
emptyFieldPlaceholder: MarkdownDefaultEmptyFieldPlaceholder,
wordDelimiter: MarkdownDefaultWordDelimiter,
hasEscape: false,
@@ -1430,9 +1522,9 @@ func TestTable_formatField(t *testing.T) {
{
name: "int",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
@@ -1444,9 +1536,9 @@ func TestTable_formatField(t *testing.T) {
{
name: "int_signed",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
@@ -1458,9 +1550,9 @@ func TestTable_formatField(t *testing.T) {
{
name: "uint",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
@@ -1472,9 +1564,9 @@ func TestTable_formatField(t *testing.T) {
{
name: "float",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
@@ -1486,9 +1578,9 @@ func TestTable_formatField(t *testing.T) {
{
name: "ptr",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
@@ -1500,37 +1592,37 @@ func TestTable_formatField(t *testing.T) {
{
name: "nil_ptr",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
v: (*string)(nil),
},
- want: DefaultEmptyFieldPlaceholder,
+ want: TextDefaultEmptyFieldPlaceholder,
wantErr: false,
},
{
name: "non_nil_ptr_string",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
v: new(string),
},
- want: DefaultEmptyFieldPlaceholder,
+ want: TextDefaultEmptyFieldPlaceholder,
wantErr: false,
},
{
name: "non_nil_ptr_int",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
@@ -1542,93 +1634,121 @@ func TestTable_formatField(t *testing.T) {
{
name: "slice_string",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
v: []string{"a", "b"},
},
- want: "a" + DefaultWordDelimiter + "b",
+ want: "a" + TextDefaultWordDelimiter + "b",
wantErr: false,
},
{
name: "slice_string_included_empty",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
v: []string{"a", "", "b"},
},
- want: "a" + DefaultWordDelimiter + DefaultEmptyFieldPlaceholder + DefaultWordDelimiter + "b",
+ want: "a" + TextDefaultWordDelimiter + TextDefaultEmptyFieldPlaceholder + TextDefaultWordDelimiter + "b",
wantErr: false,
},
{
name: "slice_int",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
v: []int{0, 1, 2},
},
- want: "0" + DefaultWordDelimiter + "1" + DefaultWordDelimiter + "2",
+ want: "0" + TextDefaultWordDelimiter + "1" + TextDefaultWordDelimiter + "2",
wantErr: false,
},
{
name: "slice_uint",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
v: []uint{0, 1, 2},
},
- want: "0" + DefaultWordDelimiter + "1" + DefaultWordDelimiter + "2",
+ want: "0" + TextDefaultWordDelimiter + "1" + TextDefaultWordDelimiter + "2",
+ wantErr: false,
+ },
+ {
+ name: "slice_float32",
+ fields: fields{
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
+ hasEscape: false,
+ },
+ args: args{
+ v: []float32{0.1, 1.25, 2.001},
+ },
+ want: "0.1" + TextDefaultWordDelimiter + "1.25" + TextDefaultWordDelimiter + "2.001",
+ wantErr: false,
+ },
+ {
+ name: "slice_float64",
+ fields: fields{
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
+ hasEscape: false,
+ },
+ args: args{
+ v: []float64{0.1, 1.25, 2.001},
+ },
+ want: "0.1" + TextDefaultWordDelimiter + "1.25" + TextDefaultWordDelimiter + "2.001",
wantErr: false,
},
{
name: "slice_nil",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
v: ([]string)(nil),
},
- want: DefaultEmptyFieldPlaceholder,
+ want: TextDefaultEmptyFieldPlaceholder,
wantErr: false,
},
{
name: "slice_empty",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
v: []string{},
},
- want: DefaultEmptyFieldPlaceholder,
+ want: TextDefaultEmptyFieldPlaceholder,
wantErr: false,
},
{
name: "slice_with_byte_slice",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
@@ -1640,9 +1760,9 @@ func TestTable_formatField(t *testing.T) {
{
name: "slice_slice",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
@@ -1657,9 +1777,9 @@ func TestTable_formatField(t *testing.T) {
{
name: "slice_struct",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
@@ -1677,79 +1797,79 @@ func TestTable_formatField(t *testing.T) {
{
name: "slice_ptr",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
v: &[]string{"a", "b"},
},
- want: "a" + DefaultWordDelimiter + "b",
+ want: "a" + TextDefaultWordDelimiter + "b",
wantErr: false,
},
{
name: "slice_with_ptr_to_strings",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
v: []*string{sp(""), sp("a"), sp("b")},
},
- want: DefaultEmptyFieldPlaceholder + DefaultWordDelimiter + "a" + DefaultWordDelimiter + "b",
+ want: TextDefaultEmptyFieldPlaceholder + TextDefaultWordDelimiter + "a" + TextDefaultWordDelimiter + "b",
wantErr: false,
},
{
name: "slice_with_ptr_to_string_empty",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
v: []*string{},
},
- want: DefaultEmptyFieldPlaceholder,
+ want: TextDefaultEmptyFieldPlaceholder,
wantErr: false,
},
{
name: "slice_with_nil_ptr",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
v: []*int{nil},
},
- want: DefaultEmptyFieldPlaceholder,
+ want: TextDefaultEmptyFieldPlaceholder,
wantErr: false,
},
{
name: "slice_with_ptr_mixed",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
v: []*string{nil, sp(""), sp("aaa")},
},
- want: DefaultEmptyFieldPlaceholder + DefaultWordDelimiter + DefaultEmptyFieldPlaceholder + DefaultWordDelimiter + "aaa",
+ want: TextDefaultEmptyFieldPlaceholder + TextDefaultWordDelimiter + TextDefaultEmptyFieldPlaceholder + TextDefaultWordDelimiter + "aaa",
wantErr: false,
},
{
name: "stringer_duration",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
@@ -1761,9 +1881,9 @@ func TestTable_formatField(t *testing.T) {
{
name: "stringer_ipaddress",
fields: fields{
- format: FormatText,
- emptyFieldPlaceholder: DefaultEmptyFieldPlaceholder,
- wordDelimiter: DefaultWordDelimiter,
+ format: TextFormat,
+ emptyFieldPlaceholder: TextDefaultEmptyFieldPlaceholder,
+ wordDelimiter: TextDefaultWordDelimiter,
hasEscape: false,
},
args: args{
@@ -1811,7 +1931,7 @@ func TestTable_replaceNL(t *testing.T) {
{
name: "text",
fields: fields{
- format: FormatText,
+ format: TextFormat,
wordDelimiter: "\n",
},
args: args{
@@ -1822,7 +1942,7 @@ func TestTable_replaceNL(t *testing.T) {
{
name: "markdown",
fields: fields{
- format: FormatMarkdown,
+ format: MarkdownFormat,
wordDelimiter: "
",
},
args: args{
@@ -1833,7 +1953,7 @@ func TestTable_replaceNL(t *testing.T) {
{
name: "backlog",
fields: fields{
- format: FormatBacklog,
+ format: BacklogFormat,
wordDelimiter: "&br;",
},
args: args{
@@ -1848,7 +1968,8 @@ func TestTable_replaceNL(t *testing.T) {
format: tt.fields.format,
wordDelimiter: tt.fields.wordDelimiter,
}
- got := tr.replaceNL(tt.args.s)
+ tr.setAttr()
+ got := tr.sanitize(tt.args.s)
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("\ngot:\n%v\nwant:\n%v\n", got, tt.want)
}