diff --git a/compiler/NubLang.LSP/WorkspaceManager.cs b/compiler/NubLang.LSP/WorkspaceManager.cs index ba24be7..d921f10 100644 --- a/compiler/NubLang.LSP/WorkspaceManager.cs +++ b/compiler/NubLang.LSP/WorkspaceManager.cs @@ -54,12 +54,12 @@ public class WorkspaceManager(DiagnosticsPublisher diagnosticsPublisher, ILangua { var modules = Module.Collect(_syntaxTrees.Select(x => x.Value).ToList()); - foreach (var (documentUri, syntaxTree) in _syntaxTrees) + foreach (var (fsPath, syntaxTree) in _syntaxTrees) { var typeChecker = new TypeChecker(syntaxTree, modules); var result = typeChecker.Check(); - diagnosticsPublisher.Publish(documentUri, typeChecker.Diagnostics); - _compilationUnits[documentUri] = result; + diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics); + _compilationUnits[fsPath] = result; var generator = new Generator(result); var c = generator.Emit(); @@ -67,7 +67,7 @@ public class WorkspaceManager(DiagnosticsPublisher diagnosticsPublisher, ILangua server.SendNotification("nub/output", new { content = c, - uri = documentUri + path = fsPath }); } } diff --git a/vscode-lsp/src/extension.ts b/vscode-lsp/src/extension.ts index 79e6352..8f1a95e 100644 --- a/vscode-lsp/src/extension.ts +++ b/vscode-lsp/src/extension.ts @@ -3,6 +3,8 @@ import vscode from 'vscode'; import { LanguageClient, TransportKind } from 'vscode-languageclient/node'; let client: LanguageClient; +let outputPanel: vscode.WebviewPanel | undefined; +const outputCache = new Map(); export function activate(context: vscode.ExtensionContext) { const serverExecutable = path.join(context.asAbsolutePath('server'), "nublsp"); @@ -33,16 +35,128 @@ export function activate(context: vscode.ExtensionContext) { ); client.onNotification("nub/output", (params: { path: string, content: string }) => { + const normalizedPath = vscode.Uri.file(params.path).fsPath; + outputCache.set(normalizedPath, params.content); + if (outputPanel && vscode.window.activeTextEditor) { + const activePath = vscode.window.activeTextEditor.document.uri.fsPath; + if (activePath === normalizedPath) { + updateOutputPanel(params.content); + } + } }); - vscode.commands.registerCommand('nub.openOutput', async () => { + const openOutputCommand = vscode.commands.registerCommand('nub.openOutput', async () => { + const editor = vscode.window.activeTextEditor; + if (!editor) { + vscode.window.showWarningMessage('No active editor found'); + return; + } + + const filePath = editor.document.uri.fsPath; + const cachedOutput = outputCache.get(filePath); + + if (outputPanel) { + outputPanel.reveal(vscode.ViewColumn.Beside); + } else { + outputPanel = vscode.window.createWebviewPanel( + 'nubOutput', + 'C Output', + vscode.ViewColumn.Beside, + { + enableScripts: true, + retainContextWhenHidden: true + } + ); + + outputPanel.onDidDispose(() => { + outputPanel = undefined; + }); + } + + if (cachedOutput) { + updateOutputPanel(cachedOutput); + } else { + updateOutputPanel('// Waiting for C output...'); + } }); + const changeEditorSubscription = vscode.window.onDidChangeActiveTextEditor(editor => { + if (outputPanel && editor) { + const filePath = editor.document.uri.fsPath; + const cachedOutput = outputCache.get(filePath); + + if (cachedOutput) { + updateOutputPanel(cachedOutput); + } else { + updateOutputPanel('// No C output available for this file'); + } + } + }); + + context.subscriptions.push(openOutputCommand, changeEditorSubscription); + client.start(); } +function updateOutputPanel(content: string) { + if (!outputPanel) return; + + outputPanel.webview.html = getWebviewContent(content); +} + +function getWebviewContent(content: string): string { + const escapedContent = content + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + + return ` + + + + + Nub C Output + + + + +
${escapedContent}
+ + + + +`; +} + export function deactivate(): Thenable | undefined { if (!client) { return undefined;