From 698f2c8c367f6f2210dbc3b1ce26c63cd89b0e84 Mon Sep 17 00:00:00 2001 From: Books Date: Sun, 11 Oct 2026 03:57:07 +1100 Subject: [PATCH] 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. --- crates/engine/src/lib.rs | 6 ++++++ crates/engine/src/tests.rs | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/crates/engine/src/lib.rs b/crates/engine/src/lib.rs index 412b3afdf..71b7c736a 100644 --- a/crates/engine/src/lib.rs +++ b/crates/engine/src/lib.rs @@ -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); diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index 98b21bbf6..446639b8f 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -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();