Skip to content

Commit

Permalink
feat: Add CSV imports (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
liamg authored May 13, 2022
1 parent 4a9b7f9 commit ec18aaa
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 4 deletions.
47 changes: 44 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ This is a Go module for rendering tables in the terminal.
- :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
- :fire: Support for double-width unicode characters
- :bar_chart: Load data from CSV files

## Examples

Expand Down Expand Up @@ -487,15 +488,55 @@ func main() {
┌───────────────────┬────────┬─────────────────┐
│ System │ Status │ Last Check │
├───────────────────┼────────┼─────────────────┤
│ Life Support │ OK │ May 13 08:54:29
│ Life Support │ OK │ May 13 09:09:30
├───────────────────┤ ├─────────────────┤
│ Nuclear Generator │ │ May 13 08:53:29
│ Nuclear Generator │ │ May 13 09:08:30
├───────────────────┼────────┼─────────────────┤
│ Weapons Systems │ FAIL │ May 13 08:54:29
│ Weapons Systems │ FAIL │ May 13 09:09:30
├───────────────────┼────────┤ │
│ Shields │ OK │ │
└───────────────────┴────────┴─────────────────┘
```

### Example: Load Data From Csv
```go
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! │
└────┴────────────┴────────────────────────────────────────────┘
```
<!--/eg-->

Expand Down
4 changes: 4 additions & 0 deletions _examples/12-load-data-from-csv/data.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
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!"
21 changes: 21 additions & 0 deletions _examples/12-load-data-from-csv/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
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()
}
30 changes: 29 additions & 1 deletion table.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package table

import (
"encoding/csv"
"fmt"
"github.com/mattn/go-runewidth"
"io"
"strings"

"github.com/mattn/go-runewidth"
)

// Table holds information required to render a table to the terminal
Expand Down Expand Up @@ -182,6 +184,32 @@ func (t *Table) AddRows(rows ...[]string) {
t.data = append(t.data, rows...)
}

// LoadCSV loads CSV data from a reader and adds it to the table. Existing rows/headers/footers are retained.
func (t *Table) LoadCSV(r io.Reader, hasHeaders bool) error {
cr := csv.NewReader(r)

if hasHeaders {
headers, err := cr.Read()
if err != nil {
return err
}
t.SetHeaders(headers...)
}

for {
data, err := cr.Read()
if err != nil {
if err == io.EOF {
break
}
return err
}
t.AddRow(data...)
}

return nil
}

func (t *Table) getAlignment(colIndex int, header bool, footer bool) Alignment {
switch {
case header:
Expand Down
27 changes: 27 additions & 0 deletions table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -465,3 +465,30 @@ func Test_Unicode(t *testing.T) {
└─────────────────────────────┴───┴───┘
`, "\n"+builder.String())
}

func TestCSV(t *testing.T) {

input := strings.NewReader(`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!"`)

builder := &strings.Builder{}
table := New(builder)
if err := table.LoadCSV(input, true); err != nil {
panic(err)
}
table.Render()

assert.Equal(t, `
┌────┬────────────┬────────────────────────────────────────────┐
│ 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! │
└────┴────────────┴────────────────────────────────────────────┘
`, "\n"+builder.String())
}

0 comments on commit ec18aaa

Please sign in to comment.