TableWriter for Go
tablewriter is a Go library for generating rich text-based tables with support for multiple output formats, including ASCII, Unicode, Markdown, HTML, and colorized terminals. Perfect for CLI tools, logs, and web applications.
Key Features
- Multi-format rendering: ASCII, Unicode, Markdown, HTML, ANSI-colored
- Advanced styling: Cell merging, alignment, padding, borders
- Flexible input: CSV, structs, slices, or streaming data
- High performance: Minimal allocations, buffer reuse
- Modern features: Generics support, hierarchical merging, real-time streaming
Installation
Legacy Version (v0.0.5)
For use with legacy applications:
go get github.com/olekukonko/[email protected]Latest Version
The latest stable version
go get github.com/olekukonko/[email protected]Warning: Version v1.0.0 contains missing functionality and should not be used.
Version Guidance
- Legacy: Use
v0.0.5(stable)- New Features: Use
@latest(includes generics, super fast streaming APIs)- Legacy Docs: See README_LEGACY.md
Why TableWriter?
- CLI Ready: Instant compatibility with terminal outputs
- Database Friendly: Native support for
sql.Null*types - Secure: Auto-escaping for HTML/Markdown
- Extensible: Custom renderers and formatters
Quick Example
package main
import (
"github.com/olekukonko/tablewriter"
"os"
)
func main() {
data := [][]string{
{"Package", "Version", "Status"},
{"tablewriter", "v0.0.5", "legacy"},
{"tablewriter", "v1.1.4", "latest"},
}
table := tablewriter.NewWriter(os.Stdout)
table.Header(data[0])
table.Bulk(data[1:])
table.Render()
}Output:
โโโโโโโโโโโโโโโฌโโโโโโโโโโฌโโโโโโโโโ
โ PACKAGE โ VERSION โ STATUS โ
โโโโโโโโโโโโโโโผโโโโโโโโโโผโโโโโโโโโค
โ tablewriter โ v0.0.5 โ legacy โ
โ tablewriter โ v1.1.4 โ latest โ
โโโโโโโโโโโโโโโดโโโโโโโโโโดโโโโโโโโโDetailed Usage
Create a table with NewTable or NewWriter, configure it using options or a Config struct, add data with Append or Bulk, and render to an io.Writer. Use renderers like Blueprint (ASCII), HTML, Markdown, Colorized, or Ocean (streaming).
Here's how the API primitives map to the generated ASCII table:
API Call ASCII Table Component
-------- ---------------------
table.Header([]string{"NAME", "AGE"}) โโโโโโโโฌโโโโโโ โ Borders.Top
โ NAME โ AGE โ โ Header row
โโโโโโโโผโโโโโโค โ Lines.ShowTop (header separator)
table.Append([]string{"Alice", "25"}) โ Aliceโ 25 โ โ Data row
โโโโโโโโผโโโโโโค โ Separators.BetweenRows
table.Append([]string{"Bob", "30"}) โ Bob โ 30 โ โ Data row
โโโโโโโโผโโโโโโค โ Lines.ShowBottom (footer separator)
table.Footer([]string{"Total", "2"}) โ Totalโ 2 โ โ Footer row
โโโโโโโโดโโโโโโ โ Borders.BottomThe core components include:
Renderer - Implements the core interface for converting table data into output formats. Available renderers include Blueprint (ASCII), HTML, Markdown, Colorized (ASCII with color), Ocean (streaming ASCII), and SVG.
Config - The root configuration struct that controls all table behavior and appearance
- Behavior - Controls high-level rendering behaviors including auto-hiding empty columns, trimming row whitespace, header/footer visibility, and compact mode for optimized merged cell calculations
- CellConfig - The comprehensive configuration template used for table sections (header, row, footer). Combines formatting, padding, alignment, filtering, callbacks, and width constraints with global and per-column control
- StreamConfig - Configuration for streaming mode including enable/disable state and strict column validation
Rendition - Defines how a renderer formats tables and contains the complete visual styling configuration
- Borders - Control the outer frame visibility (top, bottom, left, right edges) of the table
- Lines - Control horizontal boundary lines (above/below headers, above footers) that separate different table sections
- Separators - Control the visibility of separators between rows and between columns within the table content
- Symbols - Define the characters used for drawing table borders, corners, and junctions
These components can be configured with various tablewriter.With*() functional options when creating a new table.
Examples
Basic Examples
1. Simple Tables
Create a basic table with headers and rows.
default
package main
import (
"fmt"
"github.com/olekukonko/tablewriter"
"os"
)
type Age int
func (a Age) String() string {
return fmt.Sprintf("%d yrs", a)
}
func main() {
data := [][]any{
{"Alice", Age(25), "New York"},
{"Bob", Age(30), "Boston"},
}
table := tablewriter.NewTable(os.Stdout)
table.Header("Name", "Age", "City")
table.Bulk(data)
table.Render()
}Output:
โโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโ
โ NAME โ AGE โ CITY โ
โโโโโโโโโผโโโโโโโโโผโโโโโโโโโโโค
โ Alice โ 25 yrs โ New York โ
โ Bob โ 30 yrs โ Boston โ
โโโโโโโโโดโโโโโโโโโดโโโโโโโโโโโwith customization
package main
import (
"fmt"
"github.com/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/renderer"
"github.com/olekukonko/tablewriter/tw"
"os"
)
type Age int
func (a Age) String() string {
return fmt.Sprintf("%d yrs", a)
}
func main() {
data := [][]any{
{"Alice", Age(25), "New York"},
{"Bob", Age(30), "Boston"},
}
symbols := tw.NewSymbolCustom("Nature").
WithRow("~").
WithColumn("|").
WithTopLeft("๐ฑ").
WithTopMid("๐ฟ").
WithTopRight("๐ฑ").
WithMidLeft("๐").
WithCenter("โ").
WithMidRight("๐").
WithBottomLeft("๐ป").
WithBottomMid("๐พ").
WithBottomRight("๐ป")
table := tablewriter.NewTable(os.Stdout, tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{Symbols: symbols})))
table.Header("Name", "Age", "City")
table.Bulk(data)
table.Render()
}๐ฑ~~~~~~โ~~~~~~~~โ~~~~~~~~~๐ฑ
| NAME | AGE | CITY |
๐~~~~~~โ~~~~~~~~โ~~~~~~~~~๐
| Alice | 25 yrs | New York |
| Bob | 30 yrs | Boston |
๐ป~~~~~~โ~~~~~~~~โ~~~~~~~~~๐ปSee symbols example for more
2. Markdown Table
Generate a Markdown table for documentation.
package main
import (
"fmt"
"github.com/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/renderer"
"os"
"strings"
"unicode"
)
type Name struct {
First string
Last string
}
// this will be ignored since Format() is present
func (n Name) String() string {
return fmt.Sprintf("%s %s", n.First, n.Last)
}
// Note: Format() overrides String() if both exist.
func (n Name) Format() string {
return fmt.Sprintf("%s %s", n.clean(n.First), n.clean(n.Last))
}
// clean ensures the first letter is capitalized and the rest are lowercase
func (n Name) clean(s string) string {
s = strings.TrimSpace(strings.ToLower(s))
words := strings.Fields(s)
s = strings.Join(words, "")
if s == "" {
return s
}
// Capitalize the first letter
runes := []rune(s)
runes[0] = unicode.ToUpper(runes[0])
return string(runes)
}
type Age int
// Age int will be ignore and string will be used
func (a Age) String() string {
return fmt.Sprintf("%d yrs", a)
}
func main() {
data := [][]any{
{Name{"Al i CE", " Ma SK"}, Age(25), "New York"},
{Name{"bOb", "mar le y"}, Age(30), "Boston"},
}
table := tablewriter.NewTable(os.Stdout,
tablewriter.WithRenderer(renderer.NewMarkdown()),
)
table.Header([]string{"Name", "Age", "City"})
table.Bulk(data)
table.Render()
}Output:
| NAME | AGE | CITY |
|:----------:|:------:|:--------:|
| Alice Mask | 25 yrs | New York |
| Bob Marley | 30 yrs | Boston |3. CSV Input
Create a table from a CSV file with custom row alignment.
package main
import (
"github.com/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/tw"
"log"
"os"
)
func main() {
// Assuming "test.csv" contains: "First Name,Last Name,SSN\nJohn,Barry,123456\nKathy,Smith,687987"
table, err := tablewriter.NewCSV(os.Stdout, "test.csv", true)
if err != nil {
log.Fatalf("Error: %v", err)
}
table.Configure(func(config *tablewriter.Config) {
config.Row.Alignment.Global = tw.AlignLeft
})
table.Render()
}Output:
โโโโโโโโโโโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโ
โ FIRST NAME โ LAST NAME โ SSN โ
โโโโโโโโโโโโโโผโโโโโโโโโโโโผโโโโโโโโโโค
โ John โ Barry โ 123456 โ
โ Kathy โ Smith โ 687987 โ
โโโโโโโโโโโโโโดโโโโโโโโโโโโดโโโโโโโโโโAdvanced Examples
4. Colorized Table with Long Values
Create a colorized table with wrapped long values, per-column colors, and a styled footer (inspired by TestColorizedLongValues and TestColorizedCustomColors).
/* Detailed source-code truncated for AI context efficiency. */Output (colors visible in ANSI-compatible terminals):
5. Streaming Table with Truncation
Stream a table incrementally with truncation and a footer, simulating a real-time data feed (inspired by TestOceanStreamTruncation and TestOceanStreamSlowOutput).
package main
import (
"github.com/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/tw"
"log"
"os"
"time"
)
func main() {
table := tablewriter.NewTable(os.Stdout, tablewriter.WithStreaming(tw.StreamConfig{Enable: true}))
// Start streaming
if err := table.Start(); err != nil {
log.Fatalf("Start failed: %v", err)
}
defer table.Close()
// Stream header
table.Header([]string{"ID", "Description", "Status"})
// Stream rows with simulated delay
data := [][]string{
{"1", "This description is too long", "OK"},
{"2", "Short desc", "DONE"},
{"3", "Another long description here", "ERROR"},
}
for _, row := range data {
table.Append(row)
time.Sleep(500 * time.Millisecond) // Simulate real-time data feed
}
// Stream footer
table.Footer([]string{"", "Total", "3"})
}Output (appears incrementally):
โโโโโโโโโโฌโโโโโโโโโโโโโโโโฌโโโโโโโโโโโ
โ ID โ DESCRIPTION โ STATUS โ
โโโโโโโโโโผโโโโโโโโโโโโโโโโผโโโโโโโโโโโค
โ 1 โ This โ OK โ
โ โ description โ โ
โ โ is too long โ โ
โ 2 โ Short desc โ DONE โ
โ 3 โ Another long โ ERROR โ
โ โ description โ โ
โ โ here โ โ
โโโโโโโโโโผโโโโโโโโโโโโโโโโผโโโโโโโโโโโค
โ โ Total โ 3 โ
โโโโโโโโโโดโโโโโโโโโโโโโโโโดโโโโโโโโโโโNote: Long descriptions are truncated with โฆ due to fixed column widths. The output appears row-by-row, simulating a real-time feed.
6. Hierarchical Merging for Organizational Data
Show hierarchical merging for a tree-like structure, such as an organizational hierarchy (inspired by TestMergeHierarchicalUnicode).
package main
import (
"github.com/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/renderer"
"github.com/olekukonko/tablewriter/tw"
"os"
)
func main() {
data := [][]string{
{"Engineering", "Backend", "API Team", "Alice"},
{"Engineering", "Backend", "Database Team", "Bob"},
{"Engineering", "Frontend", "UI Team", "Charlie"},
{"Marketing", "Digital", "SEO Team", "Dave"},
{"Marketing", "Digital", "Content Team", "Eve"},
}
table := tablewriter.NewTable(os.Stdout,
tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{
Settings: tw.Settings{Separators: tw.Separators{BetweenRows: tw.On}},
})),
tablewriter.WithConfig(tablewriter.Config{
Header: tw.CellConfig{Alignment: tw.CellAlignment{Global: tw.AlignCenter}},
Row: tw.CellConfig{
Merging: tw.CellMerging{Mode: tw.MergeHierarchical},
Alignment: tw.CellAlignment{Global: tw.AlignLeft},
},
}),
)
table.Header([]string{"Department", "Division", "Team", "Lead"})
table.Bulk(data)
table.Render()
}Output:
โโโโโโโโโโโโโโฌโโโโโโโโโโโฌโโโโโโโโโโโโโโโฌโโโโโโโโโ
โ DEPARTMENT โ DIVISION โ TEAM โ LEAD โ
โโโโโโโโโโโโโโผโโโโโโโโโโโผโโโโโโโโโโโโโโโผโโโโโโโโโค
โ Engineeringโ Backend โ API Team โ Alice โ
โ โ โโโโโโโโโโโโโโโโผโโโโโโโโโค
โ โ โ Database Teamโ Bob โ
โ โ Frontend โโโโโโโโโโโโโโโโผโโโโโโโโโค
โ โ โ UI Team โ Charlieโ
โโโโโโโโโโโโโโผโโโโโโโโโโโผโโโโโโโโโโโโโโโผโโโโโโโโโค
โ Marketing โ Digital โ SEO Team โ Dave โ
โ โ โโโโโโโโโโโโโโโโผโโโโโโโโโค
โ โ โ Content Team โ Eve โ
โโโโโโโโโโโโโโดโโโโโโโโโโโดโโโโโโโโโโโโโโโดโโโโโโโโโNote: Hierarchical merging groups repeated values (e.g., "Engineering" spans multiple rows, "Backend" spans two teams), creating a tree-like structure.
7. Custom Padding with Merging
Showcase custom padding and combined horizontal/vertical merging (inspired by TestMergeWithPadding in merge_test.go).
package main
import (
"github.com/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/renderer"
"github.com/olekukonko/tablewriter/tw"
"os"
)
func main() {
data := [][]string{
{"1/1/2014", "Domain name", "Successful", "Successful"},
{"1/1/2014", "Domain name", "Pending", "Waiting"},
{"1/1/2014", "Domain name", "Successful", "Rejected"},
{"", "", "TOTAL", "$145.93"},
}
table := tablewriter.NewTable(os.Stdout,
tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{
Settings: tw.Settings{Separators: tw.Separators{BetweenRows: tw.On}},
})),
tablewriter.WithConfig(tablewriter.Config{
Row: tw.CellConfig{
Merging: tw.CellMerging{Mode: tw.MergeBoth},
Alignment: tw.CellAlignment{PerColumn: []tw.Align{tw.Skip, tw.Skip, tw.AlignRight, tw.AlignLeft}},
},
Footer: tw.CellConfig{
Padding: tw.CellPadding{
Global: tw.Padding{Left: "*", Right: "*"},
PerColumn: []tw.Padding{{}, {}, {Bottom: "^"}, {Bottom: "^"}},
},
Alignment: tw.CellAlignment{PerColumn: []tw.Align{tw.Skip, tw.Skip, tw.AlignRight, tw.AlignLeft}},
},
}),
)
table.Header([]string{"Date", "Description", "Status", "Conclusion"})
table.Bulk(data)
table.Render()
}Output:
โโโโโโโโโโโโฌโโโโโโโโโโโโโโฌโโโโโโโโโโโโโฌโโโโโโโโโโโโโ
โ DATE โ DESCRIPTION โ STATUS โ CONCLUSION โ
โโโโโโโโโโโโผโโโโโโโโโโโโโโผโโโโโโโโโโโโโดโโโโโโโโโโโโโค
โ 1/1/2014 โ Domain name โ Successful โ
โ โ โโโโโโโโโโโโโโฌโโโโโโโโโโโโโค
โ โ โ Pending โ Waiting โ
โ โ โโโโโโโโโโโโโโผโโโโโโโโโโโโโค
โ โ โ Successful โ Rejected โ
โโโโโโโโโโโโผโโโโโโโโโโโโโโผโโโโโโโโโโโโโผโโโโโโโโโโโโโค
โ โ โ TOTAL โ $145.93 โ
โ โ โ^^^^^^^^^^^^โ^^^^^^^^^^^^โ
โโโโโโโโโโโโดโโโโโโโโโโโโโโดโโโโโโโโโโโโโดโโโโโโโโโโโโโ8. Nested Tables
Create a table with nested sub-tables for complex layouts (inspired by TestMasterClass in extra_test.go).
package main
import (
"bytes"
"github.com/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/renderer"
"github.com/olekukonko/tablewriter/tw"
"os"
)
func main() {
// Helper to create a sub-table
createSubTable := func(s string) string {
var buf bytes.Buffer
table := tablewriter.NewTable(&buf,
tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{
Borders: tw.BorderNone,
Symbols: tw.NewSymbols(tw.StyleASCII),
Settings: tw.Settings{
Separators: tw.Separators{BetweenRows: tw.On},
Lines: tw.Lines{ShowFooterLine: tw.On},
},
})),
tablewriter.WithConfig(tablewriter.Config{
MaxWidth: 10,
Row: tw.CellConfig{Alignment: tw.CellAlignment{Global: tw.AlignCenter}},
}),
)
table.Append([]string{s, s})
table.Append([]string{s, s})
table.Render()
return buf.String()
}
// Main table
table := tablewriter.NewTable(os.Stdout,
tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{
Borders: tw.BorderNone,
Settings: tw.Settings{Separators: tw.Separators{BetweenColumns: tw.On}},
})),
tablewriter.WithConfig(tablewriter.Config{
MaxWidth: 30,
Row: tw.CellConfig{Alignment: tw.CellAlignment{Global: tw.AlignCenter}},
}),
)
table.Append([]string{createSubTable("A"), createSubTable("B")})
table.Append([]string{createSubTable("C"), createSubTable("D")})
table.Render()
}Output:
A | A โ B | B
---+--- โ ---+---
A | A โ B | B
C | C โ D | D
---+--- โ ---+---
C | C โ D | D9. Structs with Database
Render a table from a slice of structs, simulating a database query (inspired by TestStructTableWithDB in struct_test.go).
package main
import (
"fmt"
"github.com/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/renderer"
"github.com/olekukonko/tablewriter/tw"
"os"
)
type Employee struct {
ID int
Name string
Age int
Department string
Salary float64
}
func employeeStringer(e interface{}) []string {
emp, ok := e.(Employee)
if !ok {
return []string{"Error: Invalid type"}
}
return []string{
fmt.Sprintf("%d", emp.ID),
emp.Name,
fmt.Sprintf("%d", emp.Age),
emp.Department,
fmt.Sprintf("%.2f", emp.Salary),
}
}
func main() {
employees := []Employee{
{ID: 1, Name: "Alice Smith", Age: 28, Department: "Engineering", Salary: 75000.50},
{ID: 2, Name: "Bob Johnson", Age: 34, Department: "Marketing", Salary: 62000.00},
{ID: 3, Name: "Charlie Brown", Age: 45, Department: "HR", Salary: 80000.75},
}
table := tablewriter.NewTable(os.Stdout,
tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{
Symbols: tw.NewSymbols(tw.StyleRounded),
})),
tablewriter.WithStringer(employeeStringer),
tablewriter.WithConfig(tablewriter.Config{
Header: tw.CellConfig{
Formatting: tw.CellFormatting{AutoFormat: tw.On},
Alignment: tw.CellAlignment{Global: tw.AlignCenter},
},
Row: tw.CellConfig{Alignment: tw.CellAlignment{Global: tw.AlignLeft}},
Footer: tw.CellConfig{Alignment: tw.CellAlignment{Global: tw.AlignRight}},
}),
)
table.Header([]string{"ID", "Name", "Age", "Department", "Salary"})
for _, emp := range employees {
table.Append(emp)
}
totalSalary := 0.0
for _, emp := range employees {
totalSalary += emp.Salary
}
table.Footer([]string{"", "", "", "Total", fmt.Sprintf("%.2f", totalSalary)})
table.Render()
}Output:
โญโโโโโฌโโโโโโโโโโโโโโโโฌโโโโโโฌโโโโโโโโโโโโโโฌโโโโโโโโโโโโฎ
โ ID โ NAME โ AGE โ DEPARTMENT โ SALARY โ
โโโโโโผโโโโโโโโโโโโโโโโผโโโโโโผโโโโโโโโโโโโโโผโโโโโโโโโโโโค
โ 1 โ Alice Smith โ 28 โ Engineering โ 75000.50 โ
โ 2 โ Bob Johnson โ 34 โ Marketing โ 62000.00 โ
โ 3 โ Charlie Brown โ 45 โ HR โ 80000.75 โ
โโโโโโผโโโโโโโโโโโโโโโโผโโโโโโผโโโโโโโโโโโโโโผโโโโโโโโโโโโค
โ โ โ โ Total โ 217001.25 โ
โฐโโโโโดโโโโโโโโโโโโโโโโดโโโโโโดโโโโโโโโโโโโโโดโโโโโโโโโโโโฏ10. Simple Html Table
package main
import (
"github.com/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/renderer"
"github.com/olekukonko/tablewriter/tw"
"os"
)
func main() {
data := [][]string{
{"North", "Q1 & Q2", "Q1 & Q2", "$2200.00"},
{"South", "Q1", "Q1", "$1000.00"},
{"South", "Q2", "Q2", "$1200.00"},
}
// Configure HTML with custom CSS classes and content escaping
htmlCfg := renderer.HTMLConfig{
TableClass: "sales-table",
HeaderClass: "table-header",
BodyClass: "table-body",
FooterClass: "table-footer",
RowClass: "table-row",
HeaderRowClass: "header-row",
FooterRowClass: "footer-row",
EscapeContent: true, // Escape HTML characters (e.g., "&" to "&")
}
table := tablewriter.NewTable(os.Stdout,
tablewriter.WithRenderer(renderer.NewHTML(htmlCfg)),
tablewriter.WithConfig(tablewriter.Config{
Header: tw.CellConfig{
Merging: tw.CellMerging{Mode: tw.MergeHorizontal}, // Merge identical header cells
Alignment: tw.CellAlignment{Global: tw.AlignCenter},
},
Row: tw.CellConfig{
Merging: tw.CellMerging{Mode: tw.MergeHorizontal}, // Merge identical row cells
Alignment: tw.CellAlignment{Global: tw.AlignLeft},
},
Footer: tw.CellConfig{Alignment: tw.CellAlignment{Global: tw.AlignRight}},
}),
)
table.Header([]string{"Region", "Quarter", "Quarter", "Sales"})
table.Bulk(data)
table.Footer([]string{"", "", "Total", "$4400.00"})
table.Render()
}Output:
| REGION | QUARTER | SALES | |
| --- | --- | --- | --- |
| North | Q1 & Q2 | $2200.00 | |
| South | Q1 | $1000.00 | |
| South | Q2 | $1200.00 | |
| | | Total | $4400.00 |11. SVG Support
package main
import (
"fmt"
"github.com/olekukonko/ll"
"github.com/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/renderer"
"os"
)
type Age int
func (a Age) String() string {
return fmt.Sprintf("%d yrs", a)
}
func main() {
data := [][]any{
{"Alice", Age(25), "New York"},
{"Bob", Age(30), "Boston"},
}
file, err := os.OpenFile("out.svg", os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
ll.Fatal(err)
}
defer file.Close()
table := tablewriter.NewTable(file, tablewriter.WithRenderer(renderer.NewSVG()))
table.Header("Name", "Age", "City")
table.Bulk(data)
table.Render()
}/* Detailed source-code truncated for AI context efficiency. */12 Simple Application
/* Detailed source-code truncated for AI context efficiency. */โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโฌโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโ
โ TREE โ SIZE โ PERMISSIONS โ MODIFIED โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโผโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโค
โ ๐ filetable โ 160 B โ drwxr-xr-x โ just now โ
โ ๐ main.go โ 2.19 KB โ -rw-r--r-- โ 22 hours ago โ
โ ๐ out.txt โ 0 B โ -rw-r--r-- โ just now โ
โ ๐ testdata โ 128 B โ drwxr-xr-x โ 1 days ago โ
โ ๐ a.txt โ 11 B โ -rw-r--r-- โ 1 days ago โ
โ ๐ b.txt โ 17 B โ -rw-r--r-- โ 1 days ago โ
โ ๐ symbols โ 128 B โ drwxr-xr-x โ just now โ
โ ๐ main.go โ 4.58 KB โ -rw-r--r-- โ 1 hours ago โ
โ ๐ out.txt โ 8.72 KB โ -rw-r--r-- โ just now โ
โโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโดโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโChanges
AutoFormatchanges See #261
What is new
Countingchanges See #294
Command-Line Tool
The csv2table tool converts CSV files to ASCII tables. See cmd/csv2table/csv2table.go for details.
Example usage:
csv2table -f test.csv -h true -a leftContributing
Contributions are welcome! Submit issues or pull requests to the GitHub repository.
License
MIT License. See the LICENSE file for details.