MCPcopy Index your code
hub / github.com/aquasecurity/table

github.com/aquasecurity/table @v1.11.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.11.0 ↗ · + Follow
141 symbols 882 edges 27 files 39 documented · 28% 6 cross-repo links
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

table: Tables for terminals

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

A fruity demonstration table

Features

  • :arrow_up_down: Headers/footers
  • :leftwards_arrow_with_hook: Text wrapping
  • :twisted_rightwards_arrows: Auto-merging of cells
  • :interrobang: Customisable line/border characters
  • :rainbow: Customisable line/border colours
  • :play_or_pause_button: Individually enable/disable borders, row lines
  • :left_right_arrow: Set alignments on a per-column basis, with separate settings for headers/footers
  • :triangular_ruler: Intelligently wrap/pad/measure ANSI coloured input
  • :dancers: Support for double-width unicode characters
  • :bar_chart: Load data from CSV files

Check out the documentation for full features/usage.

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.SetRowLines(false)
    t.AddRow("1", "Apple", "14")
    t.AddRow("2", "Banana", "88,041")
    t.AddRow("3", "Cherry", "342")
    t.AddRow("4", "Dragonfruit", "1")
    t.SetFooters("", "Count", "4")
    t.Render()
}

Output

┌────┬─────────────┬────────┐
│ ID │    Fruit    │ Stock  │
├────┼─────────────┼────────┤
│ 1  │ Apple       │ 14     │
│ 2  │ Banana      │ 88,041 │
│ 3  │ Cherry      │ 342    │
│ 4  │ Dragonfruit │ 1      │
├────┼─────────────┼────────┤
│    │    Count    │   4    │
└────┴─────────────┴────────┘

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

@~~~~@~~~~~~~~~~~~~@~~~~~~~~@
! ID !    Fruit    ! Stock  !
@~~~~@~~~~~~~~~~~~~@~~~~~~~~@
! 1  ! Apple       ! 14     !
@~~~~@~~~~~~~~~~~~~@~~~~~~~~@
! 2  ! Banana      ! 88,041 !
@~~~~@~~~~~~~~~~~~~@~~~~~~~~@
! 3  ! Cherry      ! 342    !
@~~~~@~~~~~~~~~~~~~@~~~~~~~~@
! 4  ! Dragonfruit ! 1      !
@~~~~@~~~~~~~~~~~~~@~~~~~~~~@

Example: Auto Merge Cells

package main

import (
    "os"
    "time"

    "github.com/aquasecurity/table"
)

func main() {

    t := table.New(os.Stdout)

    t.SetAutoMerge(true)

    t.SetHeaders("System", "Status", "Last Check")

    t.AddRow("Life Support", "OK", time.Now().Format(time.Stamp))
    t.AddRow("Nuclear Generator", "OK", time.Now().Add(-time.Minute).Format(time.Stamp))
    t.AddRow("Weapons Systems", "FAIL", time.Now().Format(time.Stamp))
    t.AddRow("Shields", "OK", time.Now().Format(time.Stamp))

    t.Render()
}

Output

┌───────────────────┬────────┬────────────────┐
│      System       │ Status │   Last Check   │
├───────────────────┼────────┼────────────────┤
│ Life Support      │ OK     │ May 2 09:28:05 │
├───────────────────┤        ├────────────────┤
│ Nuclear Generator │        │ May 2 09:27:05 │
├───────────────────┼────────┼────────────────┤
│ Weapons Systems   │ FAIL   │ May 2 09:28:05 │
├───────────────────┼────────┤                │
│ Shields           │ OK     │                │
└───────────────────┴────────┴────────────────┘

Example: Load Data From Csv

package main

import (
    "os"

    "github.com/aquasecurity/table"
)

func main() {

    f, err := os.Open("./_examples/12-load-data-from-csv/data.csv")
    if err != nil {
        panic(err)
    }

    t := table.New(os.Stdout)
    if err := t.LoadCSV(f, true); err != nil {
        panic(err)
    }
    t.Render()
}

Output

┌────┬────────────┬────────────────────────────────────────────┐
│ Id │    Date    │                  Message                   │
├────┼────────────┼────────────────────────────────────────────┤
│ 1  │ 2022-05-12 │ Hello world!                               │
├────┼────────────┼────────────────────────────────────────────┤
│ 2  │ 2022-05-12 │ These messages are loaded from a CSV file. │
├────┼────────────┼────────────────────────────────────────────┤
│ 3  │ 2022-05-13 │ Incredible!                                │
└────┴────────────┴────────────────────────────────────────────┘

Example: Markdown Format

package main

import (
    "os"

    "github.com/aquasecurity/table"
)

func main() {
    t := table.New(os.Stdout)
    t.SetDividers(table.MarkdownDividers)

    t.SetBorderTop(false)
    t.SetBorderBottom(false)
    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: Header Colspans

package main

import (
    "os"

    "github.com/aquasecurity/table"
)

func main() {
    t := table.New(os.Stdout)
    t.SetHeaders("Namespace", "Resource", "Vulnerabilities", "Misconfigurations")
    t.AddHeaders("Namespace", "Resource", "Critical", "High", "Medium", "Low", "Unknown", "Critical", "High", "Medium", "Low", "Unknown")
    t.SetHeaderColSpans(0, 1, 1, 5, 5)
    t.SetAutoMergeHeaders(true)
    t.AddRow("default", "Deployment/app", "2", "5", "7", "8", "0", "0", "3", "5", "19", "0")
    t.AddRow("default", "Ingress/test", "-", "-", "-", "-", "-", "1", "0", "2", "17", "0")
    t.AddRow("default", "Service/test", "0", "0", "0", "1", "0", "3", "0", "4", "9", "0")
    t.Render()
}

Output

┌───────────┬────────────────┬──────────────────────────────────────────┬──────────────────────────────────────────┐
│ Namespace │    Resource    │             Vulnerabilities              │            Misconfigurations             │
│           │                ├──────────┬──────┬────────┬─────┬─────────┼──────────┬──────┬────────┬─────┬─────────┤
│           │                │ Critical │ High │ Medium │ Low │ Unknown │ Critical │ High │ Medium │ Low │ Unknown │
├───────────┼────────────────┼──────────┼──────┼────────┼─────┼─────────┼──────────┼──────┼────────┼─────┼─────────┤
│ default   │ Deployment/app │ 2        │ 5    │ 7      │ 8   │ 0       │ 0        │ 3    │ 5      │ 19  │ 0       │
├───────────┼────────────────┼──────────┼──────┼────────┼─────┼─────────┼──────────┼──────┼────────┼─────┼─────────┤
│ default   │ Ingress/test   │ -        │ -    │ -      │ -   │ -       │ 1        │ 0    │ 2      │ 17  │ 0       │
├───────────┼────────────────┼──────────┼──────┼────────┼─────┼─────────┼──────────┼──────┼────────┼─────┼─────────┤
│ default   │ Service/test   │ 0        │ 0    │ 0      │ 1   │ 0       │ 3        │ 0    │ 4      │ 9   │ 0       │
└───────────┴────────────────┴──────────┴──────┴────────┴─────┴─────────┴──────────┴──────┴────────┴─────┴─────────┘

Example: Only Wrap When Needed

package main

import (
    "os"

    "github.com/aquasecurity/table"
)

func main() {

    t := table.New(os.Stdout)

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

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

    t.Render()
}

Output

``` ┌────┬──────────────────────────────────────────────────────────────┬────────┐ │ ID │ Fruit │ Stock │ ├────┼──────────────────────────────────────────────────────────────┼────────┤ │ 1 │ 01234567890123456789012345678901234567890123456789012345678- │ 14 │ │ │ 901234567890123456789 │ │ ├────┼──────────────────────────────────────────────────────────────┼────────┤ │ 2 │ Banana │ 88,041 │ ├────┼──────────────────────────────────────────────────────────────┼────────┤ │ 3 │ Cherry │ 342 │ ├────┼──────────────────────────────────────────────────────────────┼────────┤ │ 4 │ Dragonfruit

Core symbols most depended-on inside this repo

AddRow
called by 147
table.go
New
called by 60
table.go
String
called by 55
ansi.go
Render
called by 54
table.go
SetHeaders
called by 53
table.go
print
called by 30
table.go
newANSI
called by 20
ansi.go
Len
called by 15
ansi.go

Shape

Function 71
Method 60
Struct 7
TypeAlias 3

Languages

Go100%

Modules by API surface

table.go59 symbols
table_test.go44 symbols
ansi.go11 symbols
text_test.go2 symbols
text.go2 symbols
ansi_test.go2 symbols
style.go1 symbols
dividers.go1 symbols
cmd/examples/main.go1 symbols
align.go1 symbols
_examples/99-ansi/main.go1 symbols
_examples/95-double-width-unicode/main.go1 symbols

For agents

$ claude mcp add table \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact