Change:
VSCode Version: 1.5.2 OS Version: OSX 10.10.5, Win 7 x64 Is it possible to open a new file buffer via the API? Essentially, when you use your mouse (or keyboard shortcuts) and goto File menu New File, it creates a new Untitled file buffer in the workspace. When you Save the file, it opens a Save File dialog where you choose where to save it along with the filename. Is it possible to create a new file buffer in this same manner via the API? If not, can this feature be ? I have messed around with the API quite a bit in this area and if it is currently possible, it's not clear in the documentation. I know you can do this: But this requires that you specify the file path for this new "untitled" file. When you hit save, it forces the file to be saved at "c:project". The user is not given the chance to specify where to save the file or what filename to give it. To make a long story short, I essentially want the same functionality as going to File menu New File. Does that make sense?
is working on this
the one (little) challenging thing is that in  we seem to need the URI upfront, but if we have the URI is only known at a later point. I would need to return the URI from but that code runs async because it needs to talk to the main side where the untitled URI is basically being created.
Yeah, we could check if only the is set and then immediately call another method that simply creates a new document. Tho saying that makes me think if we should just expose that directly on the API. Something like ? That will be easier to understand than the scheme-only uri's
I like the more explicit without URI, let me try to sketch something up so we can discuss further via PR.
your proposal in sounds great. The only question would be the name of the file when the language is specified. The untitled document command right now creates documents as "Untitled-1", Untitled-2" ... it would be nice to have an option to have different names for untitled document if it has specific language. For example for SQL documents it would be "SQLQuery-1", "SQLQuery-2" ...
Not sure about that to be fair.
re there is one catch it forget to mention. We have a rule that -functions are ctor replacements for interfaces we own. The consequence is that they must return sync and cannot return a promise with the result. That might make things more complicated and if it becomes to hard we should thing another overload of
A new overload was to the method that allows to open an untitled document with optional language. For example you can call: To create a text document with XML as language. If you leave out the language options, it will just create a text document with plain text language.
so the openTextDocument gets an uri now which has to be a valid path even if it's untitled. is it going to be the same or with the new option if I don't pass any uri it would be untitled?
with the new API you no longer pass in a URI and you end up exactly in the same spot as if a user would have hit CtrlCmd+N to open a new untitled file. The optional language ID can be used to define the language of that document upfront.
[ ] To verify: A new overload was to the method that allows to open an untitled document with optional language. For example you can call: To create a text document with XML as language. If you leave out the language options, it will just create a text document with plain text language.

Discussion:
}); }); <ins> test('openTextDocument, untitled without path', function () { return workspace.openTextDocument().then(doc => { assert.equal(doc.uri.scheme, 'untitled'); assert.ok(doc.isDirty); }); }); test('openTextDocument, untitled without path but language ID', function () { return workspace.openTextDocument({ language: 'xml' }).then(doc => { assert.equal(doc.uri.scheme, 'untitled'); assert.equal(doc.languageId, 'xml'); assert.ok(doc.isDirty); }); }); </ins> test('openTextDocument, untitled closes on save', function (done) { const path = join(workspace.rootPath, './newfile.txt');

export function openTextDocument(fileName: string): Thenable<TextDocument>; /** <ins> * Opens a untitled file document with an optional language. * * @param options an optional language identifier to use for the untitled file document. * @return A promise that resolves to a [document](#TextDocument). */ export function openTextDocument(options?: { language: string; }): Thenable<TextDocument>; /** </ins> * Register a text document content provider. * * Only one provider can be registered per scheme.

set textDocuments(value) { throw errors.readonly(); }, <del> openTextDocument(uriOrFileName: vscode.Uri | string) { let uri: URI; if (typeof uriOrFileName === 'string') { uri = URI.file(uriOrFileName); } else if (uriOrFileName instanceof URI) { uri = <URI>uriOrFileName; </del> <ins> openTextDocument(uriOrFileNameOrOptions?: vscode.Uri | string | { language: string; }) { let uriPromise: TPromise<URI>; let options = uriOrFileNameOrOptions as { language: string; }; if (!options || typeof options.language === 'string') { uriPromise = extHostDocuments.createDocumentData(options); } else if (typeof uriOrFileNameOrOptions === 'string') { uriPromise = TPromise.as(URI.file(uriOrFileNameOrOptions)); } else if (uriOrFileNameOrOptions instanceof URI) { uriPromise = TPromise.as(<URI>uriOrFileNameOrOptions); </ins> } else { <del> throw new Error('illegal argument - uriOrFileName'); </del> <ins> throw new Error('illegal argument - uriOrFileNameOrOptions'); </ins> } <del> return extHostDocuments.ensureDocumentData(uri).then(() => { const data = extHostDocuments.getDocumentData(uri); return data && data.document; </del> <ins> return uriPromise.then(uri => { return extHostDocuments.ensureDocumentData(uri).then(() => { const data = extHostDocuments.getDocumentData(uri); return data && data.document; }); </ins> }); }, registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider) {

} export abstract class MainThreadDocumentsShape { <ins> $tryCreateDocument(options?: { language: string; }): TPromise<any> { throw ni(); } </ins> $tryOpenDocument(uri: URI): TPromise<any> { throw ni(); } $registerTextContentProvider(handle: number, scheme: string): void { throw ni(); } $onVirtualDocumentChange(uri: URI, value: string): void { throw ni(); }

return promise; } <ins> public createDocumentData(options?: { language: string; }): TPromise<URI> { return this._proxy.$tryCreateDocument(options); } </ins> public registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider): vscode.Disposable { if (scheme === 'file' || scheme === 'untitled') { throw new Error(`scheme '${scheme}' already registered`);

}); } <ins> $tryCreateDocument(options?: { language: string }): TPromise<URI> { return this._doCreateUntitled(void 0, options ? options.language : void 0); } </ins> private _handleAsResourceInput(uri: URI): TPromise<boolean> { return this._textModelResolverService.createModelReference(uri).then(ref => { const result = !!ref.object;

return this._fileService.resolveFile(asFileUri).then(stats => { // don't create a new file ontop of an existing file return TPromise.wrapError<boolean>('file already exists on disk'); <del> }, err => { let input = this._untitledEditorService.createOrGet(asFileUri); return input.resolve(true).then(model => { if (input.getResource().toString() !== uri.toString()) { throw new Error(`expected URI ${uri.toString()} BUT GOT ${input.getResource().toString()}`); } if (!this._modelIsSynced[uri.toString()]) { throw new Error(`expected URI ${uri.toString()} to have come to LIFE`); } return this._proxy.$acceptModelDirty(uri.toString()); // mark as dirty }).then(() => { return true; }); </del> <ins> }, err => this._doCreateUntitled(asFileUri).then(resource => !!resource)); } private _doCreateUntitled(uri?: URI, modeId?: string): TPromise<URI> { let input = this._untitledEditorService.createOrGet(uri, modeId); 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`); } return this._proxy.$acceptModelDirty(input.getResource().toString()); // mark as dirty }).then(() => { return input.getResource(); </ins> }); }