Redraw edits made while a command is still running (fixes #4) (#22)

LINE and PLINE add geometry on every point, but the canvas only rebuilt
its display list when the drawing revision or the document pointer
changed. The revision was bumped when a command finished, and the
pointer changed only on the first copy-on-write edit, so only the first
segment appeared until the command ended. Session::feed now bumps the
revision after each input once the running command has changed the
drawing.
This commit is contained in:
Books
2026-10-10 12:57:07 -04:00
committed by GitHub
parent 8be4b9b01c
commit 698f2c8c36
2 changed files with 26 additions and 0 deletions
+6
View File
@@ -627,6 +627,12 @@ impl Session {
}
None => run.machine.begin(self),
};
// Redraw what the command has added so far (LINE adds a segment per point), not only when it ends.
if let Ok(st) = self.state_mut()
&& !Arc::ptr_eq(&run.before, &st.doc)
{
st.revision += 1;
}
match step {
Ok(Step::Continue) => {
self.running = Some(run);
+20
View File
@@ -25,6 +25,26 @@ fn line_via_command_line() {
assert_eq!(s.doc().unwrap().model.len(), 3);
}
#[test]
fn edits_while_a_command_runs_redraw() {
// The canvas rebuilds when (revision, doc pointer) changes; each new segment must change it (issue #4).
fn key(s: &Session) -> (u64, usize) {
let st = s.state().unwrap();
(st.revision, Arc::as_ptr(&st.doc) as usize)
}
let mut s = Session::new();
for (cmd, pts) in [("line", ["0,0", "10,0", "10,5", "0,5"]), ("pline", ["20,0", "30,0", "30,5", "20,5"])] {
s.cmdline(cmd).unwrap();
s.cmdline(pts[0]).unwrap();
for p in &pts[1..] {
let before = key(&s);
s.cmdline(p).unwrap();
assert_ne!(key(&s), before, "{cmd}: segment to {p} not redrawn");
}
s.cmdline("").unwrap();
}
}
#[test]
fn line_undo_option_and_aliases() {
let mut s = Session::new();