Skip to content

Commit ba158cc

Browse files
authored
Merge pull request microsoft#183535 from microsoft/hediet/diff-editor-wip
First draft of diff editor v2.
2 parents 3b7c49c + 397f2e7 commit ba158cc

29 files changed

+2169
-43
lines changed

build/lib/stylelint/vscode-known-variables.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
"--vscode-commandCenter-foreground",
5252
"--vscode-commandCenter-inactiveBorder",
5353
"--vscode-commandCenter-inactiveForeground",
54+
"--vscode-commentsView-resolvedIcon",
55+
"--vscode-commentsView-unresolvedIcon",
5456
"--vscode-contrastActiveBorder",
5557
"--vscode-contrastBorder",
5658
"--vscode-debugConsole-errorForeground",
@@ -97,6 +99,7 @@
9799
"--vscode-diffEditor-removedLineBackground",
98100
"--vscode-diffEditor-removedTextBackground",
99101
"--vscode-diffEditor-removedTextBorder",
102+
"--vscode-diffEditor-unchangedRegionBackground",
100103
"--vscode-diffEditorGutter-insertedLineBackground",
101104
"--vscode-diffEditorGutter-removedLineBackground",
102105
"--vscode-diffEditorOverview-insertedForeground",
@@ -233,6 +236,8 @@
233236
"--vscode-editorOverviewRuler-background",
234237
"--vscode-editorOverviewRuler-border",
235238
"--vscode-editorOverviewRuler-bracketMatchForeground",
239+
"--vscode-editorOverviewRuler-commentForeground",
240+
"--vscode-editorOverviewRuler-commentUnresolvedForeground",
236241
"--vscode-editorOverviewRuler-commonContentForeground",
237242
"--vscode-editorOverviewRuler-currentContentForeground",
238243
"--vscode-editorOverviewRuler-deletedForeground",
@@ -309,6 +314,8 @@
309314
"--vscode-interactiveEditor-border",
310315
"--vscode-interactiveEditor-regionHighlight",
311316
"--vscode-interactiveEditor-shadow",
317+
"--vscode-interactiveEditorDiff-inserted",
318+
"--vscode-interactiveEditorDiff-removed",
312319
"--vscode-interactiveEditorInput-background",
313320
"--vscode-interactiveEditorInput-border",
314321
"--vscode-interactiveEditorInput-focusBorder",
@@ -457,7 +464,6 @@
457464
"--vscode-problemsErrorIcon-foreground",
458465
"--vscode-problemsInfoIcon-foreground",
459466
"--vscode-problemsWarningIcon-foreground",
460-
"--vscode-problemsSuccessIcon-foreground",
461467
"--vscode-profileBadge-background",
462468
"--vscode-profileBadge-foreground",
463469
"--vscode-progressBar-background",
@@ -520,6 +526,8 @@
520526
"--vscode-statusBar-noFolderBackground",
521527
"--vscode-statusBar-noFolderBorder",
522528
"--vscode-statusBar-noFolderForeground",
529+
"--vscode-statusBar-offlineBackground",
530+
"--vscode-statusBar-offlineForeground",
523531
"--vscode-statusBarItem-activeBackground",
524532
"--vscode-statusBarItem-compactHoverBackground",
525533
"--vscode-statusBarItem-errorBackground",
@@ -733,4 +741,4 @@
733741
"--z-index-run-button-container",
734742
"--zoom-factor"
735743
]
736-
}
744+
}

src/vs/base/browser/dom.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1865,7 +1865,7 @@ export function h(tag: string, ...args: [] | [attributes: { $: string } & Partia
18651865
el.appendChild(c);
18661866
} else if (typeof c === 'string') {
18671867
el.append(c);
1868-
} else {
1868+
} else if ('root' in c) {
18691869
Object.assign(result, c);
18701870
el.appendChild(c.root);
18711871
}

src/vs/editor/browser/editorBrowser.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,16 @@ export interface IDiffEditor extends editorCommon.IEditor {
12161216
* @internal
12171217
*/
12181218
setBoundarySashes(sashes: IBoundarySashes): void;
1219+
1220+
/**
1221+
* @internal
1222+
*/
1223+
goToDiff(target: 'next' | 'previous'): void;
1224+
1225+
/**
1226+
* @internal
1227+
*/
1228+
revealFirstDiff(): unknown;
12191229
}
12201230

12211231
/**

src/vs/editor/browser/widget/diffEditorWidget.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import { getThemeTypeSelector, IColorTheme, IThemeService, registerThemingPartic
6060
import { ThemeIcon } from 'vs/base/common/themables';
6161
import { MarkdownString } from 'vs/base/common/htmlContent';
6262
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
63+
import { DiffNavigator } from 'vs/editor/browser/widget/diffNavigator';
6364

6465
export interface IDiffCodeEditorWidgetOptions {
6566
originalEditor?: ICodeEditorWidgetOptions;
@@ -242,6 +243,8 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
242243

243244
private isEmbeddedDiffEditorKey: IContextKey<boolean>;
244245

246+
private _diffNavigator: DiffNavigator | undefined;
247+
245248
constructor(
246249
domElement: HTMLElement,
247250
options: Readonly<editorBrowser.IDiffEditorConstructionOptions>,
@@ -289,7 +292,10 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
289292
renderOverviewRuler: true,
290293
diffWordWrap: 'inherit',
291294
diffAlgorithm: 'advanced',
292-
accessibilityVerbose: false
295+
accessibilityVerbose: false,
296+
experimental: {
297+
collapseUnchangedRegions: false,
298+
},
293299
});
294300

295301
this.isEmbeddedDiffEditorKey = EditorContextKeys.isEmbeddedDiffEditor.bindTo(this._contextKeyService);
@@ -860,6 +866,12 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
860866
this._layoutOverviewViewport();
861867

862868
this._onDidChangeModel.fire();
869+
870+
// Diff navigator
871+
this._diffNavigator = this._register(this._instantiationService.createInstance(DiffNavigator, this, {
872+
alwaysRevealFirst: false,
873+
findResultLoop: this.getModifiedEditor().getOption(EditorOption.find).loop
874+
}));
863875
}
864876

865877
public getContainerDomNode(): HTMLElement {
@@ -1536,6 +1548,21 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
15361548
equivalentLineNumber: this._getEquivalentLineForModifiedLineNumber(lineNumber)
15371549
};
15381550
}
1551+
1552+
public goToDiff(target: 'previous' | 'next'): void {
1553+
if (target === 'next') {
1554+
this._diffNavigator?.next();
1555+
} else {
1556+
this._diffNavigator?.previous();
1557+
}
1558+
}
1559+
1560+
public revealFirstDiff(): void {
1561+
// This is a hack, but it works.
1562+
if (this._diffNavigator) {
1563+
this._diffNavigator.revealFirst = true;
1564+
}
1565+
}
15391566
}
15401567

15411568
interface IDataSource {
@@ -2785,6 +2812,9 @@ function validateDiffEditorOptions(options: Readonly<IDiffEditorOptions>, defaul
27852812
diffWordWrap: validateDiffWordWrap(options.diffWordWrap, defaults.diffWordWrap),
27862813
diffAlgorithm: validateStringSetOption(options.diffAlgorithm, defaults.diffAlgorithm, ['legacy', 'advanced'], { 'smart': 'legacy', 'experimental': 'advanced' }),
27872814
accessibilityVerbose: validateBooleanOption(options.accessibilityVerbose, defaults.accessibilityVerbose),
2815+
experimental: {
2816+
collapseUnchangedRegions: false,
2817+
},
27882818
};
27892819
}
27902820

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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 { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
7+
8+
export const diffFullLineAddDecoration = ModelDecorationOptions.register({
9+
className: 'line-insert',
10+
description: 'line-insert',
11+
isWholeLine: true,
12+
});
13+
14+
export const diffFullLineDeleteDecoration = ModelDecorationOptions.register({
15+
className: 'line-delete',
16+
description: 'line-delete',
17+
isWholeLine: true,
18+
});
19+
20+
export const diffAddDecoration = ModelDecorationOptions.register({
21+
className: 'char-insert',
22+
description: 'char-insert',
23+
});
24+
25+
export const diffDeleteDecoration = ModelDecorationOptions.register({
26+
className: 'char-delete',
27+
description: 'char-delete',
28+
});
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
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 { Emitter } from 'vs/base/common/event';
7+
import { Disposable } from 'vs/base/common/lifecycle';
8+
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
9+
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
10+
import { IDimension } from 'vs/editor/common/core/dimension';
11+
import { IPosition, Position } from 'vs/editor/common/core/position';
12+
import { IRange, Range } from 'vs/editor/common/core/range';
13+
import { ISelection, Selection } from 'vs/editor/common/core/selection';
14+
import { IEditor, IEditorAction, IEditorDecorationsCollection, IEditorModel, IEditorViewState, ScrollType } from 'vs/editor/common/editorCommon';
15+
import { IModelDecorationsChangeAccessor, IModelDeltaDecoration } from 'vs/editor/common/model';
16+
17+
export abstract class DelegatingEditor extends Disposable implements IEditor {
18+
private static idCounter = 0;
19+
private readonly _id = ++DelegatingEditor.idCounter;
20+
21+
private readonly _onDidDispose = this._register(new Emitter<void>());
22+
public readonly onDidDispose = this._onDidDispose.event;
23+
24+
protected abstract get _targetEditor(): CodeEditorWidget;
25+
26+
getId(): string { return this.getEditorType() + ':' + this._id; }
27+
28+
abstract getEditorType(): string;
29+
abstract updateOptions(newOptions: IEditorOptions): void;
30+
abstract onVisible(): void;
31+
abstract onHide(): void;
32+
abstract layout(dimension?: IDimension | undefined): void;
33+
abstract hasTextFocus(): boolean;
34+
abstract saveViewState(): IEditorViewState | null;
35+
abstract restoreViewState(state: IEditorViewState | null): void;
36+
abstract getModel(): IEditorModel | null;
37+
abstract setModel(model: IEditorModel | null): void;
38+
39+
// #region editorBrowser.IDiffEditor: Delegating to modified Editor
40+
41+
public getVisibleColumnFromPosition(position: IPosition): number {
42+
return this._targetEditor.getVisibleColumnFromPosition(position);
43+
}
44+
45+
public getStatusbarColumn(position: IPosition): number {
46+
return this._targetEditor.getStatusbarColumn(position);
47+
}
48+
49+
public getPosition(): Position | null {
50+
return this._targetEditor.getPosition();
51+
}
52+
53+
public setPosition(position: IPosition, source: string = 'api'): void {
54+
this._targetEditor.setPosition(position, source);
55+
}
56+
57+
public revealLine(lineNumber: number, scrollType: ScrollType = ScrollType.Smooth): void {
58+
this._targetEditor.revealLine(lineNumber, scrollType);
59+
}
60+
61+
public revealLineInCenter(lineNumber: number, scrollType: ScrollType = ScrollType.Smooth): void {
62+
this._targetEditor.revealLineInCenter(lineNumber, scrollType);
63+
}
64+
65+
public revealLineInCenterIfOutsideViewport(lineNumber: number, scrollType: ScrollType = ScrollType.Smooth): void {
66+
this._targetEditor.revealLineInCenterIfOutsideViewport(lineNumber, scrollType);
67+
}
68+
69+
public revealLineNearTop(lineNumber: number, scrollType: ScrollType = ScrollType.Smooth): void {
70+
this._targetEditor.revealLineNearTop(lineNumber, scrollType);
71+
}
72+
73+
public revealPosition(position: IPosition, scrollType: ScrollType = ScrollType.Smooth): void {
74+
this._targetEditor.revealPosition(position, scrollType);
75+
}
76+
77+
public revealPositionInCenter(position: IPosition, scrollType: ScrollType = ScrollType.Smooth): void {
78+
this._targetEditor.revealPositionInCenter(position, scrollType);
79+
}
80+
81+
public revealPositionInCenterIfOutsideViewport(position: IPosition, scrollType: ScrollType = ScrollType.Smooth): void {
82+
this._targetEditor.revealPositionInCenterIfOutsideViewport(position, scrollType);
83+
}
84+
85+
public revealPositionNearTop(position: IPosition, scrollType: ScrollType = ScrollType.Smooth): void {
86+
this._targetEditor.revealPositionNearTop(position, scrollType);
87+
}
88+
89+
public getSelection(): Selection | null {
90+
return this._targetEditor.getSelection();
91+
}
92+
93+
public getSelections(): Selection[] | null {
94+
return this._targetEditor.getSelections();
95+
}
96+
97+
public setSelection(range: IRange, source?: string): void;
98+
public setSelection(editorRange: Range, source?: string): void;
99+
public setSelection(selection: ISelection, source?: string): void;
100+
public setSelection(editorSelection: Selection, source?: string): void;
101+
public setSelection(something: any, source: string = 'api'): void {
102+
this._targetEditor.setSelection(something, source);
103+
}
104+
105+
public setSelections(ranges: readonly ISelection[], source: string = 'api'): void {
106+
this._targetEditor.setSelections(ranges, source);
107+
}
108+
109+
public revealLines(startLineNumber: number, endLineNumber: number, scrollType: ScrollType = ScrollType.Smooth): void {
110+
this._targetEditor.revealLines(startLineNumber, endLineNumber, scrollType);
111+
}
112+
113+
public revealLinesInCenter(startLineNumber: number, endLineNumber: number, scrollType: ScrollType = ScrollType.Smooth): void {
114+
this._targetEditor.revealLinesInCenter(startLineNumber, endLineNumber, scrollType);
115+
}
116+
117+
public revealLinesInCenterIfOutsideViewport(startLineNumber: number, endLineNumber: number, scrollType: ScrollType = ScrollType.Smooth): void {
118+
this._targetEditor.revealLinesInCenterIfOutsideViewport(startLineNumber, endLineNumber, scrollType);
119+
}
120+
121+
public revealLinesNearTop(startLineNumber: number, endLineNumber: number, scrollType: ScrollType = ScrollType.Smooth): void {
122+
this._targetEditor.revealLinesNearTop(startLineNumber, endLineNumber, scrollType);
123+
}
124+
125+
public revealRange(range: IRange, scrollType: ScrollType = ScrollType.Smooth, revealVerticalInCenter: boolean = false, revealHorizontal: boolean = true): void {
126+
this._targetEditor.revealRange(range, scrollType, revealVerticalInCenter, revealHorizontal);
127+
}
128+
129+
public revealRangeInCenter(range: IRange, scrollType: ScrollType = ScrollType.Smooth): void {
130+
this._targetEditor.revealRangeInCenter(range, scrollType);
131+
}
132+
133+
public revealRangeInCenterIfOutsideViewport(range: IRange, scrollType: ScrollType = ScrollType.Smooth): void {
134+
this._targetEditor.revealRangeInCenterIfOutsideViewport(range, scrollType);
135+
}
136+
137+
public revealRangeNearTop(range: IRange, scrollType: ScrollType = ScrollType.Smooth): void {
138+
this._targetEditor.revealRangeNearTop(range, scrollType);
139+
}
140+
141+
public revealRangeNearTopIfOutsideViewport(range: IRange, scrollType: ScrollType = ScrollType.Smooth): void {
142+
this._targetEditor.revealRangeNearTopIfOutsideViewport(range, scrollType);
143+
}
144+
145+
public revealRangeAtTop(range: IRange, scrollType: ScrollType = ScrollType.Smooth): void {
146+
this._targetEditor.revealRangeAtTop(range, scrollType);
147+
}
148+
149+
public getSupportedActions(): IEditorAction[] {
150+
return this._targetEditor.getSupportedActions();
151+
}
152+
153+
public focus(): void {
154+
this._targetEditor.focus();
155+
}
156+
157+
public trigger(source: string | null | undefined, handlerId: string, payload: any): void {
158+
this._targetEditor.trigger(source, handlerId, payload);
159+
}
160+
161+
public createDecorationsCollection(decorations?: IModelDeltaDecoration[]): IEditorDecorationsCollection {
162+
return this._targetEditor.createDecorationsCollection(decorations);
163+
}
164+
165+
public changeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => any): any {
166+
return this._targetEditor.changeDecorations(callback);
167+
}
168+
169+
// #endregion
170+
}

0 commit comments

Comments
 (0)