tabulate

package module
v0.0.0-...-d496586 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 23, 2023 License: MIT Imports: 9 Imported by: 11

README

tabulate

Tabulate is an utility library for making simple data visualizations. Tabulate works on tabular data. The data tables can be constructed explicity by calling the row and column functions, or with reflection from Go values.

Build Status Git Hub Go Report Card

Programmatic table construction

In the programmatic table construction, you first create a new table and define the headers with optional layout attributes:

tab := tabulate.New(tabulate.Unicode)
tab.Header("Year").SetAlign(tabulate.MR)
tab.Header("Income").SetAlign(tabulate.MR)

After that, you add data rows:

row := tab.Row()
row.Column("2018")
row.Column("100")

row = tab.Row()
row.Column("2019")
row.Column("110")

row = tab.Row()
row.Column("2020")
row.Column("200")

Finally, you print the table:

tab.Print(os.Stdout)

This outputs the table to the selected writer:

┏━━━━━━┳━━━━━━━━┓
┃ Year ┃ Income ┃
┡━━━━━━╇━━━━━━━━┩
│ 2018 │    100 │
│ 2019 │    110 │
│ 2020 │    200 │
└──────┴────────┘

Reflection

The reflection mode allows you to easily tabulate Go data structures. The resulting table will always have two columns: key and value. But the value columns can contain nested tables.

type Person struct {
    Name string
}

type Book struct {
    Title     string
    Author    []Person
    Publisher string
    Published int
}

tab := tabulate.New(tabulate.ASCII)
tab.Header("Key").SetAlign(tabulate.ML)
tab.Header("Value")
err := tabulate.Reflect(tab, 0, nil, &Book{
    Title: "Structure and Interpretation of Computer Programs",
    Author: []Person{
        Person{
            Name: "Harold Abelson",
        },
        Person{
            Name: "Gerald Jay Sussman",
        },
        Person{
            Name: "Julie Sussman",
        },
    },
    Publisher: "MIT Press",
    Published: 1985,
})
if err != nil {
    log.Fatal(err)
}
tab.Print(os.Stdout)

This example renders the following table:

+-----------+---------------------------------------------------+
| Key       | Value                                             |
+-----------+---------------------------------------------------+
| Title     | Structure and Interpretation of Computer Programs |
|           | +------+----------------+                         |
|           | | Key  | Value          |                         |
|           | +------+----------------+                         |
|           | | Name | Harold Abelson |                         |
|           | +------+----------------+                         |
|           | +------+--------------------+                     |
|           | | Key  | Value              |                     |
| Author    | +------+--------------------+                     |
|           | | Name | Gerald Jay Sussman |                     |
|           | +------+--------------------+                     |
|           | +------+---------------+                          |
|           | | Key  | Value         |                          |
|           | +------+---------------+                          |
|           | | Name | Julie Sussman |                          |
|           | +------+---------------+                          |
| Publisher | MIT Press                                         |
| Published | 1985                                              |
+-----------+---------------------------------------------------+

Formatting

Cell alignment

Column headers set the default alignment for all cells in the corresponding columns. The column default alignment is set when the headers are defined:

tab.Header("Year").SetAlign(tabulate.MR)

The alignment is defined with the Align constants. The first character of the constant name specifies the vertical alignment (Top, Middle, Bottom) and the second character specifies the horizointal alignment (Left, Center, Right).

Alignment Vertical Horizontal
TL Top Left
TC Top Center
TR Top Right
ML Middle Left
MC Middle Center
MR Middle Right
BL Bottom Left
BC Bottom Center
BR Bottom Right
None - -

The default alignment can be overridden by calling the SetAlign() for the data column:

row = tab.Row()
row.Column("Integer").SetAlign(tabulate.TL)

Output formats

Plain

The Plain format does not draw any table borders:

 Year  Income  Expenses
 2018  100     90
 2019  110     85
 2020  107     50

ASCII

The ASCII format creates a new tabulator that uses ASCII characters to render the table borders:

+------+--------+----------+
| Year | Income | Expenses |
+------+--------+----------+
| 2018 | 100    | 90       |
| 2019 | 110    | 85       |
| 2020 | 107    | 50       |
+------+--------+----------+

Unicode

The Unicode format creates a new tabulator that uses Unicode line drawing characters to render the table borders:

┏━━━━━━┳━━━━━━━━┳━━━━━━━━━━┓
┃ Year ┃ Income ┃ Expenses ┃
┡━━━━━━╇━━━━━━━━╇━━━━━━━━━━┩
│ 2018 │ 100    │ 90       │
│ 2019 │ 110    │ 85       │
│ 2020 │ 107    │ 50       │
└──────┴────────┴──────────┘

UnicodeLight

The UnicodeLight format creates a new tabulator that uses thin Unicode line drawing characters to render the table borders:

┌──────┬────────┬──────────┐
│ Year │ Income │ Expenses │
├──────┼────────┼──────────┤
│ 2018 │ 100    │ 90       │
│ 2019 │ 110    │ 85       │
│ 2020 │ 107    │ 50       │
└──────┴────────┴──────────┘

UnicodeBold

The UnicodeBold format creates a new tabulator that uses thick Unicode line drawing characters to render the table borders:

┏━━━━━━┳━━━━━━━━┳━━━━━━━━━━┓
┃ Year ┃ Income ┃ Expenses ┃
┣━━━━━━╋━━━━━━━━╋━━━━━━━━━━┫
┃ 2018 ┃ 100    ┃ 90       ┃
┃ 2019 ┃ 110    ┃ 85       ┃
┃ 2020 ┃ 107    ┃ 50       ┃
┗━━━━━━┻━━━━━━━━┻━━━━━━━━━━┛

Colon

The Colon format creates a new tabulator that uses colon (':') character to render vertical table borders:

Year : Income : Expenses
2018 : 100    : 90
2019 : 110    : 85
2020 : 107    : 50

Simple

The Simple format draws horizontal lines between header and body columns:

Year  Income  Expenses
----  ------  --------
2018  100     90
2019  110     85
2020  107     50

Github

The Github creates tables with the Github Markdown syntax:

| Year | Income | Expenses |
|------|--------|----------|
| 2018 | 100    | 90       |
| 2019 | 110    | 85       |
| 2020 | 107    | 50       |

Comma-Separated Values (CSV) output

The NewCSV() creates a new tabulator that outputs the data in CSV format. It uses empty borders and an escape function which handles ',' and '\n' characters inside cell values:

Year,Income,Source
2018,100,Salary
2019,110,"""Consultation"""
2020,120,"Lottery
et al"

JSON output

The NewJSON() creates a new tabulator that outputs the data in JSON format:

{"2018":["100","90"],"2019":["110","85"],"2020":["107","50"]}

Native JSON marshalling

The Tabulate object implements the MarshalJSON interface so you can marshal tabulated data directly into JSON.

tab := tabulate.New(tabulate.Unicode)
tab.Header("Key").SetAlign(tabulate.MR)
tab.Header("Value").SetAlign(tabulate.ML)

row := tab.Row()
row.Column("Boolean")
row.ColumnData(NewValue(false))

row = tab.Row()
row.Column("Integer")
row.ColumnData(NewValue(42))

data, err := json.Marshal(tab)
if err != nil {
	log.Fatalf("JSON marshal failed: %s", err)
}
fmt.Println(string(data))

This example outputs the following JSON output:

{"Boolean":false,"Integer":42}

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var Styles = map[string]Style{
	"plain":          Plain,
	"ascii":          ASCII,
	"uc":             Unicode,
	"uclight":        UnicodeLight,
	"ucbold":         UnicodeBold,
	"compactuc":      CompactUnicode,
	"compactuclight": CompactUnicodeLight,
	"compactucbold":  CompactUnicodeBold,
	"colon":          Colon,
	"simple":         Simple,
	"simpleuc":       SimpleUnicode,
	"simpleucbold":   SimpleUnicodeBold,
	"github":         Github,
	"csv":            CSV,
	"json":           JSON,
}

Styles list all supported tabulation types.

Functions

func MeasureRunes

func MeasureRunes(column string) int

MeasureRunes measures the column width by counting its runes. This assumes that all runes have the same width consuming single output column cell.

func MeasureUnicode

func MeasureUnicode(column string) int

MeasureUnicode measures the column width by taking into consideration East Asian Wide characters. The function assumes that East Asian Wide characters consume two output column cells.

func Reflect

func Reflect(tab *Tabulate, flags Flags, tags []string, v interface{}) error

Reflect tabulates the value into the tabulation object. The flags control how different values are handled. The tags lists element tags which are included in reflection. If the element does not have tabulation tag, then it is always included in tabulation.

Example
type Person struct {
	Name string
}

type Book struct {
	Title     string
	Author    []Person
	Publisher string
	Published int
}

tab := New(ASCII)
tab.Header("Key").SetAlign(ML)
tab.Header("Value")
err := Reflect(tab, InheritHeaders, nil, &Book{
	Title: "Structure and Interpretation of Computer Programs",
	Author: []Person{
		{
			Name: "Harold Abelson",
		},
		{
			Name: "Gerald Jay Sussman",
		},
		{
			Name: "Julie Sussman",
		},
	},
	Publisher: "MIT Press",
	Published: 1985,
})
if err != nil {
	log.Fatal(err)
}
tab.Print(os.Stdout)
Output:

+-----------+---------------------------------------------------+
| Key       | Value                                             |
+-----------+---------------------------------------------------+
| Title     | Structure and Interpretation of Computer Programs |
|           | +------+----------------+                         |
|           | | Key  | Value          |                         |
|           | +------+----------------+                         |
|           | | Name | Harold Abelson |                         |
|           | +------+----------------+                         |
|           | +------+--------------------+                     |
|           | | Key  | Value              |                     |
| Author    | +------+--------------------+                     |
|           | | Name | Gerald Jay Sussman |                     |
|           | +------+--------------------+                     |
|           | +------+---------------+                          |
|           | | Key  | Value         |                          |
|           | +------+---------------+                          |
|           | | Name | Julie Sussman |                          |
|           | +------+---------------+                          |
| Publisher | MIT Press                                         |
| Published | 1985                                              |
+-----------+---------------------------------------------------+

func StyleNames

func StyleNames() []string

StyleNames returns the tabulation style names as a sorted slice.

Types

type Align

type Align int

Align specifies cell alignment in horizontal and vertical directions.

const (
	TL Align = iota
	TC
	TR
	ML
	MC
	MR
	BL
	BC
	BR
	None
)

Alignment constants. The first character specifies the vertical alignment (Top, Middle, Bottom) and the second character specifies the horizointal alignment (Left, Center, Right).

func (Align) String

func (a Align) String() string

type Border

type Border struct {
	HT string
	HM string
	HB string
	VL string
	VM string
	VR string
	TL string
	TM string
	TR string
	ML string
	MM string
	MR string
	BL string
	BM string
	BR string
}

Border specifies the table border drawing elements.

type Borders

type Borders struct {
	Header Border
	Body   Border
}

Borders specifies the thable border drawing elements for the table header and body.

type Column

type Column struct {
	Align  Align
	Data   Data
	Format Format
}

Column defines a table column data and its attributes.

func (*Column) Content

func (col *Column) Content(row int) string

Content returns the specified row from the column. If the column does not have that many row, the function returns an empty string.

func (*Column) Height

func (col *Column) Height() int

Height returns the column heigh in lines.

func (*Column) SetAlign

func (col *Column) SetAlign(align Align) *Column

SetAlign sets the column alignment.

func (*Column) SetFormat

func (col *Column) SetFormat(format Format) *Column

SetFormat sets the column text format.

func (*Column) Width

func (col *Column) Width(m Measure) int

Width returns the column width in runes.

type Data

type Data interface {
	Width(m Measure) int
	Height() int
	Content(row int) string
	String() string
}

Data contains table cell data.

type Escape

type Escape func(string) string

Escape is an escape function for converting table cell value into the output format.

type Flags

type Flags int

Flags control how reflection tabulation operates on different values.

const (
	OmitEmpty Flags = 1 << iota
	InheritHeaders
)

Flag values for reflection tabulation.

type Format

type Format int

Format specifies text formatting.

const (
	FmtNone Format = iota
	FmtBold
	FmtItalic
)

Format values specify various VT100 text formatting codes.

func (Format) VT100

func (fmt Format) VT100() string

VT100 creates VT100 terminal emulation codes for the agument format.

type Lines

type Lines struct {
	Lines []string
}

Lines implements the Data interface over an array of lines.

func NewLines

func NewLines(str string) *Lines

NewLines creates a new Lines data from the argument string. The argument string is split into lines from the newline ('\n') character.

func NewLinesData

func NewLinesData(lines []string) *Lines

NewLinesData creates a new Lines data from the array of strings.

func NewText

func NewText(str string) *Lines

NewText creates a new Lines data, containing one line.

func (*Lines) Content

func (lines *Lines) Content(row int) string

Content implements the Data.Content().

func (*Lines) Height

func (lines *Lines) Height() int

Height implements the Data.Height().

func (*Lines) String

func (lines *Lines) String() string

func (*Lines) Width

func (lines *Lines) Width(m Measure) int

Width implements the Data.Width().

type Measure

type Measure func(column string) int

Measure returns the column width in display units. This can be used to remove any non-printable formatting codes from the value.

type Row

type Row struct {
	Tab     *Tabulate
	Columns []*Column
}

Row defines a data row in the tabulator.

func (*Row) Column

func (r *Row) Column(label string) *Column

Column adds a new string column to the row.

func (*Row) ColumnData

func (r *Row) ColumnData(data Data) *Column

ColumnData adds a new data column to the row.

func (*Row) Height

func (r *Row) Height() int

Height returns the row height in lines.

type Slice

type Slice struct {
	// contains filtered or unexported fields
}

Slice implements the Data interface for an array of Data elements.

func NewSlice

func NewSlice(maxWidth int) *Slice

NewSlice creates a new Slice Data type with the specified maximum rendering width.

func (*Slice) Append

func (arr *Slice) Append(data Data)

Append adds data to the array.

func (*Slice) Content

func (arr *Slice) Content(row int) string

Content implements the Data.Content().

func (*Slice) Height

func (arr *Slice) Height() int

Height implements the Data.Height().

func (*Slice) String

func (arr *Slice) String() string

func (*Slice) Width

func (arr *Slice) Width(m Measure) int

Width implements the Data.Width().

type Style

type Style int

Style specifies the table borders and rendering style.

Example (Csv)
tabulateStyle(CSV).Print(os.Stdout)
Output:

const (
	Plain Style = iota
	ASCII
	Unicode
	UnicodeLight
	UnicodeBold
	CompactUnicode
	CompactUnicodeLight
	CompactUnicodeBold
	Colon
	Simple
	SimpleUnicode
	SimpleUnicodeBold
	Github
	CSV
	JSON
)

Table styles.

func (Style) String

func (s Style) String() string

type Tabulate

type Tabulate struct {
	Padding     int
	TrimColumns bool
	Borders     Borders
	Measure     Measure
	Escape      Escape
	Output      func(t *Tabulate, o io.Writer)
	Defaults    []Align
	Headers     []*Column
	Rows        []*Row
	// contains filtered or unexported fields
}

Tabulate defined a tabulator instance.

func Array

func Array(tab *Tabulate, v [][]interface{}) (*Tabulate, error)

Array tabulates the argument v into rows and columns. If the tab defines header columns, those will be used. Otherwise the first row of v defines the header columns.

Example
tab, err := Array(New(ASCII), [][]interface{}{
	{"a", "b", "c"},
	{"1", "2", "3"},
})
if err != nil {
	log.Fatal(err)
}
tab.Print(os.Stdout)
Output:

+---+---+---+
| a | b | c |
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
Example (Second)
tab, err := Array(New(Unicode), [][]interface{}{
	{"int", "float", "struct"},
	{42, 3.14, struct {
		ival   int
		strval string
	}{
		ival:   42,
		strval: "Hello, world!",
	}},
})
if err != nil {
	log.Fatal(err)
}
tab.Print(os.Stdout)
Output:

┏━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ int ┃ float ┃ struct                     ┃
┡━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 42  │ 3.14  │ ┌────────┬───────────────┐ │
│     │       │ │ ival   │ 42            │ │
│     │       │ │ strval │ Hello, world! │ │
│     │       │ └────────┴───────────────┘ │
└─────┴───────┴────────────────────────────┘

func New

func New(style Style) *Tabulate

New creates a new tabulate object with the specified rendering style.

Example
tab := New(Unicode)

lines := strings.Split(`Year,Income,Source
2018,100,Salary
2019,110,Consultation
2020,200,Lottery`, "\n")

// Table headers.
for _, hdr := range strings.Split(lines[0], ",") {
	tab.Header(hdr)
}

// Table data rows.
for _, line := range lines[1:] {
	row := tab.Row()
	for _, col := range strings.Split(line, ",") {
		row.Column(col)
	}
}

tab.Print(os.Stdout)
Output:

┏━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┓
┃ Year ┃ Income ┃ Source       ┃
┡━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━┩
│ 2018 │ 100    │ Salary       │
│ 2019 │ 110    │ Consultation │
│ 2020 │ 200    │ Lottery      │
└──────┴────────┴──────────────┘

func (*Tabulate) Clone

func (t *Tabulate) Clone() *Tabulate

Clone creates a new tabulator sharing the headers and their attributes. The new tabulator does not share the data rows with the original tabulator.

func (*Tabulate) Content

func (t *Tabulate) Content(row int) string

Content implements the Data.Content().

func (*Tabulate) Header

func (t *Tabulate) Header(label string) *Column

Header adds a new column to the table and specifies its header label.

Example
tab := New(Unicode)
tab.Header("Year").SetAlign(MR)
tab.Header("Income").SetAlign(MR)
tab.Print(os.Stdout)
Output:

┏━━━━━━┳━━━━━━━━┓
┃ Year ┃ Income ┃
┗━━━━━━┻━━━━━━━━┛

func (*Tabulate) HeaderData

func (t *Tabulate) HeaderData(data Data) *Column

HeaderData adds a new column to the table and specifies is header data.

func (*Tabulate) Height

func (t *Tabulate) Height() int

Height implements the Data.Height().

func (*Tabulate) MarshalJSON

func (t *Tabulate) MarshalJSON() ([]byte, error)

MarshalJSON implements the JSON Marshaler interface.

Example
tab := New(Unicode)
tab.Header("Key").SetAlign(MR)
tab.Header("Value").SetAlign(ML)

row := tab.Row()
row.Column("Boolean")
row.ColumnData(NewValue(false))

row = tab.Row()
row.Column("Integer")
row.ColumnData(NewValue(42))

data, err := json.Marshal(tab)
if err != nil {
	log.Fatalf("JSON marshal failed: %s", err)
}
fmt.Println(string(data))
Output:

{"Boolean":false,"Integer":42}

func (*Tabulate) Print

func (t *Tabulate) Print(o io.Writer)

Print layouts the table into the argument io.Writer.

func (*Tabulate) Row

func (t *Tabulate) Row() *Row

Row adds a new data row to the table.

Example
tab := New(Unicode)
tab.Header("Year").SetAlign(MR)
tab.Header("Income").SetAlign(MR)

row := tab.Row()
row.Column("2018")
row.Column("100")

row = tab.Row()
row.Column("2019")
row.Column("110")

row = tab.Row()
row.Column("2020")
row.Column("200")

tab.Print(os.Stdout)
Output:

┏━━━━━━┳━━━━━━━━┓
┃ Year ┃ Income ┃
┡━━━━━━╇━━━━━━━━┩
│ 2018 │    100 │
│ 2019 │    110 │
│ 2020 │    200 │
└──────┴────────┘

func (*Tabulate) SetDefaults

func (t *Tabulate) SetDefaults(col int, align Align)

SetDefaults sets the column default attributes. These are used if the table does not have headers.

func (*Tabulate) String

func (t *Tabulate) String() string

func (*Tabulate) Width

func (t *Tabulate) Width(m Measure) int

Width implements the Data.Width().

type Value

type Value struct {
	// contains filtered or unexported fields
}

Value implements the Data interface for single value, such as bool, integer, etc.

func NewValue

func NewValue(v interface{}) *Value

NewValue creates a new Value for the argument value element.

func (*Value) Content

func (v *Value) Content(row int) string

Content implements the Data.Content().

func (*Value) Height

func (v *Value) Height() int

Height implements the Data.Height().

func (*Value) String

func (v *Value) String() string

func (*Value) Width

func (v *Value) Width(m Measure) int

Width implements the Data.Width().

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL