Merge pull request #9536 from Microsoft/sandy081/linesViewPort

Implement lineViewTop, lineViewBottom, lineViewCenter
This commit is contained in:
Sandeep Somavarapu
2016-07-20 17:31:30 +02:00
committed by GitHub
14 changed files with 566 additions and 232 deletions
+1
View File
@@ -58,6 +58,7 @@ export interface IView extends IDisposable {
getCodeEditorHelper(): ICodeEditorHelper;
getCenteredRangeInViewport(): Range;
getVisibleRangeInViewport(): Range;
change(callback:(changeAccessor:IViewZoneChangeAccessor) => any): boolean;
getWhitespaces(): editorCommon.IEditorWhitespace[];
+8
View File
@@ -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;
+8
View File
@@ -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);
},
-25
View File
@@ -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;
}
+4 -1
View File
@@ -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; }
+3
View File
@@ -3205,6 +3205,9 @@ declare module monaco.editor {
LineLastNonWhitespaceCharacter: string;
LineUp: string;
LineDown: string;
LineViewTop: string;
LineViewCenter: string;
LineViewBottom: string;
};
/**