@codingame/monaco-vscode-views-service-override 1.85.0 → 1.85.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/index-no-csp.html +4 -0
- package/assets/index.html +5 -1
- package/index.d.ts +2 -2
- package/index.js +2 -2
- package/package.json +11 -9
- package/tools/editor.js +1 -1
- package/views.d.ts +9 -4
- package/views.js +32 -10
- package/vscode/src/vs/workbench/api/browser/viewsExtensionPoint.js +2 -2
- package/vscode/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.js +1 -1
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/commands/commands.js +692 -0
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/commands/devCommands.js +240 -0
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/mergeEditor.contribution.js +77 -0
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/mergeEditorSerializer.js +42 -0
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/colors.js +71 -0
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/conflictActions.js +346 -0
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/editorGutter.js +96 -0
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/editors/baseCodeEditorView.js +145 -0
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/editors/codeEditorView.js +103 -0
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/editors/inputCodeEditorView.js +399 -0
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/editors/resultCodeEditorView.js +196 -0
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/fixedZoneWidget.js +41 -0
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/lineAlignment.js +128 -0
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/media/mergeEditor.css.js +6 -0
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/mergeEditor.js +611 -0
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/scrollSynchronizer.js +158 -0
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/viewModel.js +262 -0
- package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/viewZones.js +173 -0
- package/vscode/src/vs/workbench/contrib/webview/browser/webview.contribution.js +79 -0
- package/vscode/src/vs/workbench/contrib/webview/browser/webviewFindWidget.js +1 -1
- package/vscode/src/vs/workbench/services/history/browser/historyService.js +3 -0
- package/override/vs/workbench/contrib/notebook/common/notebookEditorInput.js +0 -3
- package/vscode/src/vs/base/browser/ui/tree/treeDefaults.js +0 -16
- package/vscode/src/vs/workbench/browser/parts/views/checkbox.js +0 -107
- package/vscode/src/vs/workbench/browser/parts/views/media/views.css.js +0 -6
- package/vscode/src/vs/workbench/browser/parts/views/treeView.js +0 -1604
- package/vscode/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.css.js +0 -6
- package/vscode/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.js +0 -390
- package/vscode/src/vs/workbench/contrib/languageDetection/browser/languageDetection.contribution.js +0 -157
- package/vscode/src/vs/workbench/contrib/notebook/common/notebookContextKeys.js +0 -5
- package/vscode/src/vs/workbench/contrib/remote/browser/media/tunnelView.css.js +0 -6
- package/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.js +0 -217
- package/vscode/src/vs/workbench/contrib/remote/browser/remoteIcons.js +0 -91
- package/vscode/src/vs/workbench/contrib/remote/browser/tunnelView.js +0 -1837
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { Disposable } from 'monaco-editor/esm/vs/base/common/lifecycle.js';
|
|
2
|
+
import { autorunWithStore } from 'monaco-editor/esm/vs/base/common/observable.js';
|
|
3
|
+
import { DocumentLineRangeMap } from 'vscode/vscode/vs/workbench/contrib/mergeEditor/browser/model/mapping';
|
|
4
|
+
import { ReentrancyBarrier } from 'vscode/vscode/vs/workbench/contrib/mergeEditor/browser/utils';
|
|
5
|
+
|
|
6
|
+
class ScrollSynchronizer extends Disposable {
|
|
7
|
+
get model() { return this.viewModel.get()?.model; }
|
|
8
|
+
get shouldAlignResult() { return this.layout.get().kind === 'columns'; }
|
|
9
|
+
get shouldAlignBase() { return this.layout.get().kind === 'mixed' && !this.layout.get().showBaseAtTop; }
|
|
10
|
+
constructor(viewModel, input1View, input2View, baseView, inputResultView, layout) {
|
|
11
|
+
super();
|
|
12
|
+
this.viewModel = viewModel;
|
|
13
|
+
this.input1View = input1View;
|
|
14
|
+
this.input2View = input2View;
|
|
15
|
+
this.baseView = baseView;
|
|
16
|
+
this.inputResultView = inputResultView;
|
|
17
|
+
this.layout = layout;
|
|
18
|
+
this.reentrancyBarrier = ( new ReentrancyBarrier());
|
|
19
|
+
const handleInput1OnScroll = this.updateScrolling = () => {
|
|
20
|
+
if (!this.model) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
this.input2View.editor.setScrollTop(this.input1View.editor.getScrollTop(), 1 );
|
|
24
|
+
if (this.shouldAlignResult) {
|
|
25
|
+
this.inputResultView.editor.setScrollTop(this.input1View.editor.getScrollTop(), 1 );
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
const mappingInput1Result = this.model.input1ResultMapping.get();
|
|
29
|
+
this.synchronizeScrolling(this.input1View.editor, this.inputResultView.editor, mappingInput1Result);
|
|
30
|
+
}
|
|
31
|
+
const baseView = this.baseView.get();
|
|
32
|
+
if (baseView) {
|
|
33
|
+
if (this.shouldAlignBase) {
|
|
34
|
+
this.baseView.get()?.editor.setScrollTop(this.input1View.editor.getScrollTop(), 1 );
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
const mapping = ( new DocumentLineRangeMap(this.model.baseInput1Diffs.get(), -1)).reverse();
|
|
38
|
+
this.synchronizeScrolling(this.input1View.editor, baseView.editor, mapping);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
this._store.add(this.input1View.editor.onDidScrollChange(this.reentrancyBarrier.makeExclusive((c) => {
|
|
43
|
+
if (c.scrollTopChanged) {
|
|
44
|
+
handleInput1OnScroll();
|
|
45
|
+
}
|
|
46
|
+
if (c.scrollLeftChanged) {
|
|
47
|
+
this.baseView.get()?.editor.setScrollLeft(c.scrollLeft, 1 );
|
|
48
|
+
this.input2View.editor.setScrollLeft(c.scrollLeft, 1 );
|
|
49
|
+
this.inputResultView.editor.setScrollLeft(c.scrollLeft, 1 );
|
|
50
|
+
}
|
|
51
|
+
})));
|
|
52
|
+
this._store.add(this.input2View.editor.onDidScrollChange(this.reentrancyBarrier.makeExclusive((c) => {
|
|
53
|
+
if (!this.model) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (c.scrollTopChanged) {
|
|
57
|
+
this.input1View.editor.setScrollTop(c.scrollTop, 1 );
|
|
58
|
+
if (this.shouldAlignResult) {
|
|
59
|
+
this.inputResultView.editor.setScrollTop(this.input2View.editor.getScrollTop(), 1 );
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
const mappingInput2Result = this.model.input2ResultMapping.get();
|
|
63
|
+
this.synchronizeScrolling(this.input2View.editor, this.inputResultView.editor, mappingInput2Result);
|
|
64
|
+
}
|
|
65
|
+
const baseView = this.baseView.get();
|
|
66
|
+
if (baseView && this.model) {
|
|
67
|
+
if (this.shouldAlignBase) {
|
|
68
|
+
this.baseView.get()?.editor.setScrollTop(c.scrollTop, 1 );
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
const mapping = ( new DocumentLineRangeMap(this.model.baseInput2Diffs.get(), -1)).reverse();
|
|
72
|
+
this.synchronizeScrolling(this.input2View.editor, baseView.editor, mapping);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (c.scrollLeftChanged) {
|
|
77
|
+
this.baseView.get()?.editor.setScrollLeft(c.scrollLeft, 1 );
|
|
78
|
+
this.input1View.editor.setScrollLeft(c.scrollLeft, 1 );
|
|
79
|
+
this.inputResultView.editor.setScrollLeft(c.scrollLeft, 1 );
|
|
80
|
+
}
|
|
81
|
+
})));
|
|
82
|
+
this._store.add(this.inputResultView.editor.onDidScrollChange(this.reentrancyBarrier.makeExclusive((c) => {
|
|
83
|
+
if (c.scrollTopChanged) {
|
|
84
|
+
if (this.shouldAlignResult) {
|
|
85
|
+
this.input1View.editor.setScrollTop(c.scrollTop, 1 );
|
|
86
|
+
this.input2View.editor.setScrollTop(c.scrollTop, 1 );
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const mapping1 = this.model?.resultInput1Mapping.get();
|
|
90
|
+
this.synchronizeScrolling(this.inputResultView.editor, this.input1View.editor, mapping1);
|
|
91
|
+
const mapping2 = this.model?.resultInput2Mapping.get();
|
|
92
|
+
this.synchronizeScrolling(this.inputResultView.editor, this.input2View.editor, mapping2);
|
|
93
|
+
}
|
|
94
|
+
const baseMapping = this.model?.resultBaseMapping.get();
|
|
95
|
+
const baseView = this.baseView.get();
|
|
96
|
+
if (baseView && this.model) {
|
|
97
|
+
this.synchronizeScrolling(this.inputResultView.editor, baseView.editor, baseMapping);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (c.scrollLeftChanged) {
|
|
101
|
+
this.baseView.get()?.editor?.setScrollLeft(c.scrollLeft, 1 );
|
|
102
|
+
this.input1View.editor.setScrollLeft(c.scrollLeft, 1 );
|
|
103
|
+
this.input2View.editor.setScrollLeft(c.scrollLeft, 1 );
|
|
104
|
+
}
|
|
105
|
+
})));
|
|
106
|
+
this._store.add(autorunWithStore((reader, store) => {
|
|
107
|
+
const baseView = this.baseView.read(reader);
|
|
108
|
+
if (baseView) {
|
|
109
|
+
store.add(baseView.editor.onDidScrollChange(this.reentrancyBarrier.makeExclusive((c) => {
|
|
110
|
+
if (c.scrollTopChanged) {
|
|
111
|
+
if (!this.model) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (this.shouldAlignBase) {
|
|
115
|
+
this.input1View.editor.setScrollTop(c.scrollTop, 1 );
|
|
116
|
+
this.input2View.editor.setScrollTop(c.scrollTop, 1 );
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
const baseInput1Mapping = ( new DocumentLineRangeMap(this.model.baseInput1Diffs.get(), -1));
|
|
120
|
+
this.synchronizeScrolling(baseView.editor, this.input1View.editor, baseInput1Mapping);
|
|
121
|
+
const baseInput2Mapping = ( new DocumentLineRangeMap(this.model.baseInput2Diffs.get(), -1));
|
|
122
|
+
this.synchronizeScrolling(baseView.editor, this.input2View.editor, baseInput2Mapping);
|
|
123
|
+
}
|
|
124
|
+
const baseMapping = this.model?.baseResultMapping.get();
|
|
125
|
+
this.synchronizeScrolling(baseView.editor, this.inputResultView.editor, baseMapping);
|
|
126
|
+
}
|
|
127
|
+
if (c.scrollLeftChanged) {
|
|
128
|
+
this.inputResultView.editor.setScrollLeft(c.scrollLeft, 1 );
|
|
129
|
+
this.input1View.editor.setScrollLeft(c.scrollLeft, 1 );
|
|
130
|
+
this.input2View.editor.setScrollLeft(c.scrollLeft, 1 );
|
|
131
|
+
}
|
|
132
|
+
})));
|
|
133
|
+
}
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
136
|
+
synchronizeScrolling(scrollingEditor, targetEditor, mapping) {
|
|
137
|
+
if (!mapping) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const visibleRanges = scrollingEditor.getVisibleRanges();
|
|
141
|
+
if (visibleRanges.length === 0) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const topLineNumber = visibleRanges[0].startLineNumber - 1;
|
|
145
|
+
const result = mapping.project(topLineNumber);
|
|
146
|
+
const sourceRange = result.inputRange;
|
|
147
|
+
const targetRange = result.outputRange;
|
|
148
|
+
const resultStartTopPx = targetEditor.getTopForLineNumber(targetRange.startLineNumber);
|
|
149
|
+
const resultEndPx = targetEditor.getTopForLineNumber(targetRange.endLineNumberExclusive);
|
|
150
|
+
const sourceStartTopPx = scrollingEditor.getTopForLineNumber(sourceRange.startLineNumber);
|
|
151
|
+
const sourceEndPx = scrollingEditor.getTopForLineNumber(sourceRange.endLineNumberExclusive);
|
|
152
|
+
const factor = Math.min((scrollingEditor.getScrollTop() - sourceStartTopPx) / (sourceEndPx - sourceStartTopPx), 1);
|
|
153
|
+
const resultScrollPosition = resultStartTopPx + (resultEndPx - resultStartTopPx) * factor;
|
|
154
|
+
targetEditor.setScrollTop(resultScrollPosition, 1 );
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export { ScrollSynchronizer };
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { __decorate, __param } from '../../../../../../../../external/tslib/tslib.es6.js';
|
|
2
|
+
import { findLast } from 'monaco-editor/esm/vs/base/common/arraysFind.js';
|
|
3
|
+
import { Disposable } from 'monaco-editor/esm/vs/base/common/lifecycle.js';
|
|
4
|
+
import { observableValue, derivedObservableWithWritableCache, derived, transaction } from 'monaco-editor/esm/vs/base/common/observable.js';
|
|
5
|
+
import { Range } from 'monaco-editor/esm/vs/editor/common/core/range.js';
|
|
6
|
+
import { localizeWithPath } from 'monaco-editor/esm/vs/nls.js';
|
|
7
|
+
import { IConfigurationService } from 'monaco-editor/esm/vs/platform/configuration/common/configuration.js';
|
|
8
|
+
import { INotificationService } from 'monaco-editor/esm/vs/platform/notification/common/notification.js';
|
|
9
|
+
import { LineRange } from 'vscode/vscode/vs/workbench/contrib/mergeEditor/browser/model/lineRange';
|
|
10
|
+
import { observableConfigValue } from 'vscode/vscode/vs/workbench/contrib/mergeEditor/browser/utils';
|
|
11
|
+
|
|
12
|
+
let MergeEditorViewModel = class MergeEditorViewModel extends Disposable {
|
|
13
|
+
constructor(model, inputCodeEditorView1, inputCodeEditorView2, resultCodeEditorView, baseCodeEditorView, showNonConflictingChanges, configurationService, notificationService) {
|
|
14
|
+
super();
|
|
15
|
+
this.model = model;
|
|
16
|
+
this.inputCodeEditorView1 = inputCodeEditorView1;
|
|
17
|
+
this.inputCodeEditorView2 = inputCodeEditorView2;
|
|
18
|
+
this.resultCodeEditorView = resultCodeEditorView;
|
|
19
|
+
this.baseCodeEditorView = baseCodeEditorView;
|
|
20
|
+
this.showNonConflictingChanges = showNonConflictingChanges;
|
|
21
|
+
this.configurationService = configurationService;
|
|
22
|
+
this.notificationService = notificationService;
|
|
23
|
+
this.manuallySetActiveModifiedBaseRange = observableValue(this, { range: undefined, counter: 0 });
|
|
24
|
+
this.attachedHistory = this._register(( new AttachedHistory(this.model.resultTextModel)));
|
|
25
|
+
this.shouldUseAppendInsteadOfAccept = observableConfigValue('mergeEditor.shouldUseAppendInsteadOfAccept', false, this.configurationService);
|
|
26
|
+
this.counter = 0;
|
|
27
|
+
this.lastFocusedEditor = derivedObservableWithWritableCache(this, (reader, lastValue) => {
|
|
28
|
+
const editors = [
|
|
29
|
+
this.inputCodeEditorView1,
|
|
30
|
+
this.inputCodeEditorView2,
|
|
31
|
+
this.resultCodeEditorView,
|
|
32
|
+
this.baseCodeEditorView.read(reader),
|
|
33
|
+
];
|
|
34
|
+
const view = editors.find((e) => e && e.isFocused.read(reader));
|
|
35
|
+
return view ? { view, counter: this.counter++ } : lastValue || { view: undefined, counter: this.counter++ };
|
|
36
|
+
});
|
|
37
|
+
this.baseShowDiffAgainst = derived(this, reader => {
|
|
38
|
+
const lastFocusedEditor = this.lastFocusedEditor.read(reader);
|
|
39
|
+
if (lastFocusedEditor.view === this.inputCodeEditorView1) {
|
|
40
|
+
return 1;
|
|
41
|
+
}
|
|
42
|
+
else if (lastFocusedEditor.view === this.inputCodeEditorView2) {
|
|
43
|
+
return 2;
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
});
|
|
47
|
+
this.selectionInBase = derived(this, reader => {
|
|
48
|
+
const sourceEditor = this.lastFocusedEditor.read(reader).view;
|
|
49
|
+
if (!sourceEditor) {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
const selections = sourceEditor.selection.read(reader) || [];
|
|
53
|
+
const rangesInBase = ( selections.map((selection) => {
|
|
54
|
+
if (sourceEditor === this.inputCodeEditorView1) {
|
|
55
|
+
return this.model.translateInputRangeToBase(1, selection);
|
|
56
|
+
}
|
|
57
|
+
else if (sourceEditor === this.inputCodeEditorView2) {
|
|
58
|
+
return this.model.translateInputRangeToBase(2, selection);
|
|
59
|
+
}
|
|
60
|
+
else if (sourceEditor === this.resultCodeEditorView) {
|
|
61
|
+
return this.model.translateResultRangeToBase(selection);
|
|
62
|
+
}
|
|
63
|
+
else if (sourceEditor === this.baseCodeEditorView.read(reader)) {
|
|
64
|
+
return selection;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
return selection;
|
|
68
|
+
}
|
|
69
|
+
}));
|
|
70
|
+
return {
|
|
71
|
+
rangesInBase,
|
|
72
|
+
sourceEditor
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
this.activeModifiedBaseRange = derived(this, (reader) => {
|
|
76
|
+
const focusedEditor = this.lastFocusedEditor.read(reader);
|
|
77
|
+
const manualRange = this.manuallySetActiveModifiedBaseRange.read(reader);
|
|
78
|
+
if (manualRange.counter > focusedEditor.counter) {
|
|
79
|
+
return manualRange.range;
|
|
80
|
+
}
|
|
81
|
+
if (!focusedEditor.view) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const cursorLineNumber = focusedEditor.view.cursorLineNumber.read(reader);
|
|
85
|
+
if (!cursorLineNumber) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
const modifiedBaseRanges = this.model.modifiedBaseRanges.read(reader);
|
|
89
|
+
return modifiedBaseRanges.find((r) => {
|
|
90
|
+
const range = this.getRangeOfModifiedBaseRange(focusedEditor.view, r, reader);
|
|
91
|
+
return range.isEmpty
|
|
92
|
+
? range.startLineNumber === cursorLineNumber
|
|
93
|
+
: range.contains(cursorLineNumber);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
this._register(resultCodeEditorView.editor.onDidChangeModelContent(e => {
|
|
97
|
+
if (this.model.isApplyingEditInResult || e.isRedoing || e.isUndoing) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const baseRangeStates = [];
|
|
101
|
+
for (const change of e.changes) {
|
|
102
|
+
const rangeInBase = this.model.translateResultRangeToBase(Range.lift(change.range));
|
|
103
|
+
const baseRanges = this.model.findModifiedBaseRangesInRange(( new LineRange(
|
|
104
|
+
rangeInBase.startLineNumber,
|
|
105
|
+
rangeInBase.endLineNumber - rangeInBase.startLineNumber
|
|
106
|
+
)));
|
|
107
|
+
if (baseRanges.length === 1) {
|
|
108
|
+
const isHandled = this.model.isHandled(baseRanges[0]).get();
|
|
109
|
+
if (!isHandled) {
|
|
110
|
+
baseRangeStates.push(baseRanges[0]);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (baseRangeStates.length === 0) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const element = {
|
|
118
|
+
model: this.model,
|
|
119
|
+
redo() {
|
|
120
|
+
transaction(tx => {
|
|
121
|
+
for (const r of baseRangeStates) {
|
|
122
|
+
this.model.setHandled(r, true, tx);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
},
|
|
126
|
+
undo() {
|
|
127
|
+
transaction(tx => {
|
|
128
|
+
for (const r of baseRangeStates) {
|
|
129
|
+
this.model.setHandled(r, false, tx);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
this.attachedHistory.pushAttachedHistoryElement(element);
|
|
135
|
+
element.redo();
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
getRangeOfModifiedBaseRange(editor, modifiedBaseRange, reader) {
|
|
139
|
+
if (editor === this.resultCodeEditorView) {
|
|
140
|
+
return this.model.getLineRangeInResult(modifiedBaseRange.baseRange, reader);
|
|
141
|
+
}
|
|
142
|
+
else if (editor === this.baseCodeEditorView.get()) {
|
|
143
|
+
return modifiedBaseRange.baseRange;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
const input = editor === this.inputCodeEditorView1 ? 1 : 2;
|
|
147
|
+
return modifiedBaseRange.getInputRange(input);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
setActiveModifiedBaseRange(range, tx) {
|
|
151
|
+
this.manuallySetActiveModifiedBaseRange.set({ range, counter: this.counter++ }, tx);
|
|
152
|
+
}
|
|
153
|
+
setState(baseRange, state, tx, inputNumber) {
|
|
154
|
+
this.manuallySetActiveModifiedBaseRange.set({ range: baseRange, counter: this.counter++ }, tx);
|
|
155
|
+
this.model.setState(baseRange, state, inputNumber, tx);
|
|
156
|
+
}
|
|
157
|
+
goToConflict(getModifiedBaseRange) {
|
|
158
|
+
let editor = this.lastFocusedEditor.get().view;
|
|
159
|
+
if (!editor) {
|
|
160
|
+
editor = this.resultCodeEditorView;
|
|
161
|
+
}
|
|
162
|
+
const curLineNumber = editor.editor.getPosition()?.lineNumber;
|
|
163
|
+
if (curLineNumber === undefined) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const modifiedBaseRange = getModifiedBaseRange(editor, curLineNumber);
|
|
167
|
+
if (modifiedBaseRange) {
|
|
168
|
+
const range = this.getRangeOfModifiedBaseRange(editor, modifiedBaseRange, undefined);
|
|
169
|
+
editor.editor.focus();
|
|
170
|
+
let startLineNumber = range.startLineNumber;
|
|
171
|
+
let endLineNumberExclusive = range.endLineNumberExclusive;
|
|
172
|
+
if (range.startLineNumber > editor.editor.getModel().getLineCount()) {
|
|
173
|
+
transaction(tx => {
|
|
174
|
+
this.setActiveModifiedBaseRange(modifiedBaseRange, tx);
|
|
175
|
+
});
|
|
176
|
+
startLineNumber = endLineNumberExclusive = editor.editor.getModel().getLineCount();
|
|
177
|
+
}
|
|
178
|
+
editor.editor.setPosition({
|
|
179
|
+
lineNumber: startLineNumber,
|
|
180
|
+
column: editor.editor.getModel().getLineFirstNonWhitespaceColumn(startLineNumber),
|
|
181
|
+
});
|
|
182
|
+
editor.editor.revealLinesNearTop(startLineNumber, endLineNumberExclusive, 0 );
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
goToNextModifiedBaseRange(predicate) {
|
|
186
|
+
this.goToConflict((e, l) => this.model.modifiedBaseRanges
|
|
187
|
+
.get()
|
|
188
|
+
.find((r) => predicate(r) &&
|
|
189
|
+
this.getRangeOfModifiedBaseRange(e, r, undefined).startLineNumber > l) ||
|
|
190
|
+
this.model.modifiedBaseRanges
|
|
191
|
+
.get()
|
|
192
|
+
.find((r) => predicate(r)));
|
|
193
|
+
}
|
|
194
|
+
goToPreviousModifiedBaseRange(predicate) {
|
|
195
|
+
this.goToConflict((e, l) => findLast(this.model.modifiedBaseRanges.get(), (r) => predicate(r) &&
|
|
196
|
+
this.getRangeOfModifiedBaseRange(e, r, undefined).endLineNumberExclusive < l) ||
|
|
197
|
+
findLast(this.model.modifiedBaseRanges.get(), (r) => predicate(r)));
|
|
198
|
+
}
|
|
199
|
+
toggleActiveConflict(inputNumber) {
|
|
200
|
+
const activeModifiedBaseRange = this.activeModifiedBaseRange.get();
|
|
201
|
+
if (!activeModifiedBaseRange) {
|
|
202
|
+
this.notificationService.error(( localizeWithPath(
|
|
203
|
+
'vs/workbench/contrib/mergeEditor/browser/view/viewModel',
|
|
204
|
+
'noConflictMessage',
|
|
205
|
+
"There is currently no conflict focused that can be toggled."
|
|
206
|
+
)));
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
transaction(tx => {
|
|
210
|
+
this.setState(activeModifiedBaseRange, this.model.getState(activeModifiedBaseRange).get().toggle(inputNumber), tx, inputNumber);
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
acceptAll(inputNumber) {
|
|
214
|
+
transaction(tx => {
|
|
215
|
+
for (const range of this.model.modifiedBaseRanges.get()) {
|
|
216
|
+
this.setState(range, this.model.getState(range).get().withInputValue(inputNumber, true), tx, inputNumber);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
MergeEditorViewModel = ( __decorate([
|
|
222
|
+
( __param(6, IConfigurationService)),
|
|
223
|
+
( __param(7, INotificationService))
|
|
224
|
+
], MergeEditorViewModel));
|
|
225
|
+
class AttachedHistory extends Disposable {
|
|
226
|
+
constructor(model) {
|
|
227
|
+
super();
|
|
228
|
+
this.model = model;
|
|
229
|
+
this.attachedHistory = [];
|
|
230
|
+
this.previousAltId = this.model.getAlternativeVersionId();
|
|
231
|
+
this._register(model.onDidChangeContent((e) => {
|
|
232
|
+
const currentAltId = model.getAlternativeVersionId();
|
|
233
|
+
if (e.isRedoing) {
|
|
234
|
+
for (const item of this.attachedHistory) {
|
|
235
|
+
if (this.previousAltId < item.altId && item.altId <= currentAltId) {
|
|
236
|
+
item.element.redo();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
else if (e.isUndoing) {
|
|
241
|
+
for (let i = this.attachedHistory.length - 1; i >= 0; i--) {
|
|
242
|
+
const item = this.attachedHistory[i];
|
|
243
|
+
if (currentAltId < item.altId && item.altId <= this.previousAltId) {
|
|
244
|
+
item.element.undo();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
while (this.attachedHistory.length > 0
|
|
250
|
+
&& this.attachedHistory[this.attachedHistory.length - 1].altId > this.previousAltId) {
|
|
251
|
+
this.attachedHistory.pop();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
this.previousAltId = currentAltId;
|
|
255
|
+
}));
|
|
256
|
+
}
|
|
257
|
+
pushAttachedHistoryElement(element) {
|
|
258
|
+
this.attachedHistory.push({ altId: this.model.getAlternativeVersionId(), element });
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export { MergeEditorViewModel };
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { $ } from 'monaco-editor/esm/vs/base/browser/dom.js';
|
|
2
|
+
import { CompareResult, lastOrDefault } from 'monaco-editor/esm/vs/base/common/arrays.js';
|
|
3
|
+
import { LineRange } from 'vscode/vscode/vs/workbench/contrib/mergeEditor/browser/model/lineRange';
|
|
4
|
+
import { join } from 'vscode/vscode/vs/workbench/contrib/mergeEditor/browser/utils';
|
|
5
|
+
import { ConflictActionsFactory, ActionsSource } from './conflictActions.js';
|
|
6
|
+
import { getAlignments } from './lineAlignment.js';
|
|
7
|
+
|
|
8
|
+
class ViewZoneComputer {
|
|
9
|
+
constructor(input1Editor, input2Editor, resultEditor) {
|
|
10
|
+
this.input1Editor = input1Editor;
|
|
11
|
+
this.input2Editor = input2Editor;
|
|
12
|
+
this.resultEditor = resultEditor;
|
|
13
|
+
this.conflictActionsFactoryInput1 = ( new ConflictActionsFactory(this.input1Editor));
|
|
14
|
+
this.conflictActionsFactoryInput2 = ( new ConflictActionsFactory(this.input2Editor));
|
|
15
|
+
this.conflictActionsFactoryResult = ( new ConflictActionsFactory(this.resultEditor));
|
|
16
|
+
}
|
|
17
|
+
computeViewZones(reader, viewModel, options) {
|
|
18
|
+
let input1LinesAdded = 0;
|
|
19
|
+
let input2LinesAdded = 0;
|
|
20
|
+
let baseLinesAdded = 0;
|
|
21
|
+
let resultLinesAdded = 0;
|
|
22
|
+
const input1ViewZones = [];
|
|
23
|
+
const input2ViewZones = [];
|
|
24
|
+
const baseViewZones = [];
|
|
25
|
+
const resultViewZones = [];
|
|
26
|
+
const model = viewModel.model;
|
|
27
|
+
const resultDiffs = model.baseResultDiffs.read(reader);
|
|
28
|
+
const baseRangeWithStoreAndTouchingDiffs = join(model.modifiedBaseRanges.read(reader), resultDiffs, (baseRange, diff) => baseRange.baseRange.touches(diff.inputRange)
|
|
29
|
+
? CompareResult.neitherLessOrGreaterThan
|
|
30
|
+
: LineRange.compareByStart(baseRange.baseRange, diff.inputRange));
|
|
31
|
+
const shouldShowCodeLenses = options.codeLensesVisible;
|
|
32
|
+
const showNonConflictingChanges = options.showNonConflictingChanges;
|
|
33
|
+
let lastModifiedBaseRange = undefined;
|
|
34
|
+
let lastBaseResultDiff = undefined;
|
|
35
|
+
for (const m of baseRangeWithStoreAndTouchingDiffs) {
|
|
36
|
+
if (shouldShowCodeLenses && m.left && (m.left.isConflicting || showNonConflictingChanges || !model.isHandled(m.left).read(reader))) {
|
|
37
|
+
const actions = ( new ActionsSource(viewModel, m.left));
|
|
38
|
+
if (options.shouldAlignResult || !actions.inputIsEmpty.read(reader)) {
|
|
39
|
+
input1ViewZones.push(( new CommandViewZone(
|
|
40
|
+
this.conflictActionsFactoryInput1,
|
|
41
|
+
m.left.input1Range.startLineNumber - 1,
|
|
42
|
+
actions.itemsInput1
|
|
43
|
+
)));
|
|
44
|
+
input2ViewZones.push(( new CommandViewZone(
|
|
45
|
+
this.conflictActionsFactoryInput2,
|
|
46
|
+
m.left.input2Range.startLineNumber - 1,
|
|
47
|
+
actions.itemsInput2
|
|
48
|
+
)));
|
|
49
|
+
if (options.shouldAlignBase) {
|
|
50
|
+
baseViewZones.push(( new Placeholder(m.left.baseRange.startLineNumber - 1, 16)));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const afterLineNumber = m.left.baseRange.startLineNumber + (lastBaseResultDiff?.resultingDeltaFromOriginalToModified ?? 0) - 1;
|
|
54
|
+
resultViewZones.push(( new CommandViewZone(this.conflictActionsFactoryResult, afterLineNumber, actions.resultItems)));
|
|
55
|
+
}
|
|
56
|
+
const lastResultDiff = lastOrDefault(m.rights);
|
|
57
|
+
if (lastResultDiff) {
|
|
58
|
+
lastBaseResultDiff = lastResultDiff;
|
|
59
|
+
}
|
|
60
|
+
let alignedLines;
|
|
61
|
+
if (m.left) {
|
|
62
|
+
alignedLines = ( getAlignments(m.left).map(a => ({
|
|
63
|
+
input1Line: a[0],
|
|
64
|
+
baseLine: a[1],
|
|
65
|
+
input2Line: a[2],
|
|
66
|
+
resultLine: undefined,
|
|
67
|
+
})));
|
|
68
|
+
lastModifiedBaseRange = m.left;
|
|
69
|
+
alignedLines[alignedLines.length - 1].resultLine =
|
|
70
|
+
m.left.baseRange.endLineNumberExclusive
|
|
71
|
+
+ (lastBaseResultDiff ? lastBaseResultDiff.resultingDeltaFromOriginalToModified : 0);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
alignedLines = [{
|
|
75
|
+
baseLine: lastResultDiff.inputRange.endLineNumberExclusive,
|
|
76
|
+
input1Line: lastResultDiff.inputRange.endLineNumberExclusive + (lastModifiedBaseRange ? (lastModifiedBaseRange.input1Range.endLineNumberExclusive - lastModifiedBaseRange.baseRange.endLineNumberExclusive) : 0),
|
|
77
|
+
input2Line: lastResultDiff.inputRange.endLineNumberExclusive + (lastModifiedBaseRange ? (lastModifiedBaseRange.input2Range.endLineNumberExclusive - lastModifiedBaseRange.baseRange.endLineNumberExclusive) : 0),
|
|
78
|
+
resultLine: lastResultDiff.outputRange.endLineNumberExclusive,
|
|
79
|
+
}];
|
|
80
|
+
}
|
|
81
|
+
for (const { input1Line, baseLine, input2Line, resultLine } of alignedLines) {
|
|
82
|
+
if (!options.shouldAlignBase && (input1Line === undefined || input2Line === undefined)) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const input1Line_ = input1Line !== undefined ? input1Line + input1LinesAdded : -1;
|
|
86
|
+
const input2Line_ = input2Line !== undefined ? input2Line + input2LinesAdded : -1;
|
|
87
|
+
const baseLine_ = baseLine + baseLinesAdded;
|
|
88
|
+
const resultLine_ = resultLine !== undefined ? resultLine + resultLinesAdded : -1;
|
|
89
|
+
const max = Math.max(options.shouldAlignBase ? baseLine_ : 0, input1Line_, input2Line_, options.shouldAlignResult ? resultLine_ : 0);
|
|
90
|
+
if (input1Line !== undefined) {
|
|
91
|
+
const diffInput1 = max - input1Line_;
|
|
92
|
+
if (diffInput1 > 0) {
|
|
93
|
+
input1ViewZones.push(( new Spacer(input1Line - 1, diffInput1)));
|
|
94
|
+
input1LinesAdded += diffInput1;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (input2Line !== undefined) {
|
|
98
|
+
const diffInput2 = max - input2Line_;
|
|
99
|
+
if (diffInput2 > 0) {
|
|
100
|
+
input2ViewZones.push(( new Spacer(input2Line - 1, diffInput2)));
|
|
101
|
+
input2LinesAdded += diffInput2;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (options.shouldAlignBase) {
|
|
105
|
+
const diffBase = max - baseLine_;
|
|
106
|
+
if (diffBase > 0) {
|
|
107
|
+
baseViewZones.push(( new Spacer(baseLine - 1, diffBase)));
|
|
108
|
+
baseLinesAdded += diffBase;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (options.shouldAlignResult && resultLine !== undefined) {
|
|
112
|
+
const diffResult = max - resultLine_;
|
|
113
|
+
if (diffResult > 0) {
|
|
114
|
+
resultViewZones.push(( new Spacer(resultLine - 1, diffResult)));
|
|
115
|
+
resultLinesAdded += diffResult;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return ( new MergeEditorViewZones(input1ViewZones, input2ViewZones, baseViewZones, resultViewZones));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
class MergeEditorViewZones {
|
|
124
|
+
constructor(input1ViewZones, input2ViewZones, baseViewZones, resultViewZones) {
|
|
125
|
+
this.input1ViewZones = input1ViewZones;
|
|
126
|
+
this.input2ViewZones = input2ViewZones;
|
|
127
|
+
this.baseViewZones = baseViewZones;
|
|
128
|
+
this.resultViewZones = resultViewZones;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
class MergeEditorViewZone {
|
|
132
|
+
}
|
|
133
|
+
class Spacer extends MergeEditorViewZone {
|
|
134
|
+
constructor(afterLineNumber, heightInLines) {
|
|
135
|
+
super();
|
|
136
|
+
this.afterLineNumber = afterLineNumber;
|
|
137
|
+
this.heightInLines = heightInLines;
|
|
138
|
+
}
|
|
139
|
+
create(viewZoneChangeAccessor, viewZoneIdsToCleanUp, disposableStore) {
|
|
140
|
+
viewZoneIdsToCleanUp.push(viewZoneChangeAccessor.addZone({
|
|
141
|
+
afterLineNumber: this.afterLineNumber,
|
|
142
|
+
heightInLines: this.heightInLines,
|
|
143
|
+
domNode: $('div.diagonal-fill'),
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
class Placeholder extends MergeEditorViewZone {
|
|
148
|
+
constructor(afterLineNumber, heightPx) {
|
|
149
|
+
super();
|
|
150
|
+
this.afterLineNumber = afterLineNumber;
|
|
151
|
+
this.heightPx = heightPx;
|
|
152
|
+
}
|
|
153
|
+
create(viewZoneChangeAccessor, viewZoneIdsToCleanUp, disposableStore) {
|
|
154
|
+
viewZoneIdsToCleanUp.push(viewZoneChangeAccessor.addZone({
|
|
155
|
+
afterLineNumber: this.afterLineNumber,
|
|
156
|
+
heightInPx: this.heightPx,
|
|
157
|
+
domNode: $('div.conflict-actions-placeholder'),
|
|
158
|
+
}));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
class CommandViewZone extends MergeEditorViewZone {
|
|
162
|
+
constructor(conflictActionsFactory, lineNumber, items) {
|
|
163
|
+
super();
|
|
164
|
+
this.conflictActionsFactory = conflictActionsFactory;
|
|
165
|
+
this.lineNumber = lineNumber;
|
|
166
|
+
this.items = items;
|
|
167
|
+
}
|
|
168
|
+
create(viewZoneChangeAccessor, viewZoneIdsToCleanUp, disposableStore) {
|
|
169
|
+
disposableStore.add(this.conflictActionsFactory.createWidget(viewZoneChangeAccessor, this.lineNumber, this.items, viewZoneIdsToCleanUp));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export { MergeEditorViewZone, MergeEditorViewZones, ViewZoneComputer };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { getActiveElement } from 'monaco-editor/esm/vs/base/browser/dom.js';
|
|
2
|
+
import { UndoCommand, RedoCommand, SelectAllCommand } from 'monaco-editor/esm/vs/editor/browser/editorExtensions.js';
|
|
3
|
+
import { CutAction, CopyAction, PasteAction } from 'monaco-editor/esm/vs/editor/contrib/clipboard/browser/clipboard.js';
|
|
4
|
+
import * as nls from 'monaco-editor/esm/vs/nls.js';
|
|
5
|
+
import { MenuRegistry, MenuId } from 'monaco-editor/esm/vs/platform/actions/common/actions.js';
|
|
6
|
+
import { ContextKeyExpr } from 'monaco-editor/esm/vs/platform/contextkey/common/contextkey.js';
|
|
7
|
+
import { IWebviewService } from 'vscode/vscode/vs/workbench/contrib/webview/browser/webview';
|
|
8
|
+
import { WebviewInput } from 'vscode/vscode/vs/workbench/contrib/webviewPanel/browser/webviewEditorInput';
|
|
9
|
+
import { IEditorService } from 'vscode/vscode/vs/workbench/services/editor/common/editorService';
|
|
10
|
+
|
|
11
|
+
const PRIORITY = 100;
|
|
12
|
+
function overrideCommandForWebview(command, f) {
|
|
13
|
+
command?.addImplementation(PRIORITY, 'webview', accessor => {
|
|
14
|
+
const webviewService = accessor.get(IWebviewService);
|
|
15
|
+
const webview = webviewService.activeWebview;
|
|
16
|
+
if (webview?.isFocused) {
|
|
17
|
+
f(webview);
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
if (getActiveElement()?.classList.contains('action-menu-item')) {
|
|
21
|
+
const editorService = accessor.get(IEditorService);
|
|
22
|
+
if (editorService.activeEditor instanceof WebviewInput) {
|
|
23
|
+
f(editorService.activeEditor.webview);
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
overrideCommandForWebview(UndoCommand, webview => webview.undo());
|
|
31
|
+
overrideCommandForWebview(RedoCommand, webview => webview.redo());
|
|
32
|
+
overrideCommandForWebview(SelectAllCommand, webview => webview.selectAll());
|
|
33
|
+
overrideCommandForWebview(CopyAction, webview => webview.copy());
|
|
34
|
+
overrideCommandForWebview(PasteAction, webview => webview.paste());
|
|
35
|
+
overrideCommandForWebview(CutAction, webview => webview.cut());
|
|
36
|
+
const PreventDefaultContextMenuItemsContextKeyName = 'preventDefaultContextMenuItems';
|
|
37
|
+
if (CutAction) {
|
|
38
|
+
MenuRegistry.appendMenuItem(MenuId.WebviewContext, {
|
|
39
|
+
command: {
|
|
40
|
+
id: CutAction.id,
|
|
41
|
+
title: ( nls.localizeWithPath('vs/workbench/contrib/webview/browser/webview.contribution', 'cut', "Cut")),
|
|
42
|
+
},
|
|
43
|
+
group: '5_cutcopypaste',
|
|
44
|
+
order: 1,
|
|
45
|
+
when: ContextKeyExpr.not(PreventDefaultContextMenuItemsContextKeyName),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (CopyAction) {
|
|
49
|
+
MenuRegistry.appendMenuItem(MenuId.WebviewContext, {
|
|
50
|
+
command: {
|
|
51
|
+
id: CopyAction.id,
|
|
52
|
+
title: ( nls.localizeWithPath(
|
|
53
|
+
'vs/workbench/contrib/webview/browser/webview.contribution',
|
|
54
|
+
'copy',
|
|
55
|
+
"Copy"
|
|
56
|
+
)),
|
|
57
|
+
},
|
|
58
|
+
group: '5_cutcopypaste',
|
|
59
|
+
order: 2,
|
|
60
|
+
when: ContextKeyExpr.not(PreventDefaultContextMenuItemsContextKeyName),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (PasteAction) {
|
|
64
|
+
MenuRegistry.appendMenuItem(MenuId.WebviewContext, {
|
|
65
|
+
command: {
|
|
66
|
+
id: PasteAction.id,
|
|
67
|
+
title: ( nls.localizeWithPath(
|
|
68
|
+
'vs/workbench/contrib/webview/browser/webview.contribution',
|
|
69
|
+
'paste',
|
|
70
|
+
"Paste"
|
|
71
|
+
)),
|
|
72
|
+
},
|
|
73
|
+
group: '5_cutcopypaste',
|
|
74
|
+
order: 3,
|
|
75
|
+
when: ContextKeyExpr.not(PreventDefaultContextMenuItemsContextKeyName),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { PreventDefaultContextMenuItemsContextKeyName };
|