1package table
2
3// Data is the interface that wraps the basic methods of a table model.
4type Data interface {
5 // At returns the contents of the cell at the given index.
6 At(row, cell int) string
7
8 // Rows returns the number of rows in the table.
9 Rows() int
10
11 // Columns returns the number of columns in the table.
12 Columns() int
13}
14
15// StringData is a string-based implementation of the Data interface.
16type StringData struct {
17 rows [][]string
18 columns int
19}
20
21// NewStringData creates a new StringData with the given number of columns.
22func NewStringData(rows ...[]string) *StringData {
23 m := StringData{columns: 0}
24
25 for _, row := range rows {
26 m.columns = max(m.columns, len(row))
27 m.rows = append(m.rows, row)
28 }
29
30 return &m
31}
32
33// Append appends the given row to the table.
34func (m *StringData) Append(row []string) {
35 m.columns = max(m.columns, len(row))
36 m.rows = append(m.rows, row)
37}
38
39// At returns the contents of the cell at the given index.
40func (m *StringData) At(row, cell int) string {
41 if row >= len(m.rows) || cell >= len(m.rows[row]) {
42 return ""
43 }
44
45 return m.rows[row][cell]
46}
47
48// Columns returns the number of columns in the table.
49func (m *StringData) Columns() int {
50 return m.columns
51}
52
53// Item appends the given row to the table.
54func (m *StringData) Item(rows ...string) *StringData {
55 m.columns = max(m.columns, len(rows))
56 m.rows = append(m.rows, rows)
57 return m
58}
59
60// Rows returns the number of rows in the table.
61func (m *StringData) Rows() int {
62 return len(m.rows)
63}
64
65// Filter applies a filter on some data.
66type Filter struct {
67 data Data
68 filter func(row int) bool
69}
70
71// NewFilter initializes a new Filter.
72func NewFilter(data Data) *Filter {
73 return &Filter{data: data}
74}
75
76// Filter applies the given filter function to the data.
77func (m *Filter) Filter(f func(row int) bool) *Filter {
78 m.filter = f
79 return m
80}
81
82// At returns the row at the given index.
83func (m *Filter) At(row, cell int) string {
84 j := 0
85 for i := range m.data.Rows() {
86 if m.filter(i) {
87 if j == row {
88 return m.data.At(i, cell)
89 }
90
91 j++
92 }
93 }
94
95 return ""
96}
97
98// Columns returns the number of columns in the table.
99func (m *Filter) Columns() int {
100 return m.data.Columns()
101}
102
103// Rows returns the number of rows in the table.
104func (m *Filter) Rows() int {
105 j := 0
106 for i := range m.data.Rows() {
107 if m.filter(i) {
108 j++
109 }
110 }
111
112 return j
113}
114
115// DataToMatrix is a helper function that converts an object that implements the
116// Data interface into a table.
117func DataToMatrix(data Data) (rows [][]string) {
118 numRows := data.Rows()
119 numCols := data.Columns()
120 rows = make([][]string, numRows)
121
122 for i := range numRows {
123 rows[i] = make([]string, numCols)
124
125 for j := range numCols {
126 rows[i][j] = data.At(i, j)
127 }
128 }
129 return
130}