cat / 012
clone

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

Bars: glyph runs drawn with their roles' escape codes, kept for the frame

Dami committed a2e67f8
A frame of 8192 x 26 numbers under data bars and icons takes 0.27 / 1.5
/ 4.9 ms at 80x24 / 200x60 / 400x120, from 0.54 / 3.7 / 11.4 ms with a
style render per run (BenchmarkFrame bars-8192x26, median of 6). A
cell's own style (its text's, a copy marker's) is still rendered, as
its address isn't the theme's.
commit
a2e67f8801fa324033d0a9728de730efa9aab753
parent
1e399dd7be22ccf6b94405556d560bc8387cf6a0
author
Dami <dami.etoile@gmail.com>
kind
refactor risk score 1.4 of 3, Jev's estimate
5 files changed, +49 -5
Mdocs/contributing/limits.md14+++++++++++++-
Minternal/ui/bars.go31++++++++++++++++++++++++++----
Minternal/ui/model.go4++++
Minternal/ui/panel.go1+
Minternal/ui/theme/rules.go4++++
M docs/contributing/limits.md +13 -1
M internal/ui/bars.go +27 -4
@@ -76,15 +76,25 @@ func (m *Model) barText(sp rowtext.Span, w int, look *sheet.Look, base *lipgloss
7676 if look.Bar {7777 cover = theme.BarCover(look.BarLen, w-1) // the last column keeps bars apart7878 }79- text := spanStyle(&m.th, *base, sp)79+ text := base80+ if !plainSpan(sp) {81+ st := spanStyle(&m.th, *base, sp)82+ text = &st83+ }8084 var b strings.Builder8185 var run strings.Builder8286 var cur *lipgloss.Style8387 flush := func() {84- if run.Len() > 0 {88+ switch {89+ case run.Len() == 0:90+ case cur == base && !colored:91+ b.WriteString(run.String())92+ case cur == text || cur == base: // either may be the cell's own, made for it8593 b.WriteString(cur.Render(run.String()))86- run.Reset()94+ default: // a theme's role, whose address stays put for the frame95+ b.WriteString(m.shade(cur).Wrap(run.String()))8796 }97+ run.Reset()8898 }8999 put := func(role *lipgloss.Style, s string) {90100 if role != cur {
@@ -105,13 +115,26 @@ func (m *Model) barText(sp rowtext.Span, w int, look *sheet.Look, base *lipgloss
105115 case ch == " ":106116 put(base, ch)107117 default:108- put(&text, ch)118+ put(text, ch)109119 }110120 }111121 flush()112122 return b.String()113123 }114124 125+// shade is role with its escape codes, kept for the frame.126+func (m *Model) shade(role *lipgloss.Style) theme.Shade {127+ if sh, ok := m.shaded[role]; ok {128+ return sh129+ }130+ if m.shaded == nil {131+ m.shaded = map[*lipgloss.Style]theme.Shade{}132+ }133+ sh := theme.ShadeOf(*role)134+ m.shaded[role] = sh135+ return sh136+}137+115138 func coverAt(cover []int, x int) int {116139 if x < len(cover) {117140 return cover[x]
M internal/ui/model.go +4 -0
M internal/ui/panel.go +1 -0
M internal/ui/theme/rules.go +4 -0