diff --git a/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts b/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts index 52f2a7ab691eb4327d734697c19ec715cd800632..2afe79106ed8c0ab3f724621933b48389b699b67 100644 --- a/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts +++ b/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts @@ -78,14 +78,6 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { return this.resource; } - setPreferredEncoding(encoding: string): void { - this.preferredEncoding = encoding; - - if (encoding) { - this.forceOpenAsText = true; // encoding is a good hint to open the file as text - } - } - getEncoding(): string { const textModel = this.textFileService.models.get(this.resource); if (textModel) { @@ -108,6 +100,14 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { } } + setPreferredEncoding(encoding: string): void { + this.preferredEncoding = encoding; + + if (encoding) { + this.forceOpenAsText = true; // encoding is a good hint to open the file as text + } + } + setForceOpenAsText(): void { this.forceOpenAsText = true; this.forceOpenAsBinary = false; diff --git a/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts b/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts index 4ed5466ae8ad024f81686202c33a90a9be114c1a..37d101a4688f55835b55e873d43acdab1aa00023 100644 --- a/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts +++ b/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts @@ -11,7 +11,7 @@ import { revertLocalChangesCommand, acceptLocalChangesCommand, CONFLICT_RESOLUTI import { SyncActionDescriptor, MenuId, MenuRegistry, ILocalizedString } from 'vs/platform/actions/common/actions'; import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes'; -import { openWindowCommand, REVEAL_IN_OS_COMMAND_ID, COPY_PATH_COMMAND_ID, REVEAL_IN_EXPLORER_COMMAND_ID, OPEN_TO_SIDE_COMMAND_ID, REVERT_FILE_COMMAND_ID, SAVE_FILE_COMMAND_ID, SAVE_FILE_LABEL, SAVE_FILE_AS_COMMAND_ID, SAVE_FILE_AS_LABEL, SAVE_ALL_IN_GROUP_COMMAND_ID, OpenEditorsGroupContext, COMPARE_WITH_SAVED_COMMAND_ID, COMPARE_RESOURCE_COMMAND_ID, SELECT_FOR_COMPARE_COMMAND_ID, ResourceSelectedForCompareContext, REVEAL_IN_OS_LABEL, DirtyEditorContext, COMPARE_SELECTED_COMMAND_ID, REMOVE_ROOT_FOLDER_COMMAND_ID, REMOVE_ROOT_FOLDER_LABEL, SAVE_FILES_COMMAND_ID, COPY_RELATIVE_PATH_COMMAND_ID } from 'vs/workbench/parts/files/electron-browser/fileCommands'; +import { openWindowCommand, REVEAL_IN_OS_COMMAND_ID, COPY_PATH_COMMAND_ID, REVEAL_IN_EXPLORER_COMMAND_ID, OPEN_TO_SIDE_COMMAND_ID, REVERT_FILE_COMMAND_ID, SAVE_FILE_COMMAND_ID, SAVE_FILE_LABEL, SAVE_FILE_AS_COMMAND_ID, SAVE_FILE_AS_LABEL, SAVE_ALL_IN_GROUP_COMMAND_ID, OpenEditorsGroupContext, COMPARE_WITH_SAVED_COMMAND_ID, COMPARE_RESOURCE_COMMAND_ID, SELECT_FOR_COMPARE_COMMAND_ID, ResourceSelectedForCompareContext, REVEAL_IN_OS_LABEL, DirtyEditorContext, COMPARE_SELECTED_COMMAND_ID, REMOVE_ROOT_FOLDER_COMMAND_ID, REMOVE_ROOT_FOLDER_LABEL, SAVE_FILES_COMMAND_ID, COPY_RELATIVE_PATH_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_LABEL } from 'vs/workbench/parts/files/electron-browser/fileCommands'; import { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -180,6 +180,7 @@ function appendToCommandPalette(id: string, title: ILocalizedString, category: s appendToCommandPalette(COPY_PATH_COMMAND_ID, { value: nls.localize('copyPathOfActive', "Copy Path of Active File"), original: 'File: Copy Path of Active File' }, category); appendToCommandPalette(COPY_RELATIVE_PATH_COMMAND_ID, { value: nls.localize('copyRelativePathOfActive', "Copy Relative Path of Active File"), original: 'File: Copy Relative Path of Active File' }, category); appendToCommandPalette(SAVE_FILE_COMMAND_ID, { value: SAVE_FILE_LABEL, original: 'File: Save' }, category); +appendToCommandPalette(SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, { value: SAVE_FILE_WITHOUT_FORMATTING_LABEL, original: 'File: Save without Formatting' }, category); appendToCommandPalette(SAVE_ALL_IN_GROUP_COMMAND_ID, { value: nls.localize('saveAllInGroup', "Save All in Group"), original: 'File: Save All in Group' }, category); appendToCommandPalette(SAVE_FILES_COMMAND_ID, { value: nls.localize('saveFiles', "Save All Files"), original: 'File: Save All Files' }, category); appendToCommandPalette(REVERT_FILE_COMMAND_ID, { value: nls.localize('revert', "Revert File"), original: 'File: Revert File' }, category); diff --git a/src/vs/workbench/parts/files/electron-browser/fileCommands.ts b/src/vs/workbench/parts/files/electron-browser/fileCommands.ts index 26a33dd09140f8142a44fff3b74a5413dabd9103..9e655107b71c8b267becadcfeb121984499b1360 100644 --- a/src/vs/workbench/parts/files/electron-browser/fileCommands.ts +++ b/src/vs/workbench/parts/files/electron-browser/fileCommands.ts @@ -17,7 +17,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { ExplorerFocusCondition, FileOnDiskContentProvider, VIEWLET_ID } from 'vs/workbench/parts/files/common/files'; import { ExplorerViewlet } from 'vs/workbench/parts/files/electron-browser/explorerViewlet'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; -import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; +import { ITextFileService, ISaveOptions } from 'vs/workbench/services/textfile/common/textfiles'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import { IListService } from 'vs/platform/list/browser/listService'; import { Tree } from 'vs/base/parts/tree/browser/treeImpl'; @@ -62,6 +62,8 @@ export const SAVE_FILE_AS_COMMAND_ID = 'workbench.action.files.saveAs'; export const SAVE_FILE_AS_LABEL = nls.localize('saveAs', "Save As..."); export const SAVE_FILE_COMMAND_ID = 'workbench.action.files.save'; export const SAVE_FILE_LABEL = nls.localize('save', "Save"); +export const SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID = 'workbench.action.files.saveWithoutFormatting'; +export const SAVE_FILE_WITHOUT_FORMATTING_LABEL = nls.localize('saveWithoutFormatting', "Save without Formatting"); export const SAVE_ALL_COMMAND_ID = 'saveAll'; export const SAVE_ALL_LABEL = nls.localize('saveAll', "Save All"); @@ -85,6 +87,7 @@ export const openWindowCommand = (accessor: ServicesAccessor, paths: (string | U function save( resource: URI, isSaveAs: boolean, + options: ISaveOptions, editorService: IEditorService, fileService: IFileService, untitledEditorService: IUntitledEditorService, @@ -116,7 +119,7 @@ function save( // Special case: an untitled file with associated path gets saved directly unless "saveAs" is true let savePromise: TPromise; if (!isSaveAs && resource.scheme === Schemas.untitled && untitledEditorService.hasAssociatedFilePath(resource)) { - savePromise = textFileService.save(resource).then((result) => { + savePromise = textFileService.save(resource, options).then((result) => { if (result) { return resource.with({ scheme: Schemas.file }); } @@ -127,7 +130,7 @@ function save( // Otherwise, really "Save As..." else { - savePromise = textFileService.saveAs(resource); + savePromise = textFileService.saveAs(resource, void 0, options); } return savePromise.then((target) => { @@ -159,8 +162,14 @@ function save( activeControl.group.pinEditor(activeControl.input); } - // Just save - return textFileService.save(resource, { force: true /* force a change to the file to trigger external watchers if any */ }); + // Just save (force a change to the file to trigger external watchers if any) + if (!options) { + options = { force: true }; + } else { + options.force = true; + } + + return textFileService.save(resource, options); } return TPromise.as(false); @@ -480,7 +489,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ resource = getResourceForCommand(resourceOrObject, accessor.get(IListService), editorService); } - return save(resource, true, editorService, accessor.get(IFileService), accessor.get(IUntitledEditorService), accessor.get(ITextFileService), accessor.get(IEditorGroupsService)); + return save(resource, true, void 0, editorService, accessor.get(IFileService), accessor.get(IUntitledEditorService), accessor.get(ITextFileService), accessor.get(IEditorGroupsService)); } }); @@ -495,12 +504,29 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ if (resources.length === 1) { // If only one resource is selected explictly call save since the behavior is a bit different than save all #41841 - return save(resources[0], false, editorService, accessor.get(IFileService), accessor.get(IUntitledEditorService), accessor.get(ITextFileService), accessor.get(IEditorGroupsService)); + return save(resources[0], false, void 0, editorService, accessor.get(IFileService), accessor.get(IUntitledEditorService), accessor.get(ITextFileService), accessor.get(IEditorGroupsService)); } return saveAll(resources, editorService, accessor.get(IUntitledEditorService), accessor.get(ITextFileService), accessor.get(IEditorGroupsService)); } }); +KeybindingsRegistry.registerCommandAndKeybindingRule({ + when: undefined, + weight: KeybindingWeight.WorkbenchContrib, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_S), + id: SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, + handler: accessor => { + const editorService = accessor.get(IEditorService); + + const resource = toResource(editorService.activeEditor, { supportSideBySide: true }); + if (resource) { + return save(resource, false, { skipSaveParticipants: true }, editorService, accessor.get(IFileService), accessor.get(IUntitledEditorService), accessor.get(ITextFileService), accessor.get(IEditorGroupsService)); + } + + return void 0; + } +}); + CommandsRegistry.registerCommand({ id: SAVE_ALL_COMMAND_ID, handler: (accessor) => { diff --git a/src/vs/workbench/services/textfile/common/textFileService.ts b/src/vs/workbench/services/textfile/common/textFileService.ts index 37fc8f7dbfd2225fc3f67e7c0ca7c56fc01ed7dc..3ecf18afcd5cd37f41cce957e8999737e3479252 100644 --- a/src/vs/workbench/services/textfile/common/textFileService.ts +++ b/src/vs/workbench/services/textfile/common/textFileService.ts @@ -381,7 +381,14 @@ export abstract class TextFileService extends Disposable implements ITextFileSer if (options && options.force && this.fileService.canHandleResource(resource) && !this.isDirty(resource)) { const model = this._models.get(resource); if (model) { - model.save({ force: true, reason: SaveReason.EXPLICIT }).then(() => !model.isDirty()); + if (!options) { + options = Object.create(null); + } + + options.force = true; + options.reason = SaveReason.EXPLICIT; + + model.save(options).then(() => !model.isDirty()); } }