mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-26 18:06:43 +01:00
Merge pull request #9536 from Microsoft/sandy081/linesViewPort
Implement lineViewTop, lineViewBottom, lineViewCenter
This commit is contained in:
@@ -58,6 +58,7 @@ export interface IView extends IDisposable {
|
||||
getCodeEditorHelper(): ICodeEditorHelper;
|
||||
|
||||
getCenteredRangeInViewport(): Range;
|
||||
getVisibleRangeInViewport(): Range;
|
||||
|
||||
change(callback:(changeAccessor:IViewZoneChangeAccessor) => any): boolean;
|
||||
getWhitespaces(): editorCommon.IEditorWhitespace[];
|
||||
|
||||
@@ -596,6 +596,14 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp
|
||||
return viewModel.convertViewRangeToModelRange(currentCenteredViewRange);
|
||||
}
|
||||
|
||||
public getVisibleRangeInViewport(): Range {
|
||||
if (this._isDisposed) {
|
||||
throw new Error('ViewImpl.getVisibleRangeInViewport: View is disposed');
|
||||
}
|
||||
let visibleRange = this.layoutProvider.getLinesViewportData().visibleRange;
|
||||
return this._context.model.convertViewRangeToModelRange(visibleRange);
|
||||
}
|
||||
|
||||
// public getLineInfoProvider():view.ILineInfoProvider {
|
||||
// return this.viewLines;
|
||||
// }
|
||||
|
||||
@@ -159,6 +159,13 @@ export class CodeEditorWidget extends CommonCodeEditor implements editorBrowser.
|
||||
return this._view.getCenteredRangeInViewport();
|
||||
}
|
||||
|
||||
public getVisibleRangeInViewport(): Range {
|
||||
if (!this.hasView) {
|
||||
return null;
|
||||
}
|
||||
return this._view.getVisibleRangeInViewport();
|
||||
}
|
||||
|
||||
public getScrollWidth(): number {
|
||||
if (!this.hasView) {
|
||||
return -1;
|
||||
|
||||
@@ -287,6 +287,8 @@ export abstract class CommonCodeEditor extends EventEmitter implements editorCom
|
||||
|
||||
public abstract getCenteredRangeInViewport(): Range;
|
||||
|
||||
public abstract getVisibleRangeInViewport(): Range;
|
||||
|
||||
public getVisibleColumnFromPosition(rawPosition:editorCommon.IPosition): number {
|
||||
if (!this.model) {
|
||||
return rawPosition.column;
|
||||
@@ -788,6 +790,12 @@ export abstract class CommonCodeEditor extends EventEmitter implements editorCom
|
||||
|
||||
var viewModelHelper:IViewModelHelper = {
|
||||
viewModel: this.viewModel,
|
||||
getCurrentVisibleRange: () => {
|
||||
return this.viewModel.convertModelRangeToViewRange(this.getVisibleRangeInViewport());
|
||||
},
|
||||
getCurrentCenteredRange: () => {
|
||||
return this.viewModel.convertModelRangeToViewRange(this.getCenteredRangeInViewport());
|
||||
},
|
||||
convertModelPositionToViewPosition: (lineNumber:number, column:number) => {
|
||||
return this.viewModel.convertModelPositionToViewPosition(lineNumber, column);
|
||||
},
|
||||
|
||||
@@ -102,31 +102,6 @@ export class Cursor extends EventEmitter {
|
||||
this.model = model;
|
||||
this.viewModelHelper = viewModelHelper;
|
||||
this.enableEmptySelectionClipboard = enableEmptySelectionClipboard;
|
||||
if (!this.viewModelHelper) {
|
||||
this.viewModelHelper = {
|
||||
viewModel: this.model,
|
||||
convertModelPositionToViewPosition: (lineNumber:number, column:number) => {
|
||||
return new Position(lineNumber, column);
|
||||
},
|
||||
convertModelRangeToViewRange: (modelRange: Range) => {
|
||||
return modelRange;
|
||||
},
|
||||
convertViewToModelPosition: (lineNumber:number, column:number) => {
|
||||
return new Position(lineNumber, column);
|
||||
},
|
||||
convertViewSelectionToModelSelection: (viewSelection:Selection) => {
|
||||
return viewSelection;
|
||||
},
|
||||
validateViewPosition: (viewLineNumber:number, viewColumn:number, modelPosition:Position) => {
|
||||
return modelPosition;
|
||||
},
|
||||
validateViewRange: (viewStartLineNumber:number, viewStartColumn:number, viewEndLineNumber:number, viewEndColumn:number, modelRange:Range) => {
|
||||
return modelRange;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
this.cursors = new CursorCollection(this.editorId, this.model, this.configuration, this.viewModelHelper);
|
||||
this.cursorUndoStack = [];
|
||||
|
||||
|
||||
@@ -57,6 +57,9 @@ export interface IViewModelHelper {
|
||||
|
||||
viewModel:ICursorMoveHelperModel;
|
||||
|
||||
getCurrentVisibleRange(): Range;
|
||||
getCurrentCenteredRange(): Range;
|
||||
|
||||
convertModelPositionToViewPosition(lineNumber:number, column:number): Position;
|
||||
convertModelRangeToViewRange(modelRange:Range): Range;
|
||||
|
||||
@@ -547,6 +550,20 @@ export class OneCursor {
|
||||
public getViewLineCount(): number {
|
||||
return this.viewModelHelper.viewModel.getLineCount();
|
||||
}
|
||||
public getViewTopLine(lineFromTop: number): number {
|
||||
let visibleRange = this.viewModelHelper.getCurrentVisibleRange();
|
||||
let lineNumber = visibleRange.startLineNumber + lineFromTop - 1;
|
||||
return lineNumber > visibleRange.endLineNumber ? visibleRange.endLineNumber : lineNumber;
|
||||
}
|
||||
public getViewCenterLine(): number {
|
||||
let centeredRange = this.viewModelHelper.getCurrentCenteredRange();
|
||||
return centeredRange.startLineNumber;
|
||||
}
|
||||
public getViewBottomLine(lineFromBottom: number): number {
|
||||
let visibleRange = this.viewModelHelper.getCurrentVisibleRange();
|
||||
let lineNumber = visibleRange.endLineNumber - lineFromBottom + 1;
|
||||
return lineNumber > visibleRange.startLineNumber ? lineNumber : visibleRange.startLineNumber;
|
||||
}
|
||||
public getViewLineMaxColumn(lineNumber:number): number {
|
||||
return this.viewModelHelper.viewModel.getLineMaxColumn(lineNumber);
|
||||
}
|
||||
@@ -671,6 +688,18 @@ export class OneCursorOp {
|
||||
return this.moveUp(cursor, inSelectionMode, noOfLines, ctx);
|
||||
case editorCommon.CursorMoveViewPosition.LineDown:
|
||||
return this.moveDown(cursor, inSelectionMode, noOfLines, ctx);
|
||||
case editorCommon.CursorMoveViewPosition.LineViewTop:
|
||||
viewLineNumber= cursor.getViewTopLine(moveParams.noOfLines || 1);
|
||||
viewColumn = cursor.getViewLineFirstNonWhiteSpaceColumn(viewLineNumber);
|
||||
break;
|
||||
case editorCommon.CursorMoveViewPosition.LineViewBottom:
|
||||
viewLineNumber= cursor.getViewBottomLine(moveParams.noOfLines || 1);
|
||||
viewColumn = cursor.getViewLineFirstNonWhiteSpaceColumn(viewLineNumber);
|
||||
break;
|
||||
case editorCommon.CursorMoveViewPosition.LineViewCenter:
|
||||
viewLineNumber= cursor.getViewCenterLine();
|
||||
viewColumn = cursor.getViewLineFirstNonWhiteSpaceColumn(viewLineNumber);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4192,7 +4192,10 @@ export const CursorMoveViewPosition = {
|
||||
LineEnd: 'lineEnd',
|
||||
LineLastNonWhitespaceCharacter: 'lineLastNonWhitespaceCharacter',
|
||||
LineUp: 'lineUp',
|
||||
LineDown: 'lineDown'
|
||||
LineDown: 'lineDown',
|
||||
LineViewTop: 'lineViewTop',
|
||||
LineViewCenter: 'lineViewCenter',
|
||||
LineViewBottom: 'lineViewBottom'
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,6 +12,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import {Model} from 'vs/editor/common/model/model';
|
||||
import {IMode} from 'vs/editor/common/modes';
|
||||
import {MockConfiguration} from 'vs/editor/test/common/mocks/mockConfiguration';
|
||||
import {viewModelHelper} from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
export function testCommand(
|
||||
lines: string[],
|
||||
@@ -24,7 +25,7 @@ export function testCommand(
|
||||
|
||||
let model = Model.createFromString(lines.join('\n'), undefined, mode);
|
||||
let config = new MockConfiguration(null);
|
||||
let cursor = new Cursor(0, config, model, null, false);
|
||||
let cursor = new Cursor(0, config, model, viewModelHelper(model), false);
|
||||
|
||||
cursor.setSelections('tests', [selection]);
|
||||
|
||||
|
||||
@@ -14,13 +14,14 @@ import {IIdentifiedSingleEditOperation} from 'vs/editor/common/editorCommon';
|
||||
import {Model} from 'vs/editor/common/model/model';
|
||||
import {ILineEdit, ModelLine} from 'vs/editor/common/model/modelLine';
|
||||
import {MockConfiguration} from 'vs/editor/test/common/mocks/mockConfiguration';
|
||||
import {viewModelHelper} from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
const NO_TAB_SIZE = 0;
|
||||
|
||||
function testCommand(lines:string[], selection:Selection, edits:IIdentifiedSingleEditOperation[], expectedLines:string[], expectedSelection:Selection): void {
|
||||
let model = Model.createFromString(lines.join('\n'));
|
||||
let config = new MockConfiguration(null);
|
||||
let cursor = new Cursor(0, config, model, null, false);
|
||||
let cursor = new Cursor(0, config, model, viewModelHelper(model), false);
|
||||
|
||||
cursor.setSelections('tests', [selection]);
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import {Selection} from 'vs/editor/common/core/selection';
|
||||
import {
|
||||
EndOfLinePreference, EventType, Handler, IPosition, ISelection, IEditorOptions,
|
||||
DefaultEndOfLine, ITextModelCreationOptions, ICommand,
|
||||
ITokenizedModel, IEditOperationBuilder, ICursorStateComputerData, CursorMoveViewPosition
|
||||
ITokenizedModel, IEditOperationBuilder, ICursorStateComputerData
|
||||
} from 'vs/editor/common/editorCommon';
|
||||
import {Model} from 'vs/editor/common/model/model';
|
||||
import {IMode, IndentAction} from 'vs/editor/common/modes';
|
||||
@@ -21,6 +21,7 @@ import {LanguageConfigurationRegistry} from 'vs/editor/common/modes/languageConf
|
||||
import {MockConfiguration} from 'vs/editor/test/common/mocks/mockConfiguration';
|
||||
import {BracketMode} from 'vs/editor/test/common/testModes';
|
||||
import {MockMode} from 'vs/editor/test/common/mocks/mockMode';
|
||||
import {viewModelHelper} from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
let H = Handler;
|
||||
|
||||
@@ -30,40 +31,6 @@ function cursorCommand(cursor: Cursor, command: string, extraData?: any, overwri
|
||||
cursor.trigger(overwriteSource || 'tests', command, extraData);
|
||||
}
|
||||
|
||||
// Move command
|
||||
|
||||
function move(cursor: Cursor, args: any) {
|
||||
cursorCommand(cursor, H.CursorMove, args);
|
||||
}
|
||||
|
||||
function moveToLineStart(cursor: Cursor) {
|
||||
move(cursor, {to: CursorMoveViewPosition.LineStart});
|
||||
}
|
||||
|
||||
function moveToLineFirstNonWhiteSpaceCharacter(cursor: Cursor) {
|
||||
move(cursor, {to: CursorMoveViewPosition.LineFirstNonWhitespaceCharacter});
|
||||
}
|
||||
|
||||
function moveToLineCenter(cursor: Cursor) {
|
||||
move(cursor, {to: CursorMoveViewPosition.LineColumnCenter});
|
||||
}
|
||||
|
||||
function moveToLineEnd(cursor: Cursor) {
|
||||
move(cursor, {to: CursorMoveViewPosition.LineEnd});
|
||||
}
|
||||
|
||||
function moveToLineLastNonWhiteSpaceCharacter(cursor: Cursor) {
|
||||
move(cursor, {to: CursorMoveViewPosition.LineLastNonWhitespaceCharacter});
|
||||
}
|
||||
|
||||
function moveUpByCursorMoveCommand(cursor: Cursor, noOfLines: number= 1, inSelectionMode?: boolean) {
|
||||
move(cursor, {to: CursorMoveViewPosition.LineUp, noOfLines: noOfLines, inSelectionMode: inSelectionMode});
|
||||
}
|
||||
|
||||
function moveDownByCursorMoveCommand(cursor: Cursor, noOfLines: number= 1, inSelectionMode?: boolean) {
|
||||
move(cursor, {to: CursorMoveViewPosition.LineDown, noOfLines: noOfLines, inSelectionMode: inSelectionMode});
|
||||
}
|
||||
|
||||
function moveTo(cursor: Cursor, lineNumber: number, column: number, inSelectionMode: boolean = false) {
|
||||
cursorCommand(cursor, inSelectionMode ? H.MoveToSelect : H.MoveTo, { position: new Position(lineNumber, column) });
|
||||
}
|
||||
@@ -205,7 +172,7 @@ suite('Editor Controller - Cursor', () => {
|
||||
|
||||
thisModel = Model.createFromString(text);
|
||||
thisConfiguration = new MockConfiguration(null);
|
||||
thisCursor = new Cursor(1, thisConfiguration, thisModel, null, false);
|
||||
thisCursor = new Cursor(1, thisConfiguration, thisModel, viewModelHelper(thisModel), false);
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
@@ -225,168 +192,6 @@ suite('Editor Controller - Cursor', () => {
|
||||
cursorEqual(thisCursor, 1, 1);
|
||||
});
|
||||
|
||||
// --------- cursor move command
|
||||
|
||||
test('move to first character of line from middle', () => {
|
||||
moveTo(thisCursor, 1, 8);
|
||||
moveToLineStart(thisCursor);
|
||||
cursorEqual(thisCursor, 1, 1);
|
||||
});
|
||||
|
||||
test('move to first character of line from first non white space character', () => {
|
||||
moveTo(thisCursor, 1, 6);
|
||||
moveToLineStart(thisCursor);
|
||||
cursorEqual(thisCursor, 1, 1);
|
||||
});
|
||||
|
||||
test('move to first character of line from first character', () => {
|
||||
moveTo(thisCursor, 1, 1);
|
||||
moveToLineStart(thisCursor);
|
||||
cursorEqual(thisCursor, 1, 1);
|
||||
});
|
||||
|
||||
test('move to first non white space character of line from middle', () => {
|
||||
moveTo(thisCursor, 1, 8);
|
||||
moveToLineFirstNonWhiteSpaceCharacter(thisCursor);
|
||||
cursorEqual(thisCursor, 1, 6);
|
||||
});
|
||||
|
||||
test('move to first non white space character of line from first non white space character', () => {
|
||||
moveTo(thisCursor, 1, 6);
|
||||
moveToLineFirstNonWhiteSpaceCharacter(thisCursor);
|
||||
cursorEqual(thisCursor, 1, 6);
|
||||
});
|
||||
|
||||
test('move to first non white space character of line from first character', () => {
|
||||
moveTo(thisCursor, 1, 1);
|
||||
moveToLineFirstNonWhiteSpaceCharacter(thisCursor);
|
||||
cursorEqual(thisCursor, 1, 6);
|
||||
});
|
||||
|
||||
test('move to end of line from middle', () => {
|
||||
moveTo(thisCursor, 1, 8);
|
||||
moveToLineEnd(thisCursor);
|
||||
cursorEqual(thisCursor, 1, LINE1.length + 1);
|
||||
});
|
||||
|
||||
test('move to end of line from last non white space character', () => {
|
||||
moveTo(thisCursor, 1, LINE1.length - 1);
|
||||
moveToLineEnd(thisCursor);
|
||||
cursorEqual(thisCursor, 1, LINE1.length + 1);
|
||||
});
|
||||
|
||||
test('move to end of line from line end', () => {
|
||||
moveTo(thisCursor, 1, LINE1.length + 1);
|
||||
moveToLineEnd(thisCursor);
|
||||
cursorEqual(thisCursor, 1, LINE1.length + 1);
|
||||
});
|
||||
|
||||
test('move to last non white space character from middle', () => {
|
||||
moveTo(thisCursor, 1, 8);
|
||||
moveToLineLastNonWhiteSpaceCharacter(thisCursor);
|
||||
cursorEqual(thisCursor, 1, LINE1.length - 1);
|
||||
});
|
||||
|
||||
test('move to last non white space character from last non white space character', () => {
|
||||
moveTo(thisCursor, 1, LINE1.length - 1);
|
||||
moveToLineLastNonWhiteSpaceCharacter(thisCursor);
|
||||
cursorEqual(thisCursor, 1, LINE1.length - 1);
|
||||
});
|
||||
|
||||
test('move to last non white space character from line end', () => {
|
||||
moveTo(thisCursor, 1, LINE1.length + 1);
|
||||
moveToLineLastNonWhiteSpaceCharacter(thisCursor);
|
||||
cursorEqual(thisCursor, 1, LINE1.length - 1);
|
||||
});
|
||||
|
||||
test('move to center of line not from center', () => {
|
||||
moveTo(thisCursor, 1, 8);
|
||||
moveToLineCenter(thisCursor);
|
||||
cursorEqual(thisCursor, 1, 11);
|
||||
});
|
||||
|
||||
test('move to center of line from center', () => {
|
||||
moveTo(thisCursor, 1, 11);
|
||||
moveToLineCenter(thisCursor);
|
||||
cursorEqual(thisCursor, 1, 11);
|
||||
});
|
||||
|
||||
test('move to center of line from start', () => {
|
||||
moveToLineStart(thisCursor);
|
||||
moveToLineCenter(thisCursor);
|
||||
cursorEqual(thisCursor, 1, 11);
|
||||
});
|
||||
|
||||
test('move to center of line from end', () => {
|
||||
moveToLineEnd(thisCursor);
|
||||
moveToLineCenter(thisCursor);
|
||||
cursorEqual(thisCursor, 1, 11);
|
||||
});
|
||||
|
||||
test('move up by cursor move command', () => {
|
||||
moveTo(thisCursor, 3, 5);
|
||||
cursorEqual(thisCursor, 3, 5);
|
||||
|
||||
moveUpByCursorMoveCommand(thisCursor, 2);
|
||||
cursorEqual(thisCursor, 1, 5);
|
||||
|
||||
moveUpByCursorMoveCommand(thisCursor, 1);
|
||||
cursorEqual(thisCursor, 1, 1);
|
||||
});
|
||||
|
||||
test('move up with selection by cursor move command', () => {
|
||||
moveTo(thisCursor, 3, 5);
|
||||
cursorEqual(thisCursor, 3, 5);
|
||||
|
||||
moveUpByCursorMoveCommand(thisCursor, 1, true);
|
||||
cursorEqual(thisCursor, 2, 2, 3, 5);
|
||||
|
||||
moveUp(thisCursor, 1, true);
|
||||
cursorEqual(thisCursor, 1, 5, 3, 5);
|
||||
});
|
||||
|
||||
test('move up and down with tabs by cursor move command', () => {
|
||||
moveTo(thisCursor, 1, 5);
|
||||
cursorEqual(thisCursor, 1, 5);
|
||||
|
||||
moveDownByCursorMoveCommand(thisCursor, 4);
|
||||
cursorEqual(thisCursor, 5, 2);
|
||||
|
||||
moveUpByCursorMoveCommand(thisCursor, 1);
|
||||
cursorEqual(thisCursor, 4, 1);
|
||||
|
||||
moveUpByCursorMoveCommand(thisCursor, 1);
|
||||
cursorEqual(thisCursor, 3, 5);
|
||||
|
||||
moveUpByCursorMoveCommand(thisCursor, 1);
|
||||
cursorEqual(thisCursor, 2, 2);
|
||||
|
||||
moveUpByCursorMoveCommand(thisCursor, 1);
|
||||
cursorEqual(thisCursor, 1, 5);
|
||||
});
|
||||
|
||||
test('move up and down with end of lines starting from a long one by cursor move command', () => {
|
||||
moveToEndOfLine(thisCursor);
|
||||
cursorEqual(thisCursor, 1, LINE1.length - 1);
|
||||
|
||||
moveToEndOfLine(thisCursor);
|
||||
cursorEqual(thisCursor, 1, LINE1.length + 1);
|
||||
|
||||
moveDownByCursorMoveCommand(thisCursor, 2);
|
||||
cursorEqual(thisCursor, 3, LINE3.length + 1);
|
||||
|
||||
moveDownByCursorMoveCommand(thisCursor, 1);
|
||||
cursorEqual(thisCursor, 4, LINE4.length + 1);
|
||||
|
||||
moveDownByCursorMoveCommand(thisCursor, 1);
|
||||
cursorEqual(thisCursor, 5, LINE5.length + 1);
|
||||
|
||||
moveUpByCursorMoveCommand(thisCursor, 4);
|
||||
cursorEqual(thisCursor, 1, LINE1.length + 1);
|
||||
});
|
||||
|
||||
// --- end of cursor move command tests
|
||||
|
||||
test('move', () => {
|
||||
moveTo(thisCursor, 1, 2);
|
||||
cursorEqual(thisCursor, 1, 2);
|
||||
@@ -992,7 +797,7 @@ suite('Editor Controller - Cursor', () => {
|
||||
'\t\t}',
|
||||
'\t}'
|
||||
].join('\n'));
|
||||
let cursor = new Cursor(1, new MockConfiguration(null), model, null, true);
|
||||
let cursor = new Cursor(1, new MockConfiguration(null), model, viewModelHelper(model), true);
|
||||
|
||||
moveTo(cursor, 1, 7, false);
|
||||
cursorEqual(cursor, 1, 7);
|
||||
@@ -1026,7 +831,7 @@ suite('Editor Controller - Cursor', () => {
|
||||
'var concat = require("gulp-concat");',
|
||||
'var newer = require("gulp-newer");',
|
||||
].join('\n'));
|
||||
let cursor = new Cursor(1, new MockConfiguration(null), model, null, true);
|
||||
let cursor = new Cursor(1, new MockConfiguration(null), model, viewModelHelper(model), true);
|
||||
|
||||
moveTo(cursor, 1, 4, false);
|
||||
cursorEqual(cursor, 1, 4);
|
||||
@@ -1058,7 +863,7 @@ suite('Editor Controller - Cursor', () => {
|
||||
'var concat = require("gulp-concat");',
|
||||
'var newer = require("gulp-newer");',
|
||||
].join('\n'));
|
||||
let cursor = new Cursor(1, new MockConfiguration(null), model, null, true);
|
||||
let cursor = new Cursor(1, new MockConfiguration(null), model, viewModelHelper(model), true);
|
||||
|
||||
moveTo(cursor, 1, 4, false);
|
||||
cursorEqual(cursor, 1, 4);
|
||||
@@ -1595,7 +1400,7 @@ suite('Editor Controller - Regression tests', () => {
|
||||
'qwerty'
|
||||
];
|
||||
let model = Model.createFromString(text.join('\n'));
|
||||
let cursor = new Cursor(1, new MockConfiguration(null), model, null, true);
|
||||
let cursor = new Cursor(1, new MockConfiguration(null), model, viewModelHelper(model), true);
|
||||
|
||||
moveTo(cursor, 2, 1, false);
|
||||
cursorEqual(cursor, 2, 1, 2, 1);
|
||||
@@ -1613,7 +1418,7 @@ suite('Editor Controller - Regression tests', () => {
|
||||
''
|
||||
];
|
||||
model = Model.createFromString(text.join('\n'));
|
||||
cursor = new Cursor(1, new MockConfiguration(null), model, null, true);
|
||||
cursor = new Cursor(1, new MockConfiguration(null), model, viewModelHelper(model), true);
|
||||
|
||||
moveTo(cursor, 2, 1, false);
|
||||
cursorEqual(cursor, 2, 1, 2, 1);
|
||||
@@ -2798,7 +2603,7 @@ interface ICursorOpts {
|
||||
function usingCursor(opts:ICursorOpts, callback:(model:Model, cursor:Cursor)=>void): void {
|
||||
let model = Model.createFromString(opts.text.join('\n'), opts.modelOpts, opts.mode);
|
||||
let config = new MockConfiguration(opts.editorOpts);
|
||||
let cursor = new Cursor(1, config, model, null, false);
|
||||
let cursor = new Cursor(1, config, model, viewModelHelper(model), false);
|
||||
|
||||
callback(model, cursor);
|
||||
|
||||
|
||||
@@ -0,0 +1,462 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import {Cursor} from 'vs/editor/common/controller/cursor';
|
||||
import {Position} from 'vs/editor/common/core/position';
|
||||
import {Handler, IEditorOptions, ITextModelCreationOptions, CursorMoveViewPosition, ISelection, IPosition} from 'vs/editor/common/editorCommon';
|
||||
import {Model} from 'vs/editor/common/model/model';
|
||||
import {IMode} from 'vs/editor/common/modes';
|
||||
import {MockConfiguration} from 'vs/editor/test/common/mocks/mockConfiguration';
|
||||
import {viewModelHelper as aViewModelHelper} from 'vs/editor/test/common/editorTestUtils';
|
||||
import {IViewModelHelper} from 'vs/editor/common/controller/oneCursor';
|
||||
import {Range} from 'vs/editor/common/core/range';
|
||||
|
||||
let H = Handler;
|
||||
|
||||
suite('Cursor move command test', () => {
|
||||
const LINE1 = ' \tMy First Line\t ';
|
||||
const LINE2 = '\tMy Second Line';
|
||||
const LINE3 = ' Third Line💩';
|
||||
const LINE4 = '';
|
||||
const LINE5 = '1';
|
||||
|
||||
let thisModel: Model;
|
||||
let thisConfiguration: MockConfiguration;
|
||||
let thisCursor: Cursor;
|
||||
|
||||
setup(() => {
|
||||
let text =
|
||||
LINE1 + '\r\n' +
|
||||
LINE2 + '\n' +
|
||||
LINE3 + '\n' +
|
||||
LINE4 + '\r\n' +
|
||||
LINE5;
|
||||
|
||||
thisModel = Model.createFromString(text);
|
||||
thisConfiguration = new MockConfiguration(null);
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
thisCursor.dispose();
|
||||
thisModel.dispose();
|
||||
thisConfiguration.dispose();
|
||||
});
|
||||
|
||||
test('move to first character of line from middle', () => {
|
||||
thisCursor= aCursor();
|
||||
moveTo(thisCursor, 1, 8);
|
||||
moveToLineStart(thisCursor);
|
||||
cursorEqual(thisCursor, 1, 1);
|
||||
});
|
||||
|
||||
test('move to first character of line from first non white space character', () => {
|
||||
thisCursor= aCursor();
|
||||
moveTo(thisCursor, 1, 6);
|
||||
|
||||
moveToLineStart(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 1, 1);
|
||||
});
|
||||
|
||||
test('move to first character of line from first character', () => {
|
||||
thisCursor= aCursor();
|
||||
moveTo(thisCursor, 1, 1);
|
||||
|
||||
moveToLineStart(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 1, 1);
|
||||
});
|
||||
|
||||
test('move to first non white space character of line from middle', () => {
|
||||
thisCursor= aCursor();
|
||||
moveTo(thisCursor, 1, 8);
|
||||
|
||||
moveToLineFirstNonWhiteSpaceCharacter(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 1, 6);
|
||||
});
|
||||
|
||||
test('move to first non white space character of line from first non white space character', () => {
|
||||
thisCursor= aCursor();
|
||||
moveTo(thisCursor, 1, 6);
|
||||
|
||||
moveToLineFirstNonWhiteSpaceCharacter(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 1, 6);
|
||||
});
|
||||
|
||||
test('move to first non white space character of line from first character', () => {
|
||||
thisCursor= aCursor();
|
||||
moveTo(thisCursor, 1, 1);
|
||||
|
||||
moveToLineFirstNonWhiteSpaceCharacter(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 1, 6);
|
||||
});
|
||||
|
||||
test('move to end of line from middle', () => {
|
||||
thisCursor= aCursor();
|
||||
moveTo(thisCursor, 1, 8);
|
||||
|
||||
moveToLineEnd(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 1, LINE1.length + 1);
|
||||
});
|
||||
|
||||
test('move to end of line from last non white space character', () => {
|
||||
thisCursor= aCursor();
|
||||
moveTo(thisCursor, 1, LINE1.length - 1);
|
||||
|
||||
moveToLineEnd(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 1, LINE1.length + 1);
|
||||
});
|
||||
|
||||
test('move to end of line from line end', () => {
|
||||
thisCursor= aCursor();
|
||||
moveTo(thisCursor, 1, LINE1.length + 1);
|
||||
|
||||
moveToLineEnd(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 1, LINE1.length + 1);
|
||||
});
|
||||
|
||||
test('move to last non white space character from middle', () => {
|
||||
thisCursor= aCursor();
|
||||
moveTo(thisCursor, 1, 8);
|
||||
|
||||
moveToLineLastNonWhiteSpaceCharacter(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 1, LINE1.length - 1);
|
||||
});
|
||||
|
||||
test('move to last non white space character from last non white space character', () => {
|
||||
thisCursor= aCursor();
|
||||
moveTo(thisCursor, 1, LINE1.length - 1);
|
||||
|
||||
moveToLineLastNonWhiteSpaceCharacter(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 1, LINE1.length - 1);
|
||||
});
|
||||
|
||||
test('move to last non white space character from line end', () => {
|
||||
thisCursor= aCursor();
|
||||
moveTo(thisCursor, 1, LINE1.length + 1);
|
||||
|
||||
moveToLineLastNonWhiteSpaceCharacter(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 1, LINE1.length - 1);
|
||||
});
|
||||
|
||||
test('move to center of line not from center', () => {
|
||||
thisCursor= aCursor();
|
||||
moveTo(thisCursor, 1, 8);
|
||||
|
||||
moveToLineCenter(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 1, 11);
|
||||
});
|
||||
|
||||
test('move to center of line from center', () => {
|
||||
thisCursor= aCursor();
|
||||
moveTo(thisCursor, 1, 11);
|
||||
|
||||
moveToLineCenter(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 1, 11);
|
||||
});
|
||||
|
||||
test('move to center of line from start', () => {
|
||||
thisCursor= aCursor();
|
||||
moveToLineStart(thisCursor);
|
||||
|
||||
moveToLineCenter(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 1, 11);
|
||||
});
|
||||
|
||||
test('move to center of line from end', () => {
|
||||
thisCursor= aCursor();
|
||||
moveToLineEnd(thisCursor);
|
||||
|
||||
moveToLineCenter(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 1, 11);
|
||||
});
|
||||
|
||||
test('move up by cursor move command', () => {
|
||||
thisCursor= aCursor();
|
||||
|
||||
moveTo(thisCursor, 3, 5);
|
||||
cursorEqual(thisCursor, 3, 5);
|
||||
|
||||
moveUpByCursorMoveCommand(thisCursor, 2);
|
||||
cursorEqual(thisCursor, 1, 5);
|
||||
|
||||
moveUpByCursorMoveCommand(thisCursor, 1);
|
||||
cursorEqual(thisCursor, 1, 1);
|
||||
});
|
||||
|
||||
test('move up with selection by cursor move command', () => {
|
||||
thisCursor= aCursor();
|
||||
|
||||
moveTo(thisCursor, 3, 5);
|
||||
cursorEqual(thisCursor, 3, 5);
|
||||
|
||||
moveUpByCursorMoveCommand(thisCursor, 1, true);
|
||||
cursorEqual(thisCursor, 2, 2, 3, 5);
|
||||
|
||||
moveUpByCursorMoveCommand(thisCursor, 1, true);
|
||||
cursorEqual(thisCursor, 1, 5, 3, 5);
|
||||
});
|
||||
|
||||
test('move up and down with tabs by cursor move command', () => {
|
||||
thisCursor= aCursor();
|
||||
|
||||
moveTo(thisCursor, 1, 5);
|
||||
cursorEqual(thisCursor, 1, 5);
|
||||
|
||||
moveDownByCursorMoveCommand(thisCursor, 4);
|
||||
cursorEqual(thisCursor, 5, 2);
|
||||
|
||||
moveUpByCursorMoveCommand(thisCursor, 1);
|
||||
cursorEqual(thisCursor, 4, 1);
|
||||
|
||||
moveUpByCursorMoveCommand(thisCursor, 1);
|
||||
cursorEqual(thisCursor, 3, 5);
|
||||
|
||||
moveUpByCursorMoveCommand(thisCursor, 1);
|
||||
cursorEqual(thisCursor, 2, 2);
|
||||
|
||||
moveUpByCursorMoveCommand(thisCursor, 1);
|
||||
cursorEqual(thisCursor, 1, 5);
|
||||
});
|
||||
|
||||
test('move up and down with end of lines starting from a long one by cursor move command', () => {
|
||||
thisCursor= aCursor();
|
||||
|
||||
moveToEndOfLine(thisCursor);
|
||||
cursorEqual(thisCursor, 1, LINE1.length - 1);
|
||||
|
||||
moveToEndOfLine(thisCursor);
|
||||
cursorEqual(thisCursor, 1, LINE1.length + 1);
|
||||
|
||||
moveDownByCursorMoveCommand(thisCursor, 2);
|
||||
cursorEqual(thisCursor, 3, LINE3.length + 1);
|
||||
|
||||
moveDownByCursorMoveCommand(thisCursor, 1);
|
||||
cursorEqual(thisCursor, 4, LINE4.length + 1);
|
||||
|
||||
moveDownByCursorMoveCommand(thisCursor, 1);
|
||||
cursorEqual(thisCursor, 5, LINE5.length + 1);
|
||||
|
||||
moveUpByCursorMoveCommand(thisCursor, 4);
|
||||
cursorEqual(thisCursor, 1, LINE1.length + 1);
|
||||
});
|
||||
|
||||
test('move to view top line moves to first visible line if it is first line', () => {
|
||||
let viewModelHelper= aViewModelHelper(thisModel);
|
||||
viewModelHelper.getCurrentVisibleRange= () => new Range(1, 1, 10, 1);
|
||||
thisCursor= aCursor(viewModelHelper);
|
||||
|
||||
moveTo(thisCursor, 2, 2);
|
||||
moveToTop(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 1, 6);
|
||||
});
|
||||
|
||||
test('move to view top line moves to top visible line when first line is not visible', () => {
|
||||
let viewModelHelper= aViewModelHelper(thisModel);
|
||||
viewModelHelper.getCurrentVisibleRange= () => new Range(2, 1, 10, 1);
|
||||
thisCursor= aCursor(viewModelHelper);
|
||||
|
||||
moveTo(thisCursor, 4, 1);
|
||||
moveToTop(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 2, 2);
|
||||
});
|
||||
|
||||
test('move to view top line moves to nth line from top', () => {
|
||||
let viewModelHelper= aViewModelHelper(thisModel);
|
||||
viewModelHelper.getCurrentVisibleRange= () => new Range(1, 1, 10, 1);
|
||||
thisCursor= aCursor(viewModelHelper);
|
||||
|
||||
moveTo(thisCursor, 4, 1);
|
||||
moveToTop(thisCursor, 3);
|
||||
|
||||
cursorEqual(thisCursor, 3, 5);
|
||||
});
|
||||
|
||||
test('move to view top line moves to last line if n is greater than last visible line number', () => {
|
||||
let viewModelHelper= aViewModelHelper(thisModel);
|
||||
viewModelHelper.getCurrentVisibleRange= () => new Range(1, 1, 3, 1);
|
||||
thisCursor= aCursor(viewModelHelper);
|
||||
|
||||
moveTo(thisCursor, 2, 2);
|
||||
moveToTop(thisCursor, 4);
|
||||
|
||||
cursorEqual(thisCursor, 3, 5);
|
||||
});
|
||||
|
||||
test('move to view center line moves to the center line', () => {
|
||||
let viewModelHelper= aViewModelHelper(thisModel);
|
||||
viewModelHelper.getCurrentCenteredRange= () => new Range(3, 1, 3, 1);
|
||||
thisCursor= aCursor(viewModelHelper);
|
||||
|
||||
moveTo(thisCursor, 2, 2);
|
||||
moveToCenter(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 3, 5);
|
||||
});
|
||||
|
||||
test('move to view bottom line moves to last visible line if it is last line', () => {
|
||||
let viewModelHelper= aViewModelHelper(thisModel);
|
||||
viewModelHelper.getCurrentVisibleRange= () => new Range(1, 1, 5, 1);
|
||||
thisCursor= aCursor(viewModelHelper);
|
||||
|
||||
moveTo(thisCursor, 2, 2);
|
||||
moveToBottom(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 5, 1);
|
||||
});
|
||||
|
||||
test('move to view bottom line moves to last visible line when last line is not visible', () => {
|
||||
let viewModelHelper= aViewModelHelper(thisModel);
|
||||
viewModelHelper.getCurrentVisibleRange= () => new Range(2, 1, 3, 1);
|
||||
thisCursor= aCursor(viewModelHelper);
|
||||
|
||||
moveTo(thisCursor, 2, 2);
|
||||
moveToBottom(thisCursor);
|
||||
|
||||
cursorEqual(thisCursor, 3, 5);
|
||||
});
|
||||
|
||||
test('move to view bottom line moves to nth line from bottom', () => {
|
||||
let viewModelHelper= aViewModelHelper(thisModel);
|
||||
viewModelHelper.getCurrentVisibleRange= () => new Range(1, 1, 5, 1);
|
||||
thisCursor= aCursor(viewModelHelper);
|
||||
|
||||
moveTo(thisCursor, 4, 1);
|
||||
moveToBottom(thisCursor, 3);
|
||||
|
||||
cursorEqual(thisCursor, 3, 5);
|
||||
});
|
||||
|
||||
test('move to view bottom line moves to first line if n is lesser than first visible line number', () => {
|
||||
let viewModelHelper= aViewModelHelper(thisModel);
|
||||
viewModelHelper.getCurrentVisibleRange= () => new Range(2, 1, 5, 1);
|
||||
thisCursor= aCursor(viewModelHelper);
|
||||
|
||||
moveTo(thisCursor, 4, 1);
|
||||
moveToBottom(thisCursor, 5);
|
||||
|
||||
cursorEqual(thisCursor, 2, 2);
|
||||
});
|
||||
|
||||
function aCursor(viewModelHelper?: IViewModelHelper): Cursor {
|
||||
return new Cursor(1, thisConfiguration, thisModel, viewModelHelper || aViewModelHelper(thisModel), false);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
interface ICursorOpts {
|
||||
text: string[];
|
||||
mode?: IMode;
|
||||
modelOpts?: ITextModelCreationOptions;
|
||||
editorOpts?: IEditorOptions;
|
||||
}
|
||||
|
||||
// --------- utils
|
||||
|
||||
function cursorCommand(cursor: Cursor, command: string, extraData?: any, overwriteSource?: string) {
|
||||
cursor.trigger(overwriteSource || 'tests', command, extraData);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Move command
|
||||
|
||||
function move(cursor: Cursor, args: any) {
|
||||
cursorCommand(cursor, H.CursorMove, args);
|
||||
}
|
||||
|
||||
function moveToLineStart(cursor: Cursor) {
|
||||
move(cursor, {to: CursorMoveViewPosition.LineStart});
|
||||
}
|
||||
|
||||
function moveToLineFirstNonWhiteSpaceCharacter(cursor: Cursor) {
|
||||
move(cursor, {to: CursorMoveViewPosition.LineFirstNonWhitespaceCharacter});
|
||||
}
|
||||
|
||||
function moveToLineCenter(cursor: Cursor) {
|
||||
move(cursor, {to: CursorMoveViewPosition.LineColumnCenter});
|
||||
}
|
||||
|
||||
function moveToLineEnd(cursor: Cursor) {
|
||||
move(cursor, {to: CursorMoveViewPosition.LineEnd});
|
||||
}
|
||||
|
||||
function moveToLineLastNonWhiteSpaceCharacter(cursor: Cursor) {
|
||||
move(cursor, {to: CursorMoveViewPosition.LineLastNonWhitespaceCharacter});
|
||||
}
|
||||
|
||||
function moveUpByCursorMoveCommand(cursor: Cursor, noOfLines: number= 1, inSelectionMode?: boolean) {
|
||||
move(cursor, {to: CursorMoveViewPosition.LineUp, noOfLines: noOfLines, inSelectionMode: inSelectionMode});
|
||||
}
|
||||
|
||||
function moveDownByCursorMoveCommand(cursor: Cursor, noOfLines: number= 1, inSelectionMode?: boolean) {
|
||||
move(cursor, {to: CursorMoveViewPosition.LineDown, noOfLines: noOfLines, inSelectionMode: inSelectionMode});
|
||||
}
|
||||
|
||||
function moveToTop(cursor: Cursor, noOfLines: number= 1, inSelectionMode?: boolean) {
|
||||
move(cursor, {to: CursorMoveViewPosition.LineViewTop, noOfLines: noOfLines, inSelectionMode: inSelectionMode});
|
||||
}
|
||||
|
||||
function moveToCenter(cursor: Cursor, inSelectionMode?: boolean) {
|
||||
move(cursor, {to: CursorMoveViewPosition.LineViewCenter, inSelectionMode: inSelectionMode});
|
||||
}
|
||||
|
||||
function moveToBottom(cursor: Cursor, noOfLines: number= 1, inSelectionMode?: boolean) {
|
||||
move(cursor, {to: CursorMoveViewPosition.LineViewBottom, noOfLines: noOfLines, inSelectionMode: inSelectionMode});
|
||||
}
|
||||
|
||||
function cursorEqual(cursor: Cursor, posLineNumber: number, posColumn: number, selLineNumber: number = posLineNumber, selColumn: number = posColumn) {
|
||||
positionEqual(cursor.getPosition(), posLineNumber, posColumn);
|
||||
selectionEqual(cursor.getSelection(), posLineNumber, posColumn, selLineNumber, selColumn);
|
||||
}
|
||||
|
||||
function positionEqual(position:IPosition, lineNumber: number, column: number) {
|
||||
assert.deepEqual({
|
||||
lineNumber: position.lineNumber,
|
||||
column: position.column
|
||||
}, {
|
||||
lineNumber: lineNumber,
|
||||
column: column
|
||||
}, 'position equal');
|
||||
}
|
||||
|
||||
function selectionEqual(selection:ISelection, posLineNumber: number, posColumn: number, selLineNumber: number, selColumn: number) {
|
||||
assert.deepEqual({
|
||||
selectionStartLineNumber: selection.selectionStartLineNumber,
|
||||
selectionStartColumn: selection.selectionStartColumn,
|
||||
positionLineNumber: selection.positionLineNumber,
|
||||
positionColumn: selection.positionColumn
|
||||
}, {
|
||||
selectionStartLineNumber: selLineNumber,
|
||||
selectionStartColumn: selColumn,
|
||||
positionLineNumber: posLineNumber,
|
||||
positionColumn: posColumn
|
||||
}, 'selection equal');
|
||||
}
|
||||
|
||||
function moveTo(cursor: Cursor, lineNumber: number, column: number, inSelectionMode: boolean = false) {
|
||||
cursorCommand(cursor, inSelectionMode ? H.MoveToSelect : H.MoveTo, { position: new Position(lineNumber, column) });
|
||||
}
|
||||
|
||||
function moveToEndOfLine(cursor: Cursor, inSelectionMode: boolean = false) {
|
||||
cursorCommand(cursor, inSelectionMode ? H.CursorEndSelect : H.CursorEnd);
|
||||
}
|
||||
@@ -5,9 +5,39 @@
|
||||
'use strict';
|
||||
|
||||
import {Model} from 'vs/editor/common/model/model';
|
||||
import {IViewModelHelper} from 'vs/editor/common/controller/oneCursor';
|
||||
import {Position} from 'vs/editor/common/core/position';
|
||||
import {Range} from 'vs/editor/common/core/range';
|
||||
import {Selection} from 'vs/editor/common/core/selection';
|
||||
|
||||
export function withEditorModel(text:string[], callback:(model:Model) => void): void {
|
||||
var model = Model.createFromString(text.join('\n'));
|
||||
callback(model);
|
||||
model.dispose();
|
||||
}
|
||||
|
||||
export function viewModelHelper(model): IViewModelHelper{
|
||||
return {
|
||||
viewModel: model,
|
||||
getCurrentVisibleRange: () => { return null; },
|
||||
getCurrentCenteredRange: () => { return null; },
|
||||
convertModelPositionToViewPosition: (lineNumber: number, column: number) => {
|
||||
return new Position(lineNumber, column);
|
||||
},
|
||||
convertModelRangeToViewRange: (modelRange: Range) => {
|
||||
return modelRange;
|
||||
},
|
||||
convertViewToModelPosition: (lineNumber: number, column: number) => {
|
||||
return new Position(lineNumber, column);
|
||||
},
|
||||
convertViewSelectionToModelSelection: (viewSelection: Selection) => {
|
||||
return viewSelection;
|
||||
},
|
||||
validateViewPosition: (viewLineNumber: number, viewColumn: number, modelPosition: Position) => {
|
||||
return modelPosition;
|
||||
},
|
||||
validateViewRange: (viewStartLineNumber: number, viewStartColumn: number, viewEndLineNumber: number, viewEndColumn: number, modelRange: Range) => {
|
||||
return modelRange;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ export class MockCodeEditor extends CommonCodeEditor {
|
||||
return new MockConfiguration(options);
|
||||
}
|
||||
public getCenteredRangeInViewport(): Range { return null; }
|
||||
public getVisibleRangeInViewport(): Range { return null; }
|
||||
|
||||
public getScrollWidth(): number { return 0; }
|
||||
public getScrollLeft(): number { return 0; }
|
||||
|
||||
Vendored
+3
@@ -3205,6 +3205,9 @@ declare module monaco.editor {
|
||||
LineLastNonWhitespaceCharacter: string;
|
||||
LineUp: string;
|
||||
LineDown: string;
|
||||
LineViewTop: string;
|
||||
LineViewCenter: string;
|
||||
LineViewBottom: string;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user