v2/tools/generator/internal/reporting/sparse_table.go (110 lines of code) (raw):
/*
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT license.
*/
package reporting
import (
"sort"
"strings"
)
type SparseTable struct {
// title for the entire table
title string
// rows contains the captions for each row
rows []string
// rowWidth is the length of the longest row caption
rowWidth int
// cols contains the captions for each column
cols []string
// colWidths contains the width required for each column, indexed by caption
colWidths map[string]int
// cells is the content for each cell, arranged per row, then per column
cells map[string]map[string]string
}
func NewSparseTable(title string) *SparseTable {
return &SparseTable{
title: title,
cells: make(map[string]map[string]string),
rowWidth: len(title),
colWidths: make(map[string]int),
}
}
// Rows returns a slice containing the captions of all the rows of the table
// A new slice is returned to avoid violations of encapsulation
func (table *SparseTable) Rows() []string {
var result []string
result = append(result, table.rows...)
return result
}
// AddRow adds the specified row to the table if it doesn't already exist
func (table *SparseTable) AddRow(row string) {
if table.indexOfRow(row) == -1 {
table.rows = append(table.rows, row)
if len(row) > table.rowWidth {
table.rowWidth = len(row)
}
}
}
// SortRows allows rows to be sorted by caption
func (table *SparseTable) SortRows(less func(top string, bottom string) bool) {
sort.Slice(table.rows, func(i, j int) bool {
return less(table.rows[i], table.rows[j])
})
}
// Columns returns a slice containing the captions of all the columns of the table
// A new slice is returned to avoid violations of encapsulation
func (table *SparseTable) Columns() []string {
var result []string
result = append(result, table.cols...)
return result
}
// AddColumn adds the specified column to the table if it doesn't already exist
func (table *SparseTable) AddColumn(col string) {
index := table.indexOfColumn(col)
if index == -1 {
table.cols = append(table.cols, col)
table.colWidths[col] = len(col)
}
}
// SortColumns allows columns to be sorted by caption
func (table *SparseTable) SortColumns(less func(left string, right string) bool) {
sort.Slice(table.cols, func(i, j int) bool {
return less(table.cols[i], table.cols[j])
})
}
// SetCell sets the content of a given cell of the table
func (table *SparseTable) SetCell(row string, col string, cell string) {
table.AddColumn(col)
table.AddRow(row)
rowCells := table.getRowCells(row)
rowCells[col] = cell
if len(cell) > table.colWidths[col] {
table.colWidths[col] = len(cell)
}
}
func (table *SparseTable) WriteTo(buffer *strings.Builder) {
headings := []string{
table.title,
}
headings = append(headings, table.cols...)
mt := NewMarkdownTable(headings...)
for _, r := range table.rows {
row := table.createRow(r)
mt.AddRow(row...)
}
mt.WriteTo(buffer)
}
func (table *SparseTable) getRowCells(row string) map[string]string {
if m, ok := table.cells[row]; ok {
return m
}
result := make(map[string]string)
table.cells[row] = result
return result
}
func (table *SparseTable) createRow(row string) []string {
result := []string{row}
cells := table.getRowCells(row)
for _, c := range table.cols {
content := cells[c]
result = append(result, content)
}
return result
}
func (table *SparseTable) indexOfRow(row string) int {
for i, r := range table.rows {
if r == row {
return i
}
}
return -1
}
func (table *SparseTable) indexOfColumn(col string) int {
for i, c := range table.cols {
if c == col {
return i
}
}
return -1
}