Panics · P23 Chat: a branch past its total shows none; parameters peg into range; matches outside a passage stay out
This commit is contained in:
1 parent
30fea9ecec
commit
0b8b74b968
4 files changed
+83
-17
No files matched your search
+25
-6
@@ -308,7 +308,7 @@ impl RenderOnce for MessageEditor {
|
||||
#[derive(IntoElement)]
|
||||
pub struct BranchNavigator {
|
||||
id: ElementId,
|
||||
current: usize,
|
||||
current: Option<usize>,
|
||||
total: usize,
|
||||
on_change: Pick,
|
||||
}
|
||||
@@ -320,10 +320,12 @@ impl BranchNavigator {
|
||||
total: usize,
|
||||
on_change: impl Fn(usize, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
assert!(current < total, "version {current} of {total}");
|
||||
if current >= total {
|
||||
log::error!("branch navigator: version {current} of {total}; none shown");
|
||||
}
|
||||
Self {
|
||||
id: id.into(),
|
||||
current,
|
||||
current: (current < total).then_some(current),
|
||||
total,
|
||||
on_change: Rc::new(on_change),
|
||||
}
|
||||
@@ -355,7 +357,7 @@ impl RenderOnce for BranchNavigator {
|
||||
"back",
|
||||
IconName::ChevronLeft,
|
||||
"Previous version",
|
||||
current.checked_sub(1),
|
||||
current.and_then(|current| current.checked_sub(1)),
|
||||
))
|
||||
.child(
|
||||
tabular(
|
||||
@@ -363,13 +365,30 @@ impl RenderOnce for BranchNavigator {
|
||||
.text_size(theme.text_size(TextSize::Xs))
|
||||
.text_color(theme.colors.fg_muted),
|
||||
)
|
||||
.child(format!("{} / {total}", current + 1)),
|
||||
.child(match current {
|
||||
Some(current) => format!("{} / {total}", current + 1),
|
||||
None => format!("– / {total}"),
|
||||
}),
|
||||
)
|
||||
.child(step(
|
||||
"forward",
|
||||
IconName::ChevronRight,
|
||||
"Next version",
|
||||
(current + 1 < total).then_some(current + 1),
|
||||
current.and_then(|current| (current + 1 < total).then_some(current + 1)),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::BranchNavigator;
|
||||
|
||||
#[test]
|
||||
fn a_version_past_the_branches_shows_none() {
|
||||
let navigator =
|
||||
|current, total| BranchNavigator::new("branch", current, total, |_, _, _| {});
|
||||
assert_eq!(navigator(1, 3).current, Some(1));
|
||||
assert_eq!(navigator(3, 3).current, None);
|
||||
assert_eq!(navigator(0, 0).current, None);
|
||||
}
|
||||
}
|
||||
+31
-4
@@ -58,15 +58,25 @@ impl ParameterPanel {
|
||||
parameters: impl IntoIterator<Item = Parameter>,
|
||||
on_change: impl Fn(&SharedString, f64, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
let parameters: Vec<Parameter> = parameters.into_iter().collect();
|
||||
for parameter in ¶meters {
|
||||
let mut parameters: Vec<Parameter> = parameters.into_iter().collect();
|
||||
for parameter in &mut parameters {
|
||||
assert!(
|
||||
parameter.min < parameter.max
|
||||
&& parameter.step > 0.0
|
||||
&& (parameter.min..=parameter.max).contains(¶meter.value),
|
||||
&& parameter.value.is_finite(),
|
||||
"parameter {} has a bad range",
|
||||
parameter.key
|
||||
);
|
||||
if !(parameter.min..=parameter.max).contains(¶meter.value) {
|
||||
log::error!(
|
||||
"parameters: {} at {} lies outside {}..={}; pegged",
|
||||
parameter.key,
|
||||
parameter.value,
|
||||
parameter.min,
|
||||
parameter.max
|
||||
);
|
||||
parameter.value = parameter.value.clamp(parameter.min, parameter.max);
|
||||
}
|
||||
}
|
||||
Self {
|
||||
id: id.into(),
|
||||
@@ -309,7 +319,7 @@ impl RenderOnce for SystemPromptEditor {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Parameter, cost, places};
|
||||
use super::{Parameter, ParameterPanel, cost, places};
|
||||
|
||||
#[test]
|
||||
fn cost_counts_tokens_at_their_prices() {
|
||||
@@ -351,4 +361,21 @@ mod tests {
|
||||
"float noise adds no places"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_value_outside_its_range_pegs() {
|
||||
let knob = |value| Parameter {
|
||||
key: "temperature".into(),
|
||||
label: "Temperature".into(),
|
||||
value,
|
||||
min: 0.0,
|
||||
max: 2.0,
|
||||
step: 0.1,
|
||||
hint: None,
|
||||
};
|
||||
let panel =
|
||||
ParameterPanel::new("knobs", [knob(3.5), knob(-1.0), knob(0.7)], |_, _, _, _| {});
|
||||
let values: Vec<f64> = panel.parameters.iter().map(|knob| knob.value).collect();
|
||||
assert_eq!(values, [2.0, 0.0, 0.7]);
|
||||
}
|
||||
}
|
||||
+26
-7
@@ -232,13 +232,19 @@ impl DocumentChunkPreview {
|
||||
text: impl Into<SharedString>,
|
||||
matched: Vec<Range<usize>>,
|
||||
) -> Self {
|
||||
let text = text.into();
|
||||
assert!(
|
||||
matched.iter().all(|range| range.end <= text.len()
|
||||
&& text.is_char_boundary(range.start)
|
||||
&& text.is_char_boundary(range.end)),
|
||||
"a match lies outside the passage"
|
||||
);
|
||||
let text: SharedString = text.into();
|
||||
let matched: Vec<Range<usize>> = matched
|
||||
.into_iter()
|
||||
.filter(|range| {
|
||||
let inside = text.get(range.clone()).is_some();
|
||||
if !inside {
|
||||
log::error!(
|
||||
"document chunk: match {range:?} lies outside the passage; left out"
|
||||
);
|
||||
}
|
||||
inside
|
||||
})
|
||||
.collect();
|
||||
assert!(
|
||||
matched.windows(2).all(|pair| pair[0].end <= pair[1].start),
|
||||
"matches come in order without overlapping"
|
||||
@@ -315,3 +321,16 @@ impl RenderOnce for DocumentChunkPreview {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::DocumentChunkPreview;
|
||||
|
||||
#[test]
|
||||
fn a_match_outside_the_passage_is_left_out() {
|
||||
let ranges = vec![1..2, 2..3, 3..9];
|
||||
let preview = DocumentChunkPreview::new("guide.md", "p. 2", "éabc", ranges);
|
||||
let kept = 2..3;
|
||||
assert_eq!(preview.matched, [kept]);
|
||||
}
|
||||
}
|
||||
@@ -88,3 +88,4 @@ One line per item: what changed, what stayed and why, review rounds.
|
||||
- P20: a hex selection off the bytes and a stack frame past the stack select none; a flame focus keeps what the profile holds; the timeline's wheel reports only finite, positive ranges from finite factors; a dump's last byte must have an address; flame paints log. Kept: disassembly patterns, `zoomed`'s contract. Review: 3 rounds.
|
||||
- P21: block editor listeners painted for a block, field, cell or kind since gone log and change nothing, a dropped picture drag leaves undo alone; a visual block press or edit over text the owner replaced is dropped; nested images parse; a version or find hit past its list selects none. Review: 4 rounds.
|
||||
- P22: annotations and suggestions outside their text log and stay out, picks and decisions keeping the owner's index; `accept` returns `Option`; a gone pick, active thread or followed peer logs; yours at no count comes off; a masked field clamps a stale offset, so remote cursors and selections draw. Kept: a thread's comments, presence max, one list's order, empty marks, constant role and mode tables. Review: 3 rounds.
|
||||
- P23: a branch version past its total logs and shows a dash, its arrows off; a parameter outside its range logs and pegs; a passage's matches outside it log and stay out. Kept: one-value contracts (progress, scores, shapes, peaks, levels, limits, prices, capacity, format, hour), the composer's trigger rows and stream reveal by construction; `places` skips zero, so `decimals` meets no zero step. Review: 2 rounds.
|
||||
Reference in new issue
Block a user