forked from 1b-agent/opencadstudio-upstream
feat(view): -VIEW command-line form with the standard view presets
-VIEW asks "Enter an option [?/Delete/Orthographic/Restore/Save/sEttings/ Window]:" and takes the orthographic and isometric presets (TOP, BOTTOM, FRONT, BACK, LEFT, RIGHT, SWISO, SEISO, NEISO, NWISO, also with a leading underscore) directly, Orthographic asking for the face with <Top> as the default. Keyword prompts accept a leading underscore on their keywords. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
ff6e2a6613
commit
62ff1daade
3 files changed
+94
No files matched your search
@@ -760,6 +760,84 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
// -VIEW: the command-line form. Its presets set the standard
|
||||
// orthographic and isometric views; the rest are VIEW's verbs.
|
||||
"-VIEW" => {
|
||||
use crate::command::KeywordCommand;
|
||||
let c = KeywordCommand::new(
|
||||
"-VIEW",
|
||||
"Enter an option [?/Delete/Orthographic/Restore/Save/sEttings/Window]:",
|
||||
vec![
|
||||
("?", "?", None),
|
||||
("Delete", "DELETE", Some("Enter view name(s) to delete:")),
|
||||
("Orthographic", "ORTHOGRAPHIC", None),
|
||||
("Restore", "RESTORE", Some("Enter view name to restore:")),
|
||||
("Save", "SAVE", Some("Enter view name to save:")),
|
||||
],
|
||||
)
|
||||
.with_hidden(&["TOP", "BOTTOM", "FRONT", "BACK", "LEFT", "RIGHT", "SWISO", "SEISO", "NEISO", "NWISO"]);
|
||||
self.command_line.push_info(&c.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(c));
|
||||
}
|
||||
cmd if cmd.starts_with("-VIEW ") => {
|
||||
let words: Vec<String> = cmd["-VIEW ".len()..]
|
||||
.split_whitespace()
|
||||
.map(|word| word.trim_start_matches('_').to_ascii_uppercase())
|
||||
.collect();
|
||||
let first = words.first().map(String::as_str).unwrap_or("");
|
||||
let preset = |word: &str| -> Option<&'static str> {
|
||||
["TOP", "BOTTOM", "FRONT", "BACK", "LEFT", "RIGHT", "SWISO", "SEISO", "NEISO", "NWISO"]
|
||||
.into_iter()
|
||||
.find(|name| name.eq_ignore_ascii_case(word))
|
||||
};
|
||||
// The Orthographic face: Top/Bottom/Front/BAck/Left/Right.
|
||||
let face = |word: &str| -> Option<&'static str> {
|
||||
match word {
|
||||
"BA" | "BAC" | "BACK" => Some("BACK"),
|
||||
_ => ["TOP", "BOTTOM", "FRONT", "LEFT", "RIGHT"]
|
||||
.into_iter()
|
||||
.find(|name| !word.is_empty() && name.starts_with(word)),
|
||||
}
|
||||
};
|
||||
let orthographic = !first.is_empty() && "ORTHOGRAPHIC".starts_with(first);
|
||||
let view = if orthographic {
|
||||
match words.get(1) {
|
||||
Some(word) => face(word),
|
||||
None => {
|
||||
use crate::command::KeywordCommand;
|
||||
let c = KeywordCommand::new(
|
||||
"-VIEW ORTHOGRAPHIC",
|
||||
"Enter an option [Top/Bottom/Front/BAck/Left/Right]<Top>:",
|
||||
vec![
|
||||
("Top", "TOP", None),
|
||||
("Bottom", "BOTTOM", None),
|
||||
("Front", "FRONT", None),
|
||||
("BAck", "BACK", None),
|
||||
("Left", "LEFT", None),
|
||||
("Right", "RIGHT", None),
|
||||
],
|
||||
)
|
||||
.with_default("TOP");
|
||||
self.command_line.push_info(&c.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(c));
|
||||
return Some(self.finish_dispatch(cmd));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
preset(first)
|
||||
};
|
||||
if let Some(view) = view {
|
||||
self.command_line.push_output(crate::t!("Regenerating model.").as_ref());
|
||||
return self.dispatch_layerprops(&format!("VIEW {view}"), i);
|
||||
}
|
||||
if orthographic {
|
||||
self.command_line.push_error(crate::t!("Invalid option keyword.").as_ref());
|
||||
return Some(self.finish_dispatch(cmd));
|
||||
}
|
||||
// View names keep their case.
|
||||
let rest = cmd["-VIEW ".len()..].split_whitespace().skip(1).collect::<Vec<_>>().join(" ");
|
||||
return self.dispatch_layerprops(format!("VIEW {first} {rest}").trim_end(), i);
|
||||
}
|
||||
"VIEW" => {
|
||||
use crate::command::KeywordCommand;
|
||||
let c = KeywordCommand::new(
|
||||
|
||||
@@ -915,6 +915,7 @@ inventory::submit!(crate::command::CommandRegistration {
|
||||
"USERI",
|
||||
"USERR",
|
||||
"VIEW",
|
||||
"-VIEW",
|
||||
"VPORTS",
|
||||
"VS",
|
||||
"VW",
|
||||
|
||||
@@ -642,6 +642,9 @@ pub struct KeywordCommand {
|
||||
/// Keyword a bare Enter dispatches at the verb step (`<Default>` prompts,
|
||||
/// e.g. PLAN's `<Current>`). `None` = Enter cancels, as before.
|
||||
default: Option<&'static str>,
|
||||
/// Keywords taken at the verb step without being offered in the prompt
|
||||
/// (-VIEW's view presets).
|
||||
hidden: &'static [&'static str],
|
||||
}
|
||||
|
||||
impl KeywordCommand {
|
||||
@@ -651,6 +654,12 @@ impl KeywordCommand {
|
||||
self
|
||||
}
|
||||
|
||||
/// Keywords accepted at the verb step but not listed in the prompt.
|
||||
pub fn with_hidden(mut self, keywords: &'static [&'static str]) -> Self {
|
||||
self.hidden = keywords;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
name: &'static str,
|
||||
prompt: &'static str,
|
||||
@@ -662,6 +671,7 @@ impl KeywordCommand {
|
||||
options,
|
||||
pending: None,
|
||||
default: None,
|
||||
hidden: &[],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -734,6 +744,11 @@ impl CadCommand for KeywordCommand {
|
||||
// Consumed inputs that keep prompting return `Some(NeedPoint)` —
|
||||
// `None` would hand the same text to the command a second time.
|
||||
None => {
|
||||
// A leading underscore marks the English keyword, as in scripts.
|
||||
let t = t.strip_prefix('_').unwrap_or(t);
|
||||
if let Some(keyword) = self.hidden.iter().find(|keyword| keyword.eq_ignore_ascii_case(t)) {
|
||||
return Some(CmdResult::Dispatch(format!("{} {keyword}", self.name)));
|
||||
}
|
||||
let Some((_, keyword, value_prompt)) = match_cmd_option(&self.options, t) else {
|
||||
// Unknown verb — keep prompting rather than dispatch garbage.
|
||||
return Some(CmdResult::NeedPoint);
|
||||
|
||||
Reference in new issue
Block a user