提交 489706a7 编写于 作者: B Benjamin Pasero

Allow to edit the left hand side of a diff editor if possible (fixes #4180)

上级 43b39d5a
......@@ -10,7 +10,6 @@ import { IDiffEditor } from 'vs/editor/browser/editorBrowser';
import { IDiffEditorOptions, IEditorOptions as ICodeEditorOptions } from 'vs/editor/common/config/editorOptions';
import { BaseTextEditor, IEditorConfiguration } from 'vs/workbench/browser/parts/editor/textEditor';
import { TextEditorOptions, EditorInput, EditorOptions, TEXT_DIFF_EDITOR_ID, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, ITextDiffEditor, IEditorMemento } from 'vs/workbench/common/editor';
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { DiffNavigator } from 'vs/editor/browser/widget/diffNavigator';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
......@@ -55,7 +54,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
@IEditorGroupsService editorGroupService: IEditorGroupsService,
@ITextFileService textFileService: ITextFileService,
@IHostService hostService: IHostService,
@IClipboardService private _clipboardService: IClipboardService,
@IClipboardService private clipboardService: IClipboardService,
@IFilesConfigurationService filesConfigurationService: IFilesConfigurationService
) {
super(TextDiffEditor.ID, telemetryService, instantiationService, storageService, configurationService, themeService, textFileService, editorService, editorGroupService, hostService, filesConfigurationService);
......@@ -74,7 +73,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
}
createEditorControl(parent: HTMLElement, configuration: ICodeEditorOptions): IDiffEditor {
return this.instantiationService.createInstance(DiffEditorWidget, parent, configuration, this._clipboardService);
return this.instantiationService.createInstance(DiffEditorWidget, parent, configuration, this.clipboardService);
}
async setInput(input: EditorInput, options: EditorOptions | undefined, token: CancellationToken): Promise<void> {
......@@ -211,7 +210,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
protected getConfigurationOverrides(): ICodeEditorOptions {
const options: IDiffEditorOptions = super.getConfigurationOverrides();
options.readOnly = this.isReadOnly();
options.originalEditable = this.input instanceof DiffEditorInput && !this.input.originalInput.isReadonly();
options.lineDecorationsWidth = '2ch';
return options;
......@@ -219,8 +218,9 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
protected getAriaLabel(): string {
let ariaLabel: string;
const inputName = this.input?.getName();
if (this.isReadOnly()) {
if (this.input?.isReadonly()) {
ariaLabel = inputName ? nls.localize('readonlyEditorWithInputAriaLabel', "{0}. Readonly text compare editor.", inputName) : nls.localize('readonlyEditorAriaLabel', "Readonly text compare editor.");
} else {
ariaLabel = inputName ? nls.localize('editableEditorWithInputAriaLabel', "{0}. Text file compare editor.", inputName) : nls.localize('editableEditorAriaLabel', "Text file compare editor.");
......@@ -229,17 +229,6 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
return ariaLabel;
}
private isReadOnly(): boolean {
const input = this.input;
if (input instanceof DiffEditorInput) {
const modifiedInput = input.modifiedInput;
return modifiedInput instanceof ResourceEditorInput;
}
return false;
}
private isFileBinaryError(error: Error[]): boolean;
private isFileBinaryError(error: Error): boolean;
private isFileBinaryError(error: Error | Error[]): boolean {
......
......@@ -124,7 +124,8 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
return {
overviewRulerLanes: 3,
lineNumbersMinChars: 3,
fixedOverflowWidgets: true
fixedOverflowWidgets: true,
readOnly: this.input?.isReadonly()
};
}
......@@ -300,6 +301,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
configuration = this.configurationService.getValue<IEditorConfiguration>(resource);
}
}
if (!this.editorControl || !configuration) {
return;
}
......
......@@ -6,7 +6,6 @@
import * as nls from 'vs/nls';
import { assertIsDefined, isFunction } from 'vs/base/common/types';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { TextEditorOptions, EditorInput, EditorOptions } from 'vs/workbench/common/editor';
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel';
......@@ -110,14 +109,6 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
}
}
protected getConfigurationOverrides(): IEditorOptions {
const options = super.getConfigurationOverrides();
options.readOnly = !(this.input instanceof UntitledTextEditorInput); // all resource editors are readonly except for the untitled one;
return options;
}
protected getAriaLabel(): string {
let ariaLabel: string;
......
......@@ -5,7 +5,7 @@
import * as nls from 'vs/nls';
import { URI } from 'vs/base/common/uri';
import { toResource, IEditorCommandsContext, SideBySideEditor, IEditorIdentifier, SaveReason } from 'vs/workbench/common/editor';
import { toResource, IEditorCommandsContext, SideBySideEditor, IEditorIdentifier, SaveReason, SideBySideEditorInput } from 'vs/workbench/common/editor';
import { IWindowOpenable, IOpenWindowOptions, isWorkspaceToOpen, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
......@@ -23,7 +23,7 @@ import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/co
import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes';
import { isWindows } from 'vs/base/common/platform';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { getResourceForCommand, getMultiSelectedResources, getMultiSelectedEditors } from 'vs/workbench/contrib/files/browser/files';
import { getResourceForCommand, getMultiSelectedResources, getOpenEditorsViewMultiSelection } from 'vs/workbench/contrib/files/browser/files';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing';
import { getMultiSelectedEditorContexts } from 'vs/workbench/browser/parts/editor/editorCommands';
import { Schemas } from 'vs/base/common/network';
......@@ -315,12 +315,35 @@ CommandsRegistry.registerCommand({
async function saveSelectedEditors(accessor: ServicesAccessor, options?: ISaveEditorsOptions): Promise<void> {
const listService = accessor.get(IListService);
const editorGroupsService = accessor.get(IEditorGroupsService);
const editorGroupService = accessor.get(IEditorGroupsService);
const codeEditorService = accessor.get(ICodeEditorService);
const textFileService = accessor.get(ITextFileService);
// Retrieve selected or active editor
let editors = getOpenEditorsViewMultiSelection(listService, editorGroupService);
if (!editors) {
const activeGroup = editorGroupService.activeGroup;
if (activeGroup.activeEditor) {
editors = [];
// Special treatment for side by side editors: if the active editor
// has 2 sides, we consider both, to support saving both sides.
// We only allow this when saving, not for "Save As".
// See also https://github.com/microsoft/vscode/issues/4180
if (activeGroup.activeEditor instanceof SideBySideEditorInput && !options?.saveAs) {
editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor.master });
editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor.details });
} else {
editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor });
}
}
}
if (!editors || editors.length === 0) {
return; // nothing to save
}
// Save editors
const editors = getMultiSelectedEditors(listService, editorGroupsService);
await doSaveEditors(accessor, editors, options);
// Special treatment for embedded editors: if we detect that focus is
......@@ -435,12 +458,24 @@ CommandsRegistry.registerCommand({
handler: async accessor => {
const notificationService = accessor.get(INotificationService);
const listService = accessor.get(IListService);
const editorGroupsService = accessor.get(IEditorGroupsService);
const editorGroupService = accessor.get(IEditorGroupsService);
const editorService = accessor.get(IEditorService);
const editors = getMultiSelectedEditors(listService, editorGroupsService).filter(({ editor }) => !editor.isUntitled() /* all except untitled */);
// Retrieve selected or active editor
let editors = getOpenEditorsViewMultiSelection(listService, editorGroupService);
if (!editors) {
const activeGroup = editorGroupService.activeGroup;
if (activeGroup.activeEditor) {
editors = [{ groupId: activeGroup.id, editor: activeGroup.activeEditor }];
}
}
if (!editors || editors.length === 0) {
return; // nothing to revert
}
try {
await editorService.revert(editors, { force: true });
await editorService.revert(editors.filter(({ editor }) => !editor.isUntitled() /* all except untitled */), { force: true });
} catch (error) {
notificationService.error(nls.localize('genericRevertError', "Failed to revert '{0}': {1}", editors.map(({ editor }) => editor.getName()).join(', '), toErrorMessage(error, false)));
}
......
......@@ -53,17 +53,6 @@ export function getResourceForCommand(resource: URI | object | undefined, listSe
return editorService.activeEditor ? toResource(editorService.activeEditor, { supportSideBySide: SideBySideEditor.MASTER }) : undefined;
}
export function getEditorForCommand(listService: IListService, editorGroupService: IEditorGroupsService): IEditorIdentifier | undefined {
const focus = getFocus(listService);
if (focus instanceof OpenEditor) {
return focus;
}
const activeGroup = editorGroupService.activeGroup;
return activeGroup.activeEditor ? { groupId: activeGroup.id, editor: activeGroup.activeEditor } : undefined;
}
export function getMultiSelectedResources(resource: URI | object | undefined, listService: IListService, editorService: IEditorService): Array<URI> {
const list = listService.lastFocusedList;
if (list?.getHTMLElement() === document.activeElement) {
......@@ -103,7 +92,7 @@ export function getMultiSelectedResources(resource: URI | object | undefined, li
return !!result ? [result] : [];
}
export function getMultiSelectedEditors(listService: IListService, editorGroupsService: IEditorGroupsService): Array<IEditorIdentifier> {
export function getOpenEditorsViewMultiSelection(listService: IListService, editorGroupService: IEditorGroupsService): Array<IEditorIdentifier> | undefined {
const list = listService.lastFocusedList;
if (list?.getHTMLElement() === document.activeElement) {
// Open editors view
......@@ -122,6 +111,5 @@ export function getMultiSelectedEditors(listService: IListService, editorGroupsS
}
}
const result = getEditorForCommand(listService, editorGroupsService);
return !!result ? [result] : [];
return undefined;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册