1package fileio23import (4 "bytes"5 "context"6 "errors"7 "io"8 "strings"910 "src.rest/cat/012/internal/nuon"11 "src.rest/cat/012/internal/sheet"12)1314// NUONRows reads NUON, a notebook cell's output, as a region's rows: a15// table's header and rows, a record as one row, a list of values that16// aren't records as one column named value, and any other value as that17// column with one row. It keeps at most maxCells cells, whole rows (018// for the max-cells setting), and says what it left out.19func NUONRows(ctx context.Context, data []byte, maxCells int) (TailRows, string, error) {20 data = bytes.TrimSpace(data)21 if len(data) == 0 {22 return TailRows{}, "", nil23 }24 if data[0] != '[' && data[0] != '{' {25 data = append(append([]byte("["), data...), ']')26 }27 res, err := ImportReader(ctx, "nu", bytes.NewReader(data), Options{MaxCells: maxCells})28 if err != nil {29 return TailRows{}, "", err30 }31 return Rows(res.Sheet), strings.Join(res.Notes, "; "), nil32}3334// NUONCell is the cell a NUON value makes: its value, text as the35// value's own, and its format (a file size's Size, a date's Date time,36// in the local time zone), as importing it would store it.37func NUONCell(v nuon.Value) sheet.LiveCell { return nuonCell(v, zone()) }3839// AppendTable reads data, a NUON table, into s as more rows of the table40// importing a table put there: under its row last, each value in the41// column its header row (row 0, cols columns) names, a column named for42// the first time added after the others with its name in the header,43// the cells as importing stores them. It leaves the widths alone and44// recalculates nothing, the cells being values, and returns the rows45// and the columns the table has now.46func AppendTable(ctx context.Context, s *sheet.Sheet, last, cols int, data []byte) (rows, allCols int, err error) {47 b := &builder{s: s, maxCells: -1}48 t := tableCells{b: b, cols: make(map[string]int, cols), zone: zone(), dated: map[int]bool{}, fixed: true}49 for c := range cols {50 t.cols[s.ShownText(sheet.Addr{Col: c})] = c51 }52 r := nuon.NewReader(bytes.NewReader(data))53 for ; ; rows++ {54 if rows%256 == 0 {55 if err := ctx.Err(); err != nil {56 return rows, len(t.cols), err57 }58 }59 fields, err := r.Next()60 if errors.Is(err, io.EOF) {61 return rows, len(t.cols), nil62 }63 if err != nil {64 return rows, len(t.cols), err65 }66 t.header(r.Header())67 t.row(last+rows+1, fields)68 }69}