cat / 012
clone

a spreadsheet for the terminal: lotus 1-2-3 looks, google sheets keys and formulas, one go binary

main
012 / internal / ui / nbgridstream.go
nbgridstream.go 2.7K
1package ui23import (4 "context"56 "src.rest/cat/012/internal/fileio"7 "src.rest/cat/012/internal/sheet"8)910// A cell run as a stream prints rows until it's stopped, and its output11// grows a few times a second. Its grid takes the rows that arrived12// under those it has (nbview.View.Carry) rather than being made again,13// so what the reader has done in it stays: the pointer, the selection,14// the rows as sorted (rows arriving go under them) and the filter, which15// covers the new rows when it covered the table to its end. Columns16// widen to fit the new rows' text as fitting the table fits it, never17// narrowing, and not while the grid has the keys, so the table doesn't18// shift under the pointer: they widen once it's left. A column the19// reader resized keeps its width.2021// Append adds more, a NUON table of n rows, under the grid's rows22// (nbview.Grid); data is the whole output, which a grid not made yet23// is made from.24func (g *outGrid) Append(more []byte, n int, data []byte) {25 g.data = data26 if g.child == nil {27 g.rows += n28 return29 }30 s := g.child.sheet31 from, cols := g.rows, g.cols32 rows, all, err := fileio.AppendTable(context.Background(), s, from, cols, more)33 if err != nil {34 g.child.note = "Rows the stream printed aren't a table: " + err.Error()35 }36 g.rows, g.cols = from+rows, max(all, cols)37 g.followFilter(from, cols)38 g.measure(from, cols)39 g.widen()40}4142// followFilter has the child's filter cover the rows and columns that43// arrived when it covered the table's last row, of from, and its last44// column, of cols, and applies it to them.45func (g *outGrid) followFilter(from, cols int) {46 s := g.child.sheet47 f := s.Filter()48 if f == nil {49 return50 }51 if f.Range.To.Row >= from {52 f.Range.To.Row = max(f.Range.To.Row, g.rows)53 }54 if f.Range.To.Col >= cols-1 {55 f.Range.To.Col = max(f.Range.To.Col, g.cols-1)56 }57 s.LoadFilter(f)58}5960// measure widens need to the text of the rows after row from, and of61// the header of the columns after the first cols.62func (g *outGrid) measure(from, cols int) {63 s := g.child.sheet64 for c := len(g.fit); c < g.cols; c++ {65 g.fit, g.need = append(g.fit, s.ColWidth(c)), append(g.need, 0)66 }67 for c := range g.cols {68 first := from + 169 if c >= cols {70 first = 071 }72 w := g.need[c]73 for r := first; r <= g.rows; r++ {74 w = max(w, sheet.FitWidth(s.ShownText(sheet.Addr{Col: c, Row: r})))75 }76 g.need[c] = w77 }78}7980// widen widens the columns to what their text needs, unless the grid81// has the keys: a column keeps a width the reader gave it.82func (g *outGrid) widen() {83 if g.Entered() {84 return85 }86 s := g.child.sheet87 for c, w := range g.need {88 if now := s.ColWidth(c); now == g.fit[c] && w > now {89 s.LoadColWidth(c, w)90 g.fit[c] = s.ColWidth(c)91 }92 }93}