Skip to content

Commit

Permalink
Introduced diffEditor.experimental.useTrueInlineView (defaults to fal…
Browse files Browse the repository at this point in the history
…se). Fixes #176969
  • Loading branch information
hediet committed Jul 18, 2024
1 parent c0c38ae commit 37a9761
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { Disposable } from 'vs/base/common/lifecycle';
import { IObservable, derived } from 'vs/base/common/observable';
import { DiffEditorEditors } from 'vs/editor/browser/widget/diffEditor/components/diffEditorEditors';
import { allowsTrueInlineDiffRendering } from 'vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/diffEditorViewZones';
import { DiffEditorOptions } from 'vs/editor/browser/widget/diffEditor/diffEditorOptions';
import { DiffEditorViewModel } from 'vs/editor/browser/widget/diffEditor/diffEditorViewModel';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditor/diffEditorWidget';
Expand All @@ -28,7 +29,8 @@ export class DiffEditorDecorations extends Disposable {
}

private readonly _decorations = derived(this, (reader) => {
const diff = this._diffModel.read(reader)?.diff.read(reader);
const diffModel = this._diffModel.read(reader);
const diff = diffModel?.diff.read(reader);
if (!diff) {
return null;
}
Expand Down Expand Up @@ -56,13 +58,29 @@ export class DiffEditorDecorations extends Disposable {
modifiedDecorations.push({ range: m.lineRangeMapping.modified.toInclusiveRange()!, options: diffWholeLineAddDecoration });
}
} else {
const useInlineDiff = this._options.useTrueInlineDiffRendering.read(reader) && allowsTrueInlineDiffRendering(m.lineRangeMapping);
for (const i of m.lineRangeMapping.innerChanges || []) {
// Don't show empty markers outside the line range
if (m.lineRangeMapping.original.contains(i.originalRange.startLineNumber)) {
originalDecorations.push({ range: i.originalRange, options: (i.originalRange.isEmpty() && showEmptyDecorations) ? diffDeleteDecorationEmpty : diffDeleteDecoration });
}
if (m.lineRangeMapping.modified.contains(i.modifiedRange.startLineNumber)) {
modifiedDecorations.push({ range: i.modifiedRange, options: (i.modifiedRange.isEmpty() && showEmptyDecorations) ? diffAddDecorationEmpty : diffAddDecoration });
modifiedDecorations.push({ range: i.modifiedRange, options: (i.modifiedRange.isEmpty() && showEmptyDecorations && !useInlineDiff) ? diffAddDecorationEmpty : diffAddDecoration });
}
if (useInlineDiff) {
const deletedText = diffModel!.model.original.getValueInRange(i.originalRange);
modifiedDecorations.push({
range: i.modifiedRange,
options: {
description: 'deleted-text',
before: {
content: deletedText,
inlineClassName: 'inline-deleted-text',
},
zIndex: 100000,
showIfCollapsed: true,
}
});
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { InlineDecoration, InlineDecorationType } from 'vs/editor/common/viewMod
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { DiffEditorOptions } from '../../diffEditorOptions';
import { Range } from 'vs/editor/common/core/range';

/**
* Ensures both editors have the same height by aligning unchanged lines.
Expand Down Expand Up @@ -187,7 +188,7 @@ export class DiffEditorViewZones extends Disposable {
const renderOptions = RenderOptions.fromEditor(this._editors.modified);

for (const a of alignmentsVal) {
if (a.diff && !renderSideBySide) {
if (a.diff && !renderSideBySide && (!this._options.useTrueInlineDiffRendering.read(reader) || !allowsTrueInlineDiffRendering(a.diff))) {
if (!a.originalRange.isEmpty) {
originalModelTokenizationCompleted.read(reader); // Update view-zones once tokenization completes

Expand Down Expand Up @@ -627,3 +628,14 @@ function getAdditionalLineHeights(editor: CodeEditorWidget, viewZonesToIgnore: R

return result;
}

export function allowsTrueInlineDiffRendering(mapping: DetailedLineRangeMapping): boolean {
if (!mapping.innerChanges) {
return false;
}
return mapping.innerChanges.every(c => rangeIsSingleLine(c.modifiedRange) && rangeIsSingleLine(c.originalRange));
}

function rangeIsSingleLine(range: Range): boolean {
return range.startLineNumber === range.endLineNumber;
}
11 changes: 7 additions & 4 deletions src/vs/editor/browser/widget/diffEditor/diffEditorOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { IObservable, ISettableObservable, derived, observableFromEvent, observableValue } from 'vs/base/common/observable';
import { getIfDefined } from 'vs/base/common/observableInternal/utils';
import { Constants } from 'vs/base/common/uint';
import { allowsTrueInlineDiffRendering } from 'vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/diffEditorViewZones';
import { DiffEditorViewModel, DiffState } from 'vs/editor/browser/widget/diffEditor/diffEditorViewModel';
import { diffEditorDefaultOptions } from 'vs/editor/common/config/diffEditor';
import { IDiffEditorBaseOptions, IDiffEditorOptions, IEditorOptions, ValidDiffEditorBaseOptions, clampedFloat, clampedInt, boolean as validateBooleanOption, stringSet as validateStringSetOption } from 'vs/editor/common/config/editorOptions';
Expand Down Expand Up @@ -70,6 +71,7 @@ export class DiffEditorOptions {
public readonly showEmptyDecorations = derived(this, reader => this._options.read(reader).experimental.showEmptyDecorations!);
public readonly onlyShowAccessibleDiffViewer = derived(this, reader => this._options.read(reader).onlyShowAccessibleDiffViewer);
public readonly compactMode = derived(this, reader => this._options.read(reader).compactMode);
public readonly useTrueInlineDiffRendering = derived(this, reader => this._options.read(reader).experimental.useTrueInlineView!);

public readonly hideUnchangedRegions = derived(this, reader => this._options.read(reader).hideUnchangedRegions.enabled!);
public readonly hideUnchangedRegionsRevealLineCount = derived(this, reader => this._options.read(reader).hideUnchangedRegions.revealLineCount!);
Expand All @@ -95,14 +97,14 @@ export class DiffEditorOptions {
private readonly shouldRenderInlineViewInSmartMode = this._model
.map(this, model => getIfDefined(this, reader => {
const diffs = model?.diff.read(reader);
return diffs ? isSimpleDiff(diffs) : undefined;
return diffs ? isSimpleDiff(diffs, this.useTrueInlineDiffRendering.read(reader)) : undefined;
}))
.flatten()
.map(this, v => !!v);
}

function isSimpleDiff(diff: DiffState): boolean {
return diff.mappings.every(m => isInsertion(m.lineRangeMapping) || isDeletion(m.lineRangeMapping));
function isSimpleDiff(diff: DiffState, supportsTrueDiffRendering: boolean): boolean {
return diff.mappings.every(m => isInsertion(m.lineRangeMapping) || isDeletion(m.lineRangeMapping) || (supportsTrueDiffRendering && allowsTrueInlineDiffRendering(m.lineRangeMapping)));
}

function isInsertion(mapping: LineRangeMapping): boolean {
Expand All @@ -113,7 +115,7 @@ function isDeletion(mapping: LineRangeMapping): boolean {
return mapping.modified.length === 0;
}

function validateDiffEditorOptions(options: Readonly<IDiffEditorOptions>, defaults: ValidDiffEditorBaseOptions): ValidDiffEditorBaseOptions {
function validateDiffEditorOptions(options: Readonly<IDiffEditorOptions>, defaults: typeof diffEditorDefaultOptions | ValidDiffEditorBaseOptions): ValidDiffEditorBaseOptions {
return {
enableSplitViewResizing: validateBooleanOption(options.enableSplitViewResizing, defaults.enableSplitViewResizing),
splitViewDefaultRatio: clampedFloat(options.splitViewDefaultRatio, 0.5, 0.1, 0.9),
Expand All @@ -132,6 +134,7 @@ function validateDiffEditorOptions(options: Readonly<IDiffEditorOptions>, defaul
experimental: {
showMoves: validateBooleanOption(options.experimental?.showMoves, defaults.experimental.showMoves!),
showEmptyDecorations: validateBooleanOption(options.experimental?.showEmptyDecorations, defaults.experimental.showEmptyDecorations!),
useTrueInlineView: validateBooleanOption(options.experimental?.useTrueInlineView, defaults.experimental.useTrueInlineView!),
},
hideUnchangedRegions: {
enabled: validateBooleanOption(options.hideUnchangedRegions?.enabled ?? (options.experimental as any)?.collapseUnchangedRegions, defaults.hideUnchangedRegions.enabled!),
Expand Down
6 changes: 5 additions & 1 deletion src/vs/editor/browser/widget/diffEditor/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -276,10 +276,14 @@
background-color: var(--vscode-diffEditorGutter-insertedLineBackground, var(--vscode-diffEditor-insertedLineBackground), var(--vscode-diffEditor-insertedTextBackground));
}

.monaco-editor .char-delete, .monaco-diff-editor .char-delete {
.monaco-editor .char-delete, .monaco-diff-editor .char-delete, .monaco-editor .inline-deleted-text {
background-color: var(--vscode-diffEditor-removedTextBackground);
}

.monaco-editor .inline-deleted-text {
text-decoration: line-through;
}

.monaco-editor .line-delete, .monaco-diff-editor .line-delete {
background-color: var(--vscode-diffEditor-removedLineBackground, var(--vscode-diffEditor-removedTextBackground));
}
Expand Down
1 change: 1 addition & 0 deletions src/vs/editor/common/config/diffEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const diffEditorDefaultOptions = {
experimental: {
showMoves: false,
showEmptyDecorations: true,
useTrueInlineView: false,
},
hideUnchangedRegions: {
enabled: false,
Expand Down
7 changes: 6 additions & 1 deletion src/vs/editor/common/config/editorConfigurationSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,12 @@ const editorConfiguration: IConfigurationNode = {
type: 'boolean',
default: diffEditorDefaultOptions.experimental.showEmptyDecorations,
description: nls.localize('showEmptyDecorations', "Controls whether the diff editor shows empty decorations to see where characters got inserted or deleted."),
}
},
'diffEditor.experimental.useTrueInlineView': {
type: 'boolean',
default: diffEditorDefaultOptions.experimental.useTrueInlineView,
description: nls.localize('useTrueInlineView', "If enabled and the editor uses the inline view, word changes are rendered inline."),
},
}
};

Expand Down
5 changes: 5 additions & 0 deletions src/vs/editor/common/config/editorOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,11 @@ export interface IDiffEditorBaseOptions {
showMoves?: boolean;

showEmptyDecorations?: boolean;

/**
* Only applies when `renderSideBySide` is set to false.
*/
useTrueInlineView?: boolean;
};

/**
Expand Down
4 changes: 4 additions & 0 deletions src/vs/monaco.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3888,6 +3888,10 @@ declare namespace monaco.editor {
*/
showMoves?: boolean;
showEmptyDecorations?: boolean;
/**
* Only applies when `renderSideBySide` is set to false.
*/
useTrueInlineView?: boolean;
};
/**
* Is the diff editor inside another editor
Expand Down
3 changes: 3 additions & 0 deletions src/vs/workbench/contrib/chat/browser/codeBlockPart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,9 @@ export class CodeCompareBlockPart extends Disposable {
readOnly: false,
isInEmbeddedEditor: true,
useInlineViewWhenSpaceIsLimited: true,
experimental: {
useTrueInlineView: true,
},
renderSideBySideInlineBreakpoint: 300,
compactMode: true,
hideUnchangedRegions: { enabled: true, contextLineCount: 1 },
Expand Down

0 comments on commit 37a9761

Please sign in to comment.