Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions docs/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -967,10 +967,7 @@ them is reached by the keys that reach any bead, the line opening to let the
selection in, so looking a bead up in another root is not paid for with the
put-back key. A search offers what it can take the reader to, which under this
mode is every bead the forest holds: the ones beneath the focused bead, and the
ones behind the line, which it opens on the way. The bead the forest is rooted
at reads its whole id where a root would, and the beads under it read as its
children: a column of shortened ids is read by putting the drawn root in front
of each one, and the root this branch came out of is behind the line. It names the key
ones behind the line, which it opens on the way. It names the key
that brings them back, because it is the line a reader is looking at when they
want them back, and a row with no room for that hint gives it up whole rather
than cutting it to a key nobody can press.
Expand Down Expand Up @@ -1985,13 +1982,16 @@ glyph, literal because `bd`'s are and do not move with the terminal's theme
escape for it and inheriting is what lets a row's own brightness reach its
glyph.

**An id is shown as what it adds to its root's**, `.20` for `smt-4kd3p.20`,
and kept whole where it does not carry that prefix followed by a dot — the
dangling and re-parented nodes, and the root itself — because a bare suffix
would place it under a root it does not belong to. **It is drawn in the colour
of the glyph beside it**, so a status arrives as a block a reader finds rather
than as the one column a glyph occupies; an open bead's id goes without a
colour for the same reason its glyph does.
**An id is shown as what it adds to the id above it**, `.20` for
`smt-4kd3p.20` drawn under `smt-4kd3p`, and kept whole where the row above it
does not carry its id followed by a dot — the dangling and re-parented nodes,
and a row with nothing above it — because a bare suffix would place it under a
parent it does not belong to. The rule holds at every depth, so walking up the
rows and joining what each says gives the whole id back, which is what makes a
column of them readable. **It is drawn in the colour of the glyph beside it**,
so a status arrives as a block a reader finds rather than as the one column a
glyph occupies; an open bead's id goes without a colour for the same reason its
glyph does.

**A ground and two tiers say how live a row is**, which is the one thing
about a bead `bd list` has no way to know and so the one thing this scale is
Expand Down
2 changes: 1 addition & 1 deletion src/view/draw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ mod tests {
}

pub(super) fn row(node: &Node) -> Row {
row::cells(node, "smt-4kd3p", None, None)
row::cells(node, Some("smt-4kd3p"), None, None)
}

/// A project whose roots all read, so its line is its name and its counts.
Expand Down
16 changes: 2 additions & 14 deletions src/view/forest/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ impl TreeLayout<'_> {
place: Some(root.clone()),
content: Content::Bead(row::cells(
node,
self.shortened_against(),
None,
bead.progress,
shut_over(bead.beneath, first_copy(self.tree, at, above), folded),
)),
Expand Down Expand Up @@ -769,7 +769,7 @@ impl TreeLayout<'_> {
place: Some(place.clone()),
content: Content::Bead(row::cells(
node,
self.shortened_against(),
Some(&parent.key().id),
bead.progress,
shut_over(bead.beneath, first, folded),
)),
Expand Down Expand Up @@ -805,18 +805,6 @@ impl TreeLayout<'_> {
Some(link.bead) != self.without
}

/// The id every row here is shortened against: the bead this drawing
/// starts at. A reader reads a column of suffixes by putting the drawn
/// root in front of each one, so the bead the forest is rooted at reads
/// whole and what hangs under it reads against that. The root it came out
/// of is behind the line, shortening what is drawn there.
fn shortened_against(&self) -> &str {
match self.rooted {
Some(rooted) => &rooted.place.steps.last().unwrap_or(&rooted.place.tree).id,
None => &self.tree.root,
}
}

/// What a run stands for: its members and everything beneath them. Walked
/// again where a bead is being left out, because the tree's own answer was
/// worked out over a run this drawing is not making and reaches beads it
Expand Down
80 changes: 62 additions & 18 deletions src/view/forest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2581,8 +2581,8 @@ credential_command = "secret harbour"
"▾ orbital",
" └── ○ tow-1 raise the tower",
" ├── ○ .1 stand the mast",
" │ └── ○ .1.1 bolt the sections",
" │ └── ○ .1.1.1 dress the cables",
" │ └── ○ .1 bolt the sections",
" │ └── ○ .1 dress the cables",
" └─▸ ○ .2 pour the base",
];

Expand Down Expand Up @@ -2625,8 +2625,8 @@ credential_command = "secret harbour"
"▾ orbital",
" └── ○ tow-1 raise the tower",
" ├── ○ .1 stand the mast",
" │ └── ○ .1.1 bolt the sections",
" │ └── ◐ .1.1.1 dress the cables",
" │ └── ○ .1 bolt the sections",
" │ └── ◐ .1 dress the cables",
" └─▸ ○ .2 pour the base",
]
);
Expand Down Expand Up @@ -2696,7 +2696,7 @@ credential_command = "secret harbour"
assert!(
sketch(&forest)
.iter()
.any(|line| line.contains(".1.1.1 dress the cables")),
.any(|line| line.contains(".1 dress the cables")),
"{:#?}",
sketch(&forest)
);
Expand Down Expand Up @@ -3204,10 +3204,10 @@ credential_command = "secret harbour"
" └── ◐ rly-2 re-site the relay",
" ├── ○ .1 trench the run",
" ├── ✓ .2 strike the old mast",
" │ └── ✓ .2.1 drop the guys",
" │ └── ◐ .2.1.1 cut the stays",
" │ └── ✓ .1 drop the guys",
" │ └── ◐ .1 cut the stays",
" ├── ✓ .4 lift the feeder",
" │ └── ✓ .4.1 coil the heliax",
" │ └── ✓ .1 coil the heliax",
" └─▸ … 4 more",
]
);
Expand Down Expand Up @@ -3608,9 +3608,9 @@ credential_command = "secret harbour"
" └── ◐ sdg-4 re-point the crossover",
" ├─▸ ◐ .3 re-signal the box",
" ├── ✓ .1 slew the up line",
" │ ├── ○ .1.2 weld the closure rail",
" │ ├─▸ ✓ .1.1 key the switch",
" │ └── ✓ .1.3 lift the old chairs",
" │ ├── ○ .2 weld the closure rail",
" │ ├─▸ ✓ .1 key the switch",
" │ └── ✓ .3 lift the old chairs",
" └─▸ ✓ .2 clip the down line",
]
);
Expand Down Expand Up @@ -5447,7 +5447,7 @@ credential_command = "secret harbour"
" └── ◐ slu-1 rehang the sluice",
" ├─▸ ◐ .1 forge the new pintles",
" └── ○ .2 hang the gate",
" └┄▸ ◐ .1 forge the new pintles",
" └┄▸ ◐ slu-1.1 forge the new pintles",
]
);

Expand All @@ -5459,14 +5459,53 @@ credential_command = "secret harbour"
"▾ orbital",
" └── ◐ slu-1 rehang the sluice",
" ├── ◐ .1 forge the new pintles",
" │ └── ○ .1.1 cast the pintle blanks",
" │ └── ○ .1 cast the pintle blanks",
" └── ○ .2 hang the gate",
" └┄┄ ◐ .1 forge the new pintles",
" └── ○ .1.1 cast the pintle blanks",
" └┄┄ ◐ slu-1.1 forge the new pintles",
" └── ○ .1 cast the pintle blanks",
]
);
}

/// A column of short ids is only readable if a reader can rebuild the
/// whole one from it: they put what the row above says in front of what
/// this row says, and stop at a row that reads whole because there is
/// nothing left to put in front of it. Over every bead these fixtures
/// draw, that walk gives back the id `bd` holds it under.
#[test]
fn walking_up_the_rows_and_joining_the_ids_gives_a_beads_whole_id_back() {
let fixtures = [
flatten(snapshot()),
flatten(tower_staffed(&["tow-1.1.1.1"])),
flatten(alone("orbital", SLUICE, &panes_on(&["slu-1.1"]))),
flatten(alone("orbital", RELAY, &two_panes())),
flatten(alone("orbital", SIDING, &panes_on(&["sdg-4.3"]))),
];

let mut shortened = 0;
for mut forest in fixtures {
forest.apply(Action::ExpandSubtree);
let mut above: Vec<String> = Vec::new();
for line in forest.lines() {
let (Some(place), Content::Bead(row)) = (&line.place, &line.content) else {
continue;
};
above.truncate(place.steps.len());
let rebuilt = match above.last() {
Some(parent) if row.id.starts_with('.') => format!("{parent}{}", row.id),
_ => row.id.clone(),
};

assert_eq!(rebuilt, place.key().id, "{:#?}", sketch(&forest));

shortened += usize::from(row.id.starts_with('.'));
above.push(rebuilt);
}
}

assert!(shortened > 0, "no row was drawn short to walk up from");
}

/// Four columns a level, every line in a forest with trees in it,
/// whatever that line is doing.
///
Expand Down Expand Up @@ -6556,13 +6595,18 @@ credential_command = "secret harbour"

/// The forest row is the one place `bdi` ever prints a shortened id —
/// `row::abbreviate` has no other caller — so on a long screen the short
/// id is the only spelling the reader has been shown. A substring is what
/// reaches it: `.1.1` is a prefix of nothing.
/// id is the only spelling the reader has been shown, and what they type
/// has to reach the bead they read it off. The query is taken from the row
/// rather than written out here, because a search matches on the whole id
/// and a query spelled by hand would pass on that alone.
///
/// A substring is what reaches it: the drawn form is a prefix of nothing.
#[test]
fn a_search_matches_the_shortened_id_the_row_draws() {
let mut forest = flatten(snapshot());
let drawn = row_of(&forest, "orb-7.1").id.clone();

assert_eq!(forest.seek(".1.1"), went_to("orbital", "orb-7.1.1", 1, 1));
assert_eq!(forest.seek(&drawn), went_to("orbital", "orb-7.1", 1, 4));
}

#[test]
Expand Down
Loading