table: Tables for terminals

This is a Go module for rendering tables in the terminal.

A fruity demonstration table

Features

  • ↕ī¸ Headers/footers
  • ↩ī¸ Text wrapping
  • 🔀 Auto-merging of cells
  • ⁉ī¸ Customisable line/border characters
  • 🌈 Customisable line/border colours
  • ⏯ī¸ Individually enable/disable borders, row lines
  • ↔ī¸ Set alignments on a per-column basis, with separate settings for headers/footers
  • 📐 Intelligently wrap/pad/measure ANSI coloured input
  • đŸ”Ĩ Support for double-width unicode characters

Examples

Example: Basic

package main

import (
	"os"

	"github.com/aquasecurity/table"
)

func main() {

	t := table.New(os.Stdout)

	t.SetHeaders("ID", "Fruit", "Stock")

	t.AddRow("1", "Apple", "14")
	t.AddRow("2", "Banana", "88,041")
	t.AddRow("3", "Cherry", "342")
	t.AddRow("4", "Dragonfruit", "1")

	t.Render()
}

Output

┌────â”Ŧ─────────────â”Ŧ────────┐
│ ID │    Fruit    │ Stock  │
├────â”ŧ─────────────â”ŧ────────┤
│ 1  │ Apple       │ 14     │
├────â”ŧ─────────────â”ŧ────────┤
│ 2  │ Banana      │ 88,041 │
├────â”ŧ─────────────â”ŧ────────┤
│ 3  │ Cherry      │ 342    │
├────â”ŧ─────────────â”ŧ────────┤
│ 4  │ Dragonfruit │ 1      │
└────┴─────────────┴────────┘

Example: No Row Lines

package main

import (
	"os"

	"github.com/aquasecurity/table"
)

func main() {

	t := table.New(os.Stdout)
	t.SetRowLines(false)

	t.SetHeaders("ID", "Fruit", "Stock")

	t.AddRow("1", "Apple", "14")
	t.AddRow("2", "Banana", "88,041")
	t.AddRow("3", "Cherry", "342")
	t.AddRow("4", "Dragonfruit", "1")

	t.Render()
}

Output

┌────â”Ŧ─────────────â”Ŧ────────┐
│ ID │    Fruit    │ Stock  │
├────â”ŧ─────────────â”ŧ────────┤
│ 1  │ Apple       │ 14     │
│ 2  │ Banana      │ 88,041 │
│ 3  │ Cherry      │ 342    │
│ 4  │ Dragonfruit │ 1      │
└────┴─────────────┴────────┘

Example: No Borders

package main

import (
	"os"

	"github.com/aquasecurity/table"
)

func main() {

	t := table.New(os.Stdout)
	t.SetBorders(false)

	t.SetHeaders("ID", "Fruit", "Stock")

	t.AddRow("1", "Apple", "14")
	t.AddRow("2", "Banana", "88,041")
	t.AddRow("3", "Cherry", "342")
	t.AddRow("4", "Dragonfruit", "1")

	t.Render()
}

Output

 ID │    Fruit    │ Stock  
────â”ŧ─────────────â”ŧ────────
 1  │ Apple       │ 14     
────â”ŧ─────────────â”ŧ────────
 2  │ Banana      │ 88,041 
────â”ŧ─────────────â”ŧ────────
 3  │ Cherry      │ 342    
────â”ŧ─────────────â”ŧ────────
 4  │ Dragonfruit │ 1      

Example: No Borders Or Row Lines

package main

import (
	"os"

	"github.com/aquasecurity/table"
)

func main() {

	t := table.New(os.Stdout)
	t.SetRowLines(false)
	t.SetBorders(false)

	t.SetHeaders("ID", "Fruit", "Stock")

	t.AddRow("1", "Apple", "14")
	t.AddRow("2", "Banana", "88,041")
	t.AddRow("3", "Cherry", "342")
	t.AddRow("4", "Dragonfruit", "1")

	t.Render()
}

Output

 ID │    Fruit    │ Stock  
────â”ŧ─────────────â”ŧ────────
 1  │ Apple       │ 14     
 2  │ Banana      │ 88,041 
 3  │ Cherry      │ 342    
 4  │ Dragonfruit │ 1      

Example: Specific Borders

package main

import (
	"os"

	"github.com/aquasecurity/table"
)

func main() {

	t := table.New(os.Stdout)
	t.SetRowLines(false)
	t.SetBorderLeft(true)
	t.SetBorderRight(false)
	t.SetBorderTop(true)
	t.SetBorderBottom(false)

	t.SetHeaders("ID", "Fruit", "Stock")

	t.AddRow("1", "Apple", "14")
	t.AddRow("2", "Banana", "88,041")
	t.AddRow("3", "Cherry", "342")
	t.AddRow("4", "Dragonfruit", "1")

	t.Render()
}

Output

┌────â”Ŧ─────────────â”Ŧ────────
│ ID │    Fruit    │ Stock  
├────â”ŧ─────────────â”ŧ────────
│ 1  │ Apple       │ 14     
│ 2  │ Banana      │ 88,041 
│ 3  │ Cherry      │ 342    
│ 4  │ Dragonfruit │ 1      

Example: Footers

package main

import (
	"os"

	"github.com/aquasecurity/table"
)

func main() {

	t := table.New(os.Stdout)

	t.SetHeaders("ID", "Fruit", "Stock")
	t.SetFooters("ID", "Fruit", "Stock")

	t.AddRow("1", "Apple", "14")
	t.AddRow("2", "Banana", "88,041")
	t.AddRow("3", "Cherry", "342")
	t.AddRow("4", "Dragonfruit", "1")

	t.Render()
}

Output

┌────â”Ŧ─────────────â”Ŧ────────┐
│ ID │    Fruit    │ Stock  │
├────â”ŧ─────────────â”ŧ────────┤
│ 1  │ Apple       │ 14     │
├────â”ŧ─────────────â”ŧ────────┤
│ 2  │ Banana      │ 88,041 │
├────â”ŧ─────────────â”ŧ────────┤
│ 3  │ Cherry      │ 342    │
├────â”ŧ─────────────â”ŧ────────┤
│ 4  │ Dragonfruit │ 1      │
├────â”ŧ─────────────â”ŧ────────┤
│ ID │    Fruit    │ Stock  │
└────┴─────────────┴────────┘

Example: Padding

package main

import (
	"os"

	"github.com/aquasecurity/table"
)

func main() {

	t := table.New(os.Stdout)
	t.SetPadding(5)

	t.SetHeaders("ID", "Fruit", "Stock")

	t.AddRow("1", "Apple", "14")
	t.AddRow("2", "Banana", "88,041")
	t.AddRow("3", "Cherry", "342")
	t.AddRow("4", "Dragonfruit", "1")

	t.Render()
}

Output

┌────────────â”Ŧ─────────────────────â”Ŧ────────────────┐
│     ID     │        Fruit        │     Stock      │
├────────────â”ŧ─────────────────────â”ŧ────────────────┤
│     1      │     Apple           │     14         │
├────────────â”ŧ─────────────────────â”ŧ────────────────┤
│     2      │     Banana          │     88,041     │
├────────────â”ŧ─────────────────────â”ŧ────────────────┤
│     3      │     Cherry          │     342        │
├────────────â”ŧ─────────────────────â”ŧ────────────────┤
│     4      │     Dragonfruit     │     1          │
└────────────┴─────────────────────┴────────────────┘

Example: Alignment

package main

import (
	"os"

	"github.com/aquasecurity/table"
)

func main() {

	t := table.New(os.Stdout)
	t.SetAlignment(table.AlignLeft, table.AlignCenter, table.AlignRight)

	t.SetHeaders("ID", "Fruit", "Stock")

	t.AddRow("1", "Apple", "14")
	t.AddRow("2", "Banana", "88,041")
	t.AddRow("3", "Cherry", "342")
	t.AddRow("4", "Dragonfruit", "1")

	t.Render()
}

Output

┌────â”Ŧ─────────────â”Ŧ────────┐
│ ID │    Fruit    │ Stock  │
├────â”ŧ─────────────â”ŧ────────┤
│ 1  │    Apple    │     14 │
├────â”ŧ─────────────â”ŧ────────┤
│ 2  │   Banana    │ 88,041 │
├────â”ŧ─────────────â”ŧ────────┤
│ 3  │   Cherry    │    342 │
├────â”ŧ─────────────â”ŧ────────┤
│ 4  │ Dragonfruit │      1 │
└────┴─────────────┴────────┘

Example: Rounded Corners

package main

import (
	"os"

	"github.com/aquasecurity/table"
)

func main() {

	t := table.New(os.Stdout)
	t.SetDividers(table.UnicodeRoundedDividers)

	t.SetHeaders("ID", "Fruit", "Stock")

	t.AddRow("1", "Apple", "14")
	t.AddRow("2", "Banana", "88,041")
	t.AddRow("3", "Cherry", "342")
	t.AddRow("4", "Dragonfruit", "1")

	t.Render()
}

Output

╭────â”Ŧ─────────────â”Ŧ────────╮
│ ID │    Fruit    │ Stock  │
├────â”ŧ─────────────â”ŧ────────┤
│ 1  │ Apple       │ 14     │
├────â”ŧ─────────────â”ŧ────────┤
│ 2  │ Banana      │ 88,041 │
├────â”ŧ─────────────â”ŧ────────┤
│ 3  │ Cherry      │ 342    │
├────â”ŧ─────────────â”ŧ────────┤
│ 4  │ Dragonfruit │ 1      │
╰────┴─────────────┴────────╯

Example: Custom Dividers

package main

import (
	"os"

	"github.com/aquasecurity/table"
)

func main() {

	t := table.New(os.Stdout)
	t.SetDividers(table.Dividers{
		ALL: "@",
		NES: "@",
		NSW: "@",
		NEW: "@",
		ESW: "@",
		NE:  "@",
		NW:  "@",
		SW:  "@",
		ES:  "@",
		EW:  "~",
		NS:  "!",
	})

	t.SetHeaders("ID", "Fruit", "Stock")

	t.AddRow("1", "Apple", "14")
	t.AddRow("2", "Banana", "88,041")
	t.AddRow("3", "Cherry", "342")
	t.AddRow("4", "Dragonfruit", "1")

	t.Render()
}

Output

Example: Double-width Unicode

package main

import (
	"os"

	"github.com/aquasecurity/table"
)

func main() {
	t := table.New(os.Stdout)
	t.SetHeaders("A", "B", "C")
	t.AddRow("đŸ”Ĩ unicode đŸ”Ĩ characters đŸ”Ĩ", "2", "3")
	t.AddRow("4", "5", "6")
	t.Render()
}

Output

a table with double-width runes

Example: ANSI Colours

package main

import (
	"os"

	"github.com/aquasecurity/table"
)

func main() {

	t := table.New(os.Stdout)

	t.SetHeaders("ID", "Fruit", "Stock")
	t.SetLineStyle(table.StyleRed)

	t.AddRow("1", "Apple", "14")
	t.AddRow("2", "Banana", "88,041")
	t.AddRow("3", "Cherry", "342")
	t.AddRow("4", "Dragonfruit", "1")

	t.Render()
}

Output

a colourful table

GitHub

View Github