Skip to content

Add a plugin extension point for the Explorer page's editor - #519

Open
jaysuk wants to merge 1 commit into
Duet3D:v3.7-devfrom
jaysuk:registerFileEditor
Open

jaysuk wants to merge 1 commit into
Duet3D:v3.7-devfrom
jaysuk:registerFileEditor

Conversation

@jaysuk

@jaysuk jaysuk commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds registerFileEditor() / unregisterFileEditor() (src/plugins/index.ts) so a plugin can register an alternative editor component for the Explorer page's editor tabs, in place of the built-in Monaco editor.

  • An entry matches by an absolute SD-card path predicate (matches: (path: string) => boolean) — the first registered match wins, and Monaco is always the fallback when nothing matches.
  • State lives in useUiStore() (a new fileEditors array, right next to the existing contextMenuItems), following the same pattern registerPluginContextMenuItem/registerEmbeddableComponent already use. src/plugins/index.ts is a thin wrapper over the store action, same as those two.
  • The Explorer page's own <MonacoEditor> tag becomes a dynamic <component :is="editorComponentFor(tab.filename)">, resolving against the registry with Monaco as the default.
  • A registered component must implement the exact same props/emits/exposed-methods contract Monaco's own editor already does — documented as FileEditorEntry / FileEditorInstance in stores/ui.ts. The Explorer page's own editorRefs map now types against FileEditorInstance directly instead of a private duplicate, so there's exactly one place that contract is written down.

Motivation

A plugin (dwc-gcode-editor) already exists that gives G-code files real syntax highlighting and diagnostics DWC's own generic Monaco integration has no way to provide (it isn't G-code-aware). One of its host plugins, Flexible Layouts, already lets users switch to it for G-code files specifically inside that plugin's own Explorer widget. Without this extension point, that switch can only ever apply there — it can't reach DWC's own native Explorer page at all, since there's currently no supported way for a plugin to affect which editor that page uses. This closes that gap the same way the existing context-menu/setting-tab/job-view-tab extension points already let a plugin extend other parts of DWC.

Testing

  • vue-tsc --noEmit and npm run build both pass.
  • No existing behaviour change for anyone who hasn't registered a file editor — editorComponentFor() falls through to MonacoEditor exactly as before when the registry is empty.
  • Not yet exercised: an actual registerFileEditor() call wired up end-to-end from dwc-gcode-editor's Flexible Layouts host, or manually clicked through in a running dev build against a real Explorer tab. I want to flag that honestly rather than imply it here — the extension point itself (registration, storage, dynamic-component resolution, the type contract) is what's under review; the follow-up plugin-side wiring and an end-to-end manual check are next, not yet done.

🤖 Generated with Claude Code

registerFileEditor()/unregisterFileEditor() (src/plugins/index.ts) let a plugin register
an alternative editor component for the Explorer page's editor tabs, matched by an
absolute SD-card path predicate - the first registered match wins, and DWC's own built-in
Monaco editor is always the fallback when nothing matches.

Mirrors the existing registerPluginContextMenuItem/registerEmbeddableComponent pattern:
state lives in useUiStore() (a new fileEditors array, next to the existing
contextMenuItems), the plugins module is a thin wrapper over the store action. The
Explorer page's own MonacoEditor tag becomes a dynamic <component :is="editorComponentFor(...)">,
resolving the same way.

A registered component must implement the exact same props/emits/exposed-methods contract
Monaco already does - documented as FileEditorEntry/FileEditorInstance in stores/ui.ts, and
the Explorer page's own editorRefs map now types against FileEditorInstance directly
instead of a private duplicate, so there is exactly one place that contract is stated.

Motivation: a plugin (dwc-gcode-editor, github.com/jaysuk/dwc-gcode-editor) already exists
that gives G-code files real syntax highlighting and diagnostics DWC's own generic Monaco
integration has no way to provide, and one of its host plugins (Flexible Layouts) already
lets users switch to it for G-code files specifically. Without this, that switch can only
ever apply inside that plugin's own Explorer widget - this lets it (or any other plugin)
extend DWC's own native Explorer page the same way.

vue-tsc --noEmit and npm run build both pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@chrishamm

Copy link
Copy Markdown
Collaborator

Thanks for the PR, but I don't want to merge this one in its current shape. Swapping out the whole editor component gets in the way of features that have to live inside the editor. Breakpoints and step-over are on the list for the Explorer editor, and everything they need (gutter clicks, current-line highlighting, file position to line mapping) is editor-internal. Once plugins can replace the component, I either have to turn that into a public contract every third-party editor must keep up with, or debugging stops working for exactly the .g files your predicate would claim.

What the plugin actually needs is a way to contribute G-code diagnostics to the built-in editor, so I'd rather add a hook for that: a diagnostics provider that DWC feeds into Monaco's markers, plus access to the Monaco namespace if you need it. The file size argument doesn't apply here either, the built-in editor already handles files up to 32 MiB and falls back to a textarea above that.

Two smaller things in case you keep this branch around: the component isn't markRaw'd like the other register* calls, and re-registering while an editor tab is open remounts it and drops unsaved changes.

@chrishamm chrishamm left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting this to changes requested so the state matches my comment above. The editor
component swap is the part I won't take. A diagnostics hook into the built-in editor
is what I would merge instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants