diff --git a/src/sql/parts/common/customInputConverter.ts b/src/sql/parts/common/customInputConverter.ts index a91f15343f..55a5ed61a8 100644 --- a/src/sql/parts/common/customInputConverter.ts +++ b/src/sql/parts/common/customInputConverter.ts @@ -18,6 +18,7 @@ import { QueryPlanInput } from 'sql/parts/queryPlan/queryPlanInput'; import { NotebookInput, NotebookInputModel, NotebookInputValidator } from 'sql/parts/notebook/notebookInput'; import { DEFAULT_NOTEBOOK_PROVIDER, INotebookService } from 'sql/services/notebook/notebookService'; import { getProviderForFileName } from 'sql/parts/notebook/notebookUtils'; +import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; const fs = require('fs'); @@ -28,6 +29,7 @@ export const untitledFilePrefix = 'SQLQuery'; // mode identifier for SQL mode export const sqlModeId = 'sql'; +export const notebookModeId = 'notebook'; /** * Checks if the specified input is supported by one our custom input types, and if so convert it @@ -58,7 +60,7 @@ export function convertEditorInput(input: EditorInput, options: IQueryEditorOpti //Notebook let notebookValidator = instantiationService.createInstance(NotebookInputValidator); uri = getNotebookEditorUri(input, instantiationService); - if(uri && notebookValidator.isNotebookEnabled()){ + if (uri && notebookValidator.isNotebookEnabled()) { return withService(instantiationService, INotebookService, notebookService => { let fileName: string = 'untitled'; let providerId: string = DEFAULT_NOTEBOOK_PROVIDER; @@ -95,6 +97,13 @@ export function getSupportedInputResource(input: IEditorInput): URI { } } + if (input instanceof ResourceEditorInput) { + let resourceCast: ResourceEditorInput = input; + if (resourceCast) { + return resourceCast.getResource(); + } + } + return undefined; } @@ -152,7 +161,6 @@ function getQueryPlanEditorUri(input: EditorInput): URI { return undefined; } - /** * If input is a supported notebook editor file (.ipynb), return it's URI. Otherwise return undefined. * @param input The EditorInput to get the URI of. @@ -162,18 +170,15 @@ function getNotebookEditorUri(input: EditorInput, instantiationService: IInstant return undefined; } - - // If this editor is not already of type notebook input if (!(input instanceof NotebookInput)) { let uri: URI = getSupportedInputResource(input); if (uri) { - if (hasFileExtension(getNotebookFileExtensions(instantiationService), input, false)) { + if (hasFileExtension(getNotebookFileExtensions(instantiationService), input, false) || hasNotebookFileMode(input)) { return uri; } } } - return undefined; } @@ -183,6 +188,18 @@ function getNotebookFileExtensions(instantiationService: IInstantiationService): }); } +/** + * Checks whether the given EditorInput is set to either undefined or notebook mode + * @param input The EditorInput to check the mode of + */ +function hasNotebookFileMode(input: EditorInput): boolean { + if (input instanceof UntitledEditorInput) { + let untitledCast: UntitledEditorInput = input; + return (untitledCast && untitledCast.getModeId() === notebookModeId); + } + return false; +} + function withService(instantiationService: IInstantiationService, serviceId: ServiceIdentifier, action: (service: TService) => TResult, ): TResult { return instantiationService.invokeFunction(accessor => { let service = accessor.get(serviceId); @@ -225,3 +242,17 @@ function hasFileExtension(extensions: string[], input: EditorInput, checkUntitle return false; } +// Returns file mode - notebookModeId or sqlModeId +export function getFileMode(instantiationService: IInstantiationService, resource: URI): string { + if (!resource) { + return sqlModeId; + } + return withService(instantiationService, INotebookService, notebookService => { + for (const editor of notebookService.listNotebookEditors()) { + if (editor.notebookParams.notebookUri === resource) { + return notebookModeId; + } + } + return sqlModeId; + }); +} \ No newline at end of file diff --git a/src/sql/parts/notebook/notebook.component.ts b/src/sql/parts/notebook/notebook.component.ts index 068086e6c3..51937c8b22 100644 --- a/src/sql/parts/notebook/notebook.component.ts +++ b/src/sql/parts/notebook/notebook.component.ts @@ -46,6 +46,9 @@ import { KernelsDropdown, AttachToDropdown, AddCellAction, TrustedAction, SaveNo import { IObjectExplorerService } from 'sql/parts/objectExplorer/common/objectExplorerService'; import * as TaskUtilities from 'sql/workbench/common/taskUtilities'; import { ISingleNotebookEditOperation } from 'sql/workbench/api/common/sqlExtHostTypes'; +import { IResourceInput } from 'vs/platform/editor/common/editor'; +import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; +import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService'; export const NOTEBOOK_SELECTOR: string = 'notebook-component'; @@ -89,7 +92,9 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe @Inject(IKeybindingService) private keybindingService: IKeybindingService, @Inject(IHistoryService) private historyService: IHistoryService, @Inject(IWindowService) private windowService: IWindowService, - @Inject(IViewletService) private viewletService: IViewletService + @Inject(IViewletService) private viewletService: IViewletService, + @Inject(IUntitledEditorService) private untitledEditorService: IUntitledEditorService, + @Inject(IEditorGroupsService) private editorGroupService: IEditorGroupsService ) { super(); this.updateProfile(); @@ -400,11 +405,11 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe let target = URI.parse(path); let resource = self._model.notebookUri; self._model.notebookUri = target; - this.saveNotebook().then(result => { - if(result) - { - this.notebookService.renameNotebookEditor(resource, target, this); - } + this.saveNotebook().then(result => { + if(result) + { + return this.replaceUntitledNotebookEditor(resource, target); + } return result; }); } @@ -416,6 +421,27 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe } } + // Replaces untitled notebook editor with the saved file name + private async replaceUntitledNotebookEditor(resource: URI, target: URI): Promise { + let encodingOfSource = this.untitledEditorService.getEncoding(resource); + const replacement: IResourceInput = { + resource: target, + encoding: encodingOfSource, + options: { + pinned: true + } + }; + + return TPromise.join(this.editorGroupService.groups.map(g => + this.editorService.replaceEditors([{ + editor: { resource }, + replacement + }], g))).then(() => { + this.notebookService.renameNotebookEditor(resource, target, this); + return true; + }); + } + private async saveNotebook(): Promise { try { let saved = await this._model.saveModel(); diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index 71fe3d0b99..42cc527056 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -29,7 +29,8 @@ import { coalesce } from 'vs/base/common/arrays'; import { isCodeEditor, isDiffEditor, ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser'; import { IEditorGroupView, IEditorOpeningEvent, EditorGroupsServiceImpl, EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor'; import { IUriDisplayService } from 'vs/platform/uriDisplay/common/uriDisplay'; -import { convertEditorInput } from 'sql/parts/common/customInputConverter'; +//{{ SQL CARBON EDIT }} +import { convertEditorInput, getFileMode } from 'sql/parts/common/customInputConverter'; type ICachedEditorInput = ResourceEditorInput | IFileEditorInput | DataUriEditorInput; @@ -67,7 +68,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { @IInstantiationService private instantiationService: IInstantiationService, @IUriDisplayService private uriDisplayService: IUriDisplayService, @IFileService private fileService: IFileService, - @IConfigurationService private configurationService: IConfigurationService + @IConfigurationService private configurationService: IConfigurationService, ) { super(); @@ -495,9 +496,11 @@ export class EditorService extends Disposable implements EditorServiceImpl { const untitledInput = input; if (!untitledInput.resource || typeof untitledInput.filePath === 'string' || (untitledInput.resource instanceof URI && untitledInput.resource.scheme === Schemas.untitled)) { // {{SQL CARBON EDIT}} + + let mode: string = getFileMode( this.instantiationService, untitledInput.resource); return convertEditorInput(this.untitledEditorService.createOrGet( untitledInput.filePath ? URI.file(untitledInput.filePath) : untitledInput.resource, - 'sql', + mode, untitledInput.contents, untitledInput.encoding ), undefined, this.instantiationService);