Skip to content

Commit 54f5758

Browse files
authored
Merge pull request microsoft#152364 from microsoft/3wm
2 parents 54003f8 + c3c62cb commit 54f5758

18 files changed

+1361
-1305
lines changed
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { Codicon } from 'vs/base/common/codicons';
7+
import { URI, UriComponents } from 'vs/base/common/uri';
8+
import { localize } from 'vs/nls';
9+
import { Action2, MenuId } from 'vs/platform/actions/common/actions';
10+
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
11+
import { MergeEditorInput, MergeEditorInputData } from 'vs/workbench/contrib/mergeEditor/browser/mergeEditorInput';
12+
import { ctxIsMergeEditor, ctxUsesColumnLayout, MergeEditor } from 'vs/workbench/contrib/mergeEditor/browser/view/mergeEditor';
13+
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
14+
15+
export class OpenMergeEditor extends Action2 {
16+
17+
constructor() {
18+
super({
19+
id: '_open.mergeEditor',
20+
title: localize('title', "Open Merge Editor"),
21+
});
22+
}
23+
run(accessor: ServicesAccessor, ...args: any[]): void {
24+
const validatedArgs = IRelaxedOpenArgs.validate(args[0]);
25+
26+
const instaService = accessor.get(IInstantiationService);
27+
const input = instaService.createInstance(
28+
MergeEditorInput,
29+
validatedArgs.ancestor,
30+
validatedArgs.input1,
31+
validatedArgs.input2,
32+
validatedArgs.output,
33+
);
34+
accessor.get(IEditorService).openEditor(input);
35+
}
36+
}
37+
38+
namespace IRelaxedOpenArgs {
39+
function toUri(obj: unknown): URI {
40+
if (typeof obj === 'string') {
41+
return URI.parse(obj, true);
42+
} else if (obj && typeof obj === 'object') {
43+
return URI.revive(<UriComponents>obj);
44+
}
45+
throw new TypeError('invalid argument');
46+
}
47+
48+
function isUriComponents(obj: unknown): obj is UriComponents {
49+
if (!obj || typeof obj !== 'object') {
50+
return false;
51+
}
52+
return typeof (<UriComponents>obj).scheme === 'string'
53+
&& typeof (<UriComponents>obj).authority === 'string'
54+
&& typeof (<UriComponents>obj).path === 'string'
55+
&& typeof (<UriComponents>obj).query === 'string'
56+
&& typeof (<UriComponents>obj).fragment === 'string';
57+
}
58+
59+
function toInputResource(obj: unknown): MergeEditorInputData {
60+
if (typeof obj === 'string') {
61+
return new MergeEditorInputData(URI.parse(obj, true), undefined, undefined);
62+
}
63+
if (!obj || typeof obj !== 'object') {
64+
throw new TypeError('invalid argument');
65+
}
66+
67+
if (isUriComponents(obj)) {
68+
return new MergeEditorInputData(URI.revive(obj), undefined, undefined);
69+
}
70+
71+
const uri = toUri((<IRelaxedInputData>obj).uri);
72+
const detail = (<IRelaxedInputData>obj).detail;
73+
const description = (<IRelaxedInputData>obj).description;
74+
return new MergeEditorInputData(uri, detail, description);
75+
}
76+
77+
export function validate(obj: unknown): IOpenEditorArgs {
78+
if (!obj || typeof obj !== 'object') {
79+
throw new TypeError('invalid argument');
80+
}
81+
const ancestor = toUri((<IRelaxedOpenArgs>obj).ancestor);
82+
const output = toUri((<IRelaxedOpenArgs>obj).output);
83+
const input1 = toInputResource((<IRelaxedOpenArgs>obj).input1);
84+
const input2 = toInputResource((<IRelaxedOpenArgs>obj).input2);
85+
return { ancestor, input1, input2, output };
86+
}
87+
}
88+
89+
type IRelaxedInputData = { uri: UriComponents; detail?: string; description?: string };
90+
91+
type IRelaxedOpenArgs = {
92+
ancestor: UriComponents | string;
93+
input1: IRelaxedInputData | string;
94+
input2: IRelaxedInputData | string;
95+
output: UriComponents | string;
96+
};
97+
98+
interface IOpenEditorArgs {
99+
ancestor: URI;
100+
input1: MergeEditorInputData;
101+
input2: MergeEditorInputData;
102+
output: URI;
103+
}
104+
105+
export class ToggleLayout extends Action2 {
106+
constructor() {
107+
super({
108+
id: 'merge.toggleLayout',
109+
title: localize('toggle.title', "Switch to column view"),
110+
icon: Codicon.layoutCentered,
111+
toggled: {
112+
condition: ctxUsesColumnLayout,
113+
icon: Codicon.layoutPanel,
114+
title: localize('toggle.title2', "Switch to 2 by 1 view"),
115+
},
116+
menu: [{
117+
id: MenuId.EditorTitle,
118+
when: ctxIsMergeEditor,
119+
group: 'navigation'
120+
}]
121+
});
122+
}
123+
124+
run(accessor: ServicesAccessor): void {
125+
const { activeEditorPane } = accessor.get(IEditorService);
126+
if (activeEditorPane instanceof MergeEditor) {
127+
activeEditorPane.toggleLayout();
128+
}
129+
}
130+
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { VSBuffer } from 'vs/base/common/buffer';
7+
import { Codicon } from 'vs/base/common/codicons';
8+
import { ITextModelService } from 'vs/editor/common/services/resolverService';
9+
import { localize } from 'vs/nls';
10+
import { Action2 } from 'vs/platform/actions/common/actions';
11+
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
12+
import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider';
13+
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
14+
import { INotificationService } from 'vs/platform/notification/common/notification';
15+
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
16+
import { MergeEditor } from 'vs/workbench/contrib/mergeEditor/browser/view/mergeEditor';
17+
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
18+
import { IWorkbenchFileService } from 'vs/workbench/services/files/common/files';
19+
import { URI } from 'vs/base/common/uri';
20+
import { MergeEditorInput } from 'vs/workbench/contrib/mergeEditor/browser/mergeEditorInput';
21+
22+
interface MergeEditorContents {
23+
languageId: string;
24+
base: string;
25+
input1: string;
26+
input2: string;
27+
result: string;
28+
}
29+
30+
export class MergeEditorCopyContentsToJSON extends Action2 {
31+
32+
constructor() {
33+
super({
34+
id: 'merge.dev.copyContents',
35+
title: localize('merge.dev.copyContents', "Developer Merge Editor: Copy Contents of Inputs, Base and Result as JSON"),
36+
icon: Codicon.layoutCentered,
37+
f1: true,
38+
});
39+
}
40+
41+
run(accessor: ServicesAccessor): void {
42+
const { activeEditorPane } = accessor.get(IEditorService);
43+
const clipboardService = accessor.get(IClipboardService);
44+
const notificationService = accessor.get(INotificationService);
45+
46+
if (!(activeEditorPane instanceof MergeEditor)) {
47+
notificationService.info({
48+
name: localize('mergeEditor.name', 'Merge Editor'),
49+
message: localize('mergeEditor.noActiveMergeEditor', "No active merge editor")
50+
});
51+
return;
52+
}
53+
const model = activeEditorPane.model;
54+
if (!model) {
55+
return;
56+
}
57+
const contents: MergeEditorContents = {
58+
languageId: model.result.getLanguageId(),
59+
base: model.base.getValue(),
60+
input1: model.input1.getValue(),
61+
input2: model.input2.getValue(),
62+
result: model.result.getValue(),
63+
};
64+
const jsonStr = JSON.stringify(contents, undefined, 4);
65+
clipboardService.writeText(jsonStr);
66+
67+
notificationService.info({
68+
name: localize('mergeEditor.name', 'Merge Editor'),
69+
message: localize('mergeEditor.successfullyCopiedMergeEditorContents', "Successfully copied merge editor contents"),
70+
});
71+
}
72+
}
73+
74+
export class MergeEditorOpenContents extends Action2 {
75+
76+
constructor() {
77+
super({
78+
id: 'merge.dev.openContents',
79+
title: localize('merge.dev.openContents', "Developer Merge Editor: Open Contents of Inputs, Base and Result from JSON"),
80+
icon: Codicon.layoutCentered,
81+
f1: true,
82+
});
83+
}
84+
85+
async run(accessor: ServicesAccessor): Promise<void> {
86+
const service = accessor.get(IWorkbenchFileService);
87+
const instaService = accessor.get(IInstantiationService);
88+
const editorService = accessor.get(IEditorService);
89+
const inputService = accessor.get(IQuickInputService);
90+
const clipboardService = accessor.get(IClipboardService);
91+
const textModelService = accessor.get(ITextModelService);
92+
93+
const result = await inputService.input({
94+
prompt: localize('mergeEditor.enterJSON', 'Enter JSON'),
95+
value: await clipboardService.readText(),
96+
});
97+
if (!result) {
98+
return;
99+
}
100+
101+
const content: MergeEditorContents = JSON.parse(result);
102+
103+
const scheme = 'merge-editor-dev';
104+
105+
let provider = service.getProvider(scheme) as InMemoryFileSystemProvider | undefined;
106+
if (!provider) {
107+
provider = new InMemoryFileSystemProvider();
108+
service.registerProvider(scheme, provider);
109+
}
110+
111+
const baseUri = URI.from({ scheme, path: '/ancestor' });
112+
const input1Uri = URI.from({ scheme, path: '/input1' });
113+
const input2Uri = URI.from({ scheme, path: '/input2' });
114+
const resultUri = URI.from({ scheme, path: '/result' });
115+
116+
function writeFile(uri: URI, content: string): Promise<void> {
117+
return provider!.writeFile(uri, VSBuffer.fromString(content).buffer, { create: true, overwrite: true, unlock: true });
118+
}
119+
120+
await Promise.all([
121+
writeFile(baseUri, content.base),
122+
writeFile(input1Uri, content.input1),
123+
writeFile(input2Uri, content.input2),
124+
writeFile(resultUri, content.result),
125+
]);
126+
127+
async function setLanguageId(uri: URI, languageId: string): Promise<void> {
128+
const ref = await textModelService.createModelReference(uri);
129+
ref.object.textEditorModel.setMode(languageId);
130+
ref.dispose();
131+
}
132+
133+
await Promise.all([
134+
setLanguageId(baseUri, content.languageId),
135+
setLanguageId(input1Uri, content.languageId),
136+
setLanguageId(input2Uri, content.languageId),
137+
setLanguageId(resultUri, content.languageId),
138+
]);
139+
140+
const input = instaService.createInstance(
141+
MergeEditorInput,
142+
baseUri,
143+
{ uri: input1Uri, description: 'Input 1', detail: '(from JSON)' },
144+
{ uri: input2Uri, description: 'Input 2', detail: '(from JSON)' },
145+
resultUri,
146+
);
147+
editorService.openEditor(input);
148+
}
149+
}

0 commit comments

Comments
 (0)