Skip to content

Commit

Permalink
Move toggle editor type command out of custom editors (#96100)
Browse files Browse the repository at this point in the history
The new toggle editor type command lets you quickly switch between a custom editor and our default editor
  • Loading branch information
mjbvz authored Apr 27, 2020
1 parent a70e14b commit cf97fca
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 92 deletions.
51 changes: 1 addition & 50 deletions src/vs/workbench/contrib/customEditor/browser/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ import { InputFocusedContextKey } from 'vs/platform/contextkey/common/contextkey
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { CustomEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput';
import { defaultCustomEditor } from 'vs/workbench/contrib/customEditor/common/contributedCustomEditors';
import { CONTEXT_CUSTOM_EDITORS, CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor';
import { CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE } from 'vs/workbench/contrib/customEditor/common/customEditor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';


Expand Down Expand Up @@ -67,51 +66,3 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
}
}).register();

(new class ToggleCustomEditorCommand extends Command {
public static readonly ID = 'editor.action.customEditor.toggle';

constructor() {
super({
id: ToggleCustomEditorCommand.ID,
precondition: CONTEXT_CUSTOM_EDITORS,
});
}

public runCommand(accessor: ServicesAccessor): void {
const editorService = accessor.get<IEditorService>(IEditorService);
const activeEditorPane = editorService.activeEditorPane;
if (!activeEditorPane) {
return;
}

const activeGroup = activeEditorPane.group;
const activeEditor = activeEditorPane.input;
const targetResource = activeEditor.resource;

if (!targetResource) {
return;
}

const customEditorService = accessor.get<ICustomEditorService>(ICustomEditorService);

let toggleView = defaultCustomEditor.id;
if (!(activeEditor instanceof CustomEditorInput)) {
const bestAvailableEditor = customEditorService.getContributedCustomEditors(targetResource).bestAvailableEditor;
if (bestAvailableEditor) {
toggleView = bestAvailableEditor.id;
} else {
return;
}
}

const newEditorInput = customEditorService.createInput(targetResource, toggleView, activeGroup.id);

editorService.replaceEditors([{
editor: activeEditor,
replacement: newEditorInput,
options: {
ignoreOverrides: true,
}
}], activeGroup);
}
}).register();
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import * as nls from 'vs/nls';
import { Registry } from 'vs/platform/registry/common/platform';
import { ToggleAutoSaveAction, GlobalNewUntitledFileAction, FocusFilesExplorer, GlobalCompareResourcesAction, SaveAllAction, ShowActiveFileInExplorer, CollapseExplorerView, RefreshExplorerView, CompareWithClipboardAction, NEW_FILE_COMMAND_ID, NEW_FILE_LABEL, NEW_FOLDER_COMMAND_ID, NEW_FOLDER_LABEL, TRIGGER_RENAME_LABEL, MOVE_FILE_TO_TRASH_LABEL, COPY_FILE_LABEL, PASTE_FILE_LABEL, FileCopiedContext, renameHandler, moveFileToTrashHandler, copyFileHandler, pasteFileHandler, deleteFileHandler, cutFileHandler, DOWNLOAD_COMMAND_ID, openFilePreserveFocusHandler, DOWNLOAD_LABEL, ShowOpenedFileInNewWindow, ReopenResourcesAction } from 'vs/workbench/contrib/files/browser/fileActions';
import { ToggleAutoSaveAction, GlobalNewUntitledFileAction, FocusFilesExplorer, GlobalCompareResourcesAction, SaveAllAction, ShowActiveFileInExplorer, CollapseExplorerView, RefreshExplorerView, CompareWithClipboardAction, NEW_FILE_COMMAND_ID, NEW_FILE_LABEL, NEW_FOLDER_COMMAND_ID, NEW_FOLDER_LABEL, TRIGGER_RENAME_LABEL, MOVE_FILE_TO_TRASH_LABEL, COPY_FILE_LABEL, PASTE_FILE_LABEL, FileCopiedContext, renameHandler, moveFileToTrashHandler, copyFileHandler, pasteFileHandler, deleteFileHandler, cutFileHandler, DOWNLOAD_COMMAND_ID, openFilePreserveFocusHandler, DOWNLOAD_LABEL, ShowOpenedFileInNewWindow, ReopenResourcesAction, ToggleEditorTypeCommand as ToggleEditorTypeAction } from 'vs/workbench/contrib/files/browser/fileActions';
import { revertLocalChangesCommand, acceptLocalChangesCommand, CONFLICT_RESOLUTION_CONTEXT } from 'vs/workbench/contrib/files/browser/editors/textFileSaveErrorHandler';
import { SyncActionDescriptor, MenuId, MenuRegistry, ILocalizedString } from 'vs/platform/actions/common/actions';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
Expand Down Expand Up @@ -37,6 +37,7 @@ const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.Workbenc
registry.registerWorkbenchAction(SyncActionDescriptor.from(SaveAllAction, { primary: undefined, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_S }, win: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_S) } }), 'File: Save All', category.value);
registry.registerWorkbenchAction(SyncActionDescriptor.from(GlobalCompareResourcesAction), 'File: Compare Active File With...', category.value);
registry.registerWorkbenchAction(SyncActionDescriptor.from(ReopenResourcesAction), 'File: Reopen With...', category.value, ActiveEditorAvailableEditorIdsContext);
registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleEditorTypeAction), 'File: Toggle Editor Type', category.value, ActiveEditorAvailableEditorIdsContext);
registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusFilesExplorer), 'File: Focus on Files Explorer', category.value);
registry.registerWorkbenchAction(SyncActionDescriptor.from(ShowActiveFileInExplorer), 'File: Reveal Active File in Side Bar', category.value);
registry.registerWorkbenchAction(SyncActionDescriptor.from(CollapseExplorerView), 'File: Collapse Folders in Explorer', category.value);
Expand Down
41 changes: 39 additions & 2 deletions src/vs/workbench/contrib/files/browser/fileActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ import { once } from 'vs/base/common/functional';
import { IEditorOptions } from 'vs/platform/editor/common/editor';
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
import { Codicon } from 'vs/base/common/codicons';
import { openEditorWith } from 'vs/workbench/contrib/files/common/openWith';
import { IViewsService } from 'vs/workbench/common/views';
import { openEditorWith, getAllAvailableEditors } from 'vs/workbench/contrib/files/common/openWith';

export const NEW_FILE_COMMAND_ID = 'explorer.newFile';
export const NEW_FILE_LABEL = nls.localize('newFile', "New File");
Expand Down Expand Up @@ -539,7 +539,44 @@ export class ReopenResourcesAction extends Action {

const options = activeEditorPane.options;
const group = activeEditorPane.group;
return openEditorWith(activeInput, undefined, options, group, this.editorService, this.configurationService, this.quickInputService);
await openEditorWith(activeInput, undefined, options, group, this.editorService, this.configurationService, this.quickInputService);
}
}

export class ToggleEditorTypeCommand extends Action {

static readonly ID = 'workbench.files.action.toggleEditorType';
static readonly LABEL = nls.localize('workbench.files.action.toggleEditorType', "Toggle Editor Type");

constructor(
id: string,
label: string,
@IEditorService private readonly editorService: IEditorService,
) {
super(id, label);
}

async run(): Promise<void> {
const activeEditorPane = this.editorService.activeEditorPane;
if (!activeEditorPane) {
return;
}

const input = activeEditorPane.input;
if (!input.resource) {
return;
}

const options = activeEditorPane.options;
const group = activeEditorPane.group;

const overrides = getAllAvailableEditors(input, input.resource, options, group, this.editorService);
const firstNonActiveOverride = overrides.find(([_, entry]) => !entry.active);
if (!firstNonActiveOverride) {
return;
}

await firstNonActiveOverride[0].open(input, options, group, firstNonActiveOverride[1].id)?.override;
}
}

Expand Down
87 changes: 48 additions & 39 deletions src/vs/workbench/contrib/files/common/openWith.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@
*--------------------------------------------------------------------------------------------*/

import { basename, extname, isEqual } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import * as nls from 'vs/nls';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
import { IEditorInput } from 'vs/workbench/common/editor';
import { IEditorInput, IEditorPane } from 'vs/workbench/common/editor';
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
import { DEFAULT_EDITOR_ID } from 'vs/workbench/contrib/files/common/files';
import { CustomEditorAssociation, CustomEditorsAssociations, customEditorsAssociationsSettingId } from 'vs/workbench/services/editor/common/editorAssociationsSetting';
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService, IOpenEditorOverrideHandler } from 'vs/workbench/services/editor/common/editorService';
import { IEditorService, IOpenEditorOverrideEntry, IOpenEditorOverrideHandler } from 'vs/workbench/services/editor/common/editorService';

const builtinProviderDisplayName = nls.localize('builtinProviderDisplayName', "Built-in");

Expand All @@ -31,23 +32,26 @@ export async function openEditorWith(
editorService: IEditorService,
configurationService: IConfigurationService,
quickInputService: IQuickInputService,
): Promise<void> {
): Promise<IEditorPane | undefined> {
const resource = input.resource;
if (!resource) {
return;
}

const resourceExt = extname(resource);
const overrides = editorService.getEditorOverrides(input, options, group);
const allEditorOverrides = getAllAvailableEditors(input, resource, options, group, editorService);
if (!allEditorOverrides.length) {
return;
}

const overrideToUse = overrides.find(([_, entry]) => entry.id === id);
const overrideToUse = typeof id === 'string' && allEditorOverrides.find(([_, entry]) => entry.id === id);
if (overrideToUse) {
overrideToUse[0].open(input, options, group, id);
return;
return overrideToUse[0].open(input, options, group, id)?.override;
}

// Prompt
const items: (IQuickPickItem & { handler?: IOpenEditorOverrideHandler })[] = overrides.map((override) => {
const resourceExt = extname(resource);

const items: (IQuickPickItem & { handler: IOpenEditorOverrideHandler })[] = allEditorOverrides.map((override) => {
return {
handler: override[0],
id: override[1].id,
Expand All @@ -61,31 +65,14 @@ export async function openEditorWith(
};
});

if (!items.length) {
return;
}

if (!items.find(item => item.id === DEFAULT_EDITOR_ID)) {
items.unshift({
id: DEFAULT_EDITOR_ID,
label: nls.localize('promptOpenWith.defaultEditor.displayName', "Text Editor"),
description: editorService.activeEditor instanceof FileEditorInput && isEqual(editorService.activeEditor.resource, resource) ? nls.localize('promptOpenWith.currentlyActive', 'Currently Active') : undefined,
detail: builtinProviderDisplayName,
buttons: resourceExt ? [{
iconClass: 'codicon-settings-gear',
tooltip: nls.localize('promptOpenWith.setDefaultTooltip', "Set as default editor for '{0}' files", resourceExt)
}] : undefined
});
}

const picker = quickInputService.createQuickPick<(IQuickPickItem & { handler?: IOpenEditorOverrideHandler })>();
const picker = quickInputService.createQuickPick<(IQuickPickItem & { handler: IOpenEditorOverrideHandler })>();
picker.items = items;
if (items.length) {
picker.selectedItems = [items[0]];
}
picker.placeholder = nls.localize('promptOpenWith.placeHolder', "Select editor for '{0}'", basename(resource));

const pickedItem = await new Promise<(IQuickPickItem & { handler?: IOpenEditorOverrideHandler }) | undefined>(resolve => {
const pickedItem = await new Promise<(IQuickPickItem & { handler: IOpenEditorOverrideHandler }) | undefined>(resolve => {
picker.onDidAccept(() => {
resolve(picker.selectedItems.length === 1 ? picker.selectedItems[0] : undefined);
picker.dispose();
Expand Down Expand Up @@ -121,18 +108,40 @@ export async function openEditorWith(
picker.show();
});

if (!pickedItem) {
return;
}
return pickedItem?.handler.open(input!, options, group, pickedItem.id)?.override;
}

if (pickedItem.id === DEFAULT_EDITOR_ID) {
const fileEditorInput = editorService.createEditorInput({ resource: resource!, forceFile: true });
const textOptions = options ? { ...options, ignoreOverrides: true } : { ignoreOverrides: true };
/**
* Get a list of all available editors, including the default text editor.
*/
export function getAllAvailableEditors(
input: IEditorInput,
resource: URI,
options: IEditorOptions | ITextEditorOptions | undefined,
group: IEditorGroup,
editorService: IEditorService,
): Array<[IOpenEditorOverrideHandler, IOpenEditorOverrideEntry]> {
const overrides = editorService.getEditorOverrides(input, options, group);
if (!overrides.some(([_, entry]) => entry.id === DEFAULT_EDITOR_ID)) {
overrides.unshift([
{
open: (input: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup) => {
if (!input.resource) {
return;
}

await editorService.openEditor(fileEditorInput, textOptions, group);
return;
const fileEditorInput = editorService.createEditorInput({ resource: input.resource, forceFile: true });
const textOptions = options ? { ...options, ignoreOverrides: true } : { ignoreOverrides: true };
return { override: editorService.openEditor(fileEditorInput, textOptions, group) };
}
},
{
id: DEFAULT_EDITOR_ID,
active: editorService.activeEditor instanceof FileEditorInput && isEqual(editorService.activeEditor.resource, resource),
label: nls.localize('promptOpenWith.defaultEditor.displayName', "Text Editor"),
detail: builtinProviderDisplayName,
}]);
}

pickedItem.handler!.open(input!, options, group, pickedItem.id);
return;
return overrides;
}

0 comments on commit cf97fca

Please sign in to comment.