Merge pull request #1423 from felixriestra:pr/python-host-model

The bundled `opencad.python` plugin drives OCS through plugin API v7: all
43 canvas entity kinds, the drawing tables, and OCS's own commands run
step by step. RustPython stays in the plugin process — the plugin crate is
outside the workspace with its own lock file, so the application's own
dependencies are unchanged.

Reconciled with the plugin command work that landed as #1425, which the
branch was written before:

- Both added `impl Drop for PluginProcessInteractiveAdapter`, which git
  merges silently into two impls that do not compile. One body now
  cancels the command and then drops it from the runner, in that order: a
  plugin waiting on a step has to be released before the runner forgets
  the command.
- `execute_command` (#1425) and `run_command` (#1423) are both routes from
  a script to the command line, and only the second was guarded. The
  SCRIPTCOMMANDS switch and the denylist are shared now, so neither route
  is the unguarded one.
- `run_command` dispatched with plugin dispatch still enabled, so a script
  naming a plugin command re-entered the plugin that was blocked waiting
  for it. It sets the suppression flag for the length of the dispatch, as
  `execute_command` does.

The denylist read the command as typed, while the dispatcher resolves
aliases: a user-defined `Q` for `QUIT` (ALIASEDIT writes those) walked
past it. It resolves the alias first.

Also: the active-command comparison ran on every message, a mouse move
included, allocating two strings for names that are already `&'static
str`; SCRIPTCOMMANDS' own messages go through the translation macros; and
`docs/.DS_Store` (now ignored) and an unrelated RTF note about constraint
commands are out of the tree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Opus 5 committed 2026-09-22 23:26:30 +03:00
commit 41ecc0c458
72 files changed
+30614 -91

No files matched your search

+11 -1
View File
@@ -35,7 +35,7 @@ mod record_api;
pub(crate) mod settings;
mod shortcuts;
mod startup;
mod style_ops;
pub(crate) mod style_ops;
mod text_inline;
mod tolerance_dialog;
mod update;
@@ -634,6 +634,8 @@ pub(super) struct OpenCADStudio {
/// Minutes between autosaves to a `.sv$` recovery file (SAVETIME command);
/// 0 disables autosave.
pub savetime_min: i32,
/// SCRIPTCOMMANDS: scripts may run OCS commands (see `UserSettings`).
pub script_commands: bool,
/// Persisted default viewport background, restored from settings and applied
/// to every drawing tab (new and opened) so a chosen background survives
/// restarts (#188). `None` = the built-in dark-grey / off-white defaults.
@@ -904,6 +906,11 @@ pub(super) struct OpenCADStudio {
/// `SelectionChangedV4` fires once per real change rather than per message.
#[cfg(not(target_arch = "wasm32"))]
last_plugin_selection: Option<(u64, u64)>,
/// `(tab id, geometry epoch)` last published to the V4 document view.
/// Built-in edits bypass HostSession, so this is checked at message
/// boundaries as well as after plugin-initiated writes.
#[cfg(not(target_arch = "wasm32"))]
last_plugin_document: Option<(u64, u64)>,
/// External add-on packages found in the plugins folder, refreshed when the
/// Plugin Manager opens.
external_plugins: Vec<crate::plugin::external::ExternalPlugin>,
@@ -4000,6 +4007,7 @@ impl OpenCADStudio {
suppress_plugin_dispatch: false,
constraint_bar_mode: 4095,
savetime_min: 10,
script_commands: true,
default_bg_color: None,
default_paper_bg_color: None,
cliprompt_lines: 3,
@@ -4101,6 +4109,8 @@ impl OpenCADStudio {
disabled_plugins: rustc_hash::FxHashSet::default(),
#[cfg(not(target_arch = "wasm32"))]
last_plugin_selection: None,
#[cfg(not(target_arch = "wasm32"))]
last_plugin_document: None,
external_plugins: Vec::new(),
loaded_plugin_ids: rustc_hash::FxHashSet::default(),
plugin_load_errors: rustc_hash::FxHashMap::default(),