Skip to content

Commit f0c758b

Browse files
committed
Support open to side from the 'open editor with' quick pick
Fixes #102124 This should enable open to side for custom editors and for notebooks
1 parent 09ca712 commit f0c758b

File tree

6 files changed

+68
-34
lines changed

6 files changed

+68
-34
lines changed

src/vs/workbench/api/browser/mainThreadNotebook.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import { URI, UriComponents } from 'vs/base/common/uri';
1616
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
1717
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
1818
import { EditorActivation, ITextEditorOptions } from 'vs/platform/editor/common/editor';
19+
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
1920
import { ILogService } from 'vs/platform/log/common/log';
20-
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
2121
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
2222
import { viewColumnToEditorGroup } from 'vs/workbench/common/editor';
2323
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
@@ -129,12 +129,12 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
129129
@IEditorGroupsService private readonly editorGroupsService: IEditorGroupsService,
130130
@IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService,
131131
@IAccessibilityService private readonly accessibilityService: IAccessibilityService,
132-
@IQuickInputService private readonly quickInputService: IQuickInputService,
133132
@ILogService private readonly logService: ILogService,
134133
@INotebookCellStatusBarService private readonly cellStatusBarService: INotebookCellStatusBarService,
135134
@IWorkingCopyService private readonly _workingCopyService: IWorkingCopyService,
136135
@INotebookEditorModelResolverService private readonly _notebookModelResolverService: INotebookEditorModelResolverService,
137136
@IUriIdentityService private readonly _uriIdentityService: IUriIdentityService,
137+
@IInstantiationService private readonly _instantiationService: IInstantiationService,
138138
) {
139139
super();
140140
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostNotebook);
@@ -733,7 +733,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
733733
const input = this.editorService.createEditorInput({ resource: URI.revive(resource), options: editorOptions });
734734

735735
// TODO: handle options.selection
736-
const editorPane = await openEditorWith(input, viewType, options, group, this.editorService, this.configurationService, this.quickInputService);
736+
const editorPane = await this._instantiationService.invokeFunction(openEditorWith, input, viewType, options, group);
737737
const notebookEditor = (editorPane as unknown as { isNotebookEditor?: boolean })?.isNotebookEditor ? (editorPane!.getControl() as INotebookEditor) : undefined;
738738

739739
if (notebookEditor) {

src/vs/workbench/browser/parts/editor/editorActions.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { AllEditorsByMostRecentlyUsedQuickAccess, ActiveGroupEditorsByMostRecent
2323
import { Codicon } from 'vs/base/common/codicons';
2424
import { IFilesConfigurationService, AutoSaveMode } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
2525
import { openEditorWith, getAllAvailableEditors } from 'vs/workbench/services/editor/common/editorOpenWith';
26+
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
2627

2728
export class ExecuteCommandAction extends Action {
2829

@@ -1803,9 +1804,8 @@ export class ReopenResourcesAction extends Action {
18031804
constructor(
18041805
id: string,
18051806
label: string,
1806-
@IQuickInputService private readonly quickInputService: IQuickInputService,
18071807
@IEditorService private readonly editorService: IEditorService,
1808-
@IConfigurationService private readonly configurationService: IConfigurationService
1808+
@IInstantiationService private readonly instantiationService: IInstantiationService,
18091809
) {
18101810
super(id, label);
18111811
}
@@ -1823,7 +1823,7 @@ export class ReopenResourcesAction extends Action {
18231823

18241824
const options = activeEditorPane.options;
18251825
const group = activeEditorPane.group;
1826-
await openEditorWith(activeInput, undefined, options, group, this.editorService, this.configurationService, this.quickInputService);
1826+
await this.instantiationService.invokeFunction(openEditorWith, activeInput, undefined, options, group);
18271827
}
18281828
}
18291829

src/vs/workbench/browser/parts/editor/editorCommands.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,6 @@ function registerOpenEditorAPICommands(): void {
484484
const editorService = accessor.get(IEditorService);
485485
const editorGroupsService = accessor.get(IEditorGroupsService);
486486
const configurationService = accessor.get(IConfigurationService);
487-
const quickInputService = accessor.get(IQuickInputService);
488487

489488
const [columnArg, optionsArg] = columnAndOptions ?? [];
490489
let group: IEditorGroup | undefined = undefined;
@@ -504,7 +503,7 @@ function registerOpenEditorAPICommands(): void {
504503
const textOptions: ITextEditorOptions = optionsArg ? { ...optionsArg, override: false } : { override: false };
505504

506505
const input = editorService.createEditorInput({ resource: URI.revive(resource) });
507-
return openEditorWith(input, id, textOptions, group, editorService, configurationService, quickInputService);
506+
return openEditorWith(accessor, input, id, textOptions, group);
508507
});
509508
}
510509

src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts

+3-7
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,11 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
1010
import { EditorInput, EditorOptions } from 'vs/workbench/common/editor';
1111
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
1212
import { BINARY_FILE_EDITOR_ID } from 'vs/workbench/contrib/files/common/files';
13-
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
1413
import { IStorageService } from 'vs/platform/storage/common/storage';
1514
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
1615
import { IOpenerService } from 'vs/platform/opener/common/opener';
17-
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
18-
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
1916
import { openEditorWith } from 'vs/workbench/services/editor/common/editorOpenWith';
17+
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
2018

2119
/**
2220
* An implementation of editor for binary files that cannot be displayed.
@@ -29,9 +27,7 @@ export class BinaryFileEditor extends BaseBinaryResourceEditor {
2927
@ITelemetryService telemetryService: ITelemetryService,
3028
@IThemeService themeService: IThemeService,
3129
@IOpenerService private readonly openerService: IOpenerService,
32-
@IEditorService private readonly editorService: IEditorService,
33-
@IConfigurationService private readonly configurationService: IConfigurationService,
34-
@IQuickInputService private readonly quickInputService: IQuickInputService,
30+
@IInstantiationService private readonly instantiationService: IInstantiationService,
3531
@IStorageService storageService: IStorageService,
3632
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
3733
) {
@@ -55,7 +51,7 @@ export class BinaryFileEditor extends BaseBinaryResourceEditor {
5551
input.setForceOpenAsText();
5652

5753
// If more editors are installed that can handle this input, show a picker
58-
await openEditorWith(input, undefined, options, this.group, this.editorService, this.configurationService, this.quickInputService);
54+
await this.instantiationService.invokeFunction(openEditorWith, input, undefined, options, this.group);
5955
}
6056
}
6157

src/vs/workbench/contrib/files/browser/fileCommands.ts

+2-8
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ import { coalesce } from 'vs/base/common/arrays';
4040
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
4141
import { EmbeddedCodeEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget';
4242
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
43-
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
44-
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
4543
import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity';
4644
import { openEditorWith } from 'vs/workbench/services/editor/common/editorOpenWith';
4745
import { isPromiseCanceledError } from 'vs/base/common/errors';
@@ -356,13 +354,11 @@ CommandsRegistry.registerCommand({
356354
handler: async (accessor, resource: URI | object) => {
357355
const editorService = accessor.get(IEditorService);
358356
const editorGroupsService = accessor.get(IEditorGroupsService);
359-
const configurationService = accessor.get(IConfigurationService);
360-
const quickInputService = accessor.get(IQuickInputService);
361357

362358
const uri = getResourceForCommand(resource, accessor.get(IListService), accessor.get(IEditorService));
363359
if (uri) {
364360
const input = editorService.createEditorInput({ resource: uri });
365-
openEditorWith(input, undefined, undefined, editorGroupsService.activeGroup, editorService, configurationService, quickInputService);
361+
openEditorWith(accessor, input, undefined, undefined, editorGroupsService.activeGroup);
366362
}
367363
}
368364
});
@@ -669,12 +665,10 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
669665

670666
if (typeof args?.viewType === 'string') {
671667
const editorGroupsService = accessor.get(IEditorGroupsService);
672-
const configurationService = accessor.get(IConfigurationService);
673-
const quickInputService = accessor.get(IQuickInputService);
674668

675669
const textInput = editorService.createEditorInput({ options: { pinned: true } });
676670
const group = editorGroupsService.activeGroup;
677-
await openEditorWith(textInput, args.viewType, { pinned: true }, group, editorService, configurationService, quickInputService);
671+
await openEditorWith(accessor, textInput, args.viewType, { pinned: true }, group);
678672
} else {
679673
await editorService.openEditor({ options: { pinned: true } }); // untitled are always pinned
680674
}

src/vs/workbench/services/editor/common/editorOpenWith.ts

+56-11
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ import { Registry } from 'vs/platform/registry/common/platform';
1111
import { ICustomEditorInfo, IEditorService, IOpenEditorOverrideHandler, IOpenEditorOverrideEntry } from 'vs/workbench/services/editor/common/editorService';
1212
import { IEditorInput, IEditorPane, IEditorInputFactoryRegistry, Extensions as EditorExtensions, EditorResourceAccessor } from 'vs/workbench/common/editor';
1313
import { ITextEditorOptions, IEditorOptions } from 'vs/platform/editor/common/editor';
14-
import { IEditorGroup, OpenEditorContext } from 'vs/workbench/services/editor/common/editorGroupsService';
14+
import { IEditorGroup, IEditorGroupsService, OpenEditorContext, preferredSideBySideGroupDirection } from 'vs/workbench/services/editor/common/editorGroupsService';
1515
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
16-
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
16+
import { IKeyMods, IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
1717
import { URI } from 'vs/base/common/uri';
1818
import { extname, basename, isEqual } from 'vs/base/common/resources';
1919
import { Codicon } from 'vs/base/common/codicons';
20+
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
2021

2122
/**
2223
* Id of the default editor for open with.
@@ -30,14 +31,17 @@ export const DEFAULT_EDITOR_ID = 'default';
3031
* @param id Id of the editor to use. If not provided, the user is prompted for which editor to use.
3132
*/
3233
export async function openEditorWith(
34+
accessor: ServicesAccessor,
3335
input: IEditorInput,
3436
id: string | undefined,
3537
options: IEditorOptions | ITextEditorOptions | undefined,
3638
group: IEditorGroup,
37-
editorService: IEditorService,
38-
configurationService: IConfigurationService,
39-
quickInputService: IQuickInputService,
4039
): Promise<IEditorPane | undefined> {
40+
const editorService = accessor.get(IEditorService);
41+
const editorGroupsService = accessor.get(IEditorGroupsService);
42+
const configurationService = accessor.get(IConfigurationService);
43+
const quickInputService = accessor.get(IQuickInputService);
44+
4145
const resource = input.resource;
4246
if (!resource) {
4347
return;
@@ -77,24 +81,38 @@ export async function openEditorWith(
7781
}] : undefined
7882
};
7983
});
84+
type QuickPickItem = IQuickPickItem & {
85+
readonly handler: IOpenEditorOverrideHandler;
86+
};
8087

81-
const picker = quickInputService.createQuickPick<(IQuickPickItem & { handler: IOpenEditorOverrideHandler })>();
88+
const picker = quickInputService.createQuickPick<QuickPickItem>();
8289
picker.items = items;
8390
if (items.length) {
8491
picker.selectedItems = [items[0]];
8592
}
8693
picker.placeholder = nls.localize('promptOpenWith.placeHolder', "Select editor for '{0}'", basename(originalResource));
8794

88-
const pickedItem = await new Promise<(IQuickPickItem & { handler: IOpenEditorOverrideHandler }) | undefined>(resolve => {
95+
type PickedResult = {
96+
readonly item: QuickPickItem;
97+
readonly keyMods?: IKeyMods;
98+
};
99+
100+
const picked = await new Promise<PickedResult | undefined>(resolve => {
89101
picker.onDidAccept(() => {
90-
resolve(picker.selectedItems.length === 1 ? picker.selectedItems[0] : undefined);
91-
picker.dispose();
102+
if (picker.selectedItems.length === 1) {
103+
resolve({
104+
item: picker.selectedItems[0],
105+
keyMods: picker.keyMods
106+
});
107+
} else {
108+
resolve(undefined);
109+
}
92110
});
93111

94112
picker.onDidTriggerItemButton(e => {
95113
const pick = e.item;
96114
const id = pick.id;
97-
resolve(pick); // open the view
115+
resolve({ item: pick }); // open the view
98116
picker.dispose();
99117

100118
// And persist the setting
@@ -121,7 +139,17 @@ export async function openEditorWith(
121139
picker.show();
122140
});
123141

124-
return pickedItem?.handler.open(input, { ...options, override: pickedItem.id }, group, OpenEditorContext.NEW_EDITOR)?.override;
142+
if (!picked) {
143+
return undefined;
144+
}
145+
146+
const targetGroup = getTargetGroup(group, picked.keyMods, configurationService, editorGroupsService);
147+
148+
const openOptions: IEditorOptions = {
149+
...options,
150+
override: picked.item.id,
151+
};
152+
return picked.item.handler.open(input, openOptions, targetGroup, OpenEditorContext.NEW_EDITOR)?.override;
125153
}
126154

127155
const builtinProviderDisplayName = nls.localize('builtinProviderDisplayName', "Built-in");
@@ -132,6 +160,23 @@ export const defaultEditorOverrideEntry = Object.freeze({
132160
detail: builtinProviderDisplayName
133161
});
134162

163+
/**
164+
* Get the group to open the editor in by looking at the pressed keys from the picker.
165+
*/
166+
function getTargetGroup(
167+
startingGroup: IEditorGroup,
168+
keyMods: IKeyMods | undefined,
169+
configurationService: IConfigurationService,
170+
editorGroupsService: IEditorGroupsService,
171+
) {
172+
if (keyMods?.alt || keyMods?.ctrlCmd) {
173+
const direction = preferredSideBySideGroupDirection(configurationService);
174+
const targetGroup = editorGroupsService.findGroup({ direction }, startingGroup.id);
175+
return targetGroup ?? editorGroupsService.addGroup(startingGroup, direction);
176+
}
177+
return startingGroup;
178+
}
179+
135180
/**
136181
* Get a list of all available editors, including the default text editor.
137182
*/

0 commit comments

Comments
 (0)