diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 99376fa1467a5..8e2a515be23b8 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -280,6 +280,11 @@ export namespace CommonCommands { category: VIEW_CATEGORY, label: 'Toggle Menu Bar' }); + export const NEW_FILE = Command.toDefaultLocalizedCommand({ + id: 'file.newFile', + category: FILE_CATEGORY, + label: 'New File...' + }); export const NEW_UNTITLED_TEXT_FILE = Command.toDefaultLocalizedCommand({ id: 'workbench.action.files.newUntitledTextFile', category: FILE_CATEGORY, @@ -1424,6 +1429,7 @@ export class CommonFrontendContribution implements FrontendApplicationContributi const items: QuickPickItemOrSeparator[] = [ { label: nls.localizeByDefault('New Text File'), + description: nls.localizeByDefault('Built-in'), execute: async () => this.commandRegistry.executeCommand(CommonCommands.NEW_UNTITLED_TEXT_FILE.id) }, ...newFileContributions.children @@ -1446,10 +1452,41 @@ export class CommonFrontendContribution implements FrontendApplicationContributi }) ]; + + const CREATE_NEW_FILE_ITEM_ID = 'create-new-file'; + const hasNewFileHandler = this.commandRegistry.getActiveHandler(CommonCommands.NEW_FILE.id) !== undefined; + const createNewFileItem: QuickPickItem & { value?: string } | undefined = hasNewFileHandler ? { + id: CREATE_NEW_FILE_ITEM_ID, + label: nls.localizeByDefault('Create New File ({0})'), + description: nls.localizeByDefault('Built-in'), + execute: async () => { + if (createNewFileItem?.value) { + const parent = await this.workingDirProvider.getUserWorkingDir(); + // Exec NEW_FILE command with the file name as additional argument + return this.commandRegistry.executeCommand(CommonCommands.NEW_FILE.id, parent, createNewFileItem.value); + } + } + } : undefined; + this.quickInputService.showQuickPick(items, { title: nls.localizeByDefault('New File...'), placeholder: nls.localizeByDefault('Select File Type or Enter File Name...'), - canSelectMany: false + canSelectMany: false, + onDidChangeValue: picker => { + if (createNewFileItem === undefined) { + return; + } + if (picker.value) { + createNewFileItem.alwaysShow = true; + createNewFileItem.value = picker.value; + createNewFileItem.label = nls.localizeByDefault('Create New File ({0})', picker.value); + picker.items = [...items, createNewFileItem]; + } else { + createNewFileItem.alwaysShow = false; + createNewFileItem.value = undefined; + picker.items = items.filter(item => item !== createNewFileItem); + } + } }); } diff --git a/packages/workspace/src/browser/workspace-commands.ts b/packages/workspace/src/browser/workspace-commands.ts index 2e7625f434485..c1070392ca395 100644 --- a/packages/workspace/src/browser/workspace-commands.ts +++ b/packages/workspace/src/browser/workspace-commands.ts @@ -88,11 +88,9 @@ export namespace WorkspaceCommands { category: WORKSPACE_CATEGORY, label: 'Close Workspace' }); - export const NEW_FILE = Command.toDefaultLocalizedCommand({ - id: 'file.newFile', - category: FILE_CATEGORY, - label: 'New File...' - }); + + export const NEW_FILE = CommonCommands.NEW_FILE; + export const NEW_FOLDER = Command.toDefaultLocalizedCommand({ id: 'file.newFolder', category: FILE_CATEGORY, @@ -225,14 +223,36 @@ export class WorkspaceCommandContribution implements CommandContribution { registerCommands(registry: CommandRegistry): void { this.registerOpenWith(registry); - registry.registerCommand(WorkspaceCommands.NEW_FILE, this.newWorkspaceRootUriAwareCommandHandler({ - execute: uri => this.getDirectory(uri).then(parent => { + registry.registerCommand(CommonCommands.NEW_FILE, this.newWorkspaceRootUriAwareCommandHandler({ + execute: (uri, ...args) => this.getDirectory(uri).then(async parent => { if (parent) { - const parentUri = parent.resource; const { fileName, fileExtension } = this.getDefaultFileConfig(); - const targetUri = parentUri.resolve(fileName + fileExtension); + let newFileName = `${fileName}${fileExtension}`; + const parentUri = parent.resource; + + const doCreateFile = async (name: string | undefined) => { + if (name) { + const fileUri = parentUri.resolve(name); + await this.fileService.create(fileUri); + this.fireCreateNewFile({ parent: parentUri, uri: fileUri }); + open(this.openerService, fileUri); + } + }; + + // If a name was provided, check if it is valid create a file and return. + // Otherwise open a dialog to get the name. + if (args !== undefined && args.length > 0 && args[0]) { + newFileName = args[0]; + if (await this.validateFileName(newFileName, parent, true) === '') { + await doCreateFile(newFileName); + return; + } + } + + const targetUri = parentUri.resolve(newFileName); const vacantChildUri = FileSystemUtils.generateUniqueResourceURI(parent, targetUri, false); + // Open dialog const dialog = new WorkspaceInputDialog({ title: nls.localizeByDefault('New File...'), maxWidth: 400, @@ -241,15 +261,7 @@ export class WorkspaceCommandContribution implements CommandContribution { placeholder: nls.localize('theia/workspace/newFilePlaceholder', 'File Name'), validate: name => this.validateFileName(name, parent, true) }, this.labelProvider); - - dialog.open().then(async name => { - if (name) { - const fileUri = parentUri.resolve(name); - await this.fileService.create(fileUri); - this.fireCreateNewFile({ parent: parentUri, uri: fileUri }); - open(this.openerService, fileUri); - } - }); + dialog.open().then(doCreateFile); } }) }));