forked from 1b-agent/opencadstudio-upstream
feat(userreg): prompt USERI/USERR for register then value
USERI/USERR set one of five integer/real header registers and needed both inputs (register + value) typed on one line; bare printed usage. Add a two-step front-end (UserRegCommand): it prompts for the register as 1–5 buttons, then the value, and dispatches USERI/USERR <n> <value> to the existing inline handler. The argument arm now requires a space so the bare name reaches the stepped command.
This commit is contained in:
1 parent
5f1019edec
commit
1533c66a3e
2 files changed
+79
-1
No files matched your search
@@ -135,7 +135,14 @@ impl OpenCADStudio {
|
||||
// even though we don't have a LISP / DIESEL runtime yet.
|
||||
// USERI 1 42 → header.user_int1 = 42
|
||||
// USERR 3 1.5e-3 → header.user_real3 = 0.0015
|
||||
cmd if cmd.starts_with("USERI") || cmd.starts_with("USERR") => {
|
||||
"USERI" | "USERR" => {
|
||||
use crate::command::UserRegCommand;
|
||||
let name = if cmd == "USERR" { "USERR" } else { "USERI" };
|
||||
let c = UserRegCommand::new(name);
|
||||
self.command_line.push_info(&c.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(c));
|
||||
}
|
||||
cmd if cmd.starts_with("USERI ") || cmd.starts_with("USERR ") => {
|
||||
let is_real = cmd.starts_with("USERR");
|
||||
let rest = if is_real {
|
||||
cmd.trim_start_matches("USERR").trim()
|
||||
|
||||
@@ -242,6 +242,77 @@ impl CadCommand for RenameCommand {
|
||||
}
|
||||
}
|
||||
|
||||
/// Interactive front-end for USERI / USERR — the five integer / real user
|
||||
/// registers in the drawing header. They take two inputs (which register, then
|
||||
/// the value), so they prompt for the register as clickable `1`–`5` buttons and
|
||||
/// then the value, and delegate to the inline `USERI <n> <value>` handler.
|
||||
pub struct UserRegCommand {
|
||||
/// `"USERI"` or `"USERR"`.
|
||||
name: &'static str,
|
||||
/// Chosen register 1–5 once the first step is answered.
|
||||
slot: Option<u8>,
|
||||
}
|
||||
|
||||
impl UserRegCommand {
|
||||
pub fn new(name: &'static str) -> Self {
|
||||
Self { name, slot: None }
|
||||
}
|
||||
}
|
||||
|
||||
impl CadCommand for UserRegCommand {
|
||||
fn name(&self) -> &'static str {
|
||||
self.name
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match self.slot {
|
||||
None => format!("{} which register? [1-5]:", self.name),
|
||||
Some(n) => format!("{}{n} new value:", self.name),
|
||||
}
|
||||
}
|
||||
|
||||
fn options(&self) -> Vec<CmdOption> {
|
||||
match self.slot {
|
||||
None => (1..=5).map(|n| CmdOption::new(&n.to_string(), &n.to_string())).collect(),
|
||||
Some(_) => Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn wants_text_input(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn on_text_input(&mut self, text: &str) -> Option<CmdResult> {
|
||||
let t = text.trim();
|
||||
if t.is_empty() {
|
||||
return None;
|
||||
}
|
||||
match self.slot {
|
||||
None => {
|
||||
// Accept a register 1–5; re-prompt on anything else.
|
||||
match t.parse::<u8>() {
|
||||
Ok(n @ 1..=5) => {
|
||||
self.slot = Some(n);
|
||||
None
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
// The inline handler validates the value (int vs real) and reports
|
||||
// usage if it doesn't parse, so just hand the whole line over.
|
||||
Some(n) => Some(CmdResult::Dispatch(format!("{} {n} {t}", self.name))),
|
||||
}
|
||||
}
|
||||
|
||||
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
}
|
||||
|
||||
// ── Result token ──────────────────────────────────────────────────────────
|
||||
|
||||
/// Returned by every `CadCommand` method to tell main.rs what to do.
|
||||
|
||||
Reference in new issue
Block a user