diff --git a/extensions/vscode-api-tests/src/workspace.test.ts b/extensions/vscode-api-tests/src/workspace.test.ts index 87f98d1ae0f..89ba7a38602 100644 --- a/extensions/vscode-api-tests/src/workspace.test.ts +++ b/extensions/vscode-api-tests/src/workspace.test.ts @@ -100,6 +100,15 @@ suite('workspace-namespace', () => { }); }); + test('openTextDocument, untitled without path but language ID and contents', function () { + return workspace.openTextDocument({ language: 'html', contents: '

Hello world!

' }).then(doc => { + assert.equal(doc.uri.scheme, 'untitled'); + assert.equal(doc.languageId, 'html'); + assert.ok(doc.isDirty); + assert.equal(doc.getText(), '

Hello world!

'); + }); + }); + test('openTextDocument, untitled closes on save', function (done) { const path = join(workspace.rootPath || '', './newfile.txt'); diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 1b827513cb0..41a00992e5c 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -4085,7 +4085,7 @@ declare module 'vscode' { * @param options Options to control how the document will be created. * @return A promise that resolves to a [document](#TextDocument). */ - export function openTextDocument(options?: { language: string; }): Thenable; + export function openTextDocument(options?: { language?: string; contents?: string; }): Thenable; /** * Register a text document content provider. diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 5568004e938..6897300a0e2 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -368,10 +368,10 @@ export function createApiFactory(initData: IInitData, threadService: IThreadServ set textDocuments(value) { throw errors.readonly(); }, - openTextDocument(uriOrFileNameOrOptions?: vscode.Uri | string | { language: string; }) { + openTextDocument(uriOrFileNameOrOptions?: vscode.Uri | string | { language?: string; contents?: string; }) { let uriPromise: TPromise; - let options = uriOrFileNameOrOptions as { language: string; }; + let options = uriOrFileNameOrOptions as { language?: string; contents?: string; }; if (!options || typeof options.language === 'string') { uriPromise = extHostDocuments.createDocumentData(options); } else if (typeof uriOrFileNameOrOptions === 'string') { diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 57607bb3608..1862112d114 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -120,7 +120,7 @@ export abstract class MainThreadDiagnosticsShape { } export abstract class MainThreadDocumentsShape { - $tryCreateDocument(options?: { language: string; }): TPromise { throw ni(); } + $tryCreateDocument(options?: { language?: string; contents?: string; }): TPromise { throw ni(); } $tryOpenDocument(uri: URI): TPromise { throw ni(); } $registerTextContentProvider(handle: number, scheme: string): void { throw ni(); } $onVirtualDocumentChange(uri: URI, value: ITextSource): void { throw ni(); } diff --git a/src/vs/workbench/api/node/extHostDocuments.ts b/src/vs/workbench/api/node/extHostDocuments.ts index eaf14c3356f..4763902f279 100644 --- a/src/vs/workbench/api/node/extHostDocuments.ts +++ b/src/vs/workbench/api/node/extHostDocuments.ts @@ -101,7 +101,7 @@ export class ExtHostDocuments extends ExtHostDocumentsShape { return promise; } - public createDocumentData(options?: { language: string; }): TPromise { + public createDocumentData(options?: { language?: string; contents?: string }): TPromise { return this._proxy.$tryCreateDocument(options); } diff --git a/src/vs/workbench/api/node/mainThreadDocuments.ts b/src/vs/workbench/api/node/mainThreadDocuments.ts index d199404a9da..ae4e71de2c1 100644 --- a/src/vs/workbench/api/node/mainThreadDocuments.ts +++ b/src/vs/workbench/api/node/mainThreadDocuments.ts @@ -228,8 +228,8 @@ export class MainThreadDocuments extends MainThreadDocumentsShape { }); } - $tryCreateDocument(options?: { language: string }): TPromise { - return this._doCreateUntitled(void 0, options ? options.language : void 0); + $tryCreateDocument(options?: { language?: string, contents?: string }): TPromise { + return this._doCreateUntitled(void 0, options ? options.language : void 0, options ? options.contents : void 0); } private _handleAsResourceInput(uri: URI): TPromise { @@ -252,8 +252,8 @@ export class MainThreadDocuments extends MainThreadDocumentsShape { }, err => this._doCreateUntitled(asFileUri).then(resource => !!resource)); } - private _doCreateUntitled(uri?: URI, modeId?: string): TPromise { - let input = this._untitledEditorService.createOrGet(uri, modeId); + private _doCreateUntitled(uri?: URI, modeId?: string, initialValue?: string): TPromise { + let input = this._untitledEditorService.createOrGet(uri, modeId, initialValue); return input.resolve(true).then(model => { if (!this._modelIsSynced[input.getResource().toString()]) { throw new Error(`expected URI ${input.getResource().toString()} to have come to LIFE`); diff --git a/src/vs/workbench/common/editor/untitledEditorInput.ts b/src/vs/workbench/common/editor/untitledEditorInput.ts index 8d037cb8adf..67720f5039c 100644 --- a/src/vs/workbench/common/editor/untitledEditorInput.ts +++ b/src/vs/workbench/common/editor/untitledEditorInput.ts @@ -29,6 +29,7 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport private resource: URI; private _hasAssociatedFilePath: boolean; + private initialValue: string; private modeId: string; private cachedModel: UntitledEditorModel; private modelResolve: TPromise; @@ -42,6 +43,7 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport resource: URI, hasAssociatedFilePath: boolean, modeId: string, + initialValue: string, @IInstantiationService private instantiationService: IInstantiationService, @IWorkspaceContextService private contextService: IWorkspaceContextService, @ITextFileService private textFileService: ITextFileService @@ -49,6 +51,7 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport super(); this.resource = resource; + this.initialValue = initialValue; this._hasAssociatedFilePath = hasAssociatedFilePath; this.modeId = modeId; this.toUnbind = []; @@ -166,7 +169,7 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport } private createModel(): UntitledEditorModel { - const model = this.instantiationService.createInstance(UntitledEditorModel, this.modeId, this.resource, this.hasAssociatedFilePath); + const model = this.instantiationService.createInstance(UntitledEditorModel, this.modeId, this.resource, this.hasAssociatedFilePath, this.initialValue); // re-emit some events from the model this.toUnbind.push(model.onDidChangeContent(() => this._onDidModelChangeContent.fire())); diff --git a/src/vs/workbench/common/editor/untitledEditorModel.ts b/src/vs/workbench/common/editor/untitledEditorModel.ts index 628afd17cde..bd0bb5300b1 100644 --- a/src/vs/workbench/common/editor/untitledEditorModel.ts +++ b/src/vs/workbench/common/editor/untitledEditorModel.ts @@ -41,11 +41,13 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin private preferredEncoding: string; private hasAssociatedFilePath: boolean; + private initialValue: string; constructor( private modeId: string, private resource: URI, hasAssociatedFilePath: boolean, + initialValue: string, @IModeService modeService: IModeService, @IModelService modelService: IModelService, @IBackupFileService private backupFileService: IBackupFileService, @@ -55,6 +57,7 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin super(modelService, modeService); this.hasAssociatedFilePath = hasAssociatedFilePath; + this.initialValue = initialValue; this.dirty = false; this.versionId = 0; @@ -171,7 +174,7 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin // untitled associated to file path are dirty right away as well as untitled with content this.setDirty(this.hasAssociatedFilePath || !!backupContent); - return this.doLoad(backupContent || '').then(model => { + return this.doLoad(backupContent || this.initialValue || '').then(model => { const configuration = this.configurationService.getConfiguration(); // Encoding diff --git a/src/vs/workbench/services/untitled/common/untitledEditorService.ts b/src/vs/workbench/services/untitled/common/untitledEditorService.ts index df195bc70d4..149bcfa809a 100644 --- a/src/vs/workbench/services/untitled/common/untitledEditorService.ts +++ b/src/vs/workbench/services/untitled/common/untitledEditorService.ts @@ -68,7 +68,7 @@ export interface IUntitledEditorService { * It is valid to pass in a file resource. In that case the path will be used as identifier. * The use case is to be able to create a new file with a specific path with VSCode. */ - createOrGet(resource?: URI, modeId?: string): UntitledEditorInput; + createOrGet(resource?: URI, modeId?: string, initialValue?: string): UntitledEditorInput; /** * A check to find out if a untitled resource has a file path associated or not. @@ -154,7 +154,7 @@ export class UntitledEditorService implements IUntitledEditorService { .map((i) => i.getResource()); } - public createOrGet(resource?: URI, modeId?: string): UntitledEditorInput { + public createOrGet(resource?: URI, modeId?: string, initialValue?: string): UntitledEditorInput { let hasAssociatedFilePath = false; if (resource) { hasAssociatedFilePath = (resource.scheme === 'file'); @@ -171,10 +171,10 @@ export class UntitledEditorService implements IUntitledEditorService { } // Create new otherwise - return this.doCreate(resource, hasAssociatedFilePath, modeId); + return this.doCreate(resource, hasAssociatedFilePath, modeId, initialValue); } - private doCreate(resource?: URI, hasAssociatedFilePath?: boolean, modeId?: string): UntitledEditorInput { + private doCreate(resource?: URI, hasAssociatedFilePath?: boolean, modeId?: string, initialValue?: string): UntitledEditorInput { if (!resource) { // Create new taking a resource URI that is not already taken @@ -185,7 +185,7 @@ export class UntitledEditorService implements IUntitledEditorService { } while (Object.keys(UntitledEditorService.CACHE).indexOf(resource.toString()) >= 0); } - const input = this.instantiationService.createInstance(UntitledEditorInput, resource, hasAssociatedFilePath, modeId); + const input = this.instantiationService.createInstance(UntitledEditorInput, resource, hasAssociatedFilePath, modeId, initialValue); const contentListener = input.onDidModelChangeContent(() => { this._onDidChangeContent.fire(resource);