feat(editor): intellisense registry seam for the pro completion engine

This commit is contained in:
David Montero Crespo 2026-08-15 06:13:18 +02:00
parent 5b82299793
commit 55bc03d281
2 changed files with 50 additions and 0 deletions

View File

@ -2,6 +2,7 @@ import Editor from '@monaco-editor/react';
import { useEditorStore } from '../../store/useEditorStore';
import { useSimulatorStore } from '../../store/useSimulatorStore';
import { registerRetroAsm, LANGUAGE_ID as RETRO_ASM_ID } from './retroAsmLanguage';
import { attachIntellisenseMonaco } from '../../lib/intellisenseRegistry';
function getLanguage(filename: string): string {
const ext = filename.split('.').pop()?.toLowerCase() ?? '';
@ -62,6 +63,10 @@ export const CodeEditor = () => {
// Register the 8080/Z80 assembly language once so Monaco knows how
// to tokenize .s / .asm files when they're opened.
registerRetroAsm(monaco);
// Hand the monaco instance to the intellisense seam. Inert in OSS;
// with the pro overlay loaded it registers the completion engine
// (idempotent per monaco instance, so per-file remounts are fine).
attachIntellisenseMonaco(monaco);
}}
onChange={(value) => {
if (activeFileId) setFileContent(activeFileId, value || '');

View File

@ -0,0 +1,45 @@
/**
* Intellisense registry.
*
* Seam between the OSS editor and the pro overlay's code-completion engine
* (the private `velxio-intellisense` package). OSS ships no completion
* engine of its own, so without an overlay this registry is inert and the
* editor behaves exactly as before.
*
* Two-sided handshake, because arrival order is not guaranteed:
*
* - CodeEditor's `beforeMount` calls `attachIntellisenseMonaco(monaco)`
* every time an editor instance is created (which happens on every
* file switch — the editor is keyed by file id).
* - The overlay calls `installIntellisenseImpl(impl)` from `mountPro()`,
* which lands via an async `import('@pro/index')` and may resolve
* before or after the first editor mounted.
*
* Whichever side arrives last triggers the install. The impl itself is
* responsible for being idempotent per monaco instance (the package guards
* with a WeakSet), so replaying it on every mount is safe and cheap.
*/
type IntellisenseImpl = (monaco: unknown) => void;
let _impl: IntellisenseImpl | null = null;
let _monaco: unknown = null;
export function installIntellisenseImpl(impl: IntellisenseImpl | null): void {
_impl = impl;
if (_impl && _monaco) run(_impl, _monaco);
}
export function attachIntellisenseMonaco(monaco: unknown): void {
_monaco = monaco;
if (_impl) run(_impl, monaco);
}
function run(impl: IntellisenseImpl, monaco: unknown): void {
try {
impl(monaco);
} catch (err) {
// eslint-disable-next-line no-console
console.warn('[oss] intellisense impl threw:', err);
}
}