From a2bee8b49e66aaa7298201660fb4875faa34e1da Mon Sep 17 00:00:00 2001 From: Marco Arnulfo <103679419+marcoarnulfo@users.noreply.github.com> Date: Mon, 19 Oct 2026 08:30:56 +0200 Subject: [PATCH] LTSCALE typed at the command line asks for the scale factor (fixes #1194) (#1199) --- crates/engine/src/cmd/props.rs | 37 ++++++++++++++++++++++++++++++++-- crates/engine/src/tests.rs | 19 +++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/crates/engine/src/cmd/props.rs b/crates/engine/src/cmd/props.rs index 6e68a9d8..454756ff 100644 --- a/crates/engine/src/cmd/props.rs +++ b/crates/engine/src/cmd/props.rs @@ -11,7 +11,7 @@ use cadcraft_geom::Vec3; use serde_json::{Value, json}; use super::*; -use crate::{Result, Session}; +use crate::{Accept, Input, Interactive, Prompt, Result, Session, Step}; pub fn specs() -> Vec { vec![ @@ -30,7 +30,7 @@ pub fn specs() -> Vec { .noundo(), CommandSpec::new("-linetype", "Linetype", run_linetype).params("{current?, load?, file? | text?, reload?} (as LINETYPE)").interactive(|_| Ok(Box::new(linfile::DashLinetype::new()))), CommandSpec::new("lweight", "Lineweight...", run_lweight).menu(&["Format", "Lineweight..."]).alias(&["lw", "lineweight"]).params("{lineweight: mm | ByLayer}"), - CommandSpec::new("ltscale", "Linetype Scale", run_ltscale).alias(&["lts"]).params("{scale}"), + CommandSpec::new("ltscale", "Linetype Scale", run_ltscale).alias(&["lts"]).params("{scale}").interactive(|_| Ok(Box::new(LtscaleM))), CommandSpec::new("units", "Units...", run_units).menu(&["Format", "Units..."]).alias(&["un"]).params("{lunits?: 1..5, luprec?: 0..8, aunits?: 0..4, auprec?: 0..8, insunits?}"), CommandSpec::new("limits", "Drawing Limits", run_limits).menu(&["Format", "Drawing Limits"]).params("{min: [x,y], max: [x,y]}"), CommandSpec::new("style", "Text Style...", run_style) @@ -471,6 +471,39 @@ fn run_ltscale(s: &mut Session, p: &Value) -> Result { Ok(json!({ "message": "Regenerating model." })) } +/// Typed LTSCALE: "Enter new linetype scale factor <1.0000>:". +struct LtscaleM; + +impl Interactive for LtscaleM { + fn name(&self) -> &'static str { + "LTSCALE" + } + fn prompt(&self, s: &Session) -> Prompt { + let cur = s.doc().map(|d| d.header.f64("LTSCALE", 1.0)).unwrap_or(1.0); + Prompt::new("Enter new linetype scale factor", Accept::NUMBER).default(format!("{cur:.4}")) + } + fn input(&mut self, s: &mut Session, i: Input) -> Result { + let text = match i { + Input::Enter | Input::Cancel => return Ok(Step::Done), + Input::Text(t) => t, + _ => return Ok(Step::Continue), + }; + let scale = text.trim().parse::().ok().filter(|v| v.is_finite() && *v > 0.0); + match scale.map(|v| run_ltscale(s, &json!({ "scale": v }))) { + Some(Ok(r)) => { + if let Some(m) = r.get("message").and_then(Value::as_str) { + s.echo(m.to_string()); + } + Ok(Step::Done) + } + _ => { + s.echo("Requires a positive number."); + Ok(Step::Continue) + } + } + } +} + fn run_units(s: &mut Session, p: &Value) -> Result { let d = s.doc_mut()?; for (k, lo, hi) in [("lunits", 1, 5), ("luprec", 0, 8), ("aunits", 0, 4), ("auprec", 0, 8), ("insunits", 0, 24)] { diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index 93eba770..f205c2ea 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -1274,6 +1274,25 @@ fn bare_variable_name_runs_setvar() { assert!(s.cmdline("-pickadd").is_err()); } +#[test] +fn typed_ltscale_asks_for_the_scale() { + let mut s = Session::new(); + s.execute("setvar", &json!({"name": "LTSCALE", "value": 2.5})).unwrap(); + s.cmdline("ltscale").unwrap(); + assert!(s.prompt_text().contains("Enter new linetype scale factor <2.5000>"), "{}", s.prompt_text()); + // A scale that is not positive is refused and asked again. + s.cmdline("0").unwrap(); + assert!(s.current_prompt().is_some(), "asked again"); + s.cmdline("0.1").unwrap(); + assert!(s.current_prompt().is_none()); + assert_eq!(s.doc().unwrap().header.f64("LTSCALE", 0.0), 0.1); + // Enter keeps the current scale. + s.cmdline("lts").unwrap(); + s.cmdline("").unwrap(); + assert!(s.current_prompt().is_none()); + assert_eq!(s.doc().unwrap().header.f64("LTSCALE", 0.0), 0.1); +} + fn setvar_prompt_open(s: &Session) -> bool { s.running.as_ref().is_some_and(|r| r.id == "setvar") }