package table // Data is the interface that wraps the basic methods of a table model. type Data interface { // At returns the contents of the cell at the given index. At(row, cell int) string // Rows returns the number of rows in the table. Rows() int // Columns returns the number of columns in the table. Columns() int } // StringData is a string-based implementation of the Data interface. type StringData struct { rows [][]string columns int } // NewStringData creates a new StringData with the given number of columns. func NewStringData(rows ...[]string) *StringData { m := StringData{columns: 0} for _, row := range rows { m.columns = max(m.columns, len(row)) m.rows = append(m.rows, row) } return &m } // Append appends the given row to the table. func (m *StringData) Append(row []string) { m.columns = max(m.columns, len(row)) m.rows = append(m.rows, row) } // At returns the contents of the cell at the given index. func (m *StringData) At(row, cell int) string { if row >= len(m.rows) || cell >= len(m.rows[row]) { return "" } return m.rows[row][cell] } // Columns returns the number of columns in the table. func (m *StringData) Columns() int { return m.columns } // Item appends the given row to the table. func (m *StringData) Item(rows ...string) *StringData { m.columns = max(m.columns, len(rows)) m.rows = append(m.rows, rows) return m } // Rows returns the number of rows in the table. func (m *StringData) Rows() int { return len(m.rows) } // Filter applies a filter on some data. type Filter struct { data Data filter func(row int) bool } // NewFilter initializes a new Filter. func NewFilter(data Data) *Filter { return &Filter{data: data} } // Filter applies the given filter function to the data. func (m *Filter) Filter(f func(row int) bool) *Filter { m.filter = f return m } // At returns the row at the given index. func (m *Filter) At(row, cell int) string { j := 0 for i := 0; i < m.data.Rows(); i++ { if m.filter(i) { if j == row { return m.data.At(i, cell) } j++ } } return "" } // Columns returns the number of columns in the table. func (m *Filter) Columns() int { return m.data.Columns() } // Rows returns the number of rows in the table. func (m *Filter) Rows() int { j := 0 for i := 0; i < m.data.Rows(); i++ { if m.filter(i) { j++ } } return j } // dataToMatrix converts an object that implements the Data interface to a table. func dataToMatrix(data Data) (rows [][]string) { numRows := data.Rows() numCols := data.Columns() rows = make([][]string, numRows) for i := 0; i < numRows; i++ { rows[i] = make([]string, numCols) for j := 0; j < numCols; j++ { rows[i][j] = data.At(i, j) } } return }