Skip to main content

max / quasi

Let a list row say row-ness the way a table row does `Cells` gained `current` and the plural `menu` on 2026-09-02 and `Row` did not, although `Cells::current`'s own doc says the two carry the same fact under the same name. So a screen holding both a list and a table wrote one in the chain and the other by assignment, which is the drift that doc admits rather than keeps. `menu` takes the whole menu at once because the measured sites hand over a `Vec` they already have: audiofiles' file list builds one conditionally on how many rows are chosen, and pushing it act by act would take the condition apart. It extends, so it composes with the singular `offers`. Additive, so 0.101.1 stands. 192 lib tests, 1138 across the workspace.
Author: Max Johnson <me@maxj.phd> · 2026-09-03 15:31 UTC
Signed with PGP, not checked
Commit: 8f9c513293e11feb23e24d13a3a2552d3858d58b
Parent: 39abad7
1 file changed, +74 insertions, -0 deletions
@@ -6464,6 +6464,43 @@
6464 6464 self
6465 6465 }
6466 6466
6467 + /// Offer these acts on the row itself, rather than inside a part.
6468 + ///
6469 + /// The plural of [`offers`](Self::offers). [`Cells`] got this pair on
6470 + /// 2026-09-02 and this container did not, though [`Cells::current`]'s own
6471 + /// doc says the two carry the same facts under the same names, so a screen
6472 + /// mixing a list and a table had to write one of them in the chain and the
6473 + /// other by assignment.
6474 + ///
6475 + /// The whole menu at once, because the measured sites hand over a `Vec`
6476 + /// they already have: audiofiles' file list builds one conditionally on
6477 + /// how many rows are chosen, and pushing it act by act would take the
6478 + /// condition apart.
6479 + ///
6480 + /// [`Cells::current`]: Cells::current
6481 + #[must_use]
6482 + pub fn menu(mut self, acts: impl IntoIterator<Item = Act>) -> Self {
6483 + self.menu.extend(acts);
6484 + self
6485 + }
6486 +
6487 + /// This is the row being shown elsewhere.
6488 + ///
6489 + /// Was reachable only by assigning the field, which is why a row built by
6490 + /// a chain had to fall out of the chain to say it. [`Cells`] carries the
6491 + /// same fact under the same name and got its builder first; this is the
6492 + /// other half of that fix.
6493 + ///
6494 + /// The app's own pointer into a set, as distinct from
6495 + /// [`selected`](Self::selected), which is the user's tick. Conflating them
6496 + /// is what stopped a screen with bulk actions describing its checkboxes at
6497 + /// all, and that argument is on the field.
6498 + #[must_use]
6499 + pub const fn current(mut self, current: bool) -> Self {
6500 + self.current = current;
6501 + self
6502 + }
6503 +
6467 6504 /// How much of this row's set is done.
6468 6505 #[must_use]
6469 6506 pub fn meter(mut self, meter: Meter) -> Self {
@@ -10065,6 +10102,43 @@
10065 10102 );
10066 10103 }
10067 10104
10105 + /// A list row and a table row say the same facts the same way.
10106 + ///
10107 + /// [`Cells`] gained `current` and the plural `menu` on 2026-09-02 and
10108 + /// [`Row`] did not, although [`Cells::current`]'s own doc says the two
10109 + /// carry the same fact under the same name. So a screen holding both had to
10110 + /// write one in the chain and the other by assignment, which is the drift
10111 + /// that doc was written to admit rather than to keep.
10112 + ///
10113 + /// [`Cells::current`]: Cells::current
10114 + #[test]
10115 + fn a_list_row_and_a_table_row_say_row_ness_alike() {
10116 + let acts = || {
10117 + [
10118 + Act::new("Rename", Action::post("/rename")),
10119 + Act::new("Delete", Action::post("/delete")),
10120 + ]
10121 + };
10122 +
10123 + let row = Row::new("kick.wav").current(true).menu(acts());
10124 + let cells = Cells::new(["kick.wav"]).current(true).menu(acts());
10125 +
10126 + assert!(row.current);
10127 + assert!(cells.current);
10128 + assert_eq!(row.menu.len(), 2);
10129 + assert_eq!(cells.menu.len(), 2);
10130 +
10131 + // The plural extends rather than replacing, so it composes with the
10132 + // singular the way `Cells` does.
10133 + let row = row.offers(Act::new("Reveal", Action::local()));
10134 + assert_eq!(row.menu.len(), 3);
10135 +
10136 + // And neither is set until it is said.
10137 + let plain = Row::new("kick.wav");
10138 + assert!(!plain.current);
10139 + assert!(plain.menu.is_empty());
10140 + }
10141 +
10068 10142 /// Every fact a field carries is reachable without leaving the chain.
10069 10143 ///
10070 10144 /// Five members had no builder and were set by assigning the public field: