mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-13 23:44:09 +01:00
Record the visible line count for the text in value before selectionStart in the text area state
This commit is contained in:
@@ -201,6 +201,9 @@ export class TextAreaHandler extends ViewPart {
|
||||
},
|
||||
getValueLengthInRange: (range: Range, eol: EndOfLinePreference): number => {
|
||||
return this._context.viewModel.getValueLengthInRange(range, eol);
|
||||
},
|
||||
modifyPosition: (position: Position, offset: number): Position => {
|
||||
return this._context.viewModel.modifyPosition(position, offset);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -230,7 +233,7 @@ export class TextAreaHandler extends ViewPart {
|
||||
mode
|
||||
};
|
||||
},
|
||||
getScreenReaderContent: (currentState: TextAreaState): TextAreaState => {
|
||||
getScreenReaderContent: (): TextAreaState => {
|
||||
if (this._accessibilitySupport === AccessibilitySupport.Disabled) {
|
||||
// We know for a fact that a screen reader is not attached
|
||||
// On OSX, we write the character before the cursor to allow for "long-press" composition
|
||||
@@ -245,7 +248,7 @@ export class TextAreaHandler extends ViewPart {
|
||||
}
|
||||
|
||||
if (textBefore.length > 0) {
|
||||
return new TextAreaState(textBefore, textBefore.length, textBefore.length, position, position);
|
||||
return new TextAreaState(textBefore, textBefore.length, textBefore.length, Range.fromPositions(position), 0);
|
||||
}
|
||||
}
|
||||
// on macOS, write current selection into textarea will allow system text services pick selected text,
|
||||
@@ -255,7 +258,7 @@ export class TextAreaHandler extends ViewPart {
|
||||
const LIMIT_CHARS = 500;
|
||||
if (platform.isMacintosh && !selection.isEmpty() && simpleModel.getValueLengthInRange(selection, EndOfLinePreference.TextDefined) < LIMIT_CHARS) {
|
||||
const text = simpleModel.getValueInRange(selection, EndOfLinePreference.TextDefined);
|
||||
return new TextAreaState(text, 0, text.length, selection.getStartPosition(), selection.getEndPosition());
|
||||
return new TextAreaState(text, 0, text.length, selection, 0);
|
||||
}
|
||||
|
||||
// on Safari, document.execCommand('cut') and document.execCommand('copy') will just not work
|
||||
@@ -263,7 +266,7 @@ export class TextAreaHandler extends ViewPart {
|
||||
// is selected in the textarea.
|
||||
if (browser.isSafari && !selection.isEmpty()) {
|
||||
const placeholderText = 'vscode-placeholder';
|
||||
return new TextAreaState(placeholderText, 0, placeholderText.length, null, null);
|
||||
return new TextAreaState(placeholderText, 0, placeholderText.length, null, undefined);
|
||||
}
|
||||
|
||||
return TextAreaState.EMPTY;
|
||||
@@ -279,13 +282,13 @@ export class TextAreaHandler extends ViewPart {
|
||||
const position = selection.getStartPosition();
|
||||
const [wordAtPosition, positionOffsetInWord] = this._getAndroidWordAtPosition(position);
|
||||
if (wordAtPosition.length > 0) {
|
||||
return new TextAreaState(wordAtPosition, positionOffsetInWord, positionOffsetInWord, position, position);
|
||||
return new TextAreaState(wordAtPosition, positionOffsetInWord, positionOffsetInWord, Range.fromPositions(position), 0);
|
||||
}
|
||||
}
|
||||
return TextAreaState.EMPTY;
|
||||
}
|
||||
|
||||
return PagedScreenReaderStrategy.fromEditorSelection(currentState, simpleModel, this._selections[0], this._accessibilityPageSize, this._accessibilitySupport === AccessibilitySupport.Unknown);
|
||||
return PagedScreenReaderStrategy.fromEditorSelection(simpleModel, this._selections[0], this._accessibilityPageSize, this._accessibilitySupport === AccessibilitySupport.Unknown);
|
||||
},
|
||||
|
||||
deduceModelPosition: (viewAnchorPosition: Position, deltaOffset: number, lineFeedCnt: number): Position => {
|
||||
|
||||
@@ -52,7 +52,7 @@ export interface ClipboardStoredMetadata {
|
||||
|
||||
export interface ITextAreaInputHost {
|
||||
getDataToCopy(): ClipboardDataToCopy;
|
||||
getScreenReaderContent(currentState: TextAreaState): TextAreaState;
|
||||
getScreenReaderContent(): TextAreaState;
|
||||
deduceModelPosition(viewAnchorPosition: Position, deltaOffset: number, lineFeedCnt: number): Position;
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ export class TextAreaInput extends Disposable {
|
||||
// For example, if the cursor is in the middle of a word like Mic|osoft
|
||||
// and Microsoft is chosen from the keyboard's suggestions, the e.data will contain "Microsoft".
|
||||
// This is not really usable because it doesn't tell us where the edit began and where it ended.
|
||||
const newState = TextAreaState.readFromTextArea(this._textArea);
|
||||
const newState = TextAreaState.readFromTextArea(this._textArea, this._textAreaState);
|
||||
const typeInput = TextAreaState.deduceAndroidCompositionInput(this._textAreaState, newState);
|
||||
this._textAreaState = newState;
|
||||
this._onType.fire(typeInput);
|
||||
@@ -304,7 +304,7 @@ export class TextAreaInput extends Disposable {
|
||||
return;
|
||||
}
|
||||
const typeInput = currentComposition.handleCompositionUpdate(e.data);
|
||||
this._textAreaState = TextAreaState.readFromTextArea(this._textArea);
|
||||
this._textAreaState = TextAreaState.readFromTextArea(this._textArea, this._textAreaState);
|
||||
this._onType.fire(typeInput);
|
||||
this._onCompositionUpdate.fire(e);
|
||||
}));
|
||||
@@ -326,7 +326,7 @@ export class TextAreaInput extends Disposable {
|
||||
// For example, if the cursor is in the middle of a word like Mic|osoft
|
||||
// and Microsoft is chosen from the keyboard's suggestions, the e.data will contain "Microsoft".
|
||||
// This is not really usable because it doesn't tell us where the edit began and where it ended.
|
||||
const newState = TextAreaState.readFromTextArea(this._textArea);
|
||||
const newState = TextAreaState.readFromTextArea(this._textArea, this._textAreaState);
|
||||
const typeInput = TextAreaState.deduceAndroidCompositionInput(this._textAreaState, newState);
|
||||
this._textAreaState = newState;
|
||||
this._onType.fire(typeInput);
|
||||
@@ -335,7 +335,7 @@ export class TextAreaInput extends Disposable {
|
||||
}
|
||||
|
||||
const typeInput = currentComposition.handleCompositionUpdate(e.data);
|
||||
this._textAreaState = TextAreaState.readFromTextArea(this._textArea);
|
||||
this._textAreaState = TextAreaState.readFromTextArea(this._textArea, this._textAreaState);
|
||||
this._onType.fire(typeInput);
|
||||
this._onCompositionEnd.fire();
|
||||
}));
|
||||
@@ -353,7 +353,7 @@ export class TextAreaInput extends Disposable {
|
||||
return;
|
||||
}
|
||||
|
||||
const newState = TextAreaState.readFromTextArea(this._textArea);
|
||||
const newState = TextAreaState.readFromTextArea(this._textArea, this._textAreaState);
|
||||
const typeInput = TextAreaState.deduceInput(this._textAreaState, newState, /*couldBeEmojiInput*/this._OS === OperatingSystem.Macintosh);
|
||||
|
||||
if (typeInput.replacePrevCharCnt === 0 && typeInput.text.length === 1 && strings.isHighSurrogate(typeInput.text.charCodeAt(0))) {
|
||||
@@ -459,7 +459,7 @@ export class TextAreaInput extends Disposable {
|
||||
|
||||
_initializeFromTest(): void {
|
||||
this._hasFocus = true;
|
||||
this._textAreaState = TextAreaState.readFromTextArea(this._textArea);
|
||||
this._textAreaState = TextAreaState.readFromTextArea(this._textArea, null);
|
||||
}
|
||||
|
||||
private _installSelectionChangeListener(): IDisposable {
|
||||
@@ -512,7 +512,7 @@ export class TextAreaInput extends Disposable {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._textAreaState.selectionStartPosition || !this._textAreaState.selectionEndPosition) {
|
||||
if (!this._textAreaState.selection) {
|
||||
// Cannot correlate a position in the textarea with a position in the editor...
|
||||
return;
|
||||
}
|
||||
@@ -611,7 +611,7 @@ export class TextAreaInput extends Disposable {
|
||||
return;
|
||||
}
|
||||
|
||||
this._setAndWriteTextAreaState(reason, this._host.getScreenReaderContent(this._textAreaState));
|
||||
this._setAndWriteTextAreaState(reason, this._host.getScreenReaderContent());
|
||||
}
|
||||
|
||||
private _ensureClipboardGetsEditorSelection(e: ClipboardEvent): void {
|
||||
|
||||
@@ -24,6 +24,7 @@ export interface ISimpleModel {
|
||||
getLineMaxColumn(lineNumber: number): number;
|
||||
getValueInRange(range: Range, eol: EndOfLinePreference): string;
|
||||
getValueLengthInRange(range: Range, eol: EndOfLinePreference): number;
|
||||
modifyPosition(position: Position, offset: number): Position;
|
||||
}
|
||||
|
||||
export interface ITypeData {
|
||||
@@ -35,32 +36,44 @@ export interface ITypeData {
|
||||
|
||||
export class TextAreaState {
|
||||
|
||||
public static readonly EMPTY = new TextAreaState('', 0, 0, null, null);
|
||||
public static readonly EMPTY = new TextAreaState('', 0, 0, null, undefined);
|
||||
|
||||
public readonly value: string;
|
||||
public readonly selectionStart: number;
|
||||
public readonly selectionEnd: number;
|
||||
public readonly selectionStartPosition: Position | null;
|
||||
public readonly selectionEndPosition: Position | null;
|
||||
|
||||
constructor(value: string, selectionStart: number, selectionEnd: number, selectionStartPosition: Position | null, selectionEndPosition: Position | null) {
|
||||
this.value = value;
|
||||
this.selectionStart = selectionStart;
|
||||
this.selectionEnd = selectionEnd;
|
||||
this.selectionStartPosition = selectionStartPosition;
|
||||
this.selectionEndPosition = selectionEndPosition;
|
||||
}
|
||||
constructor(
|
||||
public readonly value: string,
|
||||
/** the offset where selection starts inside `value` */
|
||||
public readonly selectionStart: number,
|
||||
/** the offset where selection ends inside `value` */
|
||||
public readonly selectionEnd: number,
|
||||
/** the editor range in the view coordinate system that matches the selection inside `value` */
|
||||
public readonly selection: Range | null,
|
||||
/** the visible line count (wrapped, not necessarily matching \n characters) for the text in `value` before `selectionStart` */
|
||||
public readonly newlineCountBeforeSelection: number | undefined,
|
||||
) { }
|
||||
|
||||
public toString(): string {
|
||||
return `[ <${this.value}>, selectionStart: ${this.selectionStart}, selectionEnd: ${this.selectionEnd}]`;
|
||||
}
|
||||
|
||||
public static readFromTextArea(textArea: ITextAreaWrapper): TextAreaState {
|
||||
return new TextAreaState(textArea.getValue(), textArea.getSelectionStart(), textArea.getSelectionEnd(), null, null);
|
||||
public static readFromTextArea(textArea: ITextAreaWrapper, previousState: TextAreaState | null): TextAreaState {
|
||||
const value = textArea.getValue();
|
||||
const selectionStart = textArea.getSelectionStart();
|
||||
const selectionEnd = textArea.getSelectionEnd();
|
||||
let newlineCountBeforeSelection: number | undefined = undefined;
|
||||
if (previousState) {
|
||||
const valueBeforeSelectionStart = value.substring(0, selectionStart);
|
||||
const previousValueBeforeSelectionStart = previousState.value.substring(0, previousState.selectionStart);
|
||||
if (valueBeforeSelectionStart === previousValueBeforeSelectionStart) {
|
||||
newlineCountBeforeSelection = previousState.newlineCountBeforeSelection;
|
||||
}
|
||||
}
|
||||
return new TextAreaState(value, selectionStart, selectionEnd, null, newlineCountBeforeSelection);
|
||||
}
|
||||
|
||||
public collapseSelection(): TextAreaState {
|
||||
return new TextAreaState(this.value, this.value.length, this.value.length, null, null);
|
||||
if (this.selectionStart === this.value.length) {
|
||||
return this;
|
||||
}
|
||||
return new TextAreaState(this.value, this.value.length, this.value.length, null, undefined);
|
||||
}
|
||||
|
||||
public writeToTextArea(reason: string, textArea: ITextAreaWrapper, select: boolean): void {
|
||||
@@ -76,18 +89,18 @@ export class TextAreaState {
|
||||
public deduceEditorPosition(offset: number): [Position | null, number, number] {
|
||||
if (offset <= this.selectionStart) {
|
||||
const str = this.value.substring(offset, this.selectionStart);
|
||||
return this._finishDeduceEditorPosition(this.selectionStartPosition, str, -1);
|
||||
return this._finishDeduceEditorPosition(this.selection?.getStartPosition() ?? null, str, -1);
|
||||
}
|
||||
if (offset >= this.selectionEnd) {
|
||||
const str = this.value.substring(this.selectionEnd, offset);
|
||||
return this._finishDeduceEditorPosition(this.selectionEndPosition, str, 1);
|
||||
return this._finishDeduceEditorPosition(this.selection?.getEndPosition() ?? null, str, 1);
|
||||
}
|
||||
const str1 = this.value.substring(this.selectionStart, offset);
|
||||
if (str1.indexOf(String.fromCharCode(8230)) === -1) {
|
||||
return this._finishDeduceEditorPosition(this.selectionStartPosition, str1, 1);
|
||||
return this._finishDeduceEditorPosition(this.selection?.getStartPosition() ?? null, str1, 1);
|
||||
}
|
||||
const str2 = this.value.substring(offset, this.selectionEnd);
|
||||
return this._finishDeduceEditorPosition(this.selectionEndPosition, str2, -1);
|
||||
return this._finishDeduceEditorPosition(this.selection?.getEndPosition() ?? null, str2, -1);
|
||||
}
|
||||
|
||||
private _finishDeduceEditorPosition(anchor: Position | null, deltaText: string, signum: number): [Position | null, number, number] {
|
||||
@@ -224,7 +237,10 @@ export class PagedScreenReaderStrategy {
|
||||
return new Range(startLineNumber, 1, endLineNumber + 1, 1);
|
||||
}
|
||||
|
||||
public static fromEditorSelection(previousState: TextAreaState, model: ISimpleModel, selection: Range, linesPerPage: number, trimLongText: boolean): TextAreaState {
|
||||
public static fromEditorSelection(model: ISimpleModel, selection: Range, linesPerPage: number, trimLongText: boolean): TextAreaState {
|
||||
// Chromium handles very poorly text even of a few thousand chars
|
||||
// Cut text to avoid stalling the entire UI
|
||||
const LIMIT_CHARS = 500;
|
||||
|
||||
const selectionStartPage = PagedScreenReaderStrategy._getPageOfLine(selection.startLineNumber, linesPerPage);
|
||||
const selectionStartPageRange = PagedScreenReaderStrategy._getRangeForPage(selectionStartPage, linesPerPage);
|
||||
@@ -232,13 +248,21 @@ export class PagedScreenReaderStrategy {
|
||||
const selectionEndPage = PagedScreenReaderStrategy._getPageOfLine(selection.endLineNumber, linesPerPage);
|
||||
const selectionEndPageRange = PagedScreenReaderStrategy._getRangeForPage(selectionEndPage, linesPerPage);
|
||||
|
||||
const pretextRange = selectionStartPageRange.intersectRanges(new Range(1, 1, selection.startLineNumber, selection.startColumn))!;
|
||||
let pretext = model.getValueInRange(pretextRange, EndOfLinePreference.LF);
|
||||
let pretextRange = selectionStartPageRange.intersectRanges(new Range(1, 1, selection.startLineNumber, selection.startColumn))!;
|
||||
if (trimLongText && model.getValueLengthInRange(pretextRange, EndOfLinePreference.LF) > LIMIT_CHARS) {
|
||||
const pretextStart = model.modifyPosition(pretextRange.getEndPosition(), -LIMIT_CHARS);
|
||||
pretextRange = Range.fromPositions(pretextStart, pretextRange.getEndPosition());
|
||||
}
|
||||
const pretext = model.getValueInRange(pretextRange, EndOfLinePreference.LF);
|
||||
|
||||
const lastLine = model.getLineCount();
|
||||
const lastLineMaxColumn = model.getLineMaxColumn(lastLine);
|
||||
const posttextRange = selectionEndPageRange.intersectRanges(new Range(selection.endLineNumber, selection.endColumn, lastLine, lastLineMaxColumn))!;
|
||||
let posttext = model.getValueInRange(posttextRange, EndOfLinePreference.LF);
|
||||
let posttextRange = selectionEndPageRange.intersectRanges(new Range(selection.endLineNumber, selection.endColumn, lastLine, lastLineMaxColumn))!;
|
||||
if (trimLongText && model.getValueLengthInRange(posttextRange, EndOfLinePreference.LF) > LIMIT_CHARS) {
|
||||
const posttextEnd = model.modifyPosition(posttextRange.getStartPosition(), LIMIT_CHARS);
|
||||
posttextRange = Range.fromPositions(posttextRange.getStartPosition(), posttextEnd);
|
||||
}
|
||||
const posttext = model.getValueInRange(posttextRange, EndOfLinePreference.LF);
|
||||
|
||||
|
||||
let text: string;
|
||||
@@ -254,22 +278,10 @@ export class PagedScreenReaderStrategy {
|
||||
+ model.getValueInRange(selectionRange2, EndOfLinePreference.LF)
|
||||
);
|
||||
}
|
||||
|
||||
// Chromium handles very poorly text even of a few thousand chars
|
||||
// Cut text to avoid stalling the entire UI
|
||||
if (trimLongText) {
|
||||
const LIMIT_CHARS = 500;
|
||||
if (pretext.length > LIMIT_CHARS) {
|
||||
pretext = pretext.substring(pretext.length - LIMIT_CHARS, pretext.length);
|
||||
}
|
||||
if (posttext.length > LIMIT_CHARS) {
|
||||
posttext = posttext.substring(0, LIMIT_CHARS);
|
||||
}
|
||||
if (text.length > 2 * LIMIT_CHARS) {
|
||||
text = text.substring(0, LIMIT_CHARS) + String.fromCharCode(8230) + text.substring(text.length - LIMIT_CHARS, text.length);
|
||||
}
|
||||
if (trimLongText && text.length > 2 * LIMIT_CHARS) {
|
||||
text = text.substring(0, LIMIT_CHARS) + String.fromCharCode(8230) + text.substring(text.length - LIMIT_CHARS, text.length);
|
||||
}
|
||||
|
||||
return new TextAreaState(pretext + text + posttext, pretext.length, pretext.length + text.length, new Position(selection.startLineNumber, selection.startColumn), new Position(selection.endLineNumber, selection.endColumn));
|
||||
return new TextAreaState(pretext + text + posttext, pretext.length, pretext.length + text.length, selection, pretextRange.endLineNumber - pretextRange.startLineNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,6 +267,9 @@ export class Range {
|
||||
* Test if range `a` equals `b`.
|
||||
*/
|
||||
public static equalsRange(a: IRange | null, b: IRange | null): boolean {
|
||||
if (!a && !b) {
|
||||
return true;
|
||||
}
|
||||
return (
|
||||
!!a &&
|
||||
!!b &&
|
||||
|
||||
@@ -63,6 +63,7 @@ export interface IViewModel extends ICursorSimpleModel {
|
||||
getAllOverviewRulerDecorations(theme: EditorTheme): OverviewRulerDecorationsGroup[];
|
||||
getValueInRange(range: Range, eol: EndOfLinePreference): string;
|
||||
getValueLengthInRange(range: Range, eol: EndOfLinePreference): number;
|
||||
modifyPosition(position: Position, offset: number): Position;
|
||||
|
||||
getInjectedTextAt(viewPosition: Position): InjectedText | null;
|
||||
|
||||
|
||||
@@ -788,6 +788,11 @@ export class ViewModel extends Disposable implements IViewModel {
|
||||
return this.model.getValueLengthInRange(modelRange, eol);
|
||||
}
|
||||
|
||||
public modifyPosition(position: Position, offset: number): Position {
|
||||
const modelPosition = this.coordinatesConverter.convertViewPositionToModelPosition(position);
|
||||
return this.model.modifyPosition(modelPosition, offset);
|
||||
}
|
||||
|
||||
public deduceModelPositionRelativeToViewPosition(viewAnchorPosition: Position, deltaOffset: number, lineFeedCnt: number): Position {
|
||||
const modelAnchor = this.coordinatesConverter.convertViewPositionToModelPosition(viewAnchorPosition);
|
||||
if (this.model.getEOL().length === 2) {
|
||||
|
||||
@@ -38,6 +38,11 @@ class SingleLineTestModel implements ISimpleModel {
|
||||
return this.getValueInRange(range, eol).length;
|
||||
}
|
||||
|
||||
modifyPosition(position: Position, offset: number): Position {
|
||||
const column = Math.min(this.getLineMaxColumn(position.lineNumber), Math.max(1, position.column + offset));
|
||||
return new Position(position.lineNumber, column);
|
||||
}
|
||||
|
||||
getModelLineContent(lineNumber: number): string {
|
||||
return this._line;
|
||||
}
|
||||
@@ -106,10 +111,10 @@ function doCreateTest(description: string, inputStr: string, expectedStr: string
|
||||
mode: null
|
||||
};
|
||||
},
|
||||
getScreenReaderContent: (currentState: TextAreaState): TextAreaState => {
|
||||
getScreenReaderContent: (): TextAreaState => {
|
||||
const selection = new Range(1, 1 + cursorOffset, 1, 1 + cursorOffset + cursorLength);
|
||||
|
||||
return PagedScreenReaderStrategy.fromEditorSelection(currentState, model, selection, 10, true);
|
||||
return PagedScreenReaderStrategy.fromEditorSelection(model, selection, 10, true);
|
||||
},
|
||||
deduceModelPosition: (viewAnchorPosition: Position, deltaOffset: number, lineFeedCnt: number): Position => {
|
||||
return null!;
|
||||
|
||||
@@ -46,8 +46,8 @@ suite('TextAreaInput', () => {
|
||||
getDataToCopy: function (): ClipboardDataToCopy {
|
||||
throw new Error('Function not implemented.');
|
||||
},
|
||||
getScreenReaderContent: function (currentState: TextAreaState): TextAreaState {
|
||||
return new TextAreaState('', 0, 0, null, null);
|
||||
getScreenReaderContent: function (): TextAreaState {
|
||||
return new TextAreaState('', 0, 0, null, undefined);
|
||||
},
|
||||
deduceModelPosition: function (viewAnchorPosition: Position, deltaOffset: number, lineFeedCnt: number): Position {
|
||||
throw new Error('Function not implemented.');
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as assert from 'assert';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ITextAreaWrapper, PagedScreenReaderStrategy, TextAreaState } from 'vs/editor/browser/controller/textAreaState';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { createTextModel } from 'vs/editor/test/common/testTextModel';
|
||||
|
||||
@@ -64,15 +64,15 @@ function equalsTextAreaState(a: TextAreaState, b: TextAreaState): boolean {
|
||||
a.value === b.value
|
||||
&& a.selectionStart === b.selectionStart
|
||||
&& a.selectionEnd === b.selectionEnd
|
||||
&& Position.equals(a.selectionStartPosition, b.selectionStartPosition)
|
||||
&& Position.equals(a.selectionEndPosition, b.selectionEndPosition)
|
||||
&& Range.equalsRange(a.selection, b.selection)
|
||||
&& a.newlineCountBeforeSelection === b.newlineCountBeforeSelection
|
||||
);
|
||||
}
|
||||
|
||||
suite('TextAreaState', () => {
|
||||
|
||||
function assertTextAreaState(actual: TextAreaState, value: string, selectionStart: number, selectionEnd: number): void {
|
||||
const desired = new TextAreaState(value, selectionStart, selectionEnd, null, null);
|
||||
const desired = new TextAreaState(value, selectionStart, selectionEnd, null, undefined);
|
||||
assert.ok(equalsTextAreaState(desired, actual), desired.toString() + ' == ' + actual.toString());
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ suite('TextAreaState', () => {
|
||||
textArea._value = 'Hello world!';
|
||||
textArea._selectionStart = 1;
|
||||
textArea._selectionEnd = 12;
|
||||
let actual = TextAreaState.readFromTextArea(textArea);
|
||||
let actual = TextAreaState.readFromTextArea(textArea, null);
|
||||
|
||||
assertTextAreaState(actual, 'Hello world!', 1, 12);
|
||||
assert.strictEqual(actual.value, 'Hello world!');
|
||||
@@ -99,21 +99,21 @@ suite('TextAreaState', () => {
|
||||
textArea._selectionStart = 1;
|
||||
textArea._selectionEnd = 12;
|
||||
|
||||
let state = new TextAreaState('Hi world!', 2, 2, null, null);
|
||||
let state = new TextAreaState('Hi world!', 2, 2, null, undefined);
|
||||
state.writeToTextArea('test', textArea, false);
|
||||
|
||||
assert.strictEqual(textArea._value, 'Hi world!');
|
||||
assert.strictEqual(textArea._selectionStart, 9);
|
||||
assert.strictEqual(textArea._selectionEnd, 9);
|
||||
|
||||
state = new TextAreaState('Hi world!', 3, 3, null, null);
|
||||
state = new TextAreaState('Hi world!', 3, 3, null, undefined);
|
||||
state.writeToTextArea('test', textArea, false);
|
||||
|
||||
assert.strictEqual(textArea._value, 'Hi world!');
|
||||
assert.strictEqual(textArea._selectionStart, 9);
|
||||
assert.strictEqual(textArea._selectionEnd, 9);
|
||||
|
||||
state = new TextAreaState('Hi world!', 0, 2, null, null);
|
||||
state = new TextAreaState('Hi world!', 0, 2, null, undefined);
|
||||
state.writeToTextArea('test', textArea, true);
|
||||
|
||||
assert.strictEqual(textArea._value, 'Hi world!');
|
||||
@@ -131,7 +131,7 @@ suite('TextAreaState', () => {
|
||||
textArea._selectionStart = selectionStart;
|
||||
textArea._selectionEnd = selectionEnd;
|
||||
|
||||
const newState = TextAreaState.readFromTextArea(textArea);
|
||||
const newState = TextAreaState.readFromTextArea(textArea, null);
|
||||
const actual = TextAreaState.deduceInput(prevState, newState, couldBeEmojiInput);
|
||||
|
||||
assert.deepStrictEqual(actual, {
|
||||
@@ -155,7 +155,7 @@ suite('TextAreaState', () => {
|
||||
|
||||
test('issue #2586: Replacing selected end-of-line with newline locks up the document', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState(']\n', 1, 2, null, null),
|
||||
new TextAreaState(']\n', 1, 2, null, undefined),
|
||||
']\n',
|
||||
2, 2, true,
|
||||
'\n', 0
|
||||
@@ -191,7 +191,7 @@ suite('TextAreaState', () => {
|
||||
|
||||
test('extractNewText - had the entire line selected', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 0, 12, null, null),
|
||||
new TextAreaState('Hello world!', 0, 12, null, undefined),
|
||||
'H',
|
||||
1, 1, true,
|
||||
'H', 0
|
||||
@@ -200,7 +200,7 @@ suite('TextAreaState', () => {
|
||||
|
||||
test('extractNewText - had previous text 1', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 12, 12, null, null),
|
||||
new TextAreaState('Hello world!', 12, 12, null, undefined),
|
||||
'Hello world!a',
|
||||
13, 13, true,
|
||||
'a', 0
|
||||
@@ -209,7 +209,7 @@ suite('TextAreaState', () => {
|
||||
|
||||
test('extractNewText - had previous text 2', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 0, 0, null, null),
|
||||
new TextAreaState('Hello world!', 0, 0, null, undefined),
|
||||
'aHello world!',
|
||||
1, 1, true,
|
||||
'a', 0
|
||||
@@ -218,7 +218,7 @@ suite('TextAreaState', () => {
|
||||
|
||||
test('extractNewText - had previous text 3', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 6, 11, null, null),
|
||||
new TextAreaState('Hello world!', 6, 11, null, undefined),
|
||||
'Hello other!',
|
||||
11, 11, true,
|
||||
'other', 0
|
||||
@@ -236,7 +236,7 @@ suite('TextAreaState', () => {
|
||||
|
||||
test('extractNewText - isInOverwriteMode', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 0, 0, null, null),
|
||||
new TextAreaState('Hello world!', 0, 0, null, undefined),
|
||||
'Aello world!',
|
||||
1, 1, true,
|
||||
'A', 0
|
||||
@@ -245,7 +245,7 @@ suite('TextAreaState', () => {
|
||||
|
||||
test('extractMacReplacedText - does nothing if there is selection', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 5, 5, null, null),
|
||||
new TextAreaState('Hello world!', 5, 5, null, undefined),
|
||||
'Hellö world!',
|
||||
4, 5, true,
|
||||
'ö', 0
|
||||
@@ -254,7 +254,7 @@ suite('TextAreaState', () => {
|
||||
|
||||
test('extractMacReplacedText - does nothing if there is more than one extra char', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 5, 5, null, null),
|
||||
new TextAreaState('Hello world!', 5, 5, null, undefined),
|
||||
'Hellöö world!',
|
||||
5, 5, true,
|
||||
'öö', 1
|
||||
@@ -263,7 +263,7 @@ suite('TextAreaState', () => {
|
||||
|
||||
test('extractMacReplacedText - does nothing if there is more than one changed char', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 5, 5, null, null),
|
||||
new TextAreaState('Hello world!', 5, 5, null, undefined),
|
||||
'Helöö world!',
|
||||
5, 5, true,
|
||||
'öö', 2
|
||||
@@ -272,7 +272,7 @@ suite('TextAreaState', () => {
|
||||
|
||||
test('extractMacReplacedText', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('Hello world!', 5, 5, null, null),
|
||||
new TextAreaState('Hello world!', 5, 5, null, undefined),
|
||||
'Hellö world!',
|
||||
5, 5, true,
|
||||
'ö', 1
|
||||
@@ -281,7 +281,7 @@ suite('TextAreaState', () => {
|
||||
|
||||
test('issue #25101 - First key press ignored', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('a', 0, 1, null, null),
|
||||
new TextAreaState('a', 0, 1, null, undefined),
|
||||
'a',
|
||||
1, 1, true,
|
||||
'a', 0
|
||||
@@ -290,7 +290,7 @@ suite('TextAreaState', () => {
|
||||
|
||||
test('issue #16520 - Cmd-d of single character followed by typing same character as has no effect', () => {
|
||||
testDeduceInput(
|
||||
new TextAreaState('x x', 0, 1, null, null),
|
||||
new TextAreaState('x x', 0, 1, null, undefined),
|
||||
'x x',
|
||||
1, 1, true,
|
||||
'x', 0
|
||||
@@ -308,7 +308,7 @@ suite('TextAreaState', () => {
|
||||
textArea._selectionStart = selectionStart;
|
||||
textArea._selectionEnd = selectionEnd;
|
||||
|
||||
const newState = TextAreaState.readFromTextArea(textArea);
|
||||
const newState = TextAreaState.readFromTextArea(textArea, null);
|
||||
const actual = TextAreaState.deduceAndroidCompositionInput(prevState, newState);
|
||||
|
||||
assert.deepStrictEqual(actual, {
|
||||
@@ -323,11 +323,7 @@ suite('TextAreaState', () => {
|
||||
|
||||
test('Android composition input 1', () => {
|
||||
testDeduceAndroidCompositionInput(
|
||||
new TextAreaState(
|
||||
'Microsoft',
|
||||
4, 4,
|
||||
null, null
|
||||
),
|
||||
new TextAreaState('Microsoft', 4, 4, null, undefined),
|
||||
'Microsoft',
|
||||
4, 4,
|
||||
'', 0, 0, 0,
|
||||
@@ -336,11 +332,7 @@ suite('TextAreaState', () => {
|
||||
|
||||
test('Android composition input 2', () => {
|
||||
testDeduceAndroidCompositionInput(
|
||||
new TextAreaState(
|
||||
'Microsoft',
|
||||
4, 4,
|
||||
null, null
|
||||
),
|
||||
new TextAreaState('Microsoft', 4, 4, null, undefined),
|
||||
'Microsoft',
|
||||
0, 9,
|
||||
'', 0, 0, 5,
|
||||
@@ -349,11 +341,7 @@ suite('TextAreaState', () => {
|
||||
|
||||
test('Android composition input 3', () => {
|
||||
testDeduceAndroidCompositionInput(
|
||||
new TextAreaState(
|
||||
'Microsoft',
|
||||
0, 9,
|
||||
null, null
|
||||
),
|
||||
new TextAreaState('Microsoft', 0, 9, null, undefined),
|
||||
'Microsoft\'s',
|
||||
11, 11,
|
||||
'\'s', 0, 0, 0,
|
||||
@@ -362,11 +350,7 @@ suite('TextAreaState', () => {
|
||||
|
||||
test('Android backspace', () => {
|
||||
testDeduceAndroidCompositionInput(
|
||||
new TextAreaState(
|
||||
'undefinedVariable',
|
||||
2, 2,
|
||||
null, null
|
||||
),
|
||||
new TextAreaState('undefinedVariable', 2, 2, null, undefined),
|
||||
'udefinedVariable',
|
||||
1, 1,
|
||||
'', 1, 0, 0,
|
||||
@@ -377,7 +361,7 @@ suite('TextAreaState', () => {
|
||||
|
||||
function testPagedScreenReaderStrategy(lines: string[], selection: Selection, expected: TextAreaState): void {
|
||||
const model = createTextModel(lines.join('\n'));
|
||||
const actual = PagedScreenReaderStrategy.fromEditorSelection(TextAreaState.EMPTY, model, selection, 10, true);
|
||||
const actual = PagedScreenReaderStrategy.fromEditorSelection(model, selection, 10, true);
|
||||
assert.ok(equalsTextAreaState(actual, expected));
|
||||
model.dispose();
|
||||
}
|
||||
@@ -388,7 +372,7 @@ suite('TextAreaState', () => {
|
||||
'Hello world!'
|
||||
],
|
||||
new Selection(1, 13, 1, 13),
|
||||
new TextAreaState('Hello world!', 12, 12, new Position(1, 13), new Position(1, 13))
|
||||
new TextAreaState('Hello world!', 12, 12, new Range(1, 13, 1, 13), 0)
|
||||
);
|
||||
|
||||
testPagedScreenReaderStrategy(
|
||||
@@ -396,7 +380,7 @@ suite('TextAreaState', () => {
|
||||
'Hello world!'
|
||||
],
|
||||
new Selection(1, 1, 1, 1),
|
||||
new TextAreaState('Hello world!', 0, 0, new Position(1, 1), new Position(1, 1))
|
||||
new TextAreaState('Hello world!', 0, 0, new Range(1, 1, 1, 1), 0)
|
||||
);
|
||||
|
||||
testPagedScreenReaderStrategy(
|
||||
@@ -404,7 +388,7 @@ suite('TextAreaState', () => {
|
||||
'Hello world!'
|
||||
],
|
||||
new Selection(1, 1, 1, 6),
|
||||
new TextAreaState('Hello world!', 0, 5, new Position(1, 1), new Position(1, 6))
|
||||
new TextAreaState('Hello world!', 0, 5, new Range(1, 1, 1, 6), 0)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -415,7 +399,7 @@ suite('TextAreaState', () => {
|
||||
'How are you?'
|
||||
],
|
||||
new Selection(1, 1, 1, 1),
|
||||
new TextAreaState('Hello world!\nHow are you?', 0, 0, new Position(1, 1), new Position(1, 1))
|
||||
new TextAreaState('Hello world!\nHow are you?', 0, 0, new Range(1, 1, 1, 1), 0)
|
||||
);
|
||||
|
||||
testPagedScreenReaderStrategy(
|
||||
@@ -424,7 +408,7 @@ suite('TextAreaState', () => {
|
||||
'How are you?'
|
||||
],
|
||||
new Selection(2, 1, 2, 1),
|
||||
new TextAreaState('Hello world!\nHow are you?', 13, 13, new Position(2, 1), new Position(2, 1))
|
||||
new TextAreaState('Hello world!\nHow are you?', 13, 13, new Range(2, 1, 2, 1), 1)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -434,7 +418,7 @@ suite('TextAreaState', () => {
|
||||
'L1\nL2\nL3\nL4\nL5\nL6\nL7\nL8\nL9\nL10\nL11\nL12\nL13\nL14\nL15\nL16\nL17\nL18\nL19\nL20\nL21'
|
||||
],
|
||||
new Selection(1, 1, 1, 1),
|
||||
new TextAreaState('L1\nL2\nL3\nL4\nL5\nL6\nL7\nL8\nL9\nL10\n', 0, 0, new Position(1, 1), new Position(1, 1))
|
||||
new TextAreaState('L1\nL2\nL3\nL4\nL5\nL6\nL7\nL8\nL9\nL10\n', 0, 0, new Range(1, 1, 1, 1), 0)
|
||||
);
|
||||
|
||||
testPagedScreenReaderStrategy(
|
||||
@@ -442,7 +426,7 @@ suite('TextAreaState', () => {
|
||||
'L1\nL2\nL3\nL4\nL5\nL6\nL7\nL8\nL9\nL10\nL11\nL12\nL13\nL14\nL15\nL16\nL17\nL18\nL19\nL20\nL21'
|
||||
],
|
||||
new Selection(11, 1, 11, 1),
|
||||
new TextAreaState('L11\nL12\nL13\nL14\nL15\nL16\nL17\nL18\nL19\nL20\n', 0, 0, new Position(11, 1), new Position(11, 1))
|
||||
new TextAreaState('L11\nL12\nL13\nL14\nL15\nL16\nL17\nL18\nL19\nL20\n', 0, 0, new Range(11, 1, 11, 1), 0)
|
||||
);
|
||||
|
||||
testPagedScreenReaderStrategy(
|
||||
@@ -450,7 +434,7 @@ suite('TextAreaState', () => {
|
||||
'L1\nL2\nL3\nL4\nL5\nL6\nL7\nL8\nL9\nL10\nL11\nL12\nL13\nL14\nL15\nL16\nL17\nL18\nL19\nL20\nL21'
|
||||
],
|
||||
new Selection(12, 1, 12, 1),
|
||||
new TextAreaState('L11\nL12\nL13\nL14\nL15\nL16\nL17\nL18\nL19\nL20\n', 4, 4, new Position(12, 1), new Position(12, 1))
|
||||
new TextAreaState('L11\nL12\nL13\nL14\nL15\nL16\nL17\nL18\nL19\nL20\n', 4, 4, new Range(12, 1, 12, 1), 1)
|
||||
);
|
||||
|
||||
testPagedScreenReaderStrategy(
|
||||
@@ -458,7 +442,7 @@ suite('TextAreaState', () => {
|
||||
'L1\nL2\nL3\nL4\nL5\nL6\nL7\nL8\nL9\nL10\nL11\nL12\nL13\nL14\nL15\nL16\nL17\nL18\nL19\nL20\nL21'
|
||||
],
|
||||
new Selection(21, 1, 21, 1),
|
||||
new TextAreaState('L21', 0, 0, new Position(21, 1), new Position(21, 1))
|
||||
new TextAreaState('L21', 0, 0, new Range(21, 1, 21, 1), 0)
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user