Make SolveApp::start honour a command's enabled flag, and disable solid.move inside a sketch (#740)

`SolveApp::start` now honours a command's enabled flag, so shortcuts, the command palette and the control channel can't start a disabled command, and Move is disabled while a sketch is open.
This commit is contained in:
William Dunn authored and GitHub committed 2026-10-13 11:43:45 -04:00
1 parent 62a7f903f2
commit ff609bc320
8 files changed
+132 -4

No files matched your search

+15 -1
View File
@@ -34,6 +34,7 @@
//! - `{"note": "…"}`: a comment; `{"pending": "why"}`: the scenario waits for a fix (its test
//! is ignored)
//! - `{"expect": {…}}`: checks, see [`check`]; `{"until": {…}}` waits (frames) until they pass
//! (`"status"` takes a substring of the status line, or null for none)
//!
//! The same files drive the live app over the control channel for screenshots.
@@ -562,7 +563,8 @@ fn approx(got: f64, want: &Value, what: &str) -> Result<(), String> {
/// Checks: `bodies` (count), `volume` / `area` (total, number or [value, rel tol]), `faces`,
/// `features` (count), `errors` (timeline features in error, default 0), `dialog` (null: none
/// open, or a word its kind must contain), `tool` (null or command id), `sketching` (bool),
/// open, or a word its kind must contain), `tool` (null or command id), `status` (null, or a
/// substring of the status line), `sketching` (bool),
/// `selection` (count), `glyphs` ({constraint id: count}, none overlapping one another or a dimension value), `param` ({name: value}), `sketch_status` (solved|…), `dof`, `query`
/// ({command, params?, path, value}: a command's result).
pub fn check(h: &mut Harness, e: &Value) -> Result<(), String> {
@@ -760,6 +762,18 @@ pub fn check(h: &mut Harness, e: &Value) -> Result<(), String> {
return Err(format!("tool: got {}, want {v}", ui["tool"]));
}
}
"status" => {
// A substring of the status line's text, or null for no status at all.
let got = &ui["status"]["text"];
let ok = match v {
Value::Null => ui["status"].is_null(),
Value::String(w) => got.as_str().is_some_and(|g| g.contains(w.as_str())),
_ => false,
};
if !ok {
return Err(format!("status: got {}, want {v}", ui["status"]));
}
}
"glyphs" => {
// {constraint id: glyphs drawn for it}; glyphs never overlap one another.
let g = crate::sketch_tools::glyph_positions();