diff --git a/.vscode/launch.json b/.vscode/launch.json index 1cb73684248..329b0964312 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,7 +11,7 @@ // "runtimeArgs": ["--harmony-default-parameters", "--harmony-rest-parameters"], "stopOnEntry": false, "sourceMaps": true, - "outDir": "${workspaceRoot}/out/src" + "outDir": "${workspaceRoot}/out" // "preLaunchTask": "npm" }, { @@ -23,7 +23,7 @@ // "runtimeArgs": ["--js-flags=\"--harmony --harmony-default-parameters\""], "stopOnEntry": false, "sourceMaps": true, - "outDir": "${workspaceRoot}/out/test" + "outDir": "${workspaceRoot}/out" // "preLaunchTask": "npm" } ] diff --git a/extension.ts b/extension.ts index 23c73a90242..ef121104f0d 100644 --- a/extension.ts +++ b/extension.ts @@ -55,3 +55,8 @@ function handleKeyEvent(key: string) : Promise { return modeHandler.handleKeyEvent(key); } + +process.on('unhandledRejection', function(reason, p){ + console.log("Possibly Unhandled Rejection at: Promise ", p, " reason: ", reason); + // application specific logging here +}); diff --git a/src/mode/mode.ts b/src/mode/mode.ts index d58564d225f..01f3a30bc76 100644 --- a/src/mode/mode.ts +++ b/src/mode/mode.ts @@ -1,7 +1,5 @@ "use strict"; -import { Motion } from './../motion/motion'; - export enum ModeName { Normal, Insert, @@ -12,11 +10,9 @@ export enum ModeName { export abstract class Mode { private _isActive : boolean; private _name : ModeName; - private _motion : Motion; - constructor(name: ModeName, motion: Motion) { + constructor(name: ModeName) { this._name = name; - this._motion = motion; this._isActive = false; } @@ -24,14 +20,6 @@ export abstract class Mode { return this._name; } - get motion() : Motion { - return this._motion; - } - - set motion(val : Motion) { - this._motion = val; - } - get isActive() : boolean { return this._isActive; } diff --git a/src/mode/modeHandler.ts b/src/mode/modeHandler.ts index 75e16b1108f..53e8ab2b822 100644 --- a/src/mode/modeHandler.ts +++ b/src/mode/modeHandler.ts @@ -3,7 +3,6 @@ import * as vscode from 'vscode'; import { Mode, ModeName } from './mode'; -import { Motion, MotionMode } from './../motion/motion'; import { NormalMode } from './modeNormal'; import { InsertMode } from './modeInsert'; import { VisualMode } from './modeVisual'; @@ -182,12 +181,28 @@ export class ActionState { } export class ModeHandler implements vscode.Disposable { - private _motion: Motion; private _modes: Mode[]; private _statusBarItem: vscode.StatusBarItem; private _configuration: Configuration; private _vimState: VimState; + // Caret Styling + private _caretDecoration = vscode.window.createTextEditorDecorationType( + { + dark: { + // used for dark colored themes + backgroundColor: 'rgba(224, 224, 224, 0.4)', + borderColor: 'rgba(240, 240, 240, 0.8)' + }, + light: { + // used for light colored themes + backgroundColor: 'rgba(32, 32, 32, 0.4)', + borderColor: 'rgba(16, 16, 16, 0.8)' + }, + borderStyle: 'solid', + borderWidth: '1px' + }); + private get currentModeName(): ModeName { return this.currentMode.name; } @@ -195,12 +210,11 @@ export class ModeHandler implements vscode.Disposable { constructor() { this._configuration = Configuration.fromUserFile(); - this._motion = new Motion(null); this._vimState = new VimState(); this._modes = [ - new NormalMode(this._motion, this), - new InsertMode(this._motion), - new VisualMode(this._motion, this), + new NormalMode(this), + new InsertMode(), + new VisualMode(this), ]; this.setCurrentModeByName(ModeName.Normal); @@ -229,20 +243,6 @@ export class ModeHandler implements vscode.Disposable { mode.isActive = (mode.name === modeName); } - switch (modeName) { - case ModeName.Insert: - this._motion = this._motion.changeMode(MotionMode.Cursor); - break; - - case ModeName.Normal: - this._motion = this._motion.changeMode(MotionMode.Caret); - break; - - case ModeName.Visual: - (activeMode as VisualMode).start(); - break; - } - const statusBarText = (this.currentMode.name === ModeName.Normal) ? '' : ModeName[modeName]; this.setupStatusBarItem(statusBarText ? `-- ${statusBarText.toUpperCase()} --` : ''); } @@ -264,13 +264,15 @@ export class ModeHandler implements vscode.Disposable { let action = Actions.getRelevantAction(actionState.keysPressed.join(""), this._vimState); if (action === KeypressState.NoPossibleMatch) { - // TODO: Slightly janky, for reasons that are hard to describe. - if (this.currentModeName === ModeName.Insert) { await (this.currentMode as any).handleAction(actionState); this._vimState.actionState = new ActionState(this._vimState); - this._vimState.cursorPosition = this._motion.position.getRight(); + // TODO: Forcing a return here and handling this case is pretty janky when you + // could just allow this to pass through the post processing down below anyways. + + this._vimState.cursorStartPosition = Position.FromVSCodePosition(vscode.window.activeTextEditor.selection.start); + this._vimState.cursorPosition = Position.FromVSCodePosition(vscode.window.activeTextEditor.selection.start); return true; } else { @@ -301,7 +303,7 @@ export class ModeHandler implements vscode.Disposable { if (actionState.readyToExecute) { if (this.currentMode.name !== ModeName.Visual && this.currentMode.name !== ModeName.VisualLine) { - this._vimState.cursorStartPosition = this._motion.position; + this._vimState.cursorStartPosition = this._vimState.cursorPosition; } this._vimState = await this.executeState(); @@ -331,8 +333,11 @@ export class ModeHandler implements vscode.Disposable { // Update cursor position + let start = this._vimState.cursorStartPosition; let stop = this._vimState.cursorPosition; + // Keep the cursor within bounds + if (!(this.currentMode instanceof InsertMode)) { if (stop.character >= TextEditor.getLineAt(stop).text.length) { stop = new Position(stop.line, TextEditor.getLineAt(stop).text.length); @@ -344,25 +349,49 @@ export class ModeHandler implements vscode.Disposable { stop = stop.getLineEnd().getLeft(); this._vimState.cursorPosition = stop; } - - this._motion.moveTo(stop.line, stop.character); } else if (this.currentMode instanceof VisualMode) { if (stop.character >= Position.getLineLength(stop.line)) { stop = stop.getLineEnd().getLeft(); this._vimState.cursorPosition = stop; } - await (this.currentMode as VisualMode).handleMotion(this._vimState.cursorStartPosition, stop); - } else if (this.currentMode instanceof InsertMode) { - this._motion.moveTo(stop.line, stop.character); - } else { - console.log("TODO: My janky thing doesn't handle this case!"); + /** + * Always select the letter that we started visual mode on, no matter + * if we are in front or behind it. Imagine that we started visual mode + * with some text like this: + * + * abc|def + * + * (The | represents the cursor.) If we now press w, we'll select def, + * but if we hit b we expect to select abcd, so we need to getRight() on the + * start of the selection when it precedes where we started visual mode. + */ + + // TODO: At this point, start and stop become desynchronoized from cursor(Start)Position + // and just become where to draw the selection. This is just begging for bugs. + + if (start.compareTo(stop) > 0) { + start = start.getRight(); + } + } + + // Draw block cursor. - return; + if (this.currentMode.name !== ModeName.Insert) { + let range = new vscode.Range(stop, stop.getRight()); + vscode.window.activeTextEditor.revealRange(range, vscode.TextEditorRevealType.InCenterIfOutsideViewport); + vscode.window.activeTextEditor.setDecorations(this._caretDecoration, [range]); + } else { + vscode.window.activeTextEditor.setDecorations(this._caretDecoration, []); } - // TODO: Draw cursor and/or selection. + // Draw selection (or cursor) + if (this.currentMode.name === ModeName.Visual) { + vscode.window.activeTextEditor.selection = new vscode.Selection(start, stop); + } else { + vscode.window.activeTextEditor.selection = new vscode.Selection(stop, stop); + } // Updated desired column const movement = actionState.movement, command = actionState.command; @@ -370,7 +399,7 @@ export class ModeHandler implements vscode.Disposable { if (movement && movement.setsDesiredColumnToEOL) { this._vimState.desiredColumn = Number.POSITIVE_INFINITY; } else { - this._vimState.desiredColumn = this._motion.position.character; + this._vimState.desiredColumn = this._vimState.cursorPosition.character; } } @@ -401,15 +430,6 @@ export class ModeHandler implements vscode.Disposable { } if (actionState.operator) { - if (this.currentModeName === ModeName.Visual || - this.currentModeName === ModeName.VisualLine) { - - start = (this.currentMode as VisualMode).selectionStart; - stop = (this.currentMode as VisualMode).selectionStop; - } - - this._motion.changeMode(MotionMode.Cursor); - /* From the Vim documentation: @@ -466,6 +486,5 @@ export class ModeHandler implements vscode.Disposable { dispose() { this._statusBarItem.hide(); this._statusBarItem.dispose(); - this._motion.dispose(); } } \ No newline at end of file diff --git a/src/mode/modeInsert.ts b/src/mode/modeInsert.ts index 14185e7f11a..b23f52930b6 100644 --- a/src/mode/modeInsert.ts +++ b/src/mode/modeInsert.ts @@ -2,12 +2,11 @@ import { ModeName, Mode } from './mode'; import { TextEditor } from './../textEditor'; -import { Motion } from './../motion/motion'; import { ActionState } from './modeHandler'; export class InsertMode extends Mode { - constructor(motion: Motion) { - super(ModeName.Insert, motion); + constructor() { + super(ModeName.Insert); } async handleAction(action: ActionState): Promise { diff --git a/src/mode/modeNormal.ts b/src/mode/modeNormal.ts index 95260df9afa..61640984d14 100644 --- a/src/mode/modeNormal.ts +++ b/src/mode/modeNormal.ts @@ -1,14 +1,13 @@ "use strict"; import { ModeName, Mode } from './mode'; -import { Motion } from './../motion/motion'; import { ModeHandler } from './modeHandler'; export class NormalMode extends Mode { private _modeHandler: ModeHandler; - constructor(motion: Motion, modeHandler: ModeHandler) { - super(ModeName.Normal, motion); + constructor(modeHandler: ModeHandler) { + super(ModeName.Normal); this._modeHandler = modeHandler; } diff --git a/src/mode/modeVisual.ts b/src/mode/modeVisual.ts index a9ef4db4d36..9a0cedc146c 100644 --- a/src/mode/modeVisual.ts +++ b/src/mode/modeVisual.ts @@ -1,7 +1,6 @@ "use strict"; import { ModeName, Mode } from './mode'; -import { Motion} from './../motion/motion'; import { Position } from './../motion/position'; import { ModeHandler } from './modeHandler.ts'; @@ -29,41 +28,9 @@ export class VisualMode extends Mode { this._selectionStop = p; } - constructor(motion: Motion, modeHandler: ModeHandler) { - super(ModeName.Visual, motion); + constructor(modeHandler: ModeHandler) { + super(ModeName.Visual); this._modeHandler = modeHandler; } - - public start(): void { - this._selectionStart = this.motion.position; - this._selectionStop = this._selectionStart; - - this.motion.select(this._selectionStart, this._selectionStop); - } - - public async handleMotion(start: Position, position: Position): Promise { - this._selectionStop = position; - this._selectionStart = start; - this.motion.moveTo(this._selectionStart.line, this._selectionStart.character); - - /** - * Always select the letter that we started visual mode on, no matter - * if we are in front or behind it. Imagine that we started visual mode - * with some text like this: - * - * abc|def - * - * (The | represents the cursor.) If we now press w, we'll select def, - * but if we hit b we expect to select abcd, so we need to getRight() on the - * start of the selection when it precedes where we started visual mode. - */ - if (this._selectionStart.compareTo(this._selectionStop) <= 0) { - this.motion.select(this._selectionStart, this._selectionStop); - } else { - this.motion.select(this._selectionStart.getRight(), this._selectionStop); - } - - return true; - } } diff --git a/src/motion/motion.ts b/src/motion/motion.ts deleted file mode 100644 index 07ea3ea00fc..00000000000 --- a/src/motion/motion.ts +++ /dev/null @@ -1,249 +0,0 @@ -"use strict"; - -import * as vscode from "vscode"; -import { Position } from './position'; - -export enum MotionMode { - Caret, - Cursor, -} - -export class Motion implements vscode.Disposable { - private _motionMode : MotionMode; - private _position : Position; - private _disposables = new Array(); - - // Caret Styling - private _caretDecoration = vscode.window.createTextEditorDecorationType( - { - dark: { - // used for dark colored themes - backgroundColor: 'rgba(224, 224, 224, 0.4)', - borderColor: 'rgba(240, 240, 240, 0.8)' - }, - light: { - // used for light colored themes - backgroundColor: 'rgba(32, 32, 32, 0.4)', - borderColor: 'rgba(16, 16, 16, 0.8)' - }, - borderStyle: 'solid', - borderWidth: '1px' - }); - - public get position() : Position { - return this._position; - } - - public set position(val: Position) { - this._position = val; - this.redraw(); - } - - public constructor(mode: MotionMode) { - // initialize to current position - let currentPosition = vscode.window.activeTextEditor.selection.active; - this._position = new Position(currentPosition.line, currentPosition.character); - - if (mode !== null) { - this.changeMode(mode); - } - - this._disposables.push(vscode.window.onDidChangeTextEditorSelection(e => { - // handle scenarios where mouse used to change current position - let selection = e.selections[0]; - - if (selection) { - let line = selection.active.line; - let char = selection.active.character; - - var newPosition = new Position(line, char); - - if (char > newPosition.getLineEnd().character) { - newPosition = new Position(newPosition.line, newPosition.getLineEnd().character); - } - - this.position = newPosition; - this.changeMode(this._motionMode); - } - })); - - - } - - public changeMode(mode : MotionMode) : Motion { - this._motionMode = mode; - this.redraw(); - return this; - } - - public move(): Motion { - return this.moveTo(null, null); - } - - public moveTo(line: number, character: number) : Motion { - if (line !== null && character !== null) { - this._position = this._position.setLocation(line, character); - } - - if (!this.position.isValid()) { - throw new RangeError(`Invalid position. Line=${line}, Character=${character}`); - } - - let selection = new vscode.Selection(this.position, this.position); - vscode.window.activeTextEditor.selection = selection; - - if (this._motionMode === MotionMode.Caret) { - this.highlightBlock(this.position); - } - - return this; - } - - private redraw() : void { - switch (this._motionMode) { - case MotionMode.Caret: - // Valid Positions for Caret: [0, eol) - this.highlightBlock(this.position); - break; - - case MotionMode.Cursor: - // Valid Positions for Caret: [0, eol] - vscode.window.activeTextEditor.setDecorations(this._caretDecoration, []); - break; - } - } - - /** - * Allows us to simulate a block cursor by highlighting a 1 character - * space at the provided position in a lighter color. - */ - private highlightBlock(start: Position): void { - this.highlightRange(start, new Position(start.line, start.character + 1)); - } - - /** - * Highlights the range from start to end in the color of a block cursor. - */ - private highlightRange(start: Position, end: Position): void { - let range = new vscode.Range(start, end); - vscode.window.activeTextEditor.revealRange(range, vscode.TextEditorRevealType.InCenterIfOutsideViewport); - vscode.window.activeTextEditor.setDecorations(this._caretDecoration, [range]); - } - - public select(from: Position, to: Position): void { - let selection = new vscode.Selection(from, to); - - vscode.window.activeTextEditor.selection = selection; - - this.highlightBlock(to); - } - - public left() : Motion { - this._position = this.position.getLeft(); - return this; - } - - public right() : Motion { - this._position = this.position.getRight(); - return this; - } - - public down() : Motion { - this._position = this.position.getDown(0); - return this; - } - - public up() : Motion { - this._position = this.position.getUp(0); - return this; - } - - public wordLeft(): Motion { - this._position = this.position.getWordLeft(); - return this; - } - - public bigWordLeft(): Motion { - this._position = this.position.getBigWordLeft(); - return this; - } - - public wordRight() : Motion { - this._position = this.position.getWordRight(); - return this; - } - - public bigWordRight() : Motion { - this._position = this.position.getBigWordRight(); - return this; - } - - public lineBegin() : Motion { - this._position = this.position.getLineBegin(); - return this; - } - - public lineEnd() : Motion { - this._position = this.position.getLineEnd(); - return this; - } - - public firstLineNonBlankChar() : Motion { - this._position = this.position.setLocation(0, Position.getFirstNonBlankCharAtLine(0)); - return this; - } - - public lastLineNonBlankChar() : Motion { - let lastLine = this.position.getDocumentEnd().line; - let character = Position.getFirstNonBlankCharAtLine(lastLine); - - this._position = this.position.setLocation(lastLine, character); - return this; - } - - public documentBegin() : Motion { - this._position = this.position.getDocumentBegin(); - return this; - } - - public documentEnd() : Motion { - this._position = this.position.getDocumentEnd(); - return this; - } - - public goToEndOfLastWord(): Motion { - this._position = this.position.getLastWordEnd(); - return this; - } - - public goToEndOfLastBigWord(): Motion { - this._position = this.position.getLastBigWordEnd(); - return this; - } - - public goToEndOfCurrentWord(): Motion { - this._position = this.position.getCurrentWordEnd(); - return this; - } - - public goToEndOfCurrentBigWord(): Motion { - this._position = this.position.getCurrentBigWordEnd(); - return this; - } - - public goToEndOfCurrentParagraph(): Motion { - this._position = this.position.getCurrentParagraphEnd(); - return this; - } - - public goToBeginningOfCurrentParagraph(): Motion { - this._position = this.position.getCurrentParagraphBeginning(); - return this; - } - - dispose() { - _.each(this._disposables, d => { - d.dispose(); - }); - } -} diff --git a/src/motion/position.ts b/src/motion/position.ts index 0b4a65e4edd..1f123a4739a 100644 --- a/src/motion/position.ts +++ b/src/motion/position.ts @@ -18,6 +18,10 @@ export class Position extends vscode.Position { this._nonBigWordCharRegex = this.makeWordRegex(Position.NonBigWordCharacters); } + public static FromVSCodePosition(pos: vscode.Position): Position { + return new Position(pos.line, pos.character); + } + /** * Returns which of the 2 provided Positions comes earlier in the document. */ diff --git a/test/motion.test.ts b/test/motion.test.ts index b661f67b56a..07cb62a3c81 100644 --- a/test/motion.test.ts +++ b/test/motion.test.ts @@ -1,13 +1,11 @@ "use strict"; import * as assert from 'assert'; -import * as vscode from "vscode"; -import {TextEditor} from './../src/textEditor'; -import {Motion, MotionMode} from './../src/motion/motion'; -import {setupWorkspace, cleanUpWorkspace} from './testUtils'; +import { TextEditor } from './../src/textEditor'; +import { Position } from './../src/motion/position'; +import { setupWorkspace, cleanUpWorkspace } from './testUtils'; -suite("motion", () => { - let motionModes = [MotionMode.Caret, MotionMode.Cursor]; +suite("old motion tests", () => { let text: string[] = [ "mary had", "a", @@ -23,167 +21,123 @@ suite("motion", () => { suiteTeardown(cleanUpWorkspace); test("char right: should move one column right", () => { - for (let o of motionModes) { - let motion = new Motion(o).moveTo(0, 0); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 0); - - let next = motion.right().move(); - assert.equal(next.position.line, 0); - assert.equal(next.position.character, 1); - - let curPos = vscode.window.activeTextEditor.selection.active; - assert.equal(next.position.line, curPos.line); - assert.equal(next.position.character, curPos.character); - }; + let position = new Position(0, 0); + assert.equal(position.line, 0); + assert.equal(position.character, 0); + + let next = position.getRight(); + assert.equal(next.line, 0); + assert.equal(next.character, 1); }); test("char right", () => { - let motion = new Motion(MotionMode.Cursor); - motion = motion.moveTo(0, 9).right(); + let motion = new Position(0, 9); + motion = motion.getRight(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 9); + assert.equal(motion.line, 0); + assert.equal(motion.character, 9); }); test("char left: should move cursor one column left", () => { - motionModes.forEach(o => { - let motion = new Motion(o).moveTo(0, 5); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 5); - - motion = motion.left().move(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 4); + let position = new Position(0, 5); + assert.equal(position.line, 0); + assert.equal(position.character, 5); - let curPos = vscode.window.activeTextEditor.selection.active; - assert.equal(motion.position.line, curPos.line); - assert.equal(motion.position.character, curPos.character); - }); + position = position.getLeft(); + assert.equal(position.line, 0); + assert.equal(position.character, 4); }); test("char left: left-most column should stay at the same location", () => { - motionModes.forEach(o => { - let motion = new Motion(o).moveTo(0, 0); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 0); + let motion = new Position(0, 0); + assert.equal(motion.line, 0); + assert.equal(motion.character, 0); - motion = motion.left().move(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 0); - - let curPos = vscode.window.activeTextEditor.selection.active; - assert.equal(motion.position.line, curPos.line); - assert.equal(motion.position.character, curPos.character); - }); + motion = motion.getLeft(); + assert.equal(motion.line, 0); + assert.equal(motion.character, 0); }); test("line down: should move cursor one line down", () => { - motionModes.forEach(o => { - let motion = new Motion(o).moveTo(1, 0); - assert.equal(motion.position.line, 1); - assert.equal(motion.position.character, 0); - - motion = motion.down().move(); - assert.equal(motion.position.line, 2); - assert.equal(motion.position.character, 0); + let motion = new Position(1, 0); + assert.equal(motion.line, 1); + assert.equal(motion.character, 0); - let curPos = vscode.window.activeTextEditor.selection.active; - assert.equal(motion.position.line, curPos.line); - assert.equal(motion.position.character, curPos.character); - }); + motion = motion.getDown(0); + assert.equal(motion.line, 2); + assert.equal(motion.character, 0); }); test("line down: bottom-most line should stay at the same location", () => { - motionModes.forEach(o => { - let motion = new Motion(o).moveTo(3, 0); - assert.equal(motion.position.line, 3); - assert.equal(motion.position.character, 0); - - motion = motion.down().move(); - assert.equal(motion.position.line, 3); - assert.equal(motion.position.character, 0); + let motion = new Position(3, 0); + assert.equal(motion.line, 3); + assert.equal(motion.character, 0); - let curPos = vscode.window.activeTextEditor.selection.active; - assert.equal(motion.position.line, curPos.line); - assert.equal(motion.position.character, curPos.character); - }); + motion = motion.getDown(3); + assert.equal(motion.line, 3); + assert.equal(motion.character, 0); }); suite("line up", () => { - motionModes.forEach(o => { - test("should move cursor one line up", () => { - let motion = new Motion(o).moveTo(1, 0); - assert.equal(motion.position.line, 1); - assert.equal(motion.position.character, 0); - - motion = motion.up().move(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 0); - - let curPos = vscode.window.activeTextEditor.selection.active; - assert.equal(motion.position.line, curPos.line); - assert.equal(motion.position.character, curPos.character); - }); - - test("top-most line should stay at the same location", () => { - let motion = new Motion(o).moveTo(0, 1); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 1); - - motion = motion.up().move(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 1); - - let curPos = vscode.window.activeTextEditor.selection.active; - assert.equal(motion.position.line, curPos.line); - assert.equal(motion.position.character, curPos.character); - }); - }); + test("should move cursor one line up", () => { + let position = new Position(1, 0); + assert.equal(position.line, 1); + assert.equal(position.character, 0); + + position = position.getUp(0); + assert.equal(position.line, 0); + assert.equal(position.character, 0); + }); + + test("top-most line should stay at the same location", () => { + let motion = new Position(0, 1); + assert.equal(motion.line, 0); + assert.equal(motion.character, 1); + + motion = motion.getUp(0); + assert.equal(motion.line, 0); + assert.equal(motion.character, 1); + }); }); test("line begin", () => { - motionModes.forEach(o => { - let motion = new Motion(o).moveTo(0, 3).lineBegin(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 0); - }); + let motion = new Position(0, 3).getLineBegin(); + assert.equal(motion.line, 0); + assert.equal(motion.character, 0); }); test("line end", () => { - let motion = new Motion(MotionMode.Cursor).moveTo(0, 0).lineEnd(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, text[0].length); + let motion = new Position(0, 0).getLineEnd(); + assert.equal(motion.line, 0); + assert.equal(motion.character, text[0].length); - motion = motion.moveTo(2, 0).lineEnd(); - assert.equal(motion.position.line, 2); - assert.equal(motion.position.character, text[2].length); + motion = new Position(2, 0).getLineEnd(); + assert.equal(motion.line, 2); + assert.equal(motion.character, text[2].length); }); test("document begin", () => { - motionModes.forEach(o => { - let motion = new Motion(o).moveTo(1, 0).documentBegin(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 0); - }); + let motion = new Position(1, 0).getDocumentBegin(); + assert.equal(motion.line, 0); + assert.equal(motion.character, 0); }); test("document end", () => { - let motion = new Motion(MotionMode.Cursor).moveTo(0, 0).documentEnd(); - assert.equal(motion.position.line, text.length - 1); - assert.equal(motion.position.character, text[text.length - 1].length); + let motion = new Position(0, 0).getDocumentEnd(); + assert.equal(motion.line, text.length - 1); + assert.equal(motion.character, text[text.length - 1].length); }); test("line begin cursor on first non-blank character", () => { - let motion = new Motion(MotionMode.Caret).moveTo(3, 3).firstLineNonBlankChar(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 0); + let motion = new Position(0, 3).getFirstLineNonBlankChar(); + assert.equal(motion.line, 0); + assert.equal(motion.character, 0); }); test("last line begin cursor on first non-blank character", () => { - let motion = new Motion(MotionMode.Caret).moveTo(0, 0).lastLineNonBlankChar(); - assert.equal(motion.position.line, 3); - assert.equal(motion.position.character, 1); + let motion = new Position(3, 0).getFirstLineNonBlankChar(); + assert.equal(motion.line, 3); + assert.equal(motion.character, 1); }); }); @@ -208,201 +162,201 @@ suite("word motion", () => { suite("word right", () => { test("move to word right", () => { - let motion = new Motion(MotionMode.Caret).moveTo(0, 3).wordRight(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 4); + let motion = new Position(0, 3).getWordRight(); + assert.equal(motion.line, 0); + assert.equal(motion.character, 4); }); test("last word should move to next line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(0, 10).wordRight(); - assert.equal(motion.position.line, 1); - assert.equal(motion.position.character, 2); + let motion = new Position(0, 10).getWordRight(); + assert.equal(motion.line, 1); + assert.equal(motion.character, 2); }); test("last word should move to next line stops on empty line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(2, 7).wordRight(); - assert.equal(motion.position.line, 3); - assert.equal(motion.position.character, 0); + let motion = new Position(2, 7).getWordRight(); + assert.equal(motion.line, 3); + assert.equal(motion.character, 0); }); test("last word should move to next line skips whitespace only line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(4, 14).wordRight(); - assert.equal(motion.position.line, 6); - assert.equal(motion.position.character, 0); + let motion = new Position(4, 14).getWordRight(); + assert.equal(motion.line, 6); + assert.equal(motion.character, 0); }); test("last word on last line should go to end of document (special case!)", () => { - let motion = new Motion(MotionMode.Caret).moveTo(6, 6).wordRight(); - assert.equal(motion.position.line, 6); - assert.equal(motion.position.character, 10); + let motion = new Position(6, 6).getWordRight(); + assert.equal(motion.line, 6); + assert.equal(motion.character, 10); }); }); suite("word left", () => { test("move cursor word left across spaces", () => { - let motion = new Motion(MotionMode.Caret).moveTo(0, 3).wordLeft(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 0); + let motion = new Position(0, 3).getWordLeft(); + assert.equal(motion.line, 0); + assert.equal(motion.character, 0); }); test("move cursor word left within word", () => { - let motion = new Motion(MotionMode.Caret).moveTo(0, 5).wordLeft(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 4); + let motion = new Position(0, 5).getWordLeft(); + assert.equal(motion.line, 0); + assert.equal(motion.character, 4); }); test("first word should move to previous line, beginning of last word", () => { - let motion = new Motion(MotionMode.Caret).moveTo(1, 2).wordLeft(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 10); + let motion = new Position(1, 2).getWordLeft(); + assert.equal(motion.line, 0); + assert.equal(motion.character, 10); }); test("first word should move to previous line, stops on empty line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(4, 2).wordLeft(); - assert.equal(motion.position.line, 3); - assert.equal(motion.position.character, 0); + let motion = new Position(4, 2).getWordLeft(); + assert.equal(motion.line, 3); + assert.equal(motion.character, 0); }); test("first word should move to previous line, skips whitespace only line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(6, 0).wordLeft(); - assert.equal(motion.position.line, 4); - assert.equal(motion.position.character, 14); + let motion = new Position(6, 0).getWordLeft(); + assert.equal(motion.line, 4); + assert.equal(motion.character, 14); }); }); suite("WORD right", () => { test("move to WORD right", () => { - let motion = new Motion(MotionMode.Caret).moveTo(0, 3).bigWordRight(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 10); + let motion = new Position(0, 3).getBigWordRight(); + assert.equal(motion.line, 0); + assert.equal(motion.character, 10); }); test("last WORD should move to next line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(1, 10).bigWordRight(); - assert.equal(motion.position.line, 2); - assert.equal(motion.position.character, 0); + let motion = new Position(1, 10).getBigWordRight(); + assert.equal(motion.line, 2); + assert.equal(motion.character, 0); }); test("last WORD should move to next line stops on empty line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(2, 7).bigWordRight(); - assert.equal(motion.position.line, 3); - assert.equal(motion.position.character, 0); + let motion = new Position(2, 7).getBigWordRight(); + assert.equal(motion.line, 3); + assert.equal(motion.character, 0); }); test("last WORD should move to next line skips whitespace only line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(4, 12).bigWordRight(); - assert.equal(motion.position.line, 6); - assert.equal(motion.position.character, 0); + let motion = new Position(4, 12).getBigWordRight(); + assert.equal(motion.line, 6); + assert.equal(motion.character, 0); }); }); suite("WORD left", () => { test("move cursor WORD left across spaces", () => { - let motion = new Motion(MotionMode.Caret).moveTo(0, 3).bigWordLeft(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 0); + let motion = new Position(0, 3).getBigWordLeft(); + assert.equal(motion.line, 0); + assert.equal(motion.character, 0); }); test("move cursor WORD left within WORD", () => { - let motion = new Motion(MotionMode.Caret).moveTo(0, 5).bigWordLeft(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 3); + let motion = new Position(0, 5).getBigWordLeft(); + assert.equal(motion.line, 0); + assert.equal(motion.character, 3); }); test("first WORD should move to previous line, beginning of last WORD", () => { - let motion = new Motion(MotionMode.Caret).moveTo(2, 0).bigWordLeft(); - assert.equal(motion.position.line, 1); - assert.equal(motion.position.character, 9); + let motion = new Position(2, 0).getBigWordLeft(); + assert.equal(motion.line, 1); + assert.equal(motion.character, 9); }); test("first WORD should move to previous line, stops on empty line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(4, 2).bigWordLeft(); - assert.equal(motion.position.line, 3); - assert.equal(motion.position.character, 0); + let motion = new Position(4, 2).getBigWordLeft(); + assert.equal(motion.line, 3); + assert.equal(motion.character, 0); }); test("first WORD should move to previous line, skips whitespace only line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(6, 0).bigWordLeft(); - assert.equal(motion.position.line, 4); - assert.equal(motion.position.character, 9); + let motion = new Position(6, 0).getBigWordLeft(); + assert.equal(motion.line, 4); + assert.equal(motion.character, 9); }); }); suite("end of word right", () => { test("move to end of current word right", () => { - let motion = new Motion(MotionMode.Caret).moveTo(0, 4).goToEndOfCurrentWord(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 7); + let motion = new Position(0, 4).getCurrentWordEnd(); + assert.equal(motion.line, 0); + assert.equal(motion.character, 7); }); test("move to end of next word right", () => { - let motion = new Motion(MotionMode.Caret).moveTo(0, 7).goToEndOfCurrentWord(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 8); + let motion = new Position(0, 7).getCurrentWordEnd(); + assert.equal(motion.line, 0); + assert.equal(motion.character, 8); }); test("end of last word should move to next line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(0, 10).goToEndOfCurrentWord(); - assert.equal(motion.position.line, 1); - assert.equal(motion.position.character, 7); + let motion = new Position(0, 10).getCurrentWordEnd(); + assert.equal(motion.line, 1); + assert.equal(motion.character, 7); }); test("end of last word should move to next line skips empty line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(2, 7).goToEndOfCurrentWord(); - assert.equal(motion.position.line, 4); - assert.equal(motion.position.character, 7); + let motion = new Position(2, 7).getCurrentWordEnd(); + assert.equal(motion.line, 4); + assert.equal(motion.character, 7); }); test("end of last word should move to next line skips whitespace only line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(4, 14).goToEndOfCurrentWord(); - assert.equal(motion.position.line, 6); - assert.equal(motion.position.character, 0); + let motion = new Position(4, 14).getCurrentWordEnd(); + assert.equal(motion.line, 6); + assert.equal(motion.character, 0); }); }); suite("end of WORD right", () => { test("move to end of current WORD right", () => { - let motion = new Motion(MotionMode.Caret).moveTo(0, 4).goToEndOfCurrentBigWord(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 8); + let motion = new Position(0, 4).getCurrentBigWordEnd(); + assert.equal(motion.line, 0); + assert.equal(motion.character, 8); }); test("move to end of next WORD right", () => { - let motion = new Motion(MotionMode.Caret).moveTo(0, 8).goToEndOfCurrentBigWord(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 10); + let motion = new Position(0, 8).getCurrentBigWordEnd(); + assert.equal(motion.line, 0); + assert.equal(motion.character, 10); }); test("end of last WORD should move to next line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(0, 10).goToEndOfCurrentBigWord(); - assert.equal(motion.position.line, 1); - assert.equal(motion.position.character, 7); + let motion = new Position(0, 10).getCurrentBigWordEnd(); + assert.equal(motion.line, 1); + assert.equal(motion.character, 7); }); test("end of last WORD should move to next line skips empty line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(2, 7).goToEndOfCurrentWord(); - assert.equal(motion.position.line, 4); - assert.equal(motion.position.character, 7); + let motion = new Position(2, 7).getCurrentBigWordEnd(); + assert.equal(motion.line, 4); + assert.equal(motion.character, 7); }); test("end of last WORD should move to next line skips whitespace only line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(4, 14).goToEndOfCurrentWord(); - assert.equal(motion.position.line, 6); - assert.equal(motion.position.character, 0); + let motion = new Position(4, 14).getCurrentBigWordEnd(); + assert.equal(motion.line, 6); + assert.equal(motion.character, 0); }); }); test("line begin cursor on first non-blank character", () => { - let motion = new Motion(MotionMode.Caret).moveTo(4, 3).firstLineNonBlankChar(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 0); + let motion = new Position(4, 3).getFirstLineNonBlankChar(); + assert.equal(motion.line, 4); + assert.equal(motion.character, 2); }); test("last line begin cursor on first non-blank character", () => { - let motion = new Motion(MotionMode.Caret).moveTo(0, 0).lastLineNonBlankChar(); - assert.equal(motion.position.line, 6); - assert.equal(motion.position.character, 0); + let motion = new Position(6, 0).getFirstLineNonBlankChar(); + assert.equal(motion.line, 6); + assert.equal(motion.character, 0); }); }); @@ -430,47 +384,47 @@ suite("paragraph motion", () => { suite("paragraph down", () => { test("move down normally", () => { - let motion = new Motion(MotionMode.Caret).moveTo(0, 0).goToEndOfCurrentParagraph(); - assert.equal(motion.position.line, 1); - assert.equal(motion.position.character, 0); + let motion = new Position(0, 0).getCurrentParagraphEnd(); + assert.equal(motion.line, 1); + assert.equal(motion.character, 0); }); test("move down longer paragraph", () => { - let motion = new Motion(MotionMode.Caret).moveTo(2, 0).goToEndOfCurrentParagraph(); - assert.equal(motion.position.line, 4); - assert.equal(motion.position.character, 0); + let motion = new Position(2, 0).getCurrentParagraphEnd(); + assert.equal(motion.line, 4); + assert.equal(motion.character, 0); }); test("move down starting inside empty line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(4, 0).goToEndOfCurrentParagraph(); - assert.equal(motion.position.line, 7); - assert.equal(motion.position.character, 0); + let motion = new Position(4, 0).getCurrentParagraphEnd(); + assert.equal(motion.line, 7); + assert.equal(motion.character, 0); }); test("paragraph at end of document", () => { - let motion = new Motion(MotionMode.Caret).moveTo(7, 0).goToEndOfCurrentParagraph(); - assert.equal(motion.position.line, 8); - assert.equal(motion.position.character, 3); + let motion = new Position(7, 0).getCurrentParagraphEnd(); + assert.equal(motion.line, 8); + assert.equal(motion.character, 3); }); }); suite("paragraph up", () => { test("move up short paragraph", () => { - let motion = new Motion(MotionMode.Caret).moveTo(1, 0).goToBeginningOfCurrentParagraph(); - assert.equal(motion.position.line, 0); - assert.equal(motion.position.character, 0); + let motion = new Position(1, 0).getCurrentParagraphBeginning(); + assert.equal(motion.line, 0); + assert.equal(motion.character, 0); }); test("move up longer paragraph", () => { - let motion = new Motion(MotionMode.Caret).moveTo(3, 0).goToBeginningOfCurrentParagraph(); - assert.equal(motion.position.line, 1); - assert.equal(motion.position.character, 0); + let motion = new Position(3, 0).getCurrentParagraphBeginning(); + assert.equal(motion.line, 1); + assert.equal(motion.character, 0); }); test("move up starting inside empty line", () => { - let motion = new Motion(MotionMode.Caret).moveTo(5, 0).goToBeginningOfCurrentParagraph(); - assert.equal(motion.position.line, 1); - assert.equal(motion.position.character, 0); + let motion = new Position(5, 0).getCurrentParagraphBeginning(); + assert.equal(motion.line, 1); + assert.equal(motion.character, 0); }); }); });