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:
Hakan SevenandClaude Opus 4.8 committed 2026-07-10 12:39:22 +03:00
1 parent f5b8a7d993
commit 91ba9f7699
69 files changed
+767 -164

No files matched your search

+35
View File
@@ -1,3 +1,4 @@
mod alias;
#[cfg(not(target_arch = "wasm32"))]
mod automation;
#[cfg(not(target_arch = "wasm32"))]
@@ -629,6 +630,16 @@ pub(super) struct OpenCADStudio {
/// User-defined function-key overrides: "F3" → command string.
shortcut_overrides: rustc_hash::FxHashMap<String, String>,
// ── Command Aliases ───────────────────────────────────────────────────
/// Command-line aliases: uppercase abbreviation → uppercase command
/// ("L" → "LINE"). Loaded from `ocad.pgp` at boot and consulted before
/// every dispatch (`resolve_alias`); user-editable via ALIASEDIT. See
/// [`alias`].
command_aliases: rustc_hash::FxHashMap<String, String>,
/// Working buffer for the ALIASEDIT modal: `(alias, command)` rows being
/// edited. Seeded from `command_aliases` on open, committed back on close.
alias_editor_rows: Vec<(String, String)>,
// ── Layout Manager Panel ──────────────────────────────────────────────
layout_manager_selected: String,
layout_manager_rename_buf: String,
@@ -1081,6 +1092,7 @@ pub enum ModalKind {
PointStyle,
AttributeEditor,
LayerDeleteWarning,
Aliases,
}
/// Identifies a DimStyle field that can be edited in the dialog.
@@ -1628,6 +1640,21 @@ pub enum Message {
ShortcutsPanelOpen,
#[allow(dead_code)]
ShortcutsPanelClose,
// ── Command Alias Editor (ALIASEDIT) ────────────────────────────────
/// Open the command-alias editor modal, seeding rows from the alias table.
AliasEditorOpen,
/// Live edit of the alias or command in row `idx`.
AliasEditorInput {
idx: usize,
field: crate::ui::window::alias_editor::AliasField,
value: String,
},
/// Append a blank alias row.
AliasEditorAdd,
/// Remove alias row `idx`.
AliasEditorRemove(usize),
/// Commit the edited rows to the alias table (Apply button); stays open.
AliasEditorApply,
// ── About window ────────────────────────────────────────────────────
AboutOpen,
/// Close whatever in-canvas modal dialog is open (Plan B).
@@ -2187,6 +2214,9 @@ impl OpenCADStudio {
active_theme: Theme::Dark,
// Keyboard shortcuts
shortcut_overrides: rustc_hash::FxHashMap::default(),
// Command aliases (populated from ocad.pgp just after construction)
command_aliases: rustc_hash::FxHashMap::default(),
alias_editor_rows: Vec::new(),
// Layout Manager
layout_manager_selected: "Model".to_string(),
layout_manager_rename_buf: String::new(),
@@ -2328,6 +2358,11 @@ impl OpenCADStudio {
if let Some(s) = settings::UserSettings::load() {
app.apply_settings(&s);
}
// Load command aliases from ocad.pgp (writes the shipped default file
// on first launch). The hide-set keeps aliases out of autocomplete while
// their target command still shows.
app.command_aliases = alias::load_aliases();
app.command_line.command_aliases = app.command_aliases.clone();
// Load external plugin packages from the plugins folder once, then fold
// their ribbon tabs into the ribbon. Skipped under test/wasm.
#[cfg(all(not(target_arch = "wasm32"), not(test)))]