mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Merge from vscode 8a997f7321ae6612fc0e6eb3eac4f358a6233bfb
This commit is contained in:
@@ -88,6 +88,7 @@ export interface ISerializedFontInfo {
|
||||
readonly canUseHalfwidthRightwardsArrow: boolean;
|
||||
readonly spaceWidth: number;
|
||||
middotWidth: number;
|
||||
wsmiddotWidth: number;
|
||||
readonly maxDigitWidth: number;
|
||||
}
|
||||
|
||||
@@ -161,6 +162,7 @@ class CSSBasedConfiguration extends Disposable {
|
||||
// compatibility with older versions of VS Code which did not store this...
|
||||
savedFontInfo.fontFeatureSettings = savedFontInfo.fontFeatureSettings || EditorFontLigatures.OFF;
|
||||
savedFontInfo.middotWidth = savedFontInfo.middotWidth || savedFontInfo.spaceWidth;
|
||||
savedFontInfo.wsmiddotWidth = savedFontInfo.wsmiddotWidth || savedFontInfo.spaceWidth;
|
||||
const fontInfo = new FontInfo(savedFontInfo, false);
|
||||
this._writeToCache(fontInfo, fontInfo);
|
||||
}
|
||||
@@ -186,6 +188,7 @@ class CSSBasedConfiguration extends Disposable {
|
||||
canUseHalfwidthRightwardsArrow: readConfig.canUseHalfwidthRightwardsArrow,
|
||||
spaceWidth: Math.max(readConfig.spaceWidth, 5),
|
||||
middotWidth: Math.max(readConfig.middotWidth, 5),
|
||||
wsmiddotWidth: Math.max(readConfig.wsmiddotWidth, 5),
|
||||
maxDigitWidth: Math.max(readConfig.maxDigitWidth, 5),
|
||||
}, false);
|
||||
}
|
||||
@@ -226,9 +229,12 @@ class CSSBasedConfiguration extends Disposable {
|
||||
const rightwardsArrow = this.createRequest('→', CharWidthRequestType.Regular, all, monospace);
|
||||
const halfwidthRightwardsArrow = this.createRequest('→', CharWidthRequestType.Regular, all, null);
|
||||
|
||||
// middle dot character
|
||||
// U+00B7 - MIDDLE DOT
|
||||
const middot = this.createRequest('·', CharWidthRequestType.Regular, all, monospace);
|
||||
|
||||
// U+2E31 - WORD SEPARATOR MIDDLE DOT
|
||||
const wsmiddotWidth = this.createRequest(String.fromCharCode(0x2E31), CharWidthRequestType.Regular, all, null);
|
||||
|
||||
// monospace test: some characters
|
||||
this.createRequest('|', CharWidthRequestType.Regular, all, monospace);
|
||||
this.createRequest('/', CharWidthRequestType.Regular, all, monospace);
|
||||
@@ -294,6 +300,7 @@ class CSSBasedConfiguration extends Disposable {
|
||||
canUseHalfwidthRightwardsArrow: canUseHalfwidthRightwardsArrow,
|
||||
spaceWidth: space.width,
|
||||
middotWidth: middot.width,
|
||||
wsmiddotWidth: wsmiddotWidth.width,
|
||||
maxDigitWidth: maxDigitWidth
|
||||
}, canTrustBrowserZoomLevel);
|
||||
}
|
||||
@@ -379,7 +386,11 @@ export class Configuration extends CommonEditorConfiguration {
|
||||
emptySelectionClipboard: browser.isWebKit || browser.isFirefox,
|
||||
pixelRatio: browser.getPixelRatio(),
|
||||
zoomLevel: browser.getZoomLevel(),
|
||||
accessibilitySupport: this.accessibilityService.isScreenReaderOptimized() ? AccessibilitySupport.Enabled : AccessibilitySupport.Disabled
|
||||
accessibilitySupport: (
|
||||
this.accessibilityService.isScreenReaderOptimized()
|
||||
? AccessibilitySupport.Enabled
|
||||
: this.accessibilityService.getAccessibilitySupport()
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -57,19 +57,6 @@ export interface ITextAreaInputHost {
|
||||
deduceModelPosition(viewAnchorPosition: Position, deltaOffset: number, lineFeedCnt: number): Position;
|
||||
}
|
||||
|
||||
const enum TextAreaInputEventType {
|
||||
none,
|
||||
compositionstart,
|
||||
compositionupdate,
|
||||
compositionend,
|
||||
input,
|
||||
cut,
|
||||
copy,
|
||||
paste,
|
||||
focus,
|
||||
blur
|
||||
}
|
||||
|
||||
interface CompositionEvent extends UIEvent {
|
||||
readonly data: string;
|
||||
readonly locale: string;
|
||||
@@ -155,7 +142,6 @@ export class TextAreaInput extends Disposable {
|
||||
|
||||
private readonly _host: ITextAreaInputHost;
|
||||
private readonly _textArea: TextAreaWrapper;
|
||||
private _lastTextAreaEvent: TextAreaInputEventType;
|
||||
private readonly _asyncTriggerCut: RunOnceScheduler;
|
||||
|
||||
private _textAreaState: TextAreaState;
|
||||
@@ -169,7 +155,6 @@ export class TextAreaInput extends Disposable {
|
||||
super();
|
||||
this._host = host;
|
||||
this._textArea = this._register(new TextAreaWrapper(textArea));
|
||||
this._lastTextAreaEvent = TextAreaInputEventType.none;
|
||||
this._asyncTriggerCut = this._register(new RunOnceScheduler(() => this._onCut.fire(), 0));
|
||||
|
||||
this._textAreaState = TextAreaState.EMPTY;
|
||||
@@ -200,8 +185,6 @@ export class TextAreaInput extends Disposable {
|
||||
}));
|
||||
|
||||
this._register(dom.addDisposableListener(textArea.domNode, 'compositionstart', (e: CompositionEvent) => {
|
||||
this._lastTextAreaEvent = TextAreaInputEventType.compositionstart;
|
||||
|
||||
if (this._isDoingComposition) {
|
||||
return;
|
||||
}
|
||||
@@ -218,10 +201,10 @@ export class TextAreaInput extends Disposable {
|
||||
/**
|
||||
* Deduce the typed input from a text area's value and the last observed state.
|
||||
*/
|
||||
const deduceInputFromTextAreaValue = (couldBeEmojiInput: boolean, couldBeTypingAtOffset0: boolean): [TextAreaState, ITypeData] => {
|
||||
const deduceInputFromTextAreaValue = (couldBeEmojiInput: boolean): [TextAreaState, ITypeData] => {
|
||||
const oldState = this._textAreaState;
|
||||
const newState = TextAreaState.readFromTextArea(this._textArea);
|
||||
return [newState, TextAreaState.deduceInput(oldState, newState, couldBeEmojiInput, couldBeTypingAtOffset0)];
|
||||
return [newState, TextAreaState.deduceInput(oldState, newState, couldBeEmojiInput)];
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -258,10 +241,8 @@ export class TextAreaInput extends Disposable {
|
||||
};
|
||||
|
||||
this._register(dom.addDisposableListener(textArea.domNode, 'compositionupdate', (e: CompositionEvent) => {
|
||||
this._lastTextAreaEvent = TextAreaInputEventType.compositionupdate;
|
||||
|
||||
if (compositionDataInValid(e.locale)) {
|
||||
const [newState, typeInput] = deduceInputFromTextAreaValue(/*couldBeEmojiInput*/false, /*couldBeTypingAtOffset0*/false);
|
||||
const [newState, typeInput] = deduceInputFromTextAreaValue(/*couldBeEmojiInput*/false);
|
||||
this._textAreaState = newState;
|
||||
this._onType.fire(typeInput);
|
||||
this._onCompositionUpdate.fire(e);
|
||||
@@ -275,7 +256,6 @@ export class TextAreaInput extends Disposable {
|
||||
}));
|
||||
|
||||
this._register(dom.addDisposableListener(textArea.domNode, 'compositionend', (e: CompositionEvent) => {
|
||||
this._lastTextAreaEvent = TextAreaInputEventType.compositionend;
|
||||
// https://github.com/microsoft/monaco-editor/issues/1663
|
||||
// On iOS 13.2, Chinese system IME randomly trigger an additional compositionend event with empty data
|
||||
if (!this._isDoingComposition) {
|
||||
@@ -283,7 +263,7 @@ export class TextAreaInput extends Disposable {
|
||||
}
|
||||
if (compositionDataInValid(e.locale)) {
|
||||
// https://github.com/Microsoft/monaco-editor/issues/339
|
||||
const [newState, typeInput] = deduceInputFromTextAreaValue(/*couldBeEmojiInput*/false, /*couldBeTypingAtOffset0*/false);
|
||||
const [newState, typeInput] = deduceInputFromTextAreaValue(/*couldBeEmojiInput*/false);
|
||||
this._textAreaState = newState;
|
||||
this._onType.fire(typeInput);
|
||||
} else {
|
||||
@@ -307,10 +287,6 @@ export class TextAreaInput extends Disposable {
|
||||
}));
|
||||
|
||||
this._register(dom.addDisposableListener(textArea.domNode, 'input', () => {
|
||||
// We want to find out if this is the first `input` after a `focus`.
|
||||
const previousEventWasFocus = (this._lastTextAreaEvent === TextAreaInputEventType.focus);
|
||||
this._lastTextAreaEvent = TextAreaInputEventType.input;
|
||||
|
||||
// Pretend here we touched the text area, as the `input` event will most likely
|
||||
// result in a `selectionchange` event which we want to ignore
|
||||
this._textArea.setIgnoreSelectionChangeTime('received input event');
|
||||
@@ -319,7 +295,7 @@ export class TextAreaInput extends Disposable {
|
||||
return;
|
||||
}
|
||||
|
||||
const [newState, typeInput] = deduceInputFromTextAreaValue(/*couldBeEmojiInput*/platform.isMacintosh, /*couldBeTypingAtOffset0*/previousEventWasFocus && platform.isMacintosh);
|
||||
const [newState, typeInput] = deduceInputFromTextAreaValue(/*couldBeEmojiInput*/platform.isMacintosh);
|
||||
if (typeInput.replaceCharCnt === 0 && typeInput.text.length === 1 && strings.isHighSurrogate(typeInput.text.charCodeAt(0))) {
|
||||
// Ignore invalid input but keep it around for next time
|
||||
return;
|
||||
@@ -341,8 +317,6 @@ export class TextAreaInput extends Disposable {
|
||||
// --- Clipboard operations
|
||||
|
||||
this._register(dom.addDisposableListener(textArea.domNode, 'cut', (e: ClipboardEvent) => {
|
||||
this._lastTextAreaEvent = TextAreaInputEventType.cut;
|
||||
|
||||
// Pretend here we touched the text area, as the `cut` event will most likely
|
||||
// result in a `selectionchange` event which we want to ignore
|
||||
this._textArea.setIgnoreSelectionChangeTime('received cut event');
|
||||
@@ -352,14 +326,10 @@ export class TextAreaInput extends Disposable {
|
||||
}));
|
||||
|
||||
this._register(dom.addDisposableListener(textArea.domNode, 'copy', (e: ClipboardEvent) => {
|
||||
this._lastTextAreaEvent = TextAreaInputEventType.copy;
|
||||
|
||||
this._ensureClipboardGetsEditorSelection(e);
|
||||
}));
|
||||
|
||||
this._register(dom.addDisposableListener(textArea.domNode, 'paste', (e: ClipboardEvent) => {
|
||||
this._lastTextAreaEvent = TextAreaInputEventType.paste;
|
||||
|
||||
// Pretend here we touched the text area, as the `paste` event will most likely
|
||||
// result in a `selectionchange` event which we want to ignore
|
||||
this._textArea.setIgnoreSelectionChangeTime('received paste event');
|
||||
@@ -379,11 +349,9 @@ export class TextAreaInput extends Disposable {
|
||||
}));
|
||||
|
||||
this._register(dom.addDisposableListener(textArea.domNode, 'focus', () => {
|
||||
this._lastTextAreaEvent = TextAreaInputEventType.focus;
|
||||
this._setHasFocus(true);
|
||||
}));
|
||||
this._register(dom.addDisposableListener(textArea.domNode, 'blur', () => {
|
||||
this._lastTextAreaEvent = TextAreaInputEventType.blur;
|
||||
this._setHasFocus(false);
|
||||
}));
|
||||
}
|
||||
@@ -625,7 +593,8 @@ class ClipboardEventUtils {
|
||||
|
||||
if ((<any>window).clipboardData) {
|
||||
e.preventDefault();
|
||||
return (<any>window).clipboardData.getData('Text');
|
||||
const text: string = (<any>window).clipboardData.getData('Text');
|
||||
return [text, null];
|
||||
}
|
||||
|
||||
throw new Error('ClipboardEventUtils.getTextData: Cannot use text data!');
|
||||
|
||||
@@ -96,7 +96,7 @@ export class TextAreaState {
|
||||
return new TextAreaState(text, 0, text.length, null, null);
|
||||
}
|
||||
|
||||
public static deduceInput(previousState: TextAreaState, currentState: TextAreaState, couldBeEmojiInput: boolean, couldBeTypingAtOffset0: boolean): ITypeData {
|
||||
public static deduceInput(previousState: TextAreaState, currentState: TextAreaState, couldBeEmojiInput: boolean): ITypeData {
|
||||
if (!previousState) {
|
||||
// This is the EMPTY state
|
||||
return {
|
||||
@@ -116,18 +116,6 @@ export class TextAreaState {
|
||||
let currentSelectionStart = currentState.selectionStart;
|
||||
let currentSelectionEnd = currentState.selectionEnd;
|
||||
|
||||
if (couldBeTypingAtOffset0 && previousValue.length > 0 && previousSelectionStart === previousSelectionEnd && currentSelectionStart === currentSelectionEnd) {
|
||||
// See https://github.com/Microsoft/vscode/issues/42251
|
||||
// where typing always happens at offset 0 in the textarea
|
||||
// when using a custom title area in OSX and moving the window
|
||||
if (!strings.startsWith(currentValue, previousValue) && strings.endsWith(currentValue, previousValue)) {
|
||||
// Looks like something was typed at offset 0
|
||||
// ==> pretend we placed the cursor at offset 0 to begin with...
|
||||
previousSelectionStart = 0;
|
||||
previousSelectionEnd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Strip the previous suffix from the value (without interfering with the current selection)
|
||||
const previousSuffix = previousValue.substring(previousSelectionEnd);
|
||||
const currentSuffix = currentValue.substring(currentSelectionEnd);
|
||||
|
||||
@@ -74,6 +74,7 @@ export class ViewLineOptions {
|
||||
public readonly renderControlCharacters: boolean;
|
||||
public readonly spaceWidth: number;
|
||||
public readonly middotWidth: number;
|
||||
public readonly wsmiddotWidth: number;
|
||||
public readonly useMonospaceOptimizations: boolean;
|
||||
public readonly canUseHalfwidthRightwardsArrow: boolean;
|
||||
public readonly lineHeight: number;
|
||||
@@ -88,6 +89,7 @@ export class ViewLineOptions {
|
||||
this.renderControlCharacters = options.get(EditorOption.renderControlCharacters);
|
||||
this.spaceWidth = fontInfo.spaceWidth;
|
||||
this.middotWidth = fontInfo.middotWidth;
|
||||
this.wsmiddotWidth = fontInfo.wsmiddotWidth;
|
||||
this.useMonospaceOptimizations = (
|
||||
fontInfo.isMonospace
|
||||
&& !options.get(EditorOption.disableMonospaceOptimizations)
|
||||
@@ -105,6 +107,7 @@ export class ViewLineOptions {
|
||||
&& this.renderControlCharacters === other.renderControlCharacters
|
||||
&& this.spaceWidth === other.spaceWidth
|
||||
&& this.middotWidth === other.middotWidth
|
||||
&& this.wsmiddotWidth === other.wsmiddotWidth
|
||||
&& this.useMonospaceOptimizations === other.useMonospaceOptimizations
|
||||
&& this.canUseHalfwidthRightwardsArrow === other.canUseHalfwidthRightwardsArrow
|
||||
&& this.lineHeight === other.lineHeight
|
||||
@@ -219,6 +222,7 @@ export class ViewLine implements IVisibleLine {
|
||||
lineData.startVisibleColumn,
|
||||
options.spaceWidth,
|
||||
options.middotWidth,
|
||||
options.wsmiddotWidth,
|
||||
options.stopRenderingLineAfter,
|
||||
options.renderWhitespace,
|
||||
options.renderControlCharacters,
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as nls from 'vs/nls';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
|
||||
import { ISashEvent, IVerticalSashLayoutProvider, Sash, SashState } from 'vs/base/browser/ui/sash/sash';
|
||||
import { RunOnceScheduler, IntervalTimer } from 'vs/base/common/async';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
@@ -48,6 +48,7 @@ import { Constants } from 'vs/base/common/uint';
|
||||
import { EditorExtensionsRegistry, IDiffEditorContributionDescription } from 'vs/editor/browser/editorExtensions';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { IEditorProgressService, IProgressRunner } from 'vs/platform/progress/common/progress';
|
||||
import { ElementSizeObserver } from 'vs/editor/browser/config/elementSizeObserver';
|
||||
|
||||
interface IEditorDiffDecorations {
|
||||
decorations: IModelDeltaDecoration[];
|
||||
@@ -179,10 +180,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
private readonly _overviewDomElement: HTMLElement;
|
||||
private readonly _overviewViewportDomElement: FastDomNode<HTMLElement>;
|
||||
|
||||
private _width: number;
|
||||
private _height: number;
|
||||
private _reviewHeight: number;
|
||||
private readonly _measureDomElementToken: IntervalTimer | null;
|
||||
private readonly _elementSizeObserver: ElementSizeObserver;
|
||||
|
||||
private readonly originalEditor: CodeEditorWidget;
|
||||
private readonly _originalDomNode: HTMLElement;
|
||||
@@ -329,9 +327,10 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
this._isVisible = true;
|
||||
this._isHandlingScrollEvent = false;
|
||||
|
||||
this._width = 0;
|
||||
this._height = 0;
|
||||
this._reviewHeight = 0;
|
||||
this._elementSizeObserver = this._register(new ElementSizeObserver(this._containerDomElement, undefined, () => this._onDidContainerSizeChanged()));
|
||||
if (options.automaticLayout) {
|
||||
this._elementSizeObserver.startObserving();
|
||||
}
|
||||
|
||||
this._diffComputationResult = null;
|
||||
|
||||
@@ -360,12 +359,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
this._containerDomElement.appendChild(this._reviewPane.shadow.domNode);
|
||||
this._containerDomElement.appendChild(this._reviewPane.actionBarContainer.domNode);
|
||||
|
||||
if (options.automaticLayout) {
|
||||
this._measureDomElementToken = new IntervalTimer();
|
||||
this._measureDomElementToken.cancelAndSet(() => this._measureDomElement(false), 100);
|
||||
} else {
|
||||
this._measureDomElementToken = null;
|
||||
}
|
||||
|
||||
|
||||
// enableSplitViewResizing
|
||||
this._enableSplitViewResizing = true;
|
||||
@@ -563,10 +557,6 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
this._beginUpdateDecorationsTimeout = -1;
|
||||
}
|
||||
|
||||
if (this._measureDomElementToken) {
|
||||
this._measureDomElementToken.dispose();
|
||||
}
|
||||
|
||||
this._cleanViewZonesAndDecorations();
|
||||
|
||||
if (this._originalOverviewRuler) {
|
||||
@@ -866,7 +856,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
}
|
||||
|
||||
public layout(dimension?: editorCommon.IDimension): void {
|
||||
this._measureDomElement(false, dimension);
|
||||
this._elementSizeObserver.observe(dimension);
|
||||
}
|
||||
|
||||
public focus(): void {
|
||||
@@ -907,35 +897,21 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
|
||||
//------------ begin layouting methods
|
||||
|
||||
private _measureDomElement(forceDoLayoutCall: boolean, dimensions?: editorCommon.IDimension): void {
|
||||
dimensions = dimensions || {
|
||||
width: this._containerDomElement.clientWidth,
|
||||
height: this._containerDomElement.clientHeight
|
||||
};
|
||||
|
||||
if (dimensions.width <= 0) {
|
||||
this._width = 0;
|
||||
this._height = 0;
|
||||
this._reviewHeight = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!forceDoLayoutCall && dimensions.width === this._width && dimensions.height === this._height) {
|
||||
// Nothing has changed
|
||||
return;
|
||||
}
|
||||
|
||||
this._width = dimensions.width;
|
||||
this._height = dimensions.height;
|
||||
this._reviewHeight = this._reviewPane.isVisible() ? this._height : 0;
|
||||
|
||||
private _onDidContainerSizeChanged(): void {
|
||||
this._doLayout();
|
||||
}
|
||||
|
||||
private _getReviewHeight(): number {
|
||||
return this._reviewPane.isVisible() ? this._elementSizeObserver.getHeight() : 0;
|
||||
}
|
||||
|
||||
private _layoutOverviewRulers(): void {
|
||||
if (!this._originalOverviewRuler || !this._modifiedOverviewRuler) {
|
||||
return;
|
||||
}
|
||||
const height = this._elementSizeObserver.getHeight();
|
||||
const reviewHeight = this._getReviewHeight();
|
||||
|
||||
let freeSpace = DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH - 2 * DiffEditorWidget.ONE_OVERVIEW_WIDTH;
|
||||
let layoutInfo = this.modifiedEditor.getLayoutInfo();
|
||||
if (layoutInfo) {
|
||||
@@ -943,13 +919,13 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
top: 0,
|
||||
width: DiffEditorWidget.ONE_OVERVIEW_WIDTH,
|
||||
right: freeSpace + DiffEditorWidget.ONE_OVERVIEW_WIDTH,
|
||||
height: (this._height - this._reviewHeight)
|
||||
height: (height - reviewHeight)
|
||||
});
|
||||
this._modifiedOverviewRuler.setLayout({
|
||||
top: 0,
|
||||
right: 0,
|
||||
width: DiffEditorWidget.ONE_OVERVIEW_WIDTH,
|
||||
height: (this._height - this._reviewHeight)
|
||||
height: (height - reviewHeight)
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1095,33 +1071,38 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
}
|
||||
|
||||
public doLayout(): void {
|
||||
this._measureDomElement(true);
|
||||
this._elementSizeObserver.observe();
|
||||
this._doLayout();
|
||||
}
|
||||
|
||||
private _doLayout(): void {
|
||||
const width = this._elementSizeObserver.getWidth();
|
||||
const height = this._elementSizeObserver.getHeight();
|
||||
const reviewHeight = this._getReviewHeight();
|
||||
|
||||
let splitPoint = this._strategy.layout();
|
||||
|
||||
this._originalDomNode.style.width = splitPoint + 'px';
|
||||
this._originalDomNode.style.left = '0px';
|
||||
|
||||
this._modifiedDomNode.style.width = (this._width - splitPoint) + 'px';
|
||||
this._modifiedDomNode.style.width = (width - splitPoint) + 'px';
|
||||
this._modifiedDomNode.style.left = splitPoint + 'px';
|
||||
|
||||
this._overviewDomElement.style.top = '0px';
|
||||
this._overviewDomElement.style.height = (this._height - this._reviewHeight) + 'px';
|
||||
this._overviewDomElement.style.height = (height - reviewHeight) + 'px';
|
||||
this._overviewDomElement.style.width = DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH + 'px';
|
||||
this._overviewDomElement.style.left = (this._width - DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH) + 'px';
|
||||
this._overviewDomElement.style.left = (width - DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH) + 'px';
|
||||
this._overviewViewportDomElement.setWidth(DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH);
|
||||
this._overviewViewportDomElement.setHeight(30);
|
||||
|
||||
this.originalEditor.layout({ width: splitPoint, height: (this._height - this._reviewHeight) });
|
||||
this.modifiedEditor.layout({ width: this._width - splitPoint - DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH, height: (this._height - this._reviewHeight) });
|
||||
this.originalEditor.layout({ width: splitPoint, height: (height - reviewHeight) });
|
||||
this.modifiedEditor.layout({ width: width - splitPoint - DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH, height: (height - reviewHeight) });
|
||||
|
||||
if (this._originalOverviewRuler || this._modifiedOverviewRuler) {
|
||||
this._layoutOverviewRulers();
|
||||
}
|
||||
|
||||
this._reviewPane.layout(this._height - this._reviewHeight, this._width, this._reviewHeight);
|
||||
this._reviewPane.layout(height - reviewHeight, width, reviewHeight);
|
||||
|
||||
this._layoutOverviewViewport();
|
||||
}
|
||||
@@ -1162,11 +1143,11 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
private _createDataSource(): IDataSource {
|
||||
return {
|
||||
getWidth: () => {
|
||||
return this._width;
|
||||
return this._elementSizeObserver.getWidth();
|
||||
},
|
||||
|
||||
getHeight: () => {
|
||||
return (this._height - this._reviewHeight);
|
||||
return (this._elementSizeObserver.getHeight() - this._getReviewHeight());
|
||||
},
|
||||
|
||||
getContainerDomNode: () => {
|
||||
@@ -1200,7 +1181,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
}
|
||||
|
||||
// Just do a layout, the strategy might need it
|
||||
this._measureDomElement(true);
|
||||
this._doLayout();
|
||||
}
|
||||
|
||||
private _getLineChangeAtOrBeforeLineNumber(lineNumber: number, startLineNumberExtractor: (lineChange: editorCommon.ILineChange) => number): editorCommon.ILineChange | null {
|
||||
@@ -2181,6 +2162,7 @@ class InlineViewZonesComputer extends ViewZonesComputer {
|
||||
0,
|
||||
fontInfo.spaceWidth,
|
||||
fontInfo.middotWidth,
|
||||
fontInfo.wsmiddotWidth,
|
||||
options.get(EditorOption.stopRenderingLineAfter),
|
||||
options.get(EditorOption.renderWhitespace),
|
||||
options.get(EditorOption.renderControlCharacters),
|
||||
|
||||
@@ -783,6 +783,7 @@ export class DiffReview extends Disposable {
|
||||
0,
|
||||
fontInfo.spaceWidth,
|
||||
fontInfo.middotWidth,
|
||||
fontInfo.wsmiddotWidth,
|
||||
options.get(EditorOption.stopRenderingLineAfter),
|
||||
options.get(EditorOption.renderWhitespace),
|
||||
options.get(EditorOption.renderControlCharacters),
|
||||
|
||||
@@ -366,6 +366,10 @@ export interface IEditorOptions {
|
||||
* Defaults to 10 (ms)
|
||||
*/
|
||||
quickSuggestionsDelay?: number;
|
||||
/**
|
||||
* Controls the spacing around the editor.
|
||||
*/
|
||||
padding?: IEditorPaddingOptions;
|
||||
/**
|
||||
* Parameter hint options.
|
||||
*/
|
||||
@@ -2082,6 +2086,65 @@ function _multiCursorModifierFromString(multiCursorModifier: 'ctrlCmd' | 'alt'):
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region padding
|
||||
|
||||
/**
|
||||
* Configuration options for editor padding
|
||||
*/
|
||||
export interface IEditorPaddingOptions {
|
||||
/**
|
||||
* Spacing between top edge of editor and first line.
|
||||
*/
|
||||
top?: number;
|
||||
/**
|
||||
* Spacing between bottom edge of editor and last line.
|
||||
*/
|
||||
bottom?: number;
|
||||
}
|
||||
|
||||
export interface InternalEditorPaddingOptions {
|
||||
readonly top: number;
|
||||
readonly bottom: number;
|
||||
}
|
||||
|
||||
class EditorPadding extends BaseEditorOption<EditorOption.padding, InternalEditorPaddingOptions> {
|
||||
|
||||
constructor() {
|
||||
super(
|
||||
EditorOption.padding, 'padding', { top: 0, bottom: 0 },
|
||||
{
|
||||
'editor.padding.top': {
|
||||
type: 'number',
|
||||
default: 0,
|
||||
minimum: 0,
|
||||
maximum: 1000,
|
||||
description: nls.localize('padding.top', "Controls the amount of space between the top edge of the editor and the first line.")
|
||||
},
|
||||
'editor.padding.bottom': {
|
||||
type: 'number',
|
||||
default: 0,
|
||||
minimum: 0,
|
||||
maximum: 1000,
|
||||
description: nls.localize('padding.bottom', "Controls the amount of space between the bottom edge of the editor and the last line.")
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public validate(_input: any): InternalEditorPaddingOptions {
|
||||
if (typeof _input !== 'object') {
|
||||
return this.defaultValue;
|
||||
}
|
||||
const input = _input as IEditorPaddingOptions;
|
||||
|
||||
return {
|
||||
top: EditorIntOption.clampedInt(input.top, 0, 0, 1000),
|
||||
bottom: EditorIntOption.clampedInt(input.bottom, 0, 0, 1000)
|
||||
};
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region parameterHints
|
||||
|
||||
/**
|
||||
@@ -3188,6 +3251,7 @@ export const enum EditorOption {
|
||||
occurrencesHighlight,
|
||||
overviewRulerBorder,
|
||||
overviewRulerLanes,
|
||||
padding,
|
||||
parameterHints,
|
||||
peekWidgetDefaultFocus,
|
||||
definitionLinkOpensInPeek,
|
||||
@@ -3575,6 +3639,7 @@ export const EditorOptions = {
|
||||
EditorOption.overviewRulerLanes, 'overviewRulerLanes',
|
||||
3, 0, 3
|
||||
)),
|
||||
padding: register(new EditorPadding()),
|
||||
parameterHints: register(new EditorParameterHints()),
|
||||
peekWidgetDefaultFocus: register(new EditorStringEnumOption(
|
||||
EditorOption.peekWidgetDefaultFocus, 'peekWidgetDefaultFocus',
|
||||
@@ -3634,7 +3699,7 @@ export const EditorOptions = {
|
||||
)),
|
||||
renderWhitespace: register(new EditorStringEnumOption(
|
||||
EditorOption.renderWhitespace, 'renderWhitespace',
|
||||
'none' as 'none' | 'boundary' | 'selection' | 'all',
|
||||
'selection' as 'selection' | 'none' | 'boundary' | 'all',
|
||||
['none', 'boundary', 'selection', 'all'] as const,
|
||||
{
|
||||
enumDescriptions: [
|
||||
|
||||
@@ -135,6 +135,7 @@ export class FontInfo extends BareFontInfo {
|
||||
readonly canUseHalfwidthRightwardsArrow: boolean;
|
||||
readonly spaceWidth: number;
|
||||
readonly middotWidth: number;
|
||||
readonly wsmiddotWidth: number;
|
||||
readonly maxDigitWidth: number;
|
||||
|
||||
/**
|
||||
@@ -154,6 +155,7 @@ export class FontInfo extends BareFontInfo {
|
||||
canUseHalfwidthRightwardsArrow: boolean;
|
||||
spaceWidth: number;
|
||||
middotWidth: number;
|
||||
wsmiddotWidth: number;
|
||||
maxDigitWidth: number;
|
||||
}, isTrusted: boolean) {
|
||||
super(opts);
|
||||
@@ -164,6 +166,7 @@ export class FontInfo extends BareFontInfo {
|
||||
this.canUseHalfwidthRightwardsArrow = opts.canUseHalfwidthRightwardsArrow;
|
||||
this.spaceWidth = opts.spaceWidth;
|
||||
this.middotWidth = opts.middotWidth;
|
||||
this.wsmiddotWidth = opts.wsmiddotWidth;
|
||||
this.maxDigitWidth = opts.maxDigitWidth;
|
||||
}
|
||||
|
||||
@@ -183,6 +186,7 @@ export class FontInfo extends BareFontInfo {
|
||||
&& this.canUseHalfwidthRightwardsArrow === other.canUseHalfwidthRightwardsArrow
|
||||
&& this.spaceWidth === other.spaceWidth
|
||||
&& this.middotWidth === other.middotWidth
|
||||
&& this.wsmiddotWidth === other.wsmiddotWidth
|
||||
&& this.maxDigitWidth === other.maxDigitWidth
|
||||
);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,11 @@ export interface ITextEditorModel extends IEditorModel {
|
||||
* Figure out if this model is resolved or not.
|
||||
*/
|
||||
isResolved(): this is IResolvedTextEditorModel;
|
||||
|
||||
/**
|
||||
* The mode id of the text model if known.
|
||||
*/
|
||||
getMode(): string | undefined;
|
||||
}
|
||||
|
||||
export interface IResolvedTextEditorModel extends ITextEditorModel {
|
||||
|
||||
@@ -229,53 +229,54 @@ export enum EditorOption {
|
||||
occurrencesHighlight = 61,
|
||||
overviewRulerBorder = 62,
|
||||
overviewRulerLanes = 63,
|
||||
parameterHints = 64,
|
||||
peekWidgetDefaultFocus = 65,
|
||||
definitionLinkOpensInPeek = 66,
|
||||
quickSuggestions = 67,
|
||||
quickSuggestionsDelay = 68,
|
||||
readOnly = 69,
|
||||
renderControlCharacters = 70,
|
||||
renderIndentGuides = 71,
|
||||
renderFinalNewline = 72,
|
||||
renderLineHighlight = 73,
|
||||
renderValidationDecorations = 74,
|
||||
renderWhitespace = 75,
|
||||
revealHorizontalRightPadding = 76,
|
||||
roundedSelection = 77,
|
||||
rulers = 78,
|
||||
scrollbar = 79,
|
||||
scrollBeyondLastColumn = 80,
|
||||
scrollBeyondLastLine = 81,
|
||||
scrollPredominantAxis = 82,
|
||||
selectionClipboard = 83,
|
||||
selectionHighlight = 84,
|
||||
selectOnLineNumbers = 85,
|
||||
showFoldingControls = 86,
|
||||
showUnused = 87,
|
||||
snippetSuggestions = 88,
|
||||
smoothScrolling = 89,
|
||||
stopRenderingLineAfter = 90,
|
||||
suggest = 91,
|
||||
suggestFontSize = 92,
|
||||
suggestLineHeight = 93,
|
||||
suggestOnTriggerCharacters = 94,
|
||||
suggestSelection = 95,
|
||||
tabCompletion = 96,
|
||||
useTabStops = 97,
|
||||
wordSeparators = 98,
|
||||
wordWrap = 99,
|
||||
wordWrapBreakAfterCharacters = 100,
|
||||
wordWrapBreakBeforeCharacters = 101,
|
||||
wordWrapColumn = 102,
|
||||
wordWrapMinified = 103,
|
||||
wrappingIndent = 104,
|
||||
wrappingStrategy = 105,
|
||||
editorClassName = 106,
|
||||
pixelRatio = 107,
|
||||
tabFocusMode = 108,
|
||||
layoutInfo = 109,
|
||||
wrappingInfo = 110
|
||||
padding = 64,
|
||||
parameterHints = 65,
|
||||
peekWidgetDefaultFocus = 66,
|
||||
definitionLinkOpensInPeek = 67,
|
||||
quickSuggestions = 68,
|
||||
quickSuggestionsDelay = 69,
|
||||
readOnly = 70,
|
||||
renderControlCharacters = 71,
|
||||
renderIndentGuides = 72,
|
||||
renderFinalNewline = 73,
|
||||
renderLineHighlight = 74,
|
||||
renderValidationDecorations = 75,
|
||||
renderWhitespace = 76,
|
||||
revealHorizontalRightPadding = 77,
|
||||
roundedSelection = 78,
|
||||
rulers = 79,
|
||||
scrollbar = 80,
|
||||
scrollBeyondLastColumn = 81,
|
||||
scrollBeyondLastLine = 82,
|
||||
scrollPredominantAxis = 83,
|
||||
selectionClipboard = 84,
|
||||
selectionHighlight = 85,
|
||||
selectOnLineNumbers = 86,
|
||||
showFoldingControls = 87,
|
||||
showUnused = 88,
|
||||
snippetSuggestions = 89,
|
||||
smoothScrolling = 90,
|
||||
stopRenderingLineAfter = 91,
|
||||
suggest = 92,
|
||||
suggestFontSize = 93,
|
||||
suggestLineHeight = 94,
|
||||
suggestOnTriggerCharacters = 95,
|
||||
suggestSelection = 96,
|
||||
tabCompletion = 97,
|
||||
useTabStops = 98,
|
||||
wordSeparators = 99,
|
||||
wordWrap = 100,
|
||||
wordWrapBreakAfterCharacters = 101,
|
||||
wordWrapBreakBeforeCharacters = 102,
|
||||
wordWrapColumn = 103,
|
||||
wordWrapMinified = 104,
|
||||
wrappingIndent = 105,
|
||||
wrappingStrategy = 106,
|
||||
editorClassName = 107,
|
||||
pixelRatio = 108,
|
||||
tabFocusMode = 109,
|
||||
layoutInfo = 110,
|
||||
wrappingInfo = 111
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -111,8 +111,10 @@ export class LinesLayout {
|
||||
private _minWidth: number;
|
||||
private _lineCount: number;
|
||||
private _lineHeight: number;
|
||||
private _paddingTop: number;
|
||||
private _paddingBottom: number;
|
||||
|
||||
constructor(lineCount: number, lineHeight: number) {
|
||||
constructor(lineCount: number, lineHeight: number, paddingTop: number, paddingBottom: number) {
|
||||
this._instanceId = strings.singleLetterHash(++LinesLayout.INSTANCE_COUNT);
|
||||
this._pendingChanges = new PendingChanges();
|
||||
this._lastWhitespaceId = 0;
|
||||
@@ -121,6 +123,8 @@ export class LinesLayout {
|
||||
this._minWidth = -1; /* marker for not being computed */
|
||||
this._lineCount = lineCount;
|
||||
this._lineHeight = lineHeight;
|
||||
this._paddingTop = paddingTop;
|
||||
this._paddingBottom = paddingBottom;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,6 +162,14 @@ export class LinesLayout {
|
||||
this._lineHeight = lineHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the padding used to calculate vertical offsets.
|
||||
*/
|
||||
public setPadding(paddingTop: number, paddingBottom: number): void {
|
||||
this._paddingTop = paddingTop;
|
||||
this._paddingBottom = paddingBottom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of lines.
|
||||
*
|
||||
@@ -404,7 +416,8 @@ export class LinesLayout {
|
||||
this._checkPendingChanges();
|
||||
const linesHeight = this._lineHeight * this._lineCount;
|
||||
const whitespacesHeight = this.getWhitespacesTotalHeight();
|
||||
return linesHeight + whitespacesHeight;
|
||||
|
||||
return linesHeight + whitespacesHeight + this._paddingTop + this._paddingBottom;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -495,7 +508,7 @@ export class LinesLayout {
|
||||
|
||||
const previousWhitespacesHeight = this.getWhitespaceAccumulatedHeightBeforeLineNumber(lineNumber);
|
||||
|
||||
return previousLinesHeight + previousWhitespacesHeight;
|
||||
return previousLinesHeight + previousWhitespacesHeight + this._paddingTop;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -719,7 +732,7 @@ export class LinesLayout {
|
||||
} else {
|
||||
previousWhitespacesHeight = 0;
|
||||
}
|
||||
return previousLinesHeight + previousWhitespacesHeight;
|
||||
return previousLinesHeight + previousWhitespacesHeight + this._paddingTop;
|
||||
}
|
||||
|
||||
public getWhitespaceIndexAtOrAfterVerticallOffset(verticalOffset: number): number {
|
||||
|
||||
@@ -161,8 +161,9 @@ export class ViewLayout extends Disposable implements IViewLayout {
|
||||
this._configuration = configuration;
|
||||
const options = this._configuration.options;
|
||||
const layoutInfo = options.get(EditorOption.layoutInfo);
|
||||
const padding = options.get(EditorOption.padding);
|
||||
|
||||
this._linesLayout = new LinesLayout(lineCount, options.get(EditorOption.lineHeight));
|
||||
this._linesLayout = new LinesLayout(lineCount, options.get(EditorOption.lineHeight), padding.top, padding.bottom);
|
||||
|
||||
this._scrollable = this._register(new EditorScrollable(0, scheduleAtNextAnimationFrame));
|
||||
this._configureSmoothScrollDuration();
|
||||
@@ -202,6 +203,10 @@ export class ViewLayout extends Disposable implements IViewLayout {
|
||||
if (e.hasChanged(EditorOption.lineHeight)) {
|
||||
this._linesLayout.setLineHeight(options.get(EditorOption.lineHeight));
|
||||
}
|
||||
if (e.hasChanged(EditorOption.padding)) {
|
||||
const padding = options.get(EditorOption.padding);
|
||||
this._linesLayout.setPadding(padding.top, padding.bottom);
|
||||
}
|
||||
if (e.hasChanged(EditorOption.layoutInfo)) {
|
||||
const layoutInfo = options.get(EditorOption.layoutInfo);
|
||||
const width = layoutInfo.contentWidth;
|
||||
|
||||
@@ -68,7 +68,8 @@ export class RenderLineInput {
|
||||
public readonly tabSize: number;
|
||||
public readonly startVisibleColumn: number;
|
||||
public readonly spaceWidth: number;
|
||||
public readonly middotWidth: number;
|
||||
public readonly renderSpaceWidth: number;
|
||||
public readonly renderSpaceCharCode: number;
|
||||
public readonly stopRenderingLineAfter: number;
|
||||
public readonly renderWhitespace: RenderWhitespace;
|
||||
public readonly renderControlCharacters: boolean;
|
||||
@@ -94,6 +95,7 @@ export class RenderLineInput {
|
||||
startVisibleColumn: number,
|
||||
spaceWidth: number,
|
||||
middotWidth: number,
|
||||
wsmiddotWidth: number,
|
||||
stopRenderingLineAfter: number,
|
||||
renderWhitespace: 'none' | 'boundary' | 'selection' | 'all',
|
||||
renderControlCharacters: boolean,
|
||||
@@ -112,7 +114,6 @@ export class RenderLineInput {
|
||||
this.tabSize = tabSize;
|
||||
this.startVisibleColumn = startVisibleColumn;
|
||||
this.spaceWidth = spaceWidth;
|
||||
this.middotWidth = middotWidth;
|
||||
this.stopRenderingLineAfter = stopRenderingLineAfter;
|
||||
this.renderWhitespace = (
|
||||
renderWhitespace === 'all'
|
||||
@@ -126,6 +127,16 @@ export class RenderLineInput {
|
||||
this.renderControlCharacters = renderControlCharacters;
|
||||
this.fontLigatures = fontLigatures;
|
||||
this.selectionsOnLine = selectionsOnLine && selectionsOnLine.sort((a, b) => a.startOffset < b.startOffset ? -1 : 1);
|
||||
|
||||
const wsmiddotDiff = Math.abs(wsmiddotWidth - spaceWidth);
|
||||
const middotDiff = Math.abs(middotWidth - spaceWidth);
|
||||
if (wsmiddotDiff < middotDiff) {
|
||||
this.renderSpaceWidth = wsmiddotWidth;
|
||||
this.renderSpaceCharCode = 0x2E31; // U+2E31 - WORD SEPARATOR MIDDLE DOT
|
||||
} else {
|
||||
this.renderSpaceWidth = middotWidth;
|
||||
this.renderSpaceCharCode = 0xB7; // U+00B7 - MIDDLE DOT
|
||||
}
|
||||
}
|
||||
|
||||
private sameSelection(otherSelections: LineRange[] | null): boolean {
|
||||
@@ -162,6 +173,8 @@ export class RenderLineInput {
|
||||
&& this.tabSize === other.tabSize
|
||||
&& this.startVisibleColumn === other.startVisibleColumn
|
||||
&& this.spaceWidth === other.spaceWidth
|
||||
&& this.renderSpaceWidth === other.renderSpaceWidth
|
||||
&& this.renderSpaceCharCode === other.renderSpaceCharCode
|
||||
&& this.stopRenderingLineAfter === other.stopRenderingLineAfter
|
||||
&& this.renderWhitespace === other.renderWhitespace
|
||||
&& this.renderControlCharacters === other.renderControlCharacters
|
||||
@@ -383,7 +396,7 @@ class ResolvedRenderLineInput {
|
||||
public readonly startVisibleColumn: number,
|
||||
public readonly containsRTL: boolean,
|
||||
public readonly spaceWidth: number,
|
||||
public readonly middotWidth: number,
|
||||
public readonly renderSpaceCharCode: number,
|
||||
public readonly renderWhitespace: RenderWhitespace,
|
||||
public readonly renderControlCharacters: boolean,
|
||||
) {
|
||||
@@ -392,7 +405,6 @@ class ResolvedRenderLineInput {
|
||||
}
|
||||
|
||||
function resolveRenderLineInput(input: RenderLineInput): ResolvedRenderLineInput {
|
||||
const useMonospaceOptimizations = input.useMonospaceOptimizations;
|
||||
const lineContent = input.lineContent;
|
||||
|
||||
let isOverflowing: boolean;
|
||||
@@ -408,7 +420,7 @@ function resolveRenderLineInput(input: RenderLineInput): ResolvedRenderLineInput
|
||||
|
||||
let tokens = transformAndRemoveOverflowing(input.lineTokens, input.fauxIndentLength, len);
|
||||
if (input.renderWhitespace === RenderWhitespace.All || input.renderWhitespace === RenderWhitespace.Boundary || (input.renderWhitespace === RenderWhitespace.Selection && !!input.selectionsOnLine)) {
|
||||
tokens = _applyRenderWhitespace(lineContent, len, input.continuesWithWrappedLine, tokens, input.fauxIndentLength, input.tabSize, input.startVisibleColumn, useMonospaceOptimizations, input.selectionsOnLine, input.renderWhitespace === RenderWhitespace.Boundary);
|
||||
tokens = _applyRenderWhitespace(input, lineContent, len, tokens);
|
||||
}
|
||||
let containsForeignElements = ForeignElementType.None;
|
||||
if (input.lineDecorations.length > 0) {
|
||||
@@ -431,7 +443,7 @@ function resolveRenderLineInput(input: RenderLineInput): ResolvedRenderLineInput
|
||||
}
|
||||
|
||||
return new ResolvedRenderLineInput(
|
||||
useMonospaceOptimizations,
|
||||
input.useMonospaceOptimizations,
|
||||
input.canUseHalfwidthRightwardsArrow,
|
||||
lineContent,
|
||||
len,
|
||||
@@ -443,7 +455,7 @@ function resolveRenderLineInput(input: RenderLineInput): ResolvedRenderLineInput
|
||||
input.startVisibleColumn,
|
||||
input.containsRTL,
|
||||
input.spaceWidth,
|
||||
input.middotWidth,
|
||||
input.renderSpaceCharCode,
|
||||
input.renderWhitespace,
|
||||
input.renderControlCharacters
|
||||
);
|
||||
@@ -553,7 +565,16 @@ function splitLargeTokens(lineContent: string, tokens: LinePart[], onlyAtSpaces:
|
||||
* Moreover, a token is created for every visual indent because on some fonts the glyphs used for rendering whitespace (→ or ·) do not have the same width as .
|
||||
* The rendering phase will generate `style="width:..."` for these tokens.
|
||||
*/
|
||||
function _applyRenderWhitespace(lineContent: string, len: number, continuesWithWrappedLine: boolean, tokens: LinePart[], fauxIndentLength: number, tabSize: number, startVisibleColumn: number, useMonospaceOptimizations: boolean, selections: LineRange[] | null, onlyBoundary: boolean): LinePart[] {
|
||||
function _applyRenderWhitespace(input: RenderLineInput, lineContent: string, len: number, tokens: LinePart[]): LinePart[] {
|
||||
|
||||
const continuesWithWrappedLine = input.continuesWithWrappedLine;
|
||||
const fauxIndentLength = input.fauxIndentLength;
|
||||
const tabSize = input.tabSize;
|
||||
const startVisibleColumn = input.startVisibleColumn;
|
||||
const useMonospaceOptimizations = input.useMonospaceOptimizations;
|
||||
const selections = input.selectionsOnLine;
|
||||
const onlyBoundary = (input.renderWhitespace === RenderWhitespace.Boundary);
|
||||
const generateLinePartForEachWhitespace = (input.renderSpaceWidth !== input.spaceWidth);
|
||||
|
||||
let result: LinePart[] = [], resultLen = 0;
|
||||
let tokenIndex = 0;
|
||||
@@ -616,7 +637,14 @@ function _applyRenderWhitespace(lineContent: string, len: number, continuesWithW
|
||||
// was in whitespace token
|
||||
if (!isInWhitespace || (!useMonospaceOptimizations && tmpIndent >= tabSize)) {
|
||||
// leaving whitespace token or entering a new indent
|
||||
result[resultLen++] = new LinePart(charIndex, 'mtkw');
|
||||
if (generateLinePartForEachWhitespace) {
|
||||
const lastEndIndex = (resultLen > 0 ? result[resultLen - 1].endIndex : fauxIndentLength);
|
||||
for (let i = lastEndIndex + 1; i <= charIndex; i++) {
|
||||
result[resultLen++] = new LinePart(i, 'mtkw');
|
||||
}
|
||||
} else {
|
||||
result[resultLen++] = new LinePart(charIndex, 'mtkw');
|
||||
}
|
||||
tmpIndent = tmpIndent % tabSize;
|
||||
}
|
||||
} else {
|
||||
@@ -661,7 +689,18 @@ function _applyRenderWhitespace(lineContent: string, len: number, continuesWithW
|
||||
}
|
||||
}
|
||||
|
||||
result[resultLen++] = new LinePart(len, generateWhitespace ? 'mtkw' : tokenType);
|
||||
if (generateWhitespace) {
|
||||
if (generateLinePartForEachWhitespace) {
|
||||
const lastEndIndex = (resultLen > 0 ? result[resultLen - 1].endIndex : fauxIndentLength);
|
||||
for (let i = lastEndIndex + 1; i <= len; i++) {
|
||||
result[resultLen++] = new LinePart(i, 'mtkw');
|
||||
}
|
||||
} else {
|
||||
result[resultLen++] = new LinePart(len, 'mtkw');
|
||||
}
|
||||
} else {
|
||||
result[resultLen++] = new LinePart(len, tokenType);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -739,13 +778,10 @@ function _renderLine(input: ResolvedRenderLineInput, sb: IStringBuilder): Render
|
||||
const startVisibleColumn = input.startVisibleColumn;
|
||||
const containsRTL = input.containsRTL;
|
||||
const spaceWidth = input.spaceWidth;
|
||||
const middotWidth = input.middotWidth;
|
||||
const renderSpaceCharCode = input.renderSpaceCharCode;
|
||||
const renderWhitespace = input.renderWhitespace;
|
||||
const renderControlCharacters = input.renderControlCharacters;
|
||||
|
||||
// use U+2E31 - WORD SEPARATOR MIDDLE DOT or U+00B7 - MIDDLE DOT
|
||||
const spaceRenderWhitespaceCharacter = (middotWidth > spaceWidth ? 0x2E31 : 0xB7);
|
||||
|
||||
const characterMapping = new CharacterMapping(len + 1, parts.length);
|
||||
|
||||
let charIndex = 0;
|
||||
@@ -815,7 +851,7 @@ function _renderLine(input: ResolvedRenderLineInput, sb: IStringBuilder): Render
|
||||
} else { // must be CharCode.Space
|
||||
charWidth = 1;
|
||||
|
||||
sb.write1(spaceRenderWhitespaceCharacter); // · or word separator middle dot
|
||||
sb.write1(renderSpaceCharCode); // · or word separator middle dot
|
||||
}
|
||||
|
||||
charOffsetInPart += charWidth;
|
||||
|
||||
@@ -611,7 +611,14 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
|
||||
return;
|
||||
} else {
|
||||
const scrollAdjustment = this._getHeight();
|
||||
let scrollAdjustment = this._getHeight();
|
||||
|
||||
// if the editor has top padding, factor that into the zone height
|
||||
scrollAdjustment -= this._codeEditor.getOption(EditorOption.padding).top;
|
||||
if (scrollAdjustment <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
viewZone.heightInPx = scrollAdjustment;
|
||||
this._viewZoneId = accessor.addZone(viewZone);
|
||||
|
||||
|
||||
@@ -304,7 +304,7 @@ export class MarkerController implements IEditorContribution {
|
||||
model.currentMarker = marker;
|
||||
}
|
||||
|
||||
private _onMarkerChanged(changedResources: URI[]): void {
|
||||
private _onMarkerChanged(changedResources: readonly URI[]): void {
|
||||
const editorModel = this._editor.getModel();
|
||||
if (!editorModel) {
|
||||
return;
|
||||
|
||||
@@ -134,10 +134,10 @@ class MessageWidget {
|
||||
detailsElement.appendChild(codeElement);
|
||||
} else {
|
||||
this._codeLink = dom.$('a.code-link');
|
||||
this._codeLink.setAttribute('href', `${code.link.toString()}`);
|
||||
this._codeLink.setAttribute('href', `${code.target.toString()}`);
|
||||
|
||||
this._codeLink.onclick = (e) => {
|
||||
this._openerService.open(code.link);
|
||||
this._openerService.open(code.target);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
@@ -516,10 +516,10 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
|
||||
sourceElement.innerText = source;
|
||||
}
|
||||
this._codeLink = dom.append(sourceAndCodeElement, $('a.code-link'));
|
||||
this._codeLink.setAttribute('href', code.link.toString());
|
||||
this._codeLink.setAttribute('href', code.target.toString());
|
||||
|
||||
this._codeLink.onclick = (e) => {
|
||||
this._openerService.open(code.link);
|
||||
this._openerService.open(code.target);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
@@ -468,6 +468,7 @@ export class SnippetSession {
|
||||
// that ensures the primiary cursor stays primary despite not being
|
||||
// the one with lowest start position
|
||||
edits[idx] = EditOperation.replace(snippetSelection, snippet.toString());
|
||||
edits[idx].identifier = { major: idx, minor: 0 }; // mark the edit so only our undo edits will be used to generate end cursors
|
||||
snippets[idx] = new OneSnippet(editor, snippet, offset);
|
||||
}
|
||||
|
||||
@@ -507,7 +508,11 @@ export class SnippetSession {
|
||||
if (this._snippets[0].hasPlaceholder) {
|
||||
return this._move(true);
|
||||
} else {
|
||||
return undoEdits.map(edit => Selection.fromPositions(edit.range.getEndPosition()));
|
||||
return (
|
||||
undoEdits
|
||||
.filter(edit => !!edit.identifier) // only use our undo edits
|
||||
.map(edit => Selection.fromPositions(edit.range.getEndPosition()))
|
||||
);
|
||||
}
|
||||
});
|
||||
this._editor.revealRange(this._editor.getSelections()[0]);
|
||||
@@ -529,7 +534,11 @@ export class SnippetSession {
|
||||
if (this._snippets[0].hasPlaceholder) {
|
||||
return this._move(undefined);
|
||||
} else {
|
||||
return undoEdits.map(edit => Selection.fromPositions(edit.range.getEndPosition()));
|
||||
return (
|
||||
undoEdits
|
||||
.filter(edit => !!edit.identifier) // only use our undo edits
|
||||
.map(edit => Selection.fromPositions(edit.range.getEndPosition()))
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKe
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { Handler } from 'vs/editor/common/editorCommon';
|
||||
import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands';
|
||||
|
||||
suite('SnippetController2', function () {
|
||||
|
||||
@@ -428,4 +429,13 @@ suite('SnippetController2', function () {
|
||||
assertSelections(editor, new Selection(2, 5, 2, 5));
|
||||
assertContextKeys(contextKeys, false, false, false);
|
||||
});
|
||||
|
||||
test('issue #90135: confusing trim whitespace edits', function () {
|
||||
const ctrl = new SnippetController2(editor, logService, contextKeys);
|
||||
model.setValue('');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
|
||||
ctrl.insert('\nfoo');
|
||||
assertSelections(editor, new Selection(2, 8, 2, 8));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -127,6 +127,7 @@ export class Colorizer {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
@@ -197,6 +198,7 @@ function _fakeColorize(lines: string[], tabSize: number): string {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
@@ -236,6 +238,7 @@ function _actualColorize(lines: string[], tabSize: number, tokenizationSupport:
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
|
||||
@@ -84,6 +84,10 @@ export class SimpleModel implements IResolvedTextEditorModel {
|
||||
public isResolved(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
public getMode(): string | undefined {
|
||||
return this.model.getModeId();
|
||||
}
|
||||
}
|
||||
|
||||
export interface IOpenEditorDelegate {
|
||||
|
||||
@@ -90,7 +90,7 @@ export interface IGlobalEditorOptions {
|
||||
tabSize?: number;
|
||||
/**
|
||||
* Insert spaces when pressing `Tab`.
|
||||
* This setting is overridden based on the file contents when detectIndentation` is on.
|
||||
* This setting is overridden based on the file contents when `detectIndentation` is on.
|
||||
* Defaults to true.
|
||||
*/
|
||||
insertSpaces?: boolean;
|
||||
|
||||
@@ -501,7 +501,7 @@ export class MonarchTokenizer implements modes.ITokenizationSupport {
|
||||
}
|
||||
|
||||
let result = line.search(regex);
|
||||
if (result === -1) {
|
||||
if (result === -1 || (result !== 0 && rule.matchOnlyAtLineStart)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ suite('TextAreaState', () => {
|
||||
textArea.dispose();
|
||||
});
|
||||
|
||||
function testDeduceInput(prevState: TextAreaState | null, value: string, selectionStart: number, selectionEnd: number, couldBeEmojiInput: boolean, couldBeTypingAtOffset0: boolean, expected: string, expectedCharReplaceCnt: number): void {
|
||||
function testDeduceInput(prevState: TextAreaState | null, value: string, selectionStart: number, selectionEnd: number, couldBeEmojiInput: boolean, expected: string, expectedCharReplaceCnt: number): void {
|
||||
prevState = prevState || TextAreaState.EMPTY;
|
||||
|
||||
let textArea = new MockTextAreaWrapper();
|
||||
@@ -132,7 +132,7 @@ suite('TextAreaState', () => {
|
||||
textArea._selectionEnd = selectionEnd;
|
||||
|
||||
let newState = TextAreaState.readFromTextArea(textArea);
|
||||
let actual = TextAreaState.deduceInput(prevState, newState, couldBeEmojiInput, couldBeTypingAtOffset0);
|
||||
let actual = TextAreaState.deduceInput(prevState, newState, couldBeEmojiInput);
|
||||
|
||||
assert.equal(actual.text, expected);
|
||||
assert.equal(actual.replaceCharCnt, expectedCharReplaceCnt);
|
||||
@@ -153,7 +153,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
TextAreaState.EMPTY,
|
||||
's',
|
||||
0, 1, true, false,
|
||||
0, 1, true,
|
||||
's', 0
|
||||
);
|
||||
|
||||
@@ -163,7 +163,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('s', 0, 1, null, null),
|
||||
'せ',
|
||||
0, 1, true, false,
|
||||
0, 1, true,
|
||||
'せ', 1
|
||||
);
|
||||
|
||||
@@ -173,7 +173,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('せ', 0, 1, null, null),
|
||||
'せn',
|
||||
0, 2, true, false,
|
||||
0, 2, true,
|
||||
'せn', 1
|
||||
);
|
||||
|
||||
@@ -183,7 +183,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('せn', 0, 2, null, null),
|
||||
'せん',
|
||||
0, 2, true, false,
|
||||
0, 2, true,
|
||||
'せん', 2
|
||||
);
|
||||
|
||||
@@ -193,7 +193,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('せん', 0, 2, null, null),
|
||||
'せんs',
|
||||
0, 3, true, false,
|
||||
0, 3, true,
|
||||
'せんs', 2
|
||||
);
|
||||
|
||||
@@ -203,7 +203,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('せんs', 0, 3, null, null),
|
||||
'せんせ',
|
||||
0, 3, true, false,
|
||||
0, 3, true,
|
||||
'せんせ', 3
|
||||
);
|
||||
|
||||
@@ -213,7 +213,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('せんせ', 0, 3, null, null),
|
||||
'せんせ',
|
||||
0, 3, true, false,
|
||||
0, 3, true,
|
||||
'せんせ', 3
|
||||
);
|
||||
|
||||
@@ -223,7 +223,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('せんせ', 0, 3, null, null),
|
||||
'せんせい',
|
||||
0, 4, true, false,
|
||||
0, 4, true,
|
||||
'せんせい', 3
|
||||
);
|
||||
|
||||
@@ -233,7 +233,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('せんせい', 0, 4, null, null),
|
||||
'せんせい',
|
||||
4, 4, true, false,
|
||||
4, 4, true,
|
||||
'', 0
|
||||
);
|
||||
});
|
||||
@@ -252,7 +252,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('せんせい', 0, 4, null, null),
|
||||
'せんせい',
|
||||
0, 4, true, false,
|
||||
0, 4, true,
|
||||
'せんせい', 4
|
||||
);
|
||||
|
||||
@@ -262,7 +262,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('せんせい', 0, 4, null, null),
|
||||
'先生',
|
||||
0, 2, true, false,
|
||||
0, 2, true,
|
||||
'先生', 4
|
||||
);
|
||||
|
||||
@@ -272,7 +272,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('先生', 0, 2, null, null),
|
||||
'先生',
|
||||
2, 2, true, false,
|
||||
2, 2, true,
|
||||
'', 0
|
||||
);
|
||||
});
|
||||
@@ -281,7 +281,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
null,
|
||||
'a',
|
||||
0, 1, true, false,
|
||||
0, 1, true,
|
||||
'a', 0
|
||||
);
|
||||
});
|
||||
@@ -290,7 +290,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState(']\n', 1, 2, null, null),
|
||||
']\n',
|
||||
2, 2, true, false,
|
||||
2, 2, true,
|
||||
'\n', 0
|
||||
);
|
||||
});
|
||||
@@ -299,7 +299,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
null,
|
||||
'a',
|
||||
1, 1, true, false,
|
||||
1, 1, true,
|
||||
'a', 0
|
||||
);
|
||||
});
|
||||
@@ -308,7 +308,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
TextAreaState.EMPTY,
|
||||
'a',
|
||||
0, 1, true, false,
|
||||
0, 1, true,
|
||||
'a', 0
|
||||
);
|
||||
});
|
||||
@@ -317,7 +317,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
TextAreaState.EMPTY,
|
||||
'a',
|
||||
1, 1, true, false,
|
||||
1, 1, true,
|
||||
'a', 0
|
||||
);
|
||||
});
|
||||
@@ -326,7 +326,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 0, 12, null, null),
|
||||
'H',
|
||||
1, 1, true, false,
|
||||
1, 1, true,
|
||||
'H', 0
|
||||
);
|
||||
});
|
||||
@@ -335,7 +335,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 12, 12, null, null),
|
||||
'Hello world!a',
|
||||
13, 13, true, false,
|
||||
13, 13, true,
|
||||
'a', 0
|
||||
);
|
||||
});
|
||||
@@ -344,7 +344,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 0, 0, null, null),
|
||||
'aHello world!',
|
||||
1, 1, true, false,
|
||||
1, 1, true,
|
||||
'a', 0
|
||||
);
|
||||
});
|
||||
@@ -353,7 +353,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 6, 11, null, null),
|
||||
'Hello other!',
|
||||
11, 11, true, false,
|
||||
11, 11, true,
|
||||
'other', 0
|
||||
);
|
||||
});
|
||||
@@ -362,7 +362,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
TextAreaState.EMPTY,
|
||||
'これは',
|
||||
3, 3, true, false,
|
||||
3, 3, true,
|
||||
'これは', 0
|
||||
);
|
||||
});
|
||||
@@ -371,7 +371,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 0, 0, null, null),
|
||||
'Aello world!',
|
||||
1, 1, true, false,
|
||||
1, 1, true,
|
||||
'A', 0
|
||||
);
|
||||
});
|
||||
@@ -380,7 +380,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 5, 5, null, null),
|
||||
'Hellö world!',
|
||||
4, 5, true, false,
|
||||
4, 5, true,
|
||||
'ö', 0
|
||||
);
|
||||
});
|
||||
@@ -389,7 +389,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 5, 5, null, null),
|
||||
'Hellöö world!',
|
||||
5, 5, true, false,
|
||||
5, 5, true,
|
||||
'öö', 1
|
||||
);
|
||||
});
|
||||
@@ -398,7 +398,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 5, 5, null, null),
|
||||
'Helöö world!',
|
||||
5, 5, true, false,
|
||||
5, 5, true,
|
||||
'öö', 2
|
||||
);
|
||||
});
|
||||
@@ -407,7 +407,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 5, 5, null, null),
|
||||
'Hellö world!',
|
||||
5, 5, true, false,
|
||||
5, 5, true,
|
||||
'ö', 1
|
||||
);
|
||||
});
|
||||
@@ -416,7 +416,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('a', 0, 1, null, null),
|
||||
'a',
|
||||
1, 1, true, false,
|
||||
1, 1, true,
|
||||
'a', 0
|
||||
);
|
||||
});
|
||||
@@ -425,7 +425,7 @@ suite('TextAreaState', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('x x', 0, 1, null, null),
|
||||
'x x',
|
||||
1, 1, true, false,
|
||||
1, 1, true,
|
||||
'x', 0
|
||||
);
|
||||
});
|
||||
@@ -455,7 +455,7 @@ suite('TextAreaState', () => {
|
||||
'some6 text',
|
||||
'some7 text'
|
||||
].join('\n'),
|
||||
4, 4, true, false,
|
||||
4, 4, true,
|
||||
'📅', 0
|
||||
);
|
||||
});
|
||||
@@ -469,7 +469,7 @@ suite('TextAreaState', () => {
|
||||
null, null
|
||||
),
|
||||
'some💊1 text',
|
||||
6, 6, true, false,
|
||||
6, 6, true,
|
||||
'💊', 0
|
||||
);
|
||||
});
|
||||
@@ -483,7 +483,7 @@ suite('TextAreaState', () => {
|
||||
null, null
|
||||
),
|
||||
'qwertyu\nasdfghj\nzxcvbnm🎈',
|
||||
25, 25, true, false,
|
||||
25, 25, true,
|
||||
'🎈', 0
|
||||
);
|
||||
});
|
||||
@@ -498,39 +498,11 @@ suite('TextAreaState', () => {
|
||||
null, null
|
||||
),
|
||||
'some⌨️1 text',
|
||||
6, 6, true, false,
|
||||
6, 6, true,
|
||||
'⌨️', 0
|
||||
);
|
||||
});
|
||||
|
||||
test('issue #42251: Minor issue, character swapped when typing', () => {
|
||||
// Typing on OSX occurs at offset 0 after moving the window using the custom (non-native) titlebar.
|
||||
testDeduceInput(
|
||||
new TextAreaState(
|
||||
'ab',
|
||||
2, 2,
|
||||
null, null
|
||||
),
|
||||
'cab',
|
||||
1, 1, true, true,
|
||||
'c', 0
|
||||
);
|
||||
});
|
||||
|
||||
test('issue #49480: Double curly braces inserted', () => {
|
||||
// Characters get doubled
|
||||
testDeduceInput(
|
||||
new TextAreaState(
|
||||
'aa',
|
||||
2, 2,
|
||||
null, null
|
||||
),
|
||||
'aaa',
|
||||
3, 3, true, true,
|
||||
'a', 0
|
||||
);
|
||||
});
|
||||
|
||||
suite('PagedScreenReaderStrategy', () => {
|
||||
|
||||
function testPagedScreenReaderStrategy(lines: string[], selection: Selection, expected: TextAreaState): void {
|
||||
|
||||
@@ -42,6 +42,7 @@ export class TestConfiguration extends CommonEditorConfiguration {
|
||||
canUseHalfwidthRightwardsArrow: true,
|
||||
spaceWidth: 10,
|
||||
middotWidth: 10,
|
||||
wsmiddotWidth: 10,
|
||||
maxDigitWidth: 10,
|
||||
}, true);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
||||
test('LinesLayout 1', () => {
|
||||
|
||||
// Start off with 10 lines
|
||||
let linesLayout = new LinesLayout(10, 10);
|
||||
let linesLayout = new LinesLayout(10, 10, 0, 0);
|
||||
|
||||
// lines: [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
// whitespace: -
|
||||
@@ -137,7 +137,7 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
||||
test('LinesLayout 2', () => {
|
||||
|
||||
// Start off with 10 lines and one whitespace after line 2, of height 5
|
||||
let linesLayout = new LinesLayout(10, 1);
|
||||
let linesLayout = new LinesLayout(10, 1, 0, 0);
|
||||
let a = insertWhitespace(linesLayout, 2, 0, 5, 0);
|
||||
|
||||
// 10 lines
|
||||
@@ -232,8 +232,103 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(10), 9);
|
||||
});
|
||||
|
||||
test('LinesLayout Padding', () => {
|
||||
// Start off with 10 lines
|
||||
let linesLayout = new LinesLayout(10, 10, 15, 20);
|
||||
|
||||
// lines: [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
// whitespace: -
|
||||
assert.equal(linesLayout.getLinesTotalHeight(), 135);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 15);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 25);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 35);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 45);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(5), 55);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(6), 65);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(7), 75);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(8), 85);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(9), 95);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(10), 105);
|
||||
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(0), 1);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(10), 1);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(15), 1);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(24), 1);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(25), 2);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(34), 2);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(35), 3);
|
||||
|
||||
// Add whitespace of height 5px after 2nd line
|
||||
insertWhitespace(linesLayout, 2, 0, 5, 0);
|
||||
// lines: [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
// whitespace: a(2,5)
|
||||
assert.equal(linesLayout.getLinesTotalHeight(), 140);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 15);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 25);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 40);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 50);
|
||||
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(0), 1);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(10), 1);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(25), 2);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(34), 2);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(35), 3);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(39), 3);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(40), 3);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(41), 3);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(49), 3);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(50), 4);
|
||||
|
||||
// Add two more whitespaces of height 5px
|
||||
insertWhitespace(linesLayout, 3, 0, 5, 0);
|
||||
insertWhitespace(linesLayout, 4, 0, 5, 0);
|
||||
// lines: [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
// whitespace: a(2,5), b(3, 5), c(4, 5)
|
||||
assert.equal(linesLayout.getLinesTotalHeight(), 150);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 15);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 25);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(3), 40);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(4), 55);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(5), 70);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(6), 80);
|
||||
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(0), 1);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(15), 1);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(24), 1);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(30), 2);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(35), 3);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(39), 3);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(40), 3);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(49), 3);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(50), 4);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(54), 4);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(55), 4);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(64), 4);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(65), 5);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(69), 5);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(70), 5);
|
||||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(80), 6);
|
||||
|
||||
assert.equal(linesLayout.getVerticalOffsetForWhitespaceIndex(0), 35); // 35 -> 40
|
||||
assert.equal(linesLayout.getVerticalOffsetForWhitespaceIndex(1), 50); // 50 -> 55
|
||||
assert.equal(linesLayout.getVerticalOffsetForWhitespaceIndex(2), 65);
|
||||
|
||||
assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(0), 0);
|
||||
assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(34), 0);
|
||||
assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(35), 0);
|
||||
assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(39), 0);
|
||||
assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(40), 1);
|
||||
assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(49), 1);
|
||||
assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(50), 1);
|
||||
assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(54), 1);
|
||||
assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(55), 2);
|
||||
assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(64), 2);
|
||||
assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(65), 2);
|
||||
assert.equal(linesLayout.getWhitespaceIndexAtOrAfterVerticallOffset(70), -1);
|
||||
});
|
||||
|
||||
test('LinesLayout getLineNumberAtOrAfterVerticalOffset', () => {
|
||||
let linesLayout = new LinesLayout(10, 1);
|
||||
let linesLayout = new LinesLayout(10, 1, 0, 0);
|
||||
insertWhitespace(linesLayout, 6, 0, 10, 0);
|
||||
|
||||
// 10 lines
|
||||
@@ -282,7 +377,7 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
||||
});
|
||||
|
||||
test('LinesLayout getCenteredLineInViewport', () => {
|
||||
let linesLayout = new LinesLayout(10, 1);
|
||||
let linesLayout = new LinesLayout(10, 1, 0, 0);
|
||||
insertWhitespace(linesLayout, 6, 0, 10, 0);
|
||||
|
||||
// 10 lines
|
||||
@@ -365,7 +460,7 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
||||
});
|
||||
|
||||
test('LinesLayout getLinesViewportData 1', () => {
|
||||
let linesLayout = new LinesLayout(10, 10);
|
||||
let linesLayout = new LinesLayout(10, 10, 0, 0);
|
||||
insertWhitespace(linesLayout, 6, 0, 100, 0);
|
||||
|
||||
// 10 lines
|
||||
@@ -498,7 +593,7 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
||||
});
|
||||
|
||||
test('LinesLayout getLinesViewportData 2 & getWhitespaceViewportData', () => {
|
||||
let linesLayout = new LinesLayout(10, 10);
|
||||
let linesLayout = new LinesLayout(10, 10, 0, 0);
|
||||
let a = insertWhitespace(linesLayout, 6, 0, 100, 0);
|
||||
let b = insertWhitespace(linesLayout, 7, 0, 50, 0);
|
||||
|
||||
@@ -569,7 +664,7 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
||||
});
|
||||
|
||||
test('LinesLayout getWhitespaceAtVerticalOffset', () => {
|
||||
let linesLayout = new LinesLayout(10, 10);
|
||||
let linesLayout = new LinesLayout(10, 10, 0, 0);
|
||||
let a = insertWhitespace(linesLayout, 6, 0, 100, 0);
|
||||
let b = insertWhitespace(linesLayout, 7, 0, 50, 0);
|
||||
|
||||
@@ -612,7 +707,7 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
||||
|
||||
test('LinesLayout', () => {
|
||||
|
||||
const linesLayout = new LinesLayout(100, 20);
|
||||
const linesLayout = new LinesLayout(100, 20, 0, 0);
|
||||
|
||||
// Insert a whitespace after line number 2, of height 10
|
||||
const a = insertWhitespace(linesLayout, 2, 0, 10, 0);
|
||||
@@ -963,7 +1058,7 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
||||
});
|
||||
|
||||
test('LinesLayout changeWhitespaceAfterLineNumber & getFirstWhitespaceIndexAfterLineNumber', () => {
|
||||
const linesLayout = new LinesLayout(100, 20);
|
||||
const linesLayout = new LinesLayout(100, 20, 0, 0);
|
||||
|
||||
const a = insertWhitespace(linesLayout, 0, 0, 1, 0);
|
||||
const b = insertWhitespace(linesLayout, 7, 0, 1, 0);
|
||||
@@ -1087,7 +1182,7 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
||||
});
|
||||
|
||||
test('LinesLayout Bug', () => {
|
||||
const linesLayout = new LinesLayout(100, 20);
|
||||
const linesLayout = new LinesLayout(100, 20, 0, 0);
|
||||
|
||||
const a = insertWhitespace(linesLayout, 0, 0, 1, 0);
|
||||
const b = insertWhitespace(linesLayout, 7, 0, 1, 0);
|
||||
|
||||
@@ -40,6 +40,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
@@ -92,6 +93,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
@@ -147,6 +149,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
6,
|
||||
'boundary',
|
||||
false,
|
||||
@@ -241,6 +244,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
'boundary',
|
||||
false,
|
||||
@@ -306,6 +310,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
@@ -371,6 +376,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
@@ -413,6 +419,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
@@ -446,6 +453,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
@@ -549,6 +557,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
@@ -590,6 +599,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
@@ -622,6 +632,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
@@ -671,6 +682,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
@@ -755,6 +767,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
renderWhitespace,
|
||||
false,
|
||||
@@ -783,6 +796,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
@@ -825,6 +839,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
@@ -1242,6 +1257,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
@@ -1285,6 +1301,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
'all',
|
||||
false,
|
||||
@@ -1320,6 +1337,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
'all',
|
||||
false,
|
||||
@@ -1356,6 +1374,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
'all',
|
||||
false,
|
||||
@@ -1388,6 +1407,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
false,
|
||||
@@ -1424,6 +1444,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
false,
|
||||
@@ -1460,6 +1481,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
false,
|
||||
@@ -1493,6 +1515,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
false,
|
||||
@@ -1525,6 +1548,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10000,
|
||||
'all',
|
||||
false,
|
||||
@@ -1563,6 +1587,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
false,
|
||||
@@ -1595,6 +1620,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
false,
|
||||
@@ -1629,6 +1655,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
false,
|
||||
@@ -1662,6 +1689,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10000,
|
||||
'boundary',
|
||||
false,
|
||||
@@ -1693,6 +1721,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
false,
|
||||
@@ -1728,6 +1757,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
false,
|
||||
@@ -1759,6 +1789,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
|
||||
@@ -58,6 +58,7 @@ function getLineBreakData(factory: ILineBreaksComputerFactory, tabSize: number,
|
||||
canUseHalfwidthRightwardsArrow: true,
|
||||
spaceWidth: 7,
|
||||
middotWidth: 7,
|
||||
wsmiddotWidth: 7,
|
||||
maxDigitWidth: 7
|
||||
}, false);
|
||||
const lineBreaksComputer = factory.createLineBreaksComputer(fontInfo, tabSize, breakAfter, wrappingIndent);
|
||||
|
||||
Reference in New Issue
Block a user