cat / 012
clone

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

cat/module-path
012 / internal / sheet / refs.go
refs.go 2.5K
1package sheet23import "src.rest/cat/012/internal/formula"45// References in a stored formula are rewritten (see formula.Rewrite) by6// building a new cell: stored cells are never changed in place.78// withFormula returns a copy of c holding expression n, printed as its9// new input. Other fields (formats, say) come along unchanged.10func (c *Cell) withFormula(n Node) *Cell {11 cp := c.clone()12 cp.Input = formula.Text(n)13 cp.setExpr(n)14 return cp15}1617// rewritten returns c with its references rewritten, or c itself if none18// changed.19func (c *Cell) rewritten(rw formula.Rewriter) *Cell {20 if c.expr == nil || (len(c.refs) == 0 && len(c.ranges) == 0 && len(c.names) == 0 && len(c.xrefs) == 0) {21 return c22 }23 n, changed := formula.Rewrite(c.expr, rw)24 if !changed {25 return c26 }27 return c.withFormula(n)28}2930// NamedSheets returns the sheet names the formula at a names, as written31// and without repeats (in any case), or nil for anything else. Names of32// sheets that don't exist are included: exporters check them.33func (s *Sheet) NamedSheets(a Addr) []string {34 c := s.cells.get(a)35 if c == nil || len(c.xrefs) == 0 {36 return nil37 }38 var out []string39 seen := map[string]bool{}40 add := func(name string) {41 if k := formula.SheetKey(name); name != "" && !seen[k] {42 seen[k] = true43 out = append(out, name)44 }45 }46 formula.WalkRefs(c.expr, func(n string, _ Addr) { add(n) }, func(n string, _ Rect) { add(n) })47 return out48}4950// NamedTables returns the tables the formula at a reads by structured51// references, as written and without repeats (in any case), or nil for52// anything else. Exporters check that they write them.53func (s *Sheet) NamedTables(a Addr) []string {54 c := s.cells.get(a)55 if c == nil || c.expr == nil || len(c.names) == 0 {56 return nil57 }58 var out []string59 seen := map[string]bool{}60 formula.WalkTables(c.expr, func(t formula.TableRef) {61 if k := nameKey(t.Table); !seen[k] {62 seen[k] = true63 out = append(out, t.Table)64 }65 })66 return out67}6869// ShiftEntry returns an entry as if it were typed in one cell and copied70// dc columns and dr rows away: a formula's relative references move and71// $absolute ones stay, as in a paste. Other entries come back unchanged.72// A macro recorded with relative references replays formulas this way.73func ShiftEntry(input string, dc, dr int) (string, error) {74 if dc == 0 && dr == 0 || !IsFormulaEntry(input) {75 return input, nil76 }77 n, err := Parse(input)78 if err != nil {79 return "", err80 }81 if moved, changed := formula.Rewrite(n, formula.Shift(dc, dr)); changed {82 return formula.Text(moved), nil83 }84 return input, nil85}