diff --git a/extensions/ipynb/package.json b/extensions/ipynb/package.json index 153e8a9e34e..87070d4dba2 100644 --- a/extensions/ipynb/package.json +++ b/extensions/ipynb/package.json @@ -1,123 +1,124 @@ { - "name": "ipynb", - "displayName": "%displayName%", - "description": "%description%", - "publisher": "vscode", - "version": "1.0.0", - "license": "MIT", - "engines": { - "vscode": "^1.57.0" - }, - "enabledApiProposals": [ - "documentPaste", - "diffContentOptions", - "dropMetadata" - ], - "activationEvents": [ - "onNotebook:jupyter-notebook" - ], - "extensionKind": [ - "workspace", - "ui" - ], - "main": "./out/ipynbMain.js", - "browser": "./dist/browser/ipynbMain.js", - "capabilities": { - "virtualWorkspaces": true, - "untrustedWorkspaces": { - "supported": true - } - }, - "contributes": { - "configuration": [ - { - "properties": { - "ipynb.pasteImagesAsAttachments.enabled": { - "type": "boolean", - "scope": "resource", - "markdownDescription": "%ipynb.pasteImagesAsAttachments.enabled%", - "default": true - } - } - } - ], - "commands": [ - { - "command": "ipynb.newUntitledIpynb", - "title": "%newUntitledIpynb.title%", - "shortTitle": "%newUntitledIpynb.shortTitle%", - "category": "Create" - }, - { - "command": "ipynb.openIpynbInNotebookEditor", - "title": "%openIpynbInNotebookEditor.title%" - }, - { - "command": "ipynb.cleanInvalidImageAttachment", - "title": "%cleanInvalidImageAttachment.title%" - } - ], - "notebooks": [ - { - "type": "jupyter-notebook", - "displayName": "Jupyter Notebook", - "selector": [ - { - "filenamePattern": "*.ipynb" - } - ], - "priority": "default" - } - ], - "notebookRenderer": [ - { - "id": "vscode.markdown-it-cell-attachment-renderer", - "displayName": "%markdownAttachmentRenderer.displayName%", - "entrypoint": { - "extends": "vscode.markdown-it-renderer", - "path": "./notebook-out/cellAttachmentRenderer.js" - } - } - ], - "menus": { - "file/newFile": [ - { - "command": "ipynb.newUntitledIpynb", - "group": "notebook" - } - ], - "commandPalette": [ - { - "command": "ipynb.newUntitledIpynb" - }, - { - "command": "ipynb.openIpynbInNotebookEditor", - "when": "false" - }, - { - "command": "ipynb.cleanInvalidImageAttachment", - "when": "false" - } - ] - } - }, - "scripts": { - "compile": "npx gulp compile-extension:ipynb && npm run build-notebook", - "watch": "npx gulp watch-extension:ipynb", - "build-notebook": "node ./esbuild" - }, - "dependencies": { - "@enonic/fnv-plus": "^1.3.0", - "detect-indent": "^6.0.0", - "uuid": "^8.3.2" - }, - "devDependencies": { - "@jupyterlab/nbformat": "^3.2.9", - "@types/markdown-it": "12.2.3", - "@types/uuid": "^8.3.1" - }, - "repository": { - "type": "git", - "url": "https://github.com/microsoft/vscode.git" - } + "name": "ipynb", + "displayName": "%displayName%", + "description": "%description%", + "publisher": "vscode", + "version": "1.0.0", + "license": "MIT", + "engines": { + "vscode": "^1.57.0" + }, + "enabledApiProposals": [ + "documentPaste", + "diffContentOptions", + "dropMetadata" + ], + "activationEvents": [ + "onNotebook:jupyter-notebook", + "onNotebook:interactive" + ], + "extensionKind": [ + "workspace", + "ui" + ], + "main": "./out/ipynbMain.js", + "browser": "./dist/browser/ipynbMain.js", + "capabilities": { + "virtualWorkspaces": true, + "untrustedWorkspaces": { + "supported": true + } + }, + "contributes": { + "configuration": [ + { + "properties": { + "ipynb.pasteImagesAsAttachments.enabled": { + "type": "boolean", + "scope": "resource", + "markdownDescription": "%ipynb.pasteImagesAsAttachments.enabled%", + "default": true + } + } + } + ], + "commands": [ + { + "command": "ipynb.newUntitledIpynb", + "title": "%newUntitledIpynb.title%", + "shortTitle": "%newUntitledIpynb.shortTitle%", + "category": "Create" + }, + { + "command": "ipynb.openIpynbInNotebookEditor", + "title": "%openIpynbInNotebookEditor.title%" + }, + { + "command": "ipynb.cleanInvalidImageAttachment", + "title": "%cleanInvalidImageAttachment.title%" + } + ], + "notebooks": [ + { + "type": "jupyter-notebook", + "displayName": "Jupyter Notebook", + "selector": [ + { + "filenamePattern": "*.ipynb" + } + ], + "priority": "default" + } + ], + "notebookRenderer": [ + { + "id": "vscode.markdown-it-cell-attachment-renderer", + "displayName": "%markdownAttachmentRenderer.displayName%", + "entrypoint": { + "extends": "vscode.markdown-it-renderer", + "path": "./notebook-out/cellAttachmentRenderer.js" + } + } + ], + "menus": { + "file/newFile": [ + { + "command": "ipynb.newUntitledIpynb", + "group": "notebook" + } + ], + "commandPalette": [ + { + "command": "ipynb.newUntitledIpynb" + }, + { + "command": "ipynb.openIpynbInNotebookEditor", + "when": "false" + }, + { + "command": "ipynb.cleanInvalidImageAttachment", + "when": "false" + } + ] + } + }, + "scripts": { + "compile": "npx gulp compile-extension:ipynb && npm run build-notebook", + "watch": "npx gulp watch-extension:ipynb", + "build-notebook": "node ./esbuild" + }, + "dependencies": { + "@enonic/fnv-plus": "^1.3.0", + "detect-indent": "^6.0.0", + "uuid": "^8.3.2" + }, + "devDependencies": { + "@jupyterlab/nbformat": "^3.2.9", + "@types/markdown-it": "12.2.3", + "@types/uuid": "^8.3.1" + }, + "repository": { + "type": "git", + "url": "https://github.com/microsoft/vscode.git" + } } diff --git a/src/vs/workbench/contrib/interactive/browser/interactive.contribution.ts b/src/vs/workbench/contrib/interactive/browser/interactive.contribution.ts index 104f9ad8f68..76d63678873 100644 --- a/src/vs/workbench/contrib/interactive/browser/interactive.contribution.ts +++ b/src/vs/workbench/contrib/interactive/browser/interactive.contribution.ts @@ -38,7 +38,7 @@ import { contrastBorder, listInactiveSelectionBackground, registerColor, transpa import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { EditorPaneDescriptor, IEditorPaneRegistry } from 'vs/workbench/browser/editor'; import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; -import { EditorExtensions, EditorsOrder, IEditorFactoryRegistry, IEditorSerializer } from 'vs/workbench/common/editor'; +import { EditorExtensions, EditorsOrder, IEditorFactoryRegistry, IEditorSerializer, IUntypedEditorInput } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { PANEL_BORDER } from 'vs/workbench/common/theme'; import { ResourceNotebookCellEdit } from 'vs/workbench/contrib/bulkEdit/browser/bulkCellEdits'; @@ -81,7 +81,8 @@ export class InteractiveDocumentContribution extends Disposable implements IWork constructor( @INotebookService notebookService: INotebookService, @IEditorResolverService editorResolverService: IEditorResolverService, - @IEditorService editorService: IEditorService + @IEditorService editorService: IEditorService, + @IInstantiationService private readonly instantiationService: IInstantiationService ) { super(); @@ -134,19 +135,36 @@ export class InteractiveDocumentContribution extends Disposable implements IWork { createEditorInput: ({ resource, options }) => { const data = CellUri.parse(resource); - let notebookUri: URI = resource; let cellOptions: IResourceEditorInput | undefined; if (data) { - notebookUri = data.notebook; cellOptions = { resource, options }; } const notebookOptions = { ...options, cellOptions } as INotebookEditorOptions; - const editorInput = editorService.getEditors(EditorsOrder.SEQUENTIAL).find(editor => editor.editor instanceof InteractiveEditorInput && editor.editor.resource?.toString() === notebookUri.toString()); + const editorInput = createEditor(resource, this.instantiationService); return { - editor: editorInput!.editor, + editor: editorInput, + options: notebookOptions + }; + }, + createUntitledEditorInput: ({ resource, options }) => { + if (!resource) { + throw new Error('Interactive window editors must have a resource name'); + } + const data = CellUri.parse(resource); + let cellOptions: IResourceEditorInput | undefined; + + if (data) { + cellOptions = { resource, options }; + } + + const notebookOptions = { ...options, cellOptions } as INotebookEditorOptions; + + const editorInput = createEditor(resource, this.instantiationService); + return { + editor: editorInput, options: notebookOptions }; } @@ -180,6 +198,15 @@ class InteractiveInputContentProvider implements ITextModelContentProvider { } } +function createEditor(resource: URI, instantiationService: IInstantiationService): EditorInput { + const counter = /\/Interactive-(\d+)/.exec(resource.path); + const inputBoxPath = counter && counter[1] ? `/InteractiveInput-${counter[1]}` : 'InteractiveInput'; + const inputUri = URI.from({ scheme: Schemas.vscodeInteractiveInput, path: inputBoxPath }); + const editorInput = InteractiveEditorInput.create(instantiationService, resource, inputUri); + + return editorInput; +} + class InteractiveWindowWorkingCopyEditorHandler extends Disposable implements IWorkbenchContribution, IWorkingCopyEditorHandler { constructor( @@ -207,12 +234,7 @@ class InteractiveWindowWorkingCopyEditorHandler extends Disposable implements IW } createEditor(workingCopy: IWorkingCopyIdentifier): EditorInput { - const counter = /\/Interactive-(\d+)/.exec(workingCopy.resource.path); - const inputBoxPath = counter && counter[1] ? `/InteractiveInput-${counter[1]}` : 'InteractiveInput'; - const inputUri = URI.from({ scheme: Schemas.vscodeInteractiveInput, path: inputBoxPath }); - const editorInput = InteractiveEditorInput.create(this._instantiationService, workingCopy.resource, inputUri); - - return editorInput; + return createEditor(workingCopy.resource, this._instantiationService); } private async _installHandler(): Promise { @@ -386,9 +408,9 @@ registerAction2(class extends Action2 { } } - const editorInput = InteractiveEditorInput.create(accessor.get(IInstantiationService), notebookUri, inputUri, title); historyService.clearHistory(notebookUri); - const editorPane = await editorService.openEditor(editorInput, editorOptions, group); + const editorInput: IUntypedEditorInput = { resource: notebookUri, options: editorOptions }; + const editorPane = await editorService.openEditor(editorInput, group); const editorControl = editorPane?.getControl() as { notebookEditor: NotebookEditorWidget | undefined; codeEditor: CodeEditorWidget } | undefined; // Extensions must retain references to these URIs to manipulate the interactive editor logService.debug('New interactive window opened. Notebook editor id', editorControl?.notebookEditor?.getId()); diff --git a/src/vs/workbench/contrib/interactive/browser/interactiveEditorInput.ts b/src/vs/workbench/contrib/interactive/browser/interactiveEditorInput.ts index 5fb0e0b5058..cf2347e417b 100644 --- a/src/vs/workbench/contrib/interactive/browser/interactiveEditorInput.ts +++ b/src/vs/workbench/contrib/interactive/browser/interactiveEditorInput.ts @@ -18,6 +18,7 @@ import { IInteractiveHistoryService } from 'vs/workbench/contrib/interactive/bro import { IResolvedNotebookEditorModel } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { ICompositeNotebookEditorInput, NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; +import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; export class InteractiveEditorInput extends EditorInput implements ICompositeNotebookEditorInput { static create(instantiationService: IInstantiationService, resource: URI, inputResource: URI, title?: string) { @@ -79,6 +80,7 @@ export class InteractiveEditorInput extends EditorInput implements ICompositeNot @IInteractiveHistoryService historyService: IInteractiveHistoryService, @INotebookService private readonly _notebookService: INotebookService, @IFileDialogService private readonly _fileDialogService: IFileDialogService, + @IExtensionService private readonly _extensionService: IExtensionService ) { const input = NotebookEditorInput.create(instantiationService, resource, 'interactive', {}); super(); @@ -136,6 +138,7 @@ export class InteractiveEditorInput extends EditorInput implements ICompositeNot return this._inputResolver; } + await this._extensionService.activateByEvent('onNotebook:interactive'); this._inputResolver = this._resolveEditorModel(); return this._inputResolver;