diff --git a/extensions/notebook/package.json b/extensions/notebook/package.json index 603082502e..4278311614 100644 --- a/extensions/notebook/package.json +++ b/extensions/notebook/package.json @@ -98,14 +98,6 @@ "command": "notebook.command.analyzeNotebook", "title": "%notebook.analyzeJupyterNotebook%" }, - { - "command": "_notebook.command.new", - "title": "%notebook.command.new%", - "icon": { - "dark": "resources/dark/new_notebook_inverse.svg", - "light": "resources/light/new_notebook.svg" - } - }, { "command": "notebook.command.open", "title": "%notebook.command.open%" @@ -346,10 +338,6 @@ "command": "notebook.command.analyzeNotebook", "when": "false" }, - { - "command": "_notebook.command.new", - "when": "false" - }, { "command": "notebook.command.open" }, diff --git a/extensions/notebook/src/common/notebookUtils.ts b/extensions/notebook/src/common/notebookUtils.ts index 05952cd906..d0c0e3e665 100644 --- a/extensions/notebook/src/common/notebookUtils.ts +++ b/extensions/notebook/src/common/notebookUtils.ts @@ -19,10 +19,6 @@ export class NotebookUtils { constructor() { } - public async newNotebook(options?: azdata.nb.NotebookShowOptions): Promise { - return azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }), options); - } - public async openNotebook(): Promise { try { let filter: { [key: string]: Array } = {}; diff --git a/extensions/notebook/src/extension.ts b/extensions/notebook/src/extension.ts index 8ce2a1875b..a914a740e6 100644 --- a/extensions/notebook/src/extension.ts +++ b/extensions/notebook/src/extension.ts @@ -85,9 +85,6 @@ export async function activate(extensionContext: vscode.ExtensionContext): Promi return dialog.createDialog(); })); - extensionContext.subscriptions.push(vscode.commands.registerCommand('_notebook.command.new', async (options?: azdata.nb.NotebookShowOptions) => { - return appContext.notebookUtils.newNotebook(options); - })); extensionContext.subscriptions.push(vscode.commands.registerCommand('notebook.command.open', async () => { await appContext.notebookUtils.openNotebook(); })); diff --git a/extensions/notebook/src/jupyter/jupyterServerInstallation.ts b/extensions/notebook/src/jupyter/jupyterServerInstallation.ts index 47d9dd06a7..5cb278b1ca 100644 --- a/extensions/notebook/src/jupyter/jupyterServerInstallation.ts +++ b/extensions/notebook/src/jupyter/jupyterServerInstallation.ts @@ -906,7 +906,7 @@ export class JupyterServerInstallation implements IJupyterServerInstallation { nbformat_minor: constants.NBFORMAT_MINOR }; - await vscode.commands.executeCommand('_notebook.command.new', { + await vscode.commands.executeCommand('notebook.command.new', { initialContent: JSON.stringify(initialContent), defaultKernel: 'Python 3' }); diff --git a/extensions/notebook/src/test/common/notebookUtils.test.ts b/extensions/notebook/src/test/common/notebookUtils.test.ts index 74fcb734db..95345b6838 100644 --- a/extensions/notebook/src/test/common/notebookUtils.test.ts +++ b/extensions/notebook/src/test/common/notebookUtils.test.ts @@ -40,7 +40,7 @@ describe('notebookUtils Tests', function (): void { describe('newNotebook', function (): void { it('Should open a new notebook successfully', async function (): Promise { should(azdata.nb.notebookDocuments.length).equal(0, 'There should be not any open Notebook documents'); - await notebookUtils.newNotebook(undefined); + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' })); should(azdata.nb.notebookDocuments.length).equal(1, 'There should be exactly 1 open Notebook document'); await vscode.commands.executeCommand('workbench.action.closeActiveEditor'); should(azdata.nb.notebookDocuments.length).equal(0, 'There should be not any open Notebook documents'); @@ -48,12 +48,12 @@ describe('notebookUtils Tests', function (): void { it('Opening an untitled editor after closing should re-use previous untitled name', async function (): Promise { should(azdata.nb.notebookDocuments.length).equal(0, 'There should be not any open Notebook documents'); - await notebookUtils.newNotebook(undefined); + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' })); should(azdata.nb.notebookDocuments.length).equal(1, 'There should be exactly 1 open Notebook document'); should(azdata.nb.notebookDocuments[0].fileName).equal('Notebook-1', 'The first Untitled Notebook should have an index of 1'); await vscode.commands.executeCommand('workbench.action.closeActiveEditor'); should(azdata.nb.notebookDocuments.length).equal(0, 'There should be not any open Notebook documents'); - await notebookUtils.newNotebook(undefined); + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' })); should(azdata.nb.notebookDocuments.length).equal(1, 'There should be exactly 1 open Notebook document after second opening'); should(azdata.nb.notebookDocuments[0].fileName).equal('Notebook-1', 'The first Untitled Notebook should have an index of 1 after closing first Untitled Notebook'); await vscode.commands.executeCommand('workbench.action.closeActiveEditor'); @@ -61,10 +61,11 @@ describe('notebookUtils Tests', function (): void { it('Untitled Name index should increase', async function (): Promise { should(azdata.nb.notebookDocuments.length).equal(0, 'There should be not any open Notebook documents'); - await notebookUtils.newNotebook(undefined); + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' })); should(azdata.nb.notebookDocuments.length).equal(1, 'There should be exactly 1 open Notebook document'); - const secondNotebook = await notebookUtils.newNotebook(undefined); + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' })); should(azdata.nb.notebookDocuments.length).equal(2, 'There should be exactly 2 open Notebook documents'); + let secondNotebook = azdata.nb.activeNotebookEditor; should(secondNotebook.document.fileName).equal('Notebook-2', 'The second Untitled Notebook should have an index of 2'); await vscode.commands.executeCommand('workbench.action.closeActiveEditor'); await vscode.commands.executeCommand('workbench.action.closeActiveEditor'); @@ -94,9 +95,9 @@ describe('notebookUtils Tests', function (): void { }); it('closing and opening an untitled notebook shows correct contents', async function (): Promise { - await notebookUtils.newNotebook(); + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' })); await vscode.commands.executeCommand('workbench.action.closeActiveEditor'); - await notebookUtils.newNotebook({ + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }), { initialContent: { cells: [{ source: 'test content', @@ -183,7 +184,8 @@ describe('notebookUtils Tests', function (): void { }); it('does not show error when notebook visible for code cell', async function (): Promise { - const notebookEditor = await notebookUtils.newNotebook(undefined); + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' })); + const notebookEditor = azdata.nb.activeNotebookEditor; sinon.replaceGetter(azdata.nb, 'activeNotebookEditor', () => notebookEditor); await notebookUtils.addCell('code'); should(showErrorMessageSpy.notCalled).be.true('showErrorMessage should never be called'); @@ -192,7 +194,8 @@ describe('notebookUtils Tests', function (): void { }); it('does not show error when notebook visible for markdown cell', async function (): Promise { - const notebookEditor = await notebookUtils.newNotebook(undefined); + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' })); + const notebookEditor = azdata.nb.activeNotebookEditor; sinon.replaceGetter(azdata.nb, 'activeNotebookEditor', () => notebookEditor); await notebookUtils.addCell('markdown'); should(showErrorMessageSpy.notCalled).be.true('showErrorMessage should never be called'); @@ -203,7 +206,8 @@ describe('notebookUtils Tests', function (): void { describe('analyzeNotebook', function () { it('creates cell when oeContext exists', async function (): Promise { - const notebookEditor = await notebookUtils.newNotebook(undefined); + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' })); + const notebookEditor = azdata.nb.activeNotebookEditor; sinon.replaceGetter(azdata.nb, 'activeNotebookEditor', () => notebookEditor); sinon.stub(azdata.nb, 'showNotebookDocument').returns(Promise.resolve(notebookEditor)); const oeContext: azdata.ObjectExplorerContext = { @@ -226,7 +230,8 @@ describe('notebookUtils Tests', function (): void { }); it('does not create new cell when oeContext does not exist', async function (): Promise { - const notebookEditor = await notebookUtils.newNotebook(undefined); + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' })); + const notebookEditor = azdata.nb.activeNotebookEditor; sinon.replaceGetter(azdata.nb, 'activeNotebookEditor', () => notebookEditor); sinon.stub(azdata.nb, 'showNotebookDocument').returns(Promise.resolve(notebookEditor)); await notebookUtils.analyzeNotebook(); diff --git a/extensions/notebook/src/test/model/completionItemProvider.test.ts b/extensions/notebook/src/test/model/completionItemProvider.test.ts index 93909756f9..a45397a27d 100644 --- a/extensions/notebook/src/test/model/completionItemProvider.test.ts +++ b/extensions/notebook/src/test/model/completionItemProvider.test.ts @@ -63,7 +63,8 @@ describe('Completion Item Provider', function () { }); it('should not provide items when session does not exist in notebook provider', async () => { - let notebook = await notebookUtils.newNotebook(); + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' })); + const notebook = azdata.nb.activeNotebookEditor; await notebookUtils.addCell('code'); let document = await tryFindTextDocument(notebook); should(document).not.equal(undefined, 'Could not find text document that matched cell uri path'); @@ -75,7 +76,8 @@ describe('Completion Item Provider', function () { it('should not provide items when session list throws exception', async () => { mockSessionManager.setup(m => m.listRunning()).throws(new Error('Test Error')); - let notebook = await notebookUtils.newNotebook(); + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' })); + const notebook = azdata.nb.activeNotebookEditor; await notebookUtils.addCell('code'); let document = await tryFindTextDocument(notebook); @@ -86,7 +88,8 @@ describe('Completion Item Provider', function () { it('should not provide items when kernel does not exist in notebook provider', async () => { mockSessionManager.setup(m => m.listRunning()).returns(() => [mockJupyterSession.object]); - let notebook = await notebookUtils.newNotebook(); + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' })); + const notebook = azdata.nb.activeNotebookEditor; await notebookUtils.addCell('code'); let document = await tryFindTextDocument(notebook); @@ -102,7 +105,8 @@ describe('Completion Item Provider', function () { mockSessionManager.setup(m => m.listRunning()).returns(() => [mockJupyterSession.object]); mockJupyterSession.setup(s => s.path).returns(() => notebook.document.uri.path); - let notebook = await notebookUtils.newNotebook(); + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' })); + const notebook = azdata.nb.activeNotebookEditor; await notebookUtils.addCell('code'); let document = await tryFindTextDocument(notebook); @@ -145,7 +149,8 @@ describe('Completion Item Provider', function () { mockJupyterSession.setup(s => s.kernel).returns(() => kernel); mockSessionManager.setup(m => m.listRunning()).returns(() => [mockJupyterSession.object]); - let notebook = await notebookUtils.newNotebook(); + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' })); + const notebook = azdata.nb.activeNotebookEditor; await notebook.edit((editBuilder: azdata.nb.NotebookEditorEdit) => { editBuilder.insertCell({ cell_type: 'code', @@ -182,7 +187,8 @@ describe('Completion Item Provider', function () { mockJupyterSession.setup(s => s.kernel).returns(() => kernel); mockSessionManager.setup(m => m.listRunning()).returns(() => [mockJupyterSession.object]); - let notebook = await notebookUtils.newNotebook(); + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' })); + const notebook = azdata.nb.activeNotebookEditor; if (source) { await notebook.edit((editBuilder: azdata.nb.NotebookEditorEdit) => { editBuilder.insertCell({ diff --git a/extensions/notebook/src/test/model/jupyterController.test.ts b/extensions/notebook/src/test/model/jupyterController.test.ts index 128f2c4617..caf69bf73b 100644 --- a/extensions/notebook/src/test/model/jupyterController.test.ts +++ b/extensions/notebook/src/test/model/jupyterController.test.ts @@ -13,7 +13,6 @@ import { AppContext } from '../../common/appContext'; import { JupyterController } from '../../jupyter/jupyterController'; import { LocalPipPackageManageProvider } from '../../jupyter/localPipPackageManageProvider'; import { MockExtensionContext } from '../common/stubs'; -import { NotebookUtils } from '../../common/notebookUtils'; describe('Jupyter Controller', function () { let mockExtensionContext: vscode.ExtensionContext = new MockExtensionContext(); @@ -74,7 +73,7 @@ describe('Jupyter Controller', function () { should(showErrorMessageSpy.notCalled).be.true('showErrorMessage should not be called'); }); - it('Returns expected values from notebook provider', async () => { + it('Returns expected values from notebook provider', async () => { await controller.activate(); should(controller.executeProvider.providerId).equal('jupyter', 'Notebook provider should be jupyter'); await should(controller.executeProvider.getExecuteManager(undefined)).be.rejected(); @@ -82,10 +81,10 @@ describe('Jupyter Controller', function () { controller.executeProvider.handleNotebookClosed(undefined); }); - it('Returns execute manager for real notebook editor', async () => { + it('Returns execute manager for real notebook editor', async () => { await controller.activate(); - let notebookUtils = new NotebookUtils(); - const notebookEditor = await notebookUtils.newNotebook(undefined); + await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' })); + const notebookEditor = azdata.nb.activeNotebookEditor; let notebookManager = await controller.executeProvider.getExecuteManager(notebookEditor.document.uri); should(controller.executeProvider.executeManagerCount).equal(1); diff --git a/src/sql/workbench/api/browser/mainThreadNotebookDocumentsAndEditors.ts b/src/sql/workbench/api/browser/mainThreadNotebookDocumentsAndEditors.ts index 8b3bcef0eb..4824f2e33f 100644 --- a/src/sql/workbench/api/browser/mainThreadNotebookDocumentsAndEditors.ts +++ b/src/sql/workbench/api/browser/mainThreadNotebookDocumentsAndEditors.ts @@ -25,10 +25,9 @@ import { NotebookChangeType, CellTypes } from 'sql/workbench/services/notebook/c import { localize } from 'vs/nls'; import { IFileService } from 'vs/platform/files/common/files'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { NotebookEditor } from 'sql/workbench/contrib/notebook/browser/notebookEditor'; import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers'; import { SqlExtHostContext, SqlMainContext } from 'vs/workbench/api/common/extHost.protocol'; -import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService'; +import { NotebookEditor } from 'sql/workbench/contrib/notebook/browser/notebookEditor'; class MainThreadNotebookEditor extends Disposable { private _contentChangedEmitter = new Emitter(); @@ -323,7 +322,6 @@ export class MainThreadNotebookDocumentsAndEditors extends Disposable implements @INotebookService private readonly _notebookService: INotebookService, @IFileService private readonly _fileService: IFileService, @ITextFileService private readonly _textFileService: ITextFileService, - @IUntitledTextEditorService private readonly _untitledEditorService: IUntitledTextEditorService, ) { super(); if (extHostContext) { @@ -346,38 +344,9 @@ export class MainThreadNotebookDocumentsAndEditors extends Disposable implements } $tryShowNotebookDocument(resource: UriComponents, options: INotebookShowOptions): Promise { - // Append a numbered suffix if an untitled notebook is already open with the same path - if (resource.scheme === Schemas.untitled) { - if (!resource.path || this.untitledEditorTitleExists(resource.path)) { - resource.path = this.createPrefixedNotebookFilePath(resource.path); - } - } return Promise.resolve(this.doOpenEditor(resource, options)); } - private untitledEditorTitleExists(filePath: string): boolean { - return !!this._untitledEditorService.get(URI.from({ scheme: Schemas.untitled, path: filePath })); - } - - private createPrefixedNotebookFilePath(prefix?: string): string { - if (!prefix) { - prefix = 'Notebook'; - } - let prefixFileName = (counter: number): string => { - return `${prefix}-${counter}`; - }; - - let counter = 1; - // Get document name and check if it exists - let filePath = prefixFileName(counter); - while (this.untitledEditorTitleExists(filePath)) { - counter++; - filePath = prefixFileName(counter); - } - - return filePath; - } - $trySetTrusted(uriComponent: UriComponents, isTrusted: boolean): Promise { let uri = URI.revive(uriComponent); return this._notebookService.setTrusted(uri, isTrusted); diff --git a/src/sql/workbench/contrib/notebook/browser/notebookActions.ts b/src/sql/workbench/contrib/notebook/browser/notebookActions.ts index 58c868c48d..731461cd6f 100644 --- a/src/sql/workbench/contrib/notebook/browser/notebookActions.ts +++ b/src/sql/workbench/contrib/notebook/browser/notebookActions.ts @@ -17,7 +17,6 @@ import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilit import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile'; import { IConnectionDialogService } from 'sql/workbench/services/connection/common/connectionDialogService'; import { NotebookModel } from 'sql/workbench/services/notebook/browser/models/notebookModel'; -import { ICommandService } from 'vs/platform/commands/common/commands'; import { CellType, NotebookChangeType } from 'sql/workbench/services/notebook/common/contracts'; import { getErrorMessage } from 'vs/base/common/errors'; import { IEditorAction } from 'vs/editor/common/editorCommon'; @@ -839,13 +838,12 @@ export class NewNotebookAction extends Action { public static readonly ID = 'notebook.command.new'; public static readonly LABEL = localize('newNotebookAction', "New Notebook"); - public static readonly INTERNAL_NEW_NOTEBOOK_CMD_ID = '_notebook.command.new'; constructor( id: string, label: string, - @ICommandService private commandService: ICommandService, @IObjectExplorerService private objectExplorerService: IObjectExplorerService, @IAdsTelemetryService private _telemetryService: IAdsTelemetryService, + @INotebookService private _notebookService: INotebookService, ) { super(id, label); this.class = 'notebook-action new-notebook'; @@ -862,7 +860,7 @@ export class NewNotebookAction extends Action { } else if (context && context.connectionProfile) { connProfile = context.connectionProfile; } - return this.commandService.executeCommand(NewNotebookAction.INTERNAL_NEW_NOTEBOOK_CMD_ID, { connectionProfile: connProfile }); + await this._notebookService.openNotebook(URI.from({ scheme: 'untitled' }), { connectionProfile: connProfile }); } } diff --git a/src/sql/workbench/contrib/notebook/test/browser/notebookActions.test.ts b/src/sql/workbench/contrib/notebook/test/browser/notebookActions.test.ts index e41e23eb6a..e950710473 100644 --- a/src/sql/workbench/contrib/notebook/test/browser/notebookActions.test.ts +++ b/src/sql/workbench/contrib/notebook/test/browser/notebookActions.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import * as azdata from 'azdata'; import * as sinon from 'sinon'; import { TestConfigurationService } from 'sql/platform/connection/test/common/testConfigurationService'; -import { AddCellAction, ClearAllOutputsAction, CollapseCellsAction, CreateNotebookViewAction, DashboardViewAction, kernelNotSupported, KernelsDropdown, msgChanging, NewNotebookAction, noKernelName, noParameterCell, noParametersInCell, NotebookViewAction, NotebookViewsActionProvider, RunAllCellsAction, RunParametersAction, TrustedAction, untitledNotSupported } from 'sql/workbench/contrib/notebook/browser/notebookActions'; +import { AddCellAction, ClearAllOutputsAction, CollapseCellsAction, CreateNotebookViewAction, DashboardViewAction, kernelNotSupported, KernelsDropdown, msgChanging, noKernelName, noParameterCell, noParametersInCell, NotebookViewAction, NotebookViewsActionProvider, RunAllCellsAction, RunParametersAction, TrustedAction, untitledNotSupported } from 'sql/workbench/contrib/notebook/browser/notebookActions'; import { ClientSessionStub, ContextViewProviderStub, NotebookComponentStub, NotebookModelStub, NotebookServiceStub, NotebookViewsStub, NotebookViewStub } from 'sql/workbench/contrib/notebook/test/stubs'; import { NotebookEditorStub } from 'sql/workbench/contrib/notebook/test/testCommon'; import { ICellModel, INotebookModel, ViewMode } from 'sql/workbench/services/notebook/browser/models/modelInterfaces'; @@ -16,15 +16,12 @@ import { INotebookEditor, INotebookService } from 'sql/workbench/services/notebo import { CellType, CellTypes } from 'sql/workbench/services/notebook/common/contracts'; import * as TypeMoq from 'typemoq'; import { Emitter, Event } from 'vs/base/common/event'; -import { TestCommandService } from 'vs/editor/test/browser/editorTestServices'; -import { ICommandService } from 'vs/platform/commands/common/commands'; import { IConfigurationChangeEvent, IConfigurationOverrides, IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; import { workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices'; import { URI } from 'vs/base/common/uri'; -import { NullAdsTelemetryService } from 'sql/platform/telemetry/common/adsTelemetryService'; import { MockQuickInputService } from 'sql/workbench/contrib/notebook/test/common/quickInputServiceMock'; import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; import { Separator } from 'vs/base/common/actions'; @@ -251,22 +248,6 @@ suite('Notebook Actions', function (): void { }); }); - test('New Notebook Action', async function (): Promise { - let actualCmdId: string; - - let mockCommandService = TypeMoq.Mock.ofType(TestCommandService); - mockCommandService.setup(s => s.executeCommand(TypeMoq.It.isAny(), TypeMoq.It.isAny())) - .returns((commandId) => { - actualCmdId = commandId; - return Promise.resolve(true); - }); - - let action = new NewNotebookAction('TestId', 'TestLabel', mockCommandService.object, undefined, new NullAdsTelemetryService()); - await action.run(undefined); - - assert.strictEqual(actualCmdId, NewNotebookAction.INTERNAL_NEW_NOTEBOOK_CMD_ID); - }); - test('Should Run with Parameters Action', async function (): Promise { const testContents: azdata.nb.INotebookContents = { cells: [{ diff --git a/src/sql/workbench/services/notebook/browser/notebookServiceImpl.ts b/src/sql/workbench/services/notebook/browser/notebookServiceImpl.ts index d825c82676..f4c0245d95 100644 --- a/src/sql/workbench/services/notebook/browser/notebookServiceImpl.ts +++ b/src/sql/workbench/services/notebook/browser/notebookServiceImpl.ts @@ -339,12 +339,42 @@ export class NotebookService extends Disposable implements INotebookService { } public async openNotebook(resource: UriComponents, options: INotebookShowOptions): Promise { + // Append a numbered suffix if an untitled notebook is already open with the same path + if (resource.scheme === Schemas.untitled) { + if (!resource.path || this.untitledEditorTitleExists(resource.path)) { + resource.path = this.createPrefixedNotebookFilePath(resource.path); + } + } + const editorOptions: ITextEditorOptions = { preserveFocus: options.preserveFocus, pinned: !options.preview }; let input = await this.createNotebookInput(options, resource); - return await this._editorService.openEditor(input, editorOptions, viewColumnToEditorGroup(this._editorGroupService, options.position)); + return this._editorService.openEditor(input, editorOptions, viewColumnToEditorGroup(this._editorGroupService, options.position)); + } + + private untitledEditorTitleExists(filePath: string): boolean { + return !!this._untitledEditorService.get(URI.from({ scheme: Schemas.untitled, path: filePath })); + } + + private createPrefixedNotebookFilePath(prefix?: string): string { + if (!prefix) { + prefix = 'Notebook'; + } + let prefixFileName = (counter: number): string => { + return `${prefix}-${counter}`; + }; + + let counter = 1; + // Get document name and check if it exists + let filePath = prefixFileName(counter); + while (this.untitledEditorTitleExists(filePath)) { + counter++; + filePath = prefixFileName(counter); + } + + return filePath; } /**