Skip to main content

max / audiofiles

Take quasi 0.104: walk a region's members through the body A region's members are reached by `Body::members` now rather than by indexing a Vec, because a selective region holds frames and a plain one holds ranked members. The test walkers take an iterator instead of a slice, which is what they wanted anyway: every one of them iterates once. No screen here carries a label, so nothing about what audiofiles draws changes.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session
https://claude.ai/code/session_01P8ostB2UmZJGj5WjSHRSot
Author: Max Johnson <me@maxj.phd> · 2026-09-08 00:50 UTC
Signed with PGP, not checked
Commit: fbdde5ee186d5384dacad9a328ef638cd7612c45
Parent: ccfa7b7
3 files changed, +44 insertions, -41 deletions
M Cargo.toml +2 -2
@@ -26,8 +26,8 @@
26 26 # The described screens, which are audiofiles-browser's screens. By git URL with
27 27 # a version requirement, per the tree's rule for cross-repo deps. They were
28 28 # behind a `quasi` feature until 2026-08-25, when the last flip landed.
29 - quasi-router = { git = "https://makenot.work/git/max/quasi.git", version = "0.103" }
30 - quasi-immediate = { git = "https://makenot.work/git/max/quasi.git", version = "0.103" }
29 + quasi-router = { git = "https://makenot.work/git/max/quasi.git", version = "0.104" }
30 + quasi-immediate = { git = "https://makenot.work/git/max/quasi.git", version = "0.104" }
31 31 quasi-declare = { git = "https://makenot.work/git/max/quasi.git", version = "0.1" }
32 32 egui = { version = "0.35", default-features = false, features = ["default_fonts"] }
33 33 egui_extras = { version = "0.35", default-features = false }
@@ -199,7 +199,7 @@
199 199 walk(&placed.node, &mut out);
200 200 }
201 201 }
202 - for placed in &slot.body {
202 + for placed in slot.body.iter() {
203 203 walk(&placed.node, &mut out);
204 204 }
205 205 }
@@ -308,7 +308,7 @@
308 308 }
309 309 }
310 310 Node::Region(slot) => {
311 - for placed in &slot.body {
311 + for placed in slot.body.iter() {
312 312 walk(&placed.node, out);
313 313 }
314 314 }
@@ -343,7 +343,7 @@
343 343 fn walk(node: &Node, out: &mut Vec<Node>) {
344 344 out.push(node.clone());
345 345 if let Node::Region(slot) = node {
346 - for placed in &slot.body {
346 + for placed in slot.body.iter() {
347 347 walk(&placed.node, out);
348 348 }
349 349 }
@@ -358,7 +358,7 @@
358 358 walk(&placed.node, &mut out);
359 359 }
360 360 }
361 - for placed in &slot.body {
361 + for placed in slot.body.iter() {
362 362 walk(&placed.node, &mut out);
363 363 }
364 364 }
@@ -565,8 +565,8 @@
565 565 /// 2026-09-06 collapse: both are `Node::Table`, so without the guard this takes
566 566 /// whichever comes first and the shell's own lists come first.
567 567 fn table_of(screen: &Screen) -> (Vec<quasi_router::Column>, Vec<quasi_router::Row>) {
568 - fn find(
569 - body: &[quasi_router::Ranked],
568 + fn find<'a>(
569 + body: impl Iterator<Item = &'a quasi_router::Ranked>,
570 570 ) -> Option<(Vec<quasi_router::Column>, Vec<quasi_router::Row>)> {
571 571 for placed in body {
572 572 match &placed.node {
@@ -574,7 +574,7 @@
574 574 return Some((columns.clone(), rows.clone()));
575 575 }
576 576 Node::Region(slot) => {
577 - if let Some(found) = find(&slot.body) {
577 + if let Some(found) = find(slot.body.iter()) {
578 578 return Some(found);
579 579 }
580 580 }
@@ -587,7 +587,7 @@
587 587 screen
588 588 .slots
589 589 .iter()
590 - .find_map(|slot| find(&slot.body))
590 + .find_map(|slot| find(slot.body.iter()))
591 591 .expect("the screen draws a table")
592 592 }
593 593
@@ -680,7 +680,7 @@
680 680 fn fields(screen: &Screen) -> BTreeMap<String, Option<String>> {
681 681 let mut found = BTreeMap::new();
682 682 for slot in &screen.slots {
683 - for placed in &slot.body {
683 + for placed in slot.body.iter() {
684 684 match &placed.node {
685 685 Node::Field(field) => {
686 686 found.insert(field.name.clone(), field.value.clone());
@@ -1117,7 +1117,7 @@
1117 1117 let picker = screen_of(&response)
1118 1118 .slots
1119 1119 .iter()
1120 - .flat_map(|slot| &slot.body)
1120 + .flat_map(|slot| slot.body.iter())
1121 1121 .find_map(|placed| match &placed.node {
1122 1122 Node::Field(field) if field.name == ConfigKey::Theme.as_str() => Some(field),
1123 1123 _ => None,
@@ -1457,7 +1457,7 @@
1457 1457 let carried: Vec<_> = screen_of(&response)
1458 1458 .slots
1459 1459 .iter()
1460 - .flat_map(|slot| &slot.body)
1460 + .flat_map(|slot| slot.body.iter())
1461 1461 .filter_map(|placed| match &placed.node {
1462 1462 Node::Form { fields, .. } => Some(fields.clone()),
1463 1463 _ => None,
@@ -1481,7 +1481,7 @@
1481 1481 let now = screen_of(&response)
1482 1482 .slots
1483 1483 .iter()
1484 - .flat_map(|slot| &slot.body)
1484 + .flat_map(|slot| slot.body.iter())
1485 1485 .find_map(|placed| match &placed.node {
1486 1486 Node::Act(act) if act.label == "Sync now" => Some(act),
1487 1487 _ => None,
@@ -1525,7 +1525,7 @@
1525 1525 let response = syncing(&sync, Request::get("/sync")).expect("answered");
1526 1526 let screen = screen_of(&response);
1527 1527
1528 - let said = screen.slots.iter().flat_map(|slot| &slot.body).any(
1528 + let said = screen.slots.iter().flat_map(|slot| slot.body.iter()).any(
1529 1529 |placed| matches!(&placed.node, Node::Notice { text, .. } if text.contains("said no")),
1530 1530 );
1531 1531 assert!(said, "{state:?} swallowed the error");
@@ -1545,7 +1545,7 @@
1545 1545 screen
1546 1546 .slots
1547 1547 .iter()
1548 - .flat_map(|slot| &slot.body)
1548 + .flat_map(|slot| slot.body.iter())
1549 1549 .flat_map(|placed| match &placed.node {
1550 1550 Node::Region(slot) => slot.body.iter().map(|inner| inner.node.clone()).collect(),
1551 1551 other => vec![other.clone()],
@@ -1574,7 +1574,7 @@
1574 1574 let region = screen_of(&response)
1575 1575 .slots
1576 1576 .iter()
1577 - .flat_map(|slot| &slot.body)
1577 + .flat_map(|slot| slot.body.iter())
1578 1578 .find_map(|placed| match &placed.node {
1579 1579 Node::Region(slot) if slot.id == "subscription" => Some(slot),
1580 1580 _ => None,
@@ -1685,7 +1685,7 @@
1685 1685 let meter = screen_of(&response)
1686 1686 .slots
1687 1687 .iter()
1688 - .flat_map(|slot| &slot.body)
1688 + .flat_map(|slot| slot.body.iter())
1689 1689 .flat_map(|placed| match &placed.node {
1690 1690 Node::Region(slot) => slot.body.iter().map(|inner| inner.node.clone()).collect(),
1691 1691 other => vec![other.clone()],
@@ -2565,7 +2565,7 @@
2565 2565 let stand_in = screen_of(&response)
2566 2566 .slots
2567 2567 .iter()
2568 - .flat_map(|slot| &slot.body)
2568 + .flat_map(|slot| slot.body.iter())
2569 2569 .find_map(|placed| match &placed.node {
2570 2570 Node::StandIn { message, act, .. } => Some((message.clone(), act.clone())),
2571 2571 _ => None,
@@ -4182,8 +4182,8 @@
4182 4182 /// the first it finds -- would assert about the Bulk group and call it the
4183 4183 /// whole screen.
4184 4184 fn shortcut_sections(screen: &Screen) -> Vec<(Option<String>, Vec<(String, String)>)> {
4185 - fn walk(
4186 - body: &[quasi_router::Ranked],
4185 + fn walk<'a>(
4186 + body: impl Iterator<Item = &'a quasi_router::Ranked>,
4187 4187 found: &mut Vec<(Option<String>, Vec<(String, String)>)>,
4188 4188 heading: &mut Option<String>,
4189 4189 ) {
@@ -4196,7 +4196,7 @@
4196 4196 .map(|row| (cell_text(row, 0), cell_text(row, 1)))
4197 4197 .collect(),
4198 4198 )),
4199 - Node::Region(slot) => walk(&slot.body, found, heading),
4199 + Node::Region(slot) => walk(slot.body.iter(), found, heading),
4200 4200 _ => {}
4201 4201 }
4202 4202 }
@@ -4205,7 +4205,7 @@
4205 4205 let mut found = Vec::new();
4206 4206 let mut heading = None;
4207 4207 for slot in &screen.slots {
4208 - walk(&slot.body, &mut found, &mut heading);
4208 + walk(slot.body.iter(), &mut found, &mut heading);
4209 4209 }
4210 4210 found
4211 4211 }
@@ -4366,7 +4366,7 @@
4366 4366 /// address and nothing here sends a fragment any more.
4367 4367 fn tab_strip(screen: &Screen) -> &quasi_router::Slot {
4368 4368 fn find(slot: &quasi_router::Slot) -> Option<&quasi_router::Slot> {
4369 - if slot.showing.selective() {
4369 + if slot.showing().selective() {
4370 4370 return Some(slot);
4371 4371 }
4372 4372 slot.body.iter().find_map(|placed| match &placed.node {
@@ -4393,7 +4393,7 @@
4393 4393 let strip = tab_strip(overlay(&response));
4394 4394
4395 4395 assert_eq!(strip.labels(), vec!["Shortcuts", "Features"]);
4396 - for placed in &strip.body {
4396 + for placed in strip.body.iter() {
4397 4397 let Node::Region(panel) = &placed.node else {
4398 4398 panic!("a tab is not a region: {:?}", placed.node);
4399 4399 };
@@ -4420,11 +4420,11 @@
4420 4420 let response = helping(Request::get("/help")).unwrap();
4421 4421 let strip = tab_strip(overlay(&response));
4422 4422
4423 - let Node::Region(features) = &strip.body[1].node else {
4423 + let Node::Region(features) = &strip.body.get(1).expect("a second member").node else {
4424 4424 panic!("the second tab is not a region");
4425 4425 };
4426 4426 assert!(matches!(
4427 - features.body.first().map(|placed| &placed.node),
4427 + features.body.get(0).map(|placed| &placed.node),
4428 4428 Some(Node::Rich { .. })
4429 4429 ));
4430 4430 }
@@ -5130,7 +5130,7 @@
5130 5130 .slots
5131 5131 .iter()
5132 5132 .filter(|slot| slot.id == "library-side")
5133 - .flat_map(|slot| &slot.body)
5133 + .flat_map(|slot| slot.body.iter())
5134 5134 .find_map(|placed| match &placed.node {
5135 5135 Node::Heading { text, .. } => {
5136 5136 under_tags = text == "Tags";
@@ -6557,18 +6557,21 @@
6557 6557 fn only_field(response: &Response) -> quasi_router::Field {
6558 6558 let screen = screen_of(response);
6559 6559 let mut found = Vec::new();
6560 - fn walk(body: &[quasi_router::Ranked], found: &mut Vec<quasi_router::Field>) {
6560 + fn walk<'a>(
6561 + body: impl Iterator<Item = &'a quasi_router::Ranked>,
6562 + found: &mut Vec<quasi_router::Field>,
6563 + ) {
6561 6564 for placed in body {
6562 6565 match &placed.node {
6563 6566 Node::Field(field) => found.push((**field).clone()),
6564 6567 Node::Form { fields, .. } => found.extend(fields.iter().cloned()),
6565 - Node::Region(slot) => walk(&slot.body, found),
6568 + Node::Region(slot) => walk(slot.body.iter(), found),
6566 6569 _ => {}
6567 6570 }
6568 6571 }
6569 6572 }
6570 6573 for slot in &screen.slots {
6571 - walk(&slot.body, &mut found);
6574 + walk(slot.body.iter(), &mut found);
6572 6575 }
6573 6576 assert_eq!(found.len(), 1, "{found:?}");
6574 6577 found.remove(0)
@@ -7692,7 +7695,7 @@
7692 7695 /// puts a field inside a group per folder and its review stage puts two panes
7693 7696 /// inside a split, so a test of either has to go down.
7694 7697 fn deep_nodes(screen: &Screen) -> Vec<Node> {
7695 - fn walk(body: &[quasi_router::Ranked], into: &mut Vec<Node>) {
7698 + fn walk<'a>(body: impl Iterator<Item = &'a quasi_router::Ranked>, into: &mut Vec<Node>) {
7696 7699 for placed in body {
7697 7700 into.push(placed.node.clone());
7698 7701 if let Node::Region(slot) = &placed.node {
@@ -7709,9 +7712,9 @@
7709 7712 /// answering about the body alone.
7710 7713 fn inside(slot: &quasi_router::Slot, into: &mut Vec<Node>) {
7711 7714 if let Some(run) = slot.run.as_ref() {
7712 - walk(&run.members, into);
7715 + walk(run.members.iter(), into);
7713 7716 }
7714 - walk(&slot.body, into);
7717 + walk(slot.body.iter(), into);
7715 7718 }
7716 7719
7717 7720 let mut found = Vec::new();
@@ -10044,13 +10047,13 @@
10044 10047 ) -> BTreeMap<String, (Option<String>, Option<String>, Option<String>)> {
10045 10048 let mut found = BTreeMap::new();
10046 10049 for slot in &screen.slots {
10047 - for placed in &slot.body {
10050 + for placed in slot.body.iter() {
10048 10051 let regions = match &placed.node {
10049 10052 Node::Region(region) => std::slice::from_ref(region),
10050 10053 _ => &[][..],
10051 10054 };
10052 10055 for region in regions {
10053 - for inner in &region.body {
10056 + for inner in region.body.iter() {
10054 10057 if let Node::Form { fields, .. } = &inner.node {
10055 10058 for field in fields {
10056 10059 if field.kind == quasi_router::layout::FieldKind::Interval {
@@ -10127,9 +10130,9 @@
10127 10130 /// One axis's field, by the name its lower end submits under.
10128 10131 fn axis_field(screen: &Screen, name: &str) -> quasi_router::Field {
10129 10132 for slot in &screen.slots {
10130 - for placed in &slot.body {
10133 + for placed in slot.body.iter() {
10131 10134 if let Node::Region(region) = &placed.node {
10132 - for inner in &region.body {
10135 + for inner in region.body.iter() {
10133 10136 if let Node::Form { fields, .. } = &inner.node {
10134 10137 for field in fields {
10135 10138 if field.name == name {
@@ -10229,10 +10232,10 @@
10229 10232 }
10230 10233 };
10231 10234 for slot in &screen.slots {
10232 - for placed in &slot.body {
10235 + for placed in slot.body.iter() {
10233 10236 visit(&placed.node);
10234 10237 if let Node::Region(region) = &placed.node {
10235 - for inner in &region.body {
10238 + for inner in region.body.iter() {
10236 10239 visit(&inner.node);
10237 10240 }
10238 10241 }
@@ -11676,7 +11679,7 @@
11676 11679 // Every slot says what takes it away, on itself: only the slot knows which
11677 11680 // one it is.
11678 11681 for group in [conditions, actions] {
11679 - for placed in &group.body {
11682 + for placed in group.body.iter() {
11680 11683 let Node::Region(slot) = &placed.node else {
11681 11684 panic!("a slot is not a region: {:?}", placed.node);
11682 11685 };