forked from 1b-agent/opencadstudio-upstream
feat(alias): centralize command aliases in user-editable ocad.pgp (#286/#288)
Command aliases (L→LINE, CC→COPYCLIP) were scattered across dispatch match arms and CommandRegistration name arrays. Move them all into a single user-editable file: - assets/ocad.pgp: shipped default alias table (ALIAS,*COMMAND format), embedded and copied to config/ocad.pgp on first launch; only that user copy is read after. AA→AREA default closes #286. - resolve_alias() rewrites the leading command token at the top of dispatch_command_inner, so aliases resolve for every path (families, plugins, Repeat menu). Args after the first space are untouched. - Autocomplete hides alias keys and, when the whole input is an alias, surfaces its target command as the top (highlighted) suggestion so the highlight matches what Enter runs (AA→AREA, L→LINE). - ALIASEDIT opens a new editor modal (add/edit/delete rows) with an Apply button; Apply persists to ocad.pgp, closing discards unapplied edits. - Strip alias tokens from all 8 dispatch match-arm files and 71 module CommandRegistration arrays, keeping canonical/synonym/distinct-command names. ocad.pgp is now the sole source: deleting or remapping an alias there takes effect. CUI stays on the keyboard-shortcut panel. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
f5b8a7d993
commit
91ba9f7699
69 files changed
+767
-164
No files matched your search
@@ -118,6 +118,12 @@ impl OpenCADStudio {
|
||||
self.attr_editor_selected = 0;
|
||||
self.attr_editor_tab = crate::ui::window::attribute_editor::AttrTab::Attribute;
|
||||
}
|
||||
// Closing (✕) discards edits made since the last Apply — matching the
|
||||
// style editors. Committing happens only through the Apply button.
|
||||
Some(Aliases) => {
|
||||
self.alias_editor_rows.clear();
|
||||
self.ribbon.deactivate_tool_if("ALIASEDIT");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
self.active_modal = None;
|
||||
@@ -2631,6 +2637,52 @@ impl OpenCADStudio {
|
||||
Task::none()
|
||||
}
|
||||
|
||||
// ── Command Alias Editor (ALIASEDIT) ──────────────────────────────
|
||||
Message::AliasEditorOpen => {
|
||||
// Seed the working buffer from the current table, sorted by alias
|
||||
// so the list is stable and diffable.
|
||||
let mut rows: Vec<(String, String)> = self
|
||||
.command_aliases
|
||||
.iter()
|
||||
.map(|(a, c)| (a.clone(), c.clone()))
|
||||
.collect();
|
||||
rows.sort_by(|a, b| a.0.cmp(&b.0));
|
||||
self.alias_editor_rows = rows;
|
||||
self.active_modal = Some(super::ModalKind::Aliases);
|
||||
Task::none()
|
||||
}
|
||||
Message::AliasEditorInput { idx, field, value } => {
|
||||
use crate::ui::window::alias_editor::AliasField;
|
||||
// Aliases and commands are stored uppercase; uppercasing as the
|
||||
// user types keeps display and the committed table consistent.
|
||||
let value = value.to_uppercase();
|
||||
if let Some(rowdata) = self.alias_editor_rows.get_mut(idx) {
|
||||
match field {
|
||||
AliasField::Alias => rowdata.0 = value,
|
||||
AliasField::Command => rowdata.1 = value,
|
||||
}
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::AliasEditorAdd => {
|
||||
self.alias_editor_rows.push((String::new(), String::new()));
|
||||
Task::none()
|
||||
}
|
||||
Message::AliasEditorRemove(idx) => {
|
||||
if idx < self.alias_editor_rows.len() {
|
||||
self.alias_editor_rows.remove(idx);
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::AliasEditorApply => {
|
||||
self.apply_alias_editor_rows();
|
||||
self.command_line.push_info(&format!(
|
||||
"{} alias(es) applied.",
|
||||
self.command_aliases.len()
|
||||
));
|
||||
Task::none()
|
||||
}
|
||||
|
||||
// ── About window ──────────────────────────────────────────────
|
||||
Message::AboutOpen => {
|
||||
self.active_modal = Some(super::ModalKind::About);
|
||||
|
||||
Reference in new issue
Block a user