feat(plugin): AutoCAD-compatible PAUSE, ENTER keyword, and command streaming

This commit is contained in:
yztink committed 2026-09-20 21:03:12 -07:00
1 parent fd2062bdec
commit fbedb3736e
8 files changed
+250 -3

No files matched your search

+61 -3
View File
@@ -530,6 +530,7 @@ impl OpenCADStudio {
} else {
None
};
let is_escape = matches!(&input, StepInput::Escape);
let result: Option<CmdResult> = {
let Some(cmd) = self.tabs[i].active_cmd.as_mut() else {
return Task::none();
@@ -552,12 +553,58 @@ impl OpenCADStudio {
self.record_dimension_entity_points(i, None, handle, Vec::new());
}
self.sync_dimension_snaps(i);
match result {
if is_escape {
self.tabs[i].pending_pause_tokens = None;
}
let task = match result {
Some(r) => self.apply_cmd_result(r),
None => Task::none(),
};
if !is_escape && self.tabs[i].active_cmd.is_some() && self.tabs[i].pending_pause_tokens.is_some() {
let drain_task = self.drain_pending_pause_tokens(i);
Task::batch([task, drain_task])
} else {
task
}
}
/// Process queued tokens buffered after a PAUSE (or `\`) until the queue is
/// empty or another PAUSE / cancellation is encountered.
pub(super) fn drain_pending_pause_tokens(&mut self, tab_idx: usize) -> Task<Message> {
let Some(mut tokens) = self.tabs[tab_idx].pending_pause_tokens.take() else {
return Task::none();
};
let mut tasks = Vec::new();
while !tokens.is_empty() {
if self.tabs[tab_idx].active_cmd.is_none() {
break;
}
let token = tokens.remove(0);
let trimmed = token.trim();
if trimmed.eq_ignore_ascii_case("PAUSE") || trimmed == "\\" {
self.tabs[tab_idx].pending_pause_tokens = Some(tokens);
break;
}
if trimmed.is_empty()
|| trimmed.eq_ignore_ascii_case("ENTER")
|| trimmed.eq_ignore_ascii_case("RETURN")
|| trimmed == "\n"
{
tasks.push(self.feed_command(StepInput::Enter));
} else if trimmed.eq_ignore_ascii_case("ESC")
|| trimmed.eq_ignore_ascii_case("ESCAPE")
|| trimmed.eq_ignore_ascii_case("CANCEL")
{
self.tabs[tab_idx].pending_pause_tokens = None;
tasks.push(self.feed_command(StepInput::Escape));
break;
} else {
tasks.push(self.feed_active_cmd(&token));
}
}
Task::batch(tasks)
}
/// Run one whole command-line string. A single word or an inline-argument
/// command (`PDMODE 3`, `LAYER Walls`, `UCS Z 90` pasted as one line)
/// dispatches as-is; for a multi-token line whose first word starts an
@@ -624,10 +671,19 @@ impl OpenCADStudio {
let mut tasks = Vec::new();
// First token is the command verb itself; prompts start consuming after it.
let mut consumed = 1;
for tok in &tokens[1..] {
let mut paused = false;
for (idx, tok) in tokens[1..].iter().enumerate() {
if self.tabs[i].active_cmd.is_none() {
break;
}
let trimmed = tok.trim();
if trimmed.eq_ignore_ascii_case("PAUSE") || trimmed == "\\" {
let remainder: Vec<String> = tokens[1 + idx + 1..].to_vec();
self.tabs[i].pending_pause_tokens = Some(remainder);
consumed = tokens.len();
paused = true;
break;
}
tasks.push(self.feed_active_cmd(tok));
consumed += 1;
}
@@ -658,7 +714,9 @@ impl OpenCADStudio {
if consumed < tokens.len() {
self.command_line.unconsumed = tokens[consumed..].to_vec();
}
tasks.push(self.feed_command(StepInput::Enter));
if !paused {
tasks.push(self.feed_command(StepInput::Enter));
}
Task::batch(tasks)
}