Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/browser/widget/diffEditor/commands.ts
5236 views
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 { getActiveElement } from '../../../../base/browser/dom.js';
7
import { Codicon } from '../../../../base/common/codicons.js';
8
import { KeyCode, KeyMod } from '../../../../base/common/keyCodes.js';
9
import { ICodeEditor, IDiffEditor } from '../../editorBrowser.js';
10
import { EditorAction2, ServicesAccessor } from '../../editorExtensions.js';
11
import { ICodeEditorService } from '../../services/codeEditorService.js';
12
import { DiffEditorWidget } from './diffEditorWidget.js';
13
import { EditorContextKeys } from '../../../common/editorContextKeys.js';
14
import { localize2 } from '../../../../nls.js';
15
import { ILocalizedString } from '../../../../platform/action/common/action.js';
16
import { Action2, MenuId } from '../../../../platform/actions/common/actions.js';
17
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
18
import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';
19
import { KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js';
20
import './registrations.contribution.js';
21
import { DiffEditorSelectionHunkToolbarContext } from './features/gutterFeature.js';
22
import { URI } from '../../../../base/common/uri.js';
23
import { EditorOption } from '../../../common/config/editorOptions.js';
24
25
export class ToggleCollapseUnchangedRegions extends Action2 {
26
constructor() {
27
super({
28
id: 'diffEditor.toggleCollapseUnchangedRegions',
29
title: localize2('toggleCollapseUnchangedRegions', 'Toggle Collapse Unchanged Regions'),
30
icon: Codicon.map,
31
toggled: ContextKeyExpr.has('config.diffEditor.hideUnchangedRegions.enabled'),
32
precondition: ContextKeyExpr.has('isInDiffEditor'),
33
menu: {
34
when: ContextKeyExpr.has('isInDiffEditor'),
35
id: MenuId.EditorTitle,
36
order: 22,
37
group: 'navigation',
38
},
39
});
40
}
41
42
run(accessor: ServicesAccessor, ...args: unknown[]): void {
43
const configurationService = accessor.get(IConfigurationService);
44
const newValue = !configurationService.getValue<boolean>('diffEditor.hideUnchangedRegions.enabled');
45
configurationService.updateValue('diffEditor.hideUnchangedRegions.enabled', newValue);
46
}
47
}
48
49
export class ToggleShowMovedCodeBlocks extends Action2 {
50
constructor() {
51
super({
52
id: 'diffEditor.toggleShowMovedCodeBlocks',
53
title: localize2('toggleShowMovedCodeBlocks', 'Toggle Show Moved Code Blocks'),
54
precondition: ContextKeyExpr.has('isInDiffEditor'),
55
});
56
}
57
58
run(accessor: ServicesAccessor, ...args: unknown[]): void {
59
const configurationService = accessor.get(IConfigurationService);
60
const newValue = !configurationService.getValue<boolean>('diffEditor.experimental.showMoves');
61
configurationService.updateValue('diffEditor.experimental.showMoves', newValue);
62
}
63
}
64
65
export class ToggleUseInlineViewWhenSpaceIsLimited extends Action2 {
66
constructor() {
67
super({
68
id: 'diffEditor.toggleUseInlineViewWhenSpaceIsLimited',
69
title: localize2('toggleUseInlineViewWhenSpaceIsLimited', 'Toggle Use Inline View When Space Is Limited'),
70
precondition: ContextKeyExpr.has('isInDiffEditor'),
71
});
72
}
73
74
run(accessor: ServicesAccessor, ...args: unknown[]): void {
75
const configurationService = accessor.get(IConfigurationService);
76
const newValue = !configurationService.getValue<boolean>('diffEditor.useInlineViewWhenSpaceIsLimited');
77
configurationService.updateValue('diffEditor.useInlineViewWhenSpaceIsLimited', newValue);
78
}
79
}
80
81
const diffEditorCategory: ILocalizedString = localize2('diffEditor', "Diff Editor");
82
83
export class SwitchSide extends EditorAction2 {
84
constructor() {
85
super({
86
id: 'diffEditor.switchSide',
87
title: localize2('switchSide', 'Switch Side'),
88
icon: Codicon.arrowSwap,
89
precondition: ContextKeyExpr.has('isInDiffEditor'),
90
f1: true,
91
category: diffEditorCategory,
92
});
93
}
94
95
runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, arg?: { dryRun: boolean }): unknown {
96
const diffEditor = findFocusedDiffEditor(accessor);
97
if (diffEditor instanceof DiffEditorWidget) {
98
if (arg && arg.dryRun) {
99
return { destinationSelection: diffEditor.mapToOtherSide().destinationSelection };
100
} else {
101
diffEditor.switchSide();
102
}
103
}
104
return undefined;
105
}
106
}
107
export class ExitCompareMove extends EditorAction2 {
108
constructor() {
109
super({
110
id: 'diffEditor.exitCompareMove',
111
title: localize2('exitCompareMove', 'Exit Compare Move'),
112
icon: Codicon.close,
113
precondition: EditorContextKeys.comparingMovedCode,
114
f1: false,
115
category: diffEditorCategory,
116
keybinding: {
117
weight: 10000,
118
primary: KeyCode.Escape,
119
}
120
});
121
}
122
123
runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, ...args: unknown[]): void {
124
const diffEditor = findFocusedDiffEditor(accessor);
125
if (diffEditor instanceof DiffEditorWidget) {
126
diffEditor.exitCompareMove();
127
}
128
}
129
}
130
131
export class CollapseAllUnchangedRegions extends EditorAction2 {
132
constructor() {
133
super({
134
id: 'diffEditor.collapseAllUnchangedRegions',
135
title: localize2('collapseAllUnchangedRegions', 'Collapse All Unchanged Regions'),
136
icon: Codicon.fold,
137
precondition: ContextKeyExpr.has('isInDiffEditor'),
138
f1: true,
139
category: diffEditorCategory,
140
});
141
}
142
143
runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, ...args: unknown[]): void {
144
const diffEditor = findFocusedDiffEditor(accessor);
145
if (diffEditor instanceof DiffEditorWidget) {
146
diffEditor.collapseAllUnchangedRegions();
147
}
148
}
149
}
150
151
export class ShowAllUnchangedRegions extends EditorAction2 {
152
constructor() {
153
super({
154
id: 'diffEditor.showAllUnchangedRegions',
155
title: localize2('showAllUnchangedRegions', 'Show All Unchanged Regions'),
156
icon: Codicon.unfold,
157
precondition: ContextKeyExpr.has('isInDiffEditor'),
158
f1: true,
159
category: diffEditorCategory,
160
});
161
}
162
163
runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, ...args: unknown[]): void {
164
const diffEditor = findFocusedDiffEditor(accessor);
165
if (diffEditor instanceof DiffEditorWidget) {
166
diffEditor.showAllUnchangedRegions();
167
}
168
}
169
}
170
171
export class RevertHunkOrSelection extends Action2 {
172
constructor() {
173
super({
174
id: 'diffEditor.revert',
175
title: localize2('revert', 'Revert'),
176
f1: true,
177
category: diffEditorCategory,
178
precondition: ContextKeyExpr.has('isInDiffEditor'),
179
});
180
}
181
182
run(accessor: ServicesAccessor, arg?: DiffEditorSelectionHunkToolbarContext): unknown {
183
return arg ? this.runViaToolbarContext(accessor, arg) : this.runViaCursorOrSelection(accessor);
184
}
185
186
runViaCursorOrSelection(accessor: ServicesAccessor): unknown {
187
const diffEditor = findFocusedDiffEditor(accessor);
188
if (diffEditor instanceof DiffEditorWidget) {
189
diffEditor.revertFocusedRangeMappings();
190
}
191
return undefined;
192
}
193
194
runViaToolbarContext(accessor: ServicesAccessor, arg: DiffEditorSelectionHunkToolbarContext): unknown {
195
const diffEditor = findDiffEditor(accessor, arg.originalUri, arg.modifiedUri);
196
if (diffEditor instanceof DiffEditorWidget) {
197
diffEditor.revertRangeMappings(arg.mapping.innerChanges ?? []);
198
}
199
return undefined;
200
}
201
}
202
203
const accessibleDiffViewerCategory: ILocalizedString = localize2('accessibleDiffViewer', "Accessible Diff Viewer");
204
205
export class AccessibleDiffViewerNext extends Action2 {
206
public static id = 'editor.action.accessibleDiffViewer.next';
207
208
constructor() {
209
super({
210
id: AccessibleDiffViewerNext.id,
211
title: localize2('editor.action.accessibleDiffViewer.next', 'Go to Next Difference'),
212
category: accessibleDiffViewerCategory,
213
precondition: ContextKeyExpr.has('isInDiffEditor'),
214
keybinding: {
215
primary: KeyCode.F7,
216
weight: KeybindingWeight.EditorContrib
217
},
218
f1: true,
219
});
220
}
221
222
public override run(accessor: ServicesAccessor): void {
223
const diffEditor = findFocusedDiffEditor(accessor);
224
diffEditor?.accessibleDiffViewerNext();
225
}
226
}
227
228
export class AccessibleDiffViewerPrev extends Action2 {
229
public static id = 'editor.action.accessibleDiffViewer.prev';
230
231
constructor() {
232
super({
233
id: AccessibleDiffViewerPrev.id,
234
title: localize2('editor.action.accessibleDiffViewer.prev', 'Go to Previous Difference'),
235
category: accessibleDiffViewerCategory,
236
precondition: ContextKeyExpr.has('isInDiffEditor'),
237
keybinding: {
238
primary: KeyMod.Shift | KeyCode.F7,
239
weight: KeybindingWeight.EditorContrib
240
},
241
f1: true,
242
});
243
}
244
245
public override run(accessor: ServicesAccessor): void {
246
const diffEditor = findFocusedDiffEditor(accessor);
247
diffEditor?.accessibleDiffViewerPrev();
248
}
249
}
250
251
export function findDiffEditor(accessor: ServicesAccessor, originalUri: URI, modifiedUri: URI): IDiffEditor | null {
252
const codeEditorService = accessor.get(ICodeEditorService);
253
const diffEditors = codeEditorService.listDiffEditors();
254
255
return diffEditors.find(diffEditor => {
256
const modified = diffEditor.getModifiedEditor();
257
const original = diffEditor.getOriginalEditor();
258
259
return modified && modified.getModel()?.uri.toString() === modifiedUri.toString()
260
&& original && original.getModel()?.uri.toString() === originalUri.toString();
261
}) || null;
262
}
263
264
export function findFocusedDiffEditor(accessor: ServicesAccessor): IDiffEditor | null {
265
const codeEditorService = accessor.get(ICodeEditorService);
266
const diffEditors = codeEditorService.listDiffEditors();
267
268
const activeElement = getActiveElement();
269
if (activeElement) {
270
for (const d of diffEditors) {
271
const container = d.getContainerDomNode();
272
if (container.contains(activeElement)) {
273
return d;
274
}
275
}
276
}
277
278
return null;
279
}
280
281
282
/**
283
* If `editor` is the original or modified editor of a diff editor, it returns it.
284
* It returns null otherwise.
285
*/
286
export function findDiffEditorContainingCodeEditor(accessor: ServicesAccessor, editor: ICodeEditor): IDiffEditor | null {
287
if (!editor.getOption(EditorOption.inDiffEditor)) {
288
return null;
289
}
290
291
const codeEditorService = accessor.get(ICodeEditorService);
292
293
for (const diffEditor of codeEditorService.listDiffEditors()) {
294
const originalEditor = diffEditor.getOriginalEditor();
295
const modifiedEditor = diffEditor.getModifiedEditor();
296
if (originalEditor === editor || modifiedEditor === editor) {
297
return diffEditor;
298
}
299
}
300
return null;
301
}
302
303