Skip to main content

max / makeover-layout

Let an option say it is the chosen one A field carried one value and every renderer decided which option was selected by comparing that value to each. A description whose data already knows per row then has to collapse it to one string for the renderer to re-derive, which is the same fact stated twice. It is also the only form a compiled template can carry: a residual holds one body per loop, so "exactly one row differs" cannot be a property of the row body when the difference is decided by a comparison the body does not make. Said per option it is a branch inside the row. An option list marks itself or is matched against a value, never both. `#[non_exhaustive]` makes the new member additive, so this is a patch bump and no consumer pin moves.
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 13:40 UTC
Signed with PGP, not checked
Commit: 8c8ba7d36974de9302fd4445ca9bb4873a27bfc3
Parent: bb2b4e9
2 files changed, +42 insertions, -1 deletion
M Cargo.toml +1 -1
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "makeover-layout"
3 - version = "0.44.0"
3 + version = "0.44.1"
4 4 edition = "2024"
5 5 # One copy of this vocabulary per dependency graph, enforced by cargo rather
6 6 # than by remembering. Two versions of a description layer in one build means
@@ -97,6 +97,35 @@
97 97 /// put a block in one would be handing every host a layout problem for the
98 98 /// benefit of one.
99 99 pub detail: Option<&'a str>,
100 + /// Whether this is the option currently chosen.
101 + ///
102 + /// The alternative, and what every renderer here did before this member
103 + /// existed, is to compare the field's current value against each option's
104 + /// own. That reads the same and is not the same: it states which option is
105 + /// marked ONCE, at the field, and leaves each option to work out whether
106 + /// the sentence is about it. A description whose data already knows per row
107 + /// -- a theme list where each theme carries `selected` -- then has to
108 + /// collapse that to one string for the renderer to re-derive, which is one
109 + /// fact stated twice.
110 + ///
111 + /// # Never both
112 + ///
113 + /// An option list either marks itself here or is matched against the
114 + /// field's value, and a description that does both has said one thing two
115 + /// ways, which is how the two drift. quasi-declare refuses the pair at
116 + /// compile time. This crate cannot: it is handed a list and a value with no
117 + /// record of which spelling built them, so a renderer marks an option whose
118 + /// `chosen` is set OR whose value matches, and a caller that sets both gets
119 + /// both marked.
120 + ///
121 + /// # What it buys, beyond saying it once
122 + ///
123 + /// It is the only form a compiled template can carry. A residual holds one
124 + /// body per loop, so "exactly one row differs" cannot be a property of the
125 + /// row body when the difference is decided by a comparison the body does
126 + /// not make. Said here it is a branch inside the row, which is a shape a
127 + /// residual has.
128 + pub chosen: bool,
100 129 }
101 130
102 131 impl<'a> Choice<'a> {
@@ -119,6 +148,7 @@
119 148 label,
120 149 unavailable: None,
121 150 detail: None,
151 + chosen: false,
122 152 }
123 153 }
124 154
@@ -143,6 +173,17 @@
143 173 self
144 174 }
145 175
176 + /// The same option, marked as the one currently chosen.
177 + ///
178 + /// See [`chosen`](Self::chosen). Builder-shaped like the other two, and for
179 + /// the same reason: the marked option is one row of a list where every
180 + /// other row is not.
181 + #[must_use]
182 + pub const fn chosen(mut self) -> Self {
183 + self.chosen = true;
184 + self
185 + }
186 +
146 187 /// Whether the option can be picked right now.
147 188 ///
148 189 /// The predicate a renderer branches on, so that "unavailable" is read as