Merge pull request #196 from fiddlerwoaroof/fix/projection-identities
improvise-exdg/7xyx: a coordinate cell is CellId::Coordinate; FrameGroup::cat deleted
This commit is contained in:
+43
-13
@@ -614,14 +614,37 @@ broader than its reason — improvise-gcvb, which also records the two things
|
||||
that make it more than a one-liner: an inserted `+cat` column means the TUI
|
||||
does **not** advance, and `AddCategory` can abort.
|
||||
|
||||
### `CellId::Coordinate` — a drawn coordinate is not "no cell" (improvise-exdg)
|
||||
|
||||
A records-mode coordinate cell (the `Region` column holding `North`) used to
|
||||
project `None`. That was a **third** meaning of `None`, next to the padded slot
|
||||
and the blanked position: a visible cell that holds text and whose write
|
||||
belongs to the host. So absence was encoding a permission, the same conflation
|
||||
`Create` removed for the creating columns (improvise-poia). The pinning test,
|
||||
`a_coordinate_column_is_projected_with_no_identity`, asserted the bug and is
|
||||
gone.
|
||||
|
||||
`Coordinate` carries **nothing**. Editing a coordinate renames it across every
|
||||
measure cell in the row (gotcha 1), and no client composes that operation: it
|
||||
needs `record_col`, and the browser declines every records-mode edit before
|
||||
reaching a cell. Giving the variant a `RecordHash` would hand a client a
|
||||
surrogate with nothing to spend it on. The operand belongs with the command
|
||||
that consumes it, whenever that command exists. Nothing a client can do has
|
||||
changed. `render.rs::editable` is now an exhaustive `match` rather than a
|
||||
`matches!`, so the next variant has to be classified. `typed_cell_command`,
|
||||
`record_at_cursor` and `record_cell_at_cursor` still answer `None` for it.
|
||||
So paste onto a coordinate is still a silent `Upstream` in the browser. The
|
||||
TUI has declined it out loud since PR #184. That divergence is
|
||||
improvise-kkcy, and a named kind is what lets the browser decline deliberately
|
||||
now.
|
||||
|
||||
### `CellDisplay::id` — `None` is not "aggregate"
|
||||
|
||||
That is `Some(CellId::Aggregate(..))`, and the distinction is the whole point
|
||||
of the enum. `None` means the slot holds **no projected cell**: a `GridCache`
|
||||
position padded by `fit_to_labels`, blanked by a reframing, or a
|
||||
records-mode column that is not a cell to write into at all (a category column
|
||||
renames a coordinate across the whole row, gotcha 1, which is a different
|
||||
intent from `SetCell`). Conflating the two either hides a cell or offers a
|
||||
position padded by `fit_to_labels`, or one blanked by a reframing. Every
|
||||
records-mode column is some kind of cell (`Record`, `Derived`, `Create` or
|
||||
`Coordinate`). Conflating the two either hides a cell or offers a
|
||||
write the type system exists to make unconstructible.
|
||||
|
||||
### `CellDisplay::edit_text` — the difference corrupts data
|
||||
@@ -637,8 +660,8 @@ and an editor's seed is exactly a feedback path.
|
||||
It is the projection of `App::display_value_at_cursor`, which is what
|
||||
`EditOrDrill` seeds the TUI's buffer from, so both front ends start from one
|
||||
string rather than each deriving one. `None` where there is nothing to edit:
|
||||
the same set of positions `id` is `None` for, plus cells whose value is
|
||||
absent. An error cell carries none, because its text is a diagnostic and not
|
||||
positions whose `id` is `None`, plus pivot cells with no key. A records-mode
|
||||
cell always carries one, even an empty one. An error cell carries none, because its text is a diagnostic and not
|
||||
a value.
|
||||
|
||||
A browser found this: `tests/lockstep.rs` drove `i` through the host and the
|
||||
@@ -785,9 +808,16 @@ one**. `AxisFrame::flat` leaves `cats` empty on purpose, so it is not a way to
|
||||
smuggle a multi-level axis in flattened.
|
||||
|
||||
`FrameGroup::collapsed` is on the wire rather than left to the client because
|
||||
it is a fact about the *view*, which only the server holds. `FrameGroup::cat`
|
||||
travels so a client can echo it back in `ToggleGroup` without ever working out
|
||||
which category a label came from — which slash-joined labels made impossible.
|
||||
it is a fact about the *view*, which only the server holds. There is no
|
||||
`FrameGroup::cat` any more (improvise-7xyx). Its doc comment promised that a
|
||||
client echoes it back in `ToggleGroup`, but no client ever did. `resolve.rs`
|
||||
has no `toggle-group-under-cursor` arm (`z` is on the still-needs-the-host
|
||||
list), and neither renderer read the field. A promise about an interaction no
|
||||
code performs is the stale-sibling defect, so the field went with it. It is
|
||||
not a loss for `z`. The TUI's `ToggleGroupAtCursor` also places the cursor on
|
||||
the layout the toggle *will produce*, which a thin client cannot compute. So
|
||||
composing `z` in a browser needs its own design, and the operand should come
|
||||
back with that design rather than wait for it.
|
||||
|
||||
### `AxisFrame`: four accessors that are **not for a draw loop**
|
||||
|
||||
@@ -1294,13 +1324,13 @@ frozen behaviour reads as decided afterwards and nothing says it was only frozen
|
||||
for the duration of the move.
|
||||
|
||||
**The ticket's own proposed fix does not work, and that is worth more than the
|
||||
fix.** h0iv suggested comparing the `(cat, name)` pair, `FrameGroup` carrying
|
||||
`cat` precisely so a client need not work out which category a label came from.
|
||||
fix.** h0iv suggested comparing the `(cat, name)` pair; `FrameGroup` carried
|
||||
`cat` then (improvise-7xyx has since removed it).
|
||||
But its own reachability case is *one* category: `Month` grouped into `Q1`,
|
||||
nested under `Region`, giving `North/Q1` and `South/Q1` adjacent — the two
|
||||
headers are `(Month, Q1)` and `(Month, Q1)`, **equal as values**, so the pair
|
||||
separates nothing. `the_two_headers_are_equal_as_values_so_comparing_cat_and_name_cannot_split_them`
|
||||
pins that, so the next reader does not re-propose it. What separates them is
|
||||
separates nothing. `the_two_headers_are_equal_as_values_so_comparing_them_cannot_split_them`
|
||||
pins that as whole-value equality, so the next reader does not re-propose it. What separates them is
|
||||
that they are two different `FrameEntry::Group` entries, and `groups()` already
|
||||
borrows each from `self.entries` — so the comparison is `std::ptr::eq` on the
|
||||
header, which is the literal statement of "the same header opened both".
|
||||
|
||||
Reference in New Issue
Block a user