Enter every row a read pins before walking on, and skip a cell outside an entered ancestor's row
Tests / vet + fmt + tests (pull_request) Successful in 1m8s
Tests / Gitea release from CHANGELOG.md (pull_request) Has been skipped

This commit is contained in:
2026-09-17 16:13:59 +02:00
parent aea7b72e4b
commit c314f9cb57
3 changed files with 34 additions and 15 deletions
+4 -3
View File
@@ -965,9 +965,10 @@ renamed or retyped line is a major.
- **The rows of a table are alternatives.** Only one row renders, so a cell in one
row and a cell in another never meet, and each may select its own row of another
table; the cells of one row, and whatever they reach, do meet, and so does the
format beside them. The family fence replays the reads of each row apart,
together with the reads outside any row. A choice's items get no such treatment
yet: two items selecting different rows are still refused.
format beside them. The rule the fence applies is that two reads meet unless
they sit in two rows of one table, or in a row outside a selected ancestor's. A
choice's items get no such treatment yet: two items selecting different rows
are still refused.
- **A path is walked once without drawing before it is walked for real.** A path
that fails below its first level then moves no seeded stream, at the cost of one
draw-free walk per call, which allocates nothing.
+20 -12
View File
@@ -363,8 +363,7 @@ func (w *drawWalk) walk(n node, at drawAt) {
}
for _, e := range renderEdges(n) {
if cell, isCell := e.to.(*template); isCell && cell.cellOf != nil {
// A row already entered renders only its own cell of this column.
if r, in := at.alt.rowOf(cell.cellOf); in && r != cell.cellRow {
if at.alt.excludes(cell) {
continue
}
w.edge(n, e, drawAt{at.group, at.route, at.alt.enter(cell.cellOf, cell.cellRow)})
@@ -374,22 +373,31 @@ func (w *drawWalk) walk(n node, at drawAt) {
}
}
// excludes reports whether a cell's row cannot render with the rows entered: another
// row of its table, or a row outside an entered ancestor's.
func (s rowSet) excludes(cell *template) bool {
for _, p := range s {
if p.t == cell.cellOf {
return p.row != cell.cellRow
}
if cell.cellOf.descends(p.t) && !cell.cellOf.under(cell.cellRow, p.t, p.row) {
return true
}
}
return false
}
// edge records the reference an edge reads, then walks on with every row the read
// pins entered, so a selected row renders only its own cells.
func (w *drawWalk) edge(from node, e renderEdge, at drawAt) {
var tr *tableRead
if a, reads := refRead(from, e.label); reads {
tr = tableReadOf(from.(*template).fields[a.key], a, e.to)
tr := tableReadOf(from.(*template).fields[a.key], a, e.to)
if k := (drawKey{at.group, a.path, at.alt.key()}); !w.read[k] {
w.read[k] = true
w.reads = append(w.reads, pathRead{at, a, tr})
}
}
// A read that pins the column's table renders that row's cell alone.
if c, isColumn := e.to.(*column); isColumn && tr != nil {
if r, pinned := tr.pins.pinned(c.t); pinned {
if cell := c.t.cellNode(r, c.i); cell != nil {
w.walk(cell, drawAt{at.group, at.route, at.alt.enter(c.t, r)})
}
return
if tr != nil {
tr.pins.each(func(t *table, r int) { at.alt = at.alt.enter(t, r) })
}
}
w.walk(e.to, at)
+10
View File
@@ -465,6 +465,16 @@ func (t *table) descendant(name string) *table {
// parentRow is the row of t's parent that row r links to.
func (t *table) parentRow(r int) int { return t.parentT.byKey[t.cell(r, t.parent)] }
// descends reports whether a is an ancestor of t.
func (t *table) descends(a *table) bool {
for p := t.parentT; p != nil; p = p.parentT {
if p == a {
return true
}
}
return false
}
// under reports whether row r of t sits inside row pr of ancestor a.
func (t *table) under(r int, a *table, pr int) bool {
for c, row := t, r; c.parentT != nil; c, row = c.parentT, c.parentRow(row) {