diff --git a/src/cursor/caret.ts b/src/cursor/caret.ts deleted file mode 100644 index e3d1e46d15e..00000000000 --- a/src/cursor/caret.ts +++ /dev/null @@ -1,12 +0,0 @@ -import Cursor from "./cursor"; - -export default class Caret extends Cursor { - - protected static maxLineLength(line: number) : number { - let len = super.maxLineLength(line) - 1; - if (len < 0) { - len = 0; - } - return len; - } -} \ No newline at end of file diff --git a/src/cursor/cursor.ts b/src/cursor/cursor.ts deleted file mode 100644 index 888a031a9d0..00000000000 --- a/src/cursor/cursor.ts +++ /dev/null @@ -1,247 +0,0 @@ -import * as _ from "lodash"; -import * as vscode from "vscode"; -import TextEditor from "./../textEditor"; - -export default class Cursor { - private static prevColumn: number = 0; - - // overrride this function between cursor mode and caret mode - protected static maxLineLength(line: number) : number { - return TextEditor.readLine(line).length; - } - - static move(newPosition: vscode.Position) { - if (newPosition === null) { - return; - } - let curPosition = this.currentPosition(); - - if (newPosition.line === curPosition.line) { - this.prevColumn = newPosition.character; - } - - const newSelection = new vscode.Selection(newPosition, newPosition); - vscode.window.activeTextEditor.selection = newSelection; - } - - static currentPosition(): vscode.Position { - return vscode.window.activeTextEditor.selection.active; - } - - static left() : vscode.Position { - let pos = this.currentPosition(); - let column = pos.character; - - if (!this.isLineBeginning(pos)) { - column--; - } - - return new vscode.Position(pos.line, column); - } - - static right() : vscode.Position { - let pos = this.currentPosition(); - let column = pos.character; - - if (!this.isLineEnd(pos)) { - column++; - } - - return new vscode.Position(pos.line, column); - } - - static down() : vscode.Position { - let pos = this.currentPosition(); - let line = pos.line; - let column = this.prevColumn; - - if (!Cursor.isLastLine(pos)) { - let nextLineMaxColumn = TextEditor.readLine(++line).length - 1; - - if (nextLineMaxColumn < 0) { - nextLineMaxColumn = 0; - } - - if (nextLineMaxColumn < this.prevColumn) { - column = nextLineMaxColumn; - } - } - - return new vscode.Position(line, column); - } - - static up() : vscode.Position { - let pos = this.currentPosition(); - let line = pos.line; - let column = this.prevColumn; - - if (!this.isFirstLine(pos)) { - let nextLineMaxColumn = TextEditor.readLine(--line).length - 1; - - if (nextLineMaxColumn < 0) { - nextLineMaxColumn = 0; - } - - if (nextLineMaxColumn < this.prevColumn) { - column = nextLineMaxColumn; - } - } - - return new vscode.Position(line, column); - } - - static wordRight() : vscode.Position { - let pos = this.currentPosition(); - if (pos.character === this.lineEnd().character) { - if (this.isLastLine(pos)) { - return null; - } - let line = TextEditor.getLineAt(pos.translate(1)); - return new vscode.Position(line.lineNumber, line.firstNonWhitespaceCharacterIndex); - } - let nextPos = this.getNextWordPosition(); - if (nextPos === null) { - return this.lineEnd(); - } - return nextPos; - } - - static wordLeft(): vscode.Position { - let pos = this.currentPosition(); - let currentLine = TextEditor.getLineAt(pos); - if (pos.character <= currentLine.firstNonWhitespaceCharacterIndex && pos.line !== 0) { - let line = TextEditor.getLineAt(pos.translate(-1)); - return new vscode.Position(line.lineNumber, line.range.end.character); - } - let nextPos = this.getPreviousWordPosition(); - return nextPos; - } - - static lineBegin() : vscode.Position { - let pos = this.currentPosition(); - return new vscode.Position(pos.line, 0); - } - - static lineEnd() : vscode.Position { - let pos = this.currentPosition(); - let lineLength = this.maxLineLength(pos.line); - - return new vscode.Position(pos.line, lineLength); - } - - static firstLineNonBlankChar() : vscode.Position { - let character = Cursor.posOfFirstNonBlankChar(0); - return new vscode.Position(0, character); - } - - static lastLineNonBlankChar() : vscode.Position { - const line = vscode.window.activeTextEditor.document.lineCount - 1; - let character = Cursor.posOfFirstNonBlankChar(line); - return new vscode.Position(line, character); - } - - static documentBegin() : vscode.Position { - return new vscode.Position(0, 0); - } - - static documentEnd() : vscode.Position { - let line = vscode.window.activeTextEditor.document.lineCount - 1; - if (line < 0) { - line = 0; - } - - let column = TextEditor.readLine(line).length; - return new vscode.Position(line, column); - } - - private static isLineBeginning(position : vscode.Position) : boolean { - return position.character === 0; - } - - private static isLineEnd(position : vscode.Position) : boolean { - let lineEnd = this.maxLineLength(position.line); - if (lineEnd < 0) { - lineEnd = 0; - } - - if (position.character > lineEnd) { - throw new RangeError; - } - - return position.character === lineEnd; - } - - private static isFirstLine(position : vscode.Position) : boolean { - return position.line === 0; - } - - private static isLastLine(position : vscode.Position): boolean { - return position.line === (vscode.window.activeTextEditor.document.lineCount - 1); - } - - private static _nonWordCharacters = "/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-"; - - private static getNextWordPosition(): vscode.Position { - let segments = ["(^[\t ]*$)"]; - segments.push(`([^\\s${_.escapeRegExp(this._nonWordCharacters) }]+)`); - segments.push(`[\\s${_.escapeRegExp(this._nonWordCharacters) }]+`); - let reg = new RegExp(segments.join("|"), "g"); - let pos = this.currentPosition(); - let line = TextEditor.getLineAt(pos); - let words = line.text.match(reg); - - let startWord: number; - let endWord: number; - - if (words) { - for (var index = 0; index < words.length; index++) { - var word = words[index].trim(); - if (word.length > 0) { - startWord = line.text.indexOf(word, endWord); - endWord = startWord + word.length; - - if (pos.character < startWord) { - return new vscode.Position(pos.line, startWord); - } - } - } - } - - return null; - } - - private static getPreviousWordPosition(): vscode.Position { - let segments = ["(^[\t ]*$)"]; - segments.push(`([^\\s${_.escapeRegExp(this._nonWordCharacters) }]+)`); - segments.push(`[\\s${_.escapeRegExp(this._nonWordCharacters) }]+`); - let reg = new RegExp(segments.join("|"), "g"); - let pos = this.currentPosition(); - let line = TextEditor.getLineAt(pos); - let words = line.text.match(reg); - - let startWord: number; - let endWord: number; - - if (words) { - words = words.reverse(); - endWord = line.range.end.character; - for (var index = 0; index < words.length; index++) { - endWord = endWord - words[index].length; - var word = words[index].trim(); - if (word.length > 0) { - startWord = line.text.indexOf(word, endWord); - - if (startWord !== -1 && pos.character > startWord) { - return new vscode.Position(pos.line, startWord); - } - } - } - } - - return null; - } - - private static posOfFirstNonBlankChar(line: number): number { - return TextEditor.readLine(line).match(/^\s*/)[0].length; - } -} diff --git a/src/mode/modeInsert.ts b/src/mode/modeInsert.ts index 52c561e0aef..69626ef9901 100644 --- a/src/mode/modeInsert.ts +++ b/src/mode/modeInsert.ts @@ -1,27 +1,30 @@ import * as vscode from 'vscode'; import {ModeName, Mode} from './mode'; import TextEditor from './../textEditor'; -import Cursor from './../cursor/cursor'; +import {Cursor} from './../motion/motion'; export default class InsertMode extends Mode { - private activationKeyHandler : { [ key : string] : () => Thenable | void; }; + private activationKeyHandler : { [ key : string] : (cursor : Cursor) => Thenable | void; }; + private cursor : Cursor = new Cursor(); constructor() { super(ModeName.Insert); this.activationKeyHandler = { // insert at cursor - "i" : () => { Cursor.move(Cursor.currentPosition()); }, + "i" : (cursor) => { + // nothing + }, // insert at the beginning of the line - "I" : () => { Cursor.move(Cursor.lineBegin()); }, + "I" : (cursor) => { cursor.lineBegin().move(); }, // append after the cursor - "a" : () => { Cursor.move(Cursor.right()); }, + "a" : (cursor) => { cursor.right().move(); }, // append at the end of the line - "A" : () => { Cursor.move(Cursor.lineEnd()); }, + "A" : (cursor) => { cursor.lineEnd().move(); }, // open blank line below current line "o" : () => { @@ -40,7 +43,8 @@ export default class InsertMode extends Mode { } HandleActivation(key : string) : Thenable | void { - return this.activationKeyHandler[key](); + this.cursor.reset(); + return this.activationKeyHandler[key](this.cursor); } HandleKeyEvent(key : string) : Thenable { diff --git a/src/mode/modeNormal.ts b/src/mode/modeNormal.ts index d4062466351..d6bd889b29a 100644 --- a/src/mode/modeNormal.ts +++ b/src/mode/modeNormal.ts @@ -2,11 +2,11 @@ import * as _ from 'lodash'; import * as vscode from 'vscode'; import {ModeName, Mode} from './mode'; import {showCmdLine} from './../cmd_line/main'; -import Caret from './../cursor/caret'; -import TextEditor from './../textEditor'; +import {Caret} from './../motion/motion'; export default class CommandMode extends Mode { private keyHandler : { [key : string] : () => void; } = {}; + private caret : Caret = new Caret(); constructor() { super(ModeName.Normal); @@ -15,35 +15,34 @@ export default class CommandMode extends Mode { ":" : () => { showCmdLine(); }, "u" : () => { vscode.commands.executeCommand("undo"); }, "ctrl+r" : () => { vscode.commands.executeCommand("redo"); }, - "h" : () => { Caret.move(Caret.left()); }, - "j" : () => { Caret.move(Caret.down()); }, - "k" : () => { Caret.move(Caret.up()); }, - "l" : () => { Caret.move(Caret.right()); }, - "$" : () => { Caret.move(Caret.lineEnd()); }, - "^" : () => { Caret.move(Caret.lineBegin()); }, - "gg" : () => { Caret.move(Caret.firstLineNonBlankChar()); }, - "G" : () => { Caret.move(Caret.lastLineNonBlankChar()); }, - "w" : () => { Caret.move(Caret.wordRight()); }, - "b" : () => { Caret.move(Caret.wordLeft()); }, + "h" : () => { this.caret.left().move(); }, + "j" : () => { this.caret.down().move(); }, + "k" : () => { this.caret.up().move(); }, + "l" : () => { this.caret.right().move(); }, + "$" : () => { this.caret.lineEnd().move(); }, + "^" : () => { this.caret.lineBegin().move(); }, + "gg" : () => {this.caret.firstLineNonBlankChar().move(); }, + "G" : () => { this.caret.lastLineNonBlankChar().move(); }, + "w" : () => { this.caret.wordRight().move(); }, + "b" : () => { this.caret.wordLeft().move(); }, ">>" : () => { vscode.commands.executeCommand("editor.action.indentLines"); }, "<<" : () => { vscode.commands.executeCommand("editor.action.outdentLines"); }, "dd" : () => { vscode.commands.executeCommand("editor.action.deleteLines"); }, "dw" : () => { vscode.commands.executeCommand("deleteWordRight"); }, "db" : () => { vscode.commands.executeCommand("deleteWordLeft"); }, - "esc": () => { vscode.commands.executeCommand("workbench.action.closeMessages"); }, - "x" : () => { this.CommandDelete(1); } + // "x" : () => { this.CommandDelete(1); } + "esc": () => { vscode.commands.executeCommand("workbench.action.closeMessages"); } }; } ShouldBeActivated(key : string, currentMode : ModeName) : boolean { if (key === 'esc' || key === 'ctrl+[') { - Caret.move(Caret.left()); return true; } } HandleActivation(key : string) : void { - // do nothing + this.caret.reset(); } HandleKeyEvent(key : string) : void { @@ -65,6 +64,7 @@ export default class CommandMode extends Mode { } } +/* private CommandDelete(n: number) : void { let pos = Caret.currentPosition(); let end = pos.translate(0, n); @@ -77,4 +77,5 @@ export default class CommandMode extends Mode { } }); } +*/ } diff --git a/src/motion/motion.ts b/src/motion/motion.ts new file mode 100644 index 00000000000..d5f85c187af --- /dev/null +++ b/src/motion/motion.ts @@ -0,0 +1,255 @@ +import * as _ from "lodash"; +import * as vscode from "vscode"; +import TextEditor from "./../textEditor"; + +abstract class Motion> { + private static nonWordCharacters = "/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-"; + private prevColumn: number = 0; + + public static getActualPosition(): vscode.Position { + return vscode.window.activeTextEditor.selection.active; + } + + public position : vscode.Position; + + public constructor(line : number = null, character : number = null) { + if (line === null || character == null) { + let currentPosition = Motion.getActualPosition(); + + line = currentPosition.line; + character = currentPosition.character; + } + this.prevColumn = character; + this.position = new vscode.Position(line, character); + } + + protected abstract maxLineLength(line: number) : number; + + public reset() : T { + this.position = Motion.getActualPosition(); + return this; + } + + public move() : T { + let selection = new vscode.Selection(this.position, this.position); + vscode.window.activeTextEditor.selection = selection; + + let range = new vscode.Range(this.position, this.position); + vscode.window.activeTextEditor.revealRange(range, vscode.TextEditorRevealType.InCenterIfOutsideViewport); + + return this; + } + + public left() : T { + if (!this.isLineBeginning(this.position)) { + this.position = this.position.translate(0, -1); + this.prevColumn = this.position.character; + } + + return this; + } + + public right() : T { + if (!this.isLineEnd(this.position)) { + this.position = this.position.translate(0, 1); + this.prevColumn = this.position.character; + } + + return this; + } + + public down() : T { + if (!TextEditor.isLastLine(this.position)) { + let newLine = this.position.line + 1; + + let lineLength = TextEditor.readLine(newLine).length; + let newCharMax = lineLength > 0 ? lineLength - 1 : 0; + let newChar = Math.min(newCharMax, this.prevColumn); + + this.position = new vscode.Position(newLine, newChar); + } + + return this; + } + + public up() : T { + if (!TextEditor.isFirstLine(this.position)) { + let newLine = this.position.line - 1; + + let lineLength = TextEditor.readLine(newLine).length; + let newCharMax = lineLength > 0 ? lineLength - 1 : 0; + let newChar = Math.min(newCharMax, this.prevColumn); + + this.position = new vscode.Position(newLine, newChar); + } + + return this; + } + + public wordLeft(): T { + let currentLine = TextEditor.getLineAt(this.position); + if (this.position.character <= currentLine.firstNonWhitespaceCharacterIndex && this.position.line !== 0) { + let line = TextEditor.getLineAt(this.position.translate(-1)); + this.position = new vscode.Position(line.lineNumber, line.range.end.character); + return this; + } + + let nextPos = Motion.getPreviousWordPosition(this.position); + this.position = new vscode.Position(nextPos.line, nextPos.character); + + return this; + } + + public wordRight() : T { + if (this.position.character === this.getLineEnd().character) { + if (!TextEditor.isLastLine(this.position)) { + let line = TextEditor.getLineAt(this.position.translate(1)); + + this.position = new vscode.Position(line.lineNumber, line.firstNonWhitespaceCharacterIndex); + } + } else { + let nextPos = Motion.getNextWordPosition(this.position); + if (nextPos === null) { + return this.lineEnd(); + } + + this.position = new vscode.Position(nextPos.line, nextPos.character); + } + + return this; + } + + public lineBegin() : T { + this.position = new vscode.Position(this.position.line, 0); + return this; + } + + public lineEnd() : T { + this.position = this.getLineEnd(); + return this; + } + + public firstLineNonBlankChar() : T { + this.position = new vscode.Position(0, Motion.getFirstNonBlankCharAtLine(0)); + return this; + } + + public lastLineNonBlankChar() : T { + let line = vscode.window.activeTextEditor.document.lineCount - 1; + let character = Motion.getFirstNonBlankCharAtLine(line); + + this.position = new vscode.Position(line, character); + return this; + } + + public documentBegin() : T { + this.position = new vscode.Position(0, 0); + return this; + } + + public documentEnd() : T { + let lineCount = TextEditor.getLineCount(); + let line = lineCount > 0 ? lineCount - 1 : 0; + this.position = new vscode.Position(line, TextEditor.readLine(line).length); + return this; + } + + private isLineBeginning(position : vscode.Position) : boolean { + return position.character === 0; + } + + private isLineEnd(position : vscode.Position) : boolean { + let lineEndCharacter = this.maxLineLength(position.line); + + if (position.character > lineEndCharacter) { + throw new RangeError; + } + + return position.character === lineEndCharacter; + } + + private getLineEnd() : vscode.Position { + return new vscode.Position(this.position.line, this.maxLineLength(this.position.line)); + } + + private static getNextWordPosition(position : vscode.Position): vscode.Position { + let segments = ["(^[\t ]*$)"]; + segments.push(`([^\\s${_.escapeRegExp(Motion.nonWordCharacters) }]+)`); + segments.push(`[\\s${_.escapeRegExp(Motion.nonWordCharacters) }]+`); + + let reg = new RegExp(segments.join("|"), "g"); + let line = TextEditor.getLineAt(position); + let words = line.text.match(reg); + + let startWord: number; + let endWord: number; + + if (words) { + for (var index = 0; index < words.length; index++) { + var word = words[index].trim(); + if (word.length > 0) { + startWord = line.text.indexOf(word, endWord); + endWord = startWord + word.length; + + if (position.character < startWord) { + return new vscode.Position(position.line, startWord); + } + } + } + } + + return null; + } + + private static getPreviousWordPosition(position : vscode.Position): vscode.Position { + let segments = ["(^[\t ]*$)"]; + segments.push(`([^\\s${_.escapeRegExp(Motion.nonWordCharacters) }]+)`); + segments.push(`[\\s${_.escapeRegExp(Motion.nonWordCharacters) }]+`); + let reg = new RegExp(segments.join("|"), "g"); + + let line = TextEditor.getLineAt(position); + let words = line.text.match(reg); + + let startWord: number; + let endWord: number; + + if (words) { + words = words.reverse(); + endWord = line.range.end.character; + for (var index = 0; index < words.length; index++) { + endWord = endWord - words[index].length; + var word = words[index].trim(); + if (word.length > 0) { + startWord = line.text.indexOf(word, endWord); + + if (startWord !== -1 && position.character > startWord) { + return new vscode.Position(position.line, startWord); + } + } + } + } + + return null; + } + + private static getFirstNonBlankCharAtLine(line: number): number { + return TextEditor.readLine(line).match(/^\s*/)[0].length; + } +} + +export class Caret extends Motion { + // Valid Positions for Caret: [0, eol) + protected maxLineLength(line: number) : number { + var len = TextEditor.readLine(line).length; + return len > 0 ? len - 1 : len; + } + +} + +export class Cursor extends Motion { + // Valid Positions for Cursor: [0, eol] + protected maxLineLength(line: number) : number { + return TextEditor.readLine(line).length; + } + +} diff --git a/src/textEditor.ts b/src/textEditor.ts index d8dd86d10a0..52c7f4cc224 100644 --- a/src/textEditor.ts +++ b/src/textEditor.ts @@ -11,7 +11,14 @@ export default class TextEditor { }); } - static delete(range: vscode.Range) : Thenable { + static delete(range: vscode.Range = null) : Thenable { + if (range === null) { + let start = new vscode.Position(0, 0); + let lastLine = vscode.window.activeTextEditor.document.lineCount - 1; + let end = vscode.window.activeTextEditor.document.lineAt(lastLine).range.end; + + range = new vscode.Range(start, end); + } return vscode.window.activeTextEditor.edit((editBuilder) => { editBuilder.delete(range); }); @@ -40,8 +47,20 @@ export default class TextEditor { return vscode.window.activeTextEditor.document.lineAt(lineNo).text; } + static getLineCount() { + return vscode.window.activeTextEditor.document.lineCount; + } + static getLineAt(position: vscode.Position): vscode.TextLine { return vscode.window.activeTextEditor.document.lineAt(position); } + + static isFirstLine(position : vscode.Position) : boolean { + return position.line === 0; + } + + static isLastLine(position : vscode.Position): boolean { + return position.line === (vscode.window.activeTextEditor.document.lineCount - 1); + } } diff --git a/test/caret.test.ts b/test/caret.test.ts index 6f7b937a6a9..42ae8058d8d 100644 --- a/test/caret.test.ts +++ b/test/caret.test.ts @@ -1,7 +1,6 @@ import * as assert from 'assert'; -import * as vscode from 'vscode'; import TextEditor from './../src/textEditor'; -import Caret from './../src/cursor/caret'; +import {Caret} from './../src/motion/motion'; suite("caret", () => { let text: Array = [ @@ -15,19 +14,13 @@ suite("caret", () => { }); teardown(done => { - let range = new vscode.Range(Caret.documentBegin(), Caret.documentEnd()); - TextEditor.delete(range).then(() => done()); + TextEditor.delete().then(() => done()); }); - - test("right on right-most column should stay at the same location", () => { - Caret.move(new vscode.Position(0, 7)); - let current = Caret.currentPosition(); - assert.equal(current.line, 0); - assert.equal(current.character, 7); + test("right on right-most column should stay at the same location", () => { + let cursor = new Caret(0, 7).right(); - let right = Caret.right(); - assert.equal(right.line, 0); - assert.equal(right.character, 7); + assert.equal(cursor.position.line, 0); + assert.equal(cursor.position.character, 7); }); -}); \ No newline at end of file +}); diff --git a/test/cursor.test.ts b/test/cursor.test.ts index e146e39d522..c49e5ecbb0d 100644 --- a/test/cursor.test.ts +++ b/test/cursor.test.ts @@ -1,7 +1,8 @@ import * as assert from 'assert'; import * as vscode from 'vscode'; import TextEditor from './../src/textEditor'; -import Cursor from './../src/cursor/cursor'; +import {Cursor} from './../src/motion/motion'; + suite("cursor", () => { let text: Array = [ @@ -15,256 +16,225 @@ suite("cursor", () => { }); teardown(done => { - let range = new vscode.Range(Cursor.documentBegin(), Cursor.documentEnd()); - TextEditor.delete(range).then(() => done()); + TextEditor.delete().then(() => done()); }); test("left should move cursor one column left", () => { - Cursor.move(new vscode.Position(0, 5)); + let cursor = new Cursor(0, 5); + assert.equal(cursor.position.line, 0); + assert.equal(cursor.position.character, 5); + + let left = cursor.left(); + assert.equal(left.position.line, 0); + assert.equal(left.position.character, 4); - let current = Cursor.currentPosition(); - assert.equal(current.line, 0); - assert.equal(current.character, 5); + let moveLeft = left.move(); + assert.equal(moveLeft.position.line, 0); + assert.equal(moveLeft.position.character, 4); - let left = Cursor.left(); - assert.equal(left.line, 0); - assert.equal(left.character, 4); + let curPos = Cursor.getActualPosition(); + assert.equal(moveLeft.position.line, curPos.line); + assert.equal(moveLeft.position.character, curPos.character); }); test("left on left-most column should stay at the same location", () => { - Cursor.move(new vscode.Position(0, 0)); + let cursor = new Cursor(0, 0); + assert.equal(cursor.position.line, 0); + assert.equal(cursor.position.character, 0); + + let left = cursor.left(); + assert.equal(left.position.line, 0); + assert.equal(left.position.character, 0); - let current = Cursor.currentPosition(); - assert.equal(current.line, 0); - assert.equal(current.character, 0); + let moveLeft = left.move(); + assert.equal(moveLeft.position.line, 0); + assert.equal(moveLeft.position.character, 0); - let left = Cursor.left(); - assert.equal(left.line, 0); - assert.equal(left.character, 0); + let curPos = Cursor.getActualPosition(); + assert.equal(moveLeft.position.line, curPos.line); + assert.equal(moveLeft.position.character, curPos.character); }); test("right should move cursor one column right", () => { - Cursor.move(new vscode.Position(0, 5)); + let cursor = new Cursor(0, 5); + assert.equal(cursor.position.line, 0); + assert.equal(cursor.position.character, 5); - let current = Cursor.currentPosition(); - assert.equal(current.line, 0); - assert.equal(current.character, 5); + let next = cursor.right(); + assert.equal(next.position.line, 0); + assert.equal(next.position.character, 6); - let right = Cursor.right(); - assert.equal(right.line, 0); - assert.equal(right.character, 6); - }); + next = next.move(); + assert.equal(next.position.line, 0); + assert.equal(next.position.character, 6); - test("right on right-most column should NOT stay at the same location", () => { - Cursor.move(new vscode.Position(0, 7)); + let curPos = Cursor.getActualPosition(); + assert.equal(next.position.line, curPos.line); + assert.equal(next.position.character, curPos.character); + }); - let current = Cursor.currentPosition(); - assert.equal(current.line, 0); - assert.equal(current.character, 7); + test("right on right-most column should stay at the same location", () => { + let cursor = new Cursor(0, 8).right(); - let right = Cursor.right(); - assert.equal(right.line, 0); - assert.notEqual(right.character, 7); + assert.equal(cursor.position.line, 0); + assert.equal(cursor.position.character, 8); }); test("down should move cursor one line down", () => { - Cursor.move(new vscode.Position(1, 0)); + let cursor = new Cursor(1, 1); + assert.equal(cursor.position.line, 1); + assert.equal(cursor.position.character, 1); - let current = Cursor.currentPosition(); - assert.equal(current.line, 1); - assert.equal(current.character, 0); + let next = cursor.down(); + assert.equal(next.position.line, 2); + assert.equal(next.position.character, 1); - let down = Cursor.down(); - assert.equal(down.line, 2); - assert.equal(down.character, 0); + next = next.move(); + assert.equal(next.position.line, 2); + assert.equal(next.position.character, 1); + + let curPos = Cursor.getActualPosition(); + assert.equal(next.position.line, curPos.line); + assert.equal(next.position.character, curPos.character); }); test("down on bottom-most line should stay at the same location", () => { - Cursor.move(new vscode.Position(2, 0)); + let cursor = new Cursor(2, 0); + assert.equal(cursor.position.line, 2); + assert.equal(cursor.position.character, 0); + + let next = cursor.down(); + assert.equal(next.position.line, 2); + assert.equal(next.position.character, 0); - let current = Cursor.currentPosition(); - assert.equal(current.line, 2); - assert.equal(current.character, 0); + next = next.move(); + assert.equal(next.position.line, 2); + assert.equal(next.position.character, 0); - let down = Cursor.down(); - assert.equal(down.line, 2); - assert.equal(down.character, 0); + let curPos = Cursor.getActualPosition(); + assert.equal(next.position.line, curPos.line); + assert.equal(next.position.character, curPos.character); }); test("up should move cursor one line up", () => { - Cursor.move(new vscode.Position(1, 0)); + let cursor = new Cursor(1, 1); + assert.equal(cursor.position.line, 1); + assert.equal(cursor.position.character, 1); + + let next = cursor.up(); + assert.equal(next.position.line, 0); + assert.equal(next.position.character, 1); - let current = Cursor.currentPosition(); - assert.equal(current.line, 1); - assert.equal(current.character, 0); + next = next.move(); + assert.equal(next.position.line, 0); + assert.equal(next.position.character, 1); - let up = Cursor.up(); - assert.equal(up.line, 0); - assert.equal(up.character, 0); + let curPos = Cursor.getActualPosition(); + assert.equal(next.position.line, curPos.line); + assert.equal(next.position.character, curPos.character); }); test("up on top-most line should stay at the same location", () => { - Cursor.move(new vscode.Position(0, 0)); + let cursor = new Cursor(0, 1); + assert.equal(cursor.position.line, 0); + assert.equal(cursor.position.character, 1); - let current = Cursor.currentPosition(); - assert.equal(current.line, 0); - assert.equal(current.character, 0); + let next = cursor.up(); + assert.equal(next.position.line, 0); + assert.equal(next.position.character, 1); - let up = Cursor.up(); - assert.equal(up.line, 0); - assert.equal(up.character, 0); + next = next.move(); + assert.equal(next.position.line, 0); + assert.equal(next.position.character, 1); + + let curPos = Cursor.getActualPosition(); + assert.equal(next.position.line, curPos.line); + assert.equal(next.position.character, curPos.character); }); test("keep same column as up/down", () => { - Cursor.move(new vscode.Position(0, 0)); - Cursor.move(Cursor.right()); - Cursor.move(Cursor.right()); - - let current = Cursor.currentPosition(); - assert.equal(current.line, 0); - assert.equal(current.character, 2); + let cursor = new Cursor(0, 2).down(); - Cursor.move(Cursor.down()); + assert.equal(cursor.position.line, 1); + assert.equal(cursor.position.character, 0); - current = Cursor.currentPosition(); - assert.equal(current.line, 1); - assert.equal(current.character, 0); - - Cursor.move(Cursor.down()); - - current = Cursor.currentPosition(); - assert.equal(current.line, 2); - assert.equal(current.character, 2); + cursor = cursor.down(); + assert.equal(cursor.position.line, 2); + assert.equal(cursor.position.character, 2); }); test("get line begin cursor", () => { - Cursor.move(new vscode.Position(0, 0)); - - let pos = Cursor.lineBegin(); - - assert.equal(pos.line, 0); - assert.equal(pos.character, 0); - - Cursor.move(Cursor.down()); - - pos = Cursor.lineBegin(); - - assert.equal(pos.line, 1); - assert.equal(pos.character, 0); + let cursor = new Cursor(0, 2).lineBegin(); + assert.equal(cursor.position.line, 0); + assert.equal(cursor.position.character, 0); }); test("get line end cursor", () => { - Cursor.move(new vscode.Position(0, 0)); - - let pos = Cursor.lineEnd(); - - assert.equal(pos.line, 0); - assert.equal(pos.character, text[0].length); - - Cursor.move(Cursor.down()); + let cursor = new Cursor(0, 0).lineEnd(); + assert.equal(cursor.position.line, 0); + assert.equal(cursor.position.character, text[0].length); - pos = Cursor.lineEnd(); - - assert.equal(pos.line, 1); - assert.equal(pos.character, text[1].length); + cursor = new Cursor(2, 0).lineEnd(); + assert.equal(cursor.position.line, 2); + assert.equal(cursor.position.character, text[2].length); }); test("get document begin cursor", () => { - var cursor = Cursor.documentBegin(); - - assert.equal(cursor.line, 0); - assert.equal(cursor.character, 0); + let cursor = new Cursor(1, 1).documentBegin(); + assert.equal(cursor.position.line, 0); + assert.equal(cursor.position.character, 0); }); test("get document end cursor", () => { - var cursor = Cursor.documentEnd(); - - assert.equal(cursor.line, 2); - assert.equal(cursor.character, text[2].length); + let cursor = new Cursor(1, 1).documentEnd(); + assert.equal(cursor.position.line, text.length - 1); + assert.equal(cursor.position.character, text[text.length - 1].length); }); test("wordRight should move cursor word right", () => { - Cursor.move(new vscode.Position(0, 0)); - - let current = Cursor.currentPosition(); - assert.equal(current.line, 0); - assert.equal(current.character, 0); - - var wordRight = Cursor.wordRight(); - assert.equal(wordRight.line, 0); - assert.equal(wordRight.character, 5); + let cursor = new Cursor(0, 0).wordRight(); + assert.equal(cursor.position.line, 0); + assert.equal(cursor.position.character, 5); }); test("wordLeft should move cursor word left", () => { - Cursor.move(new vscode.Position(0, 3)); - - let current = Cursor.currentPosition(); - assert.equal(current.line, 0); - assert.equal(current.character, 3); - - var wordLeft = Cursor.wordLeft(); - assert.equal(wordLeft.line, 0); - assert.equal(wordLeft.character, 0); + let cursor = new Cursor(0, 3).wordLeft(); + assert.equal(cursor.position.line, 0); + assert.equal(cursor.position.character, 0); }); test("wordRight on last word should stay on line at last character", () => { - Cursor.move(new vscode.Position(0, 6)); - - let current = Cursor.currentPosition(); - assert.equal(current.line, 0); - assert.equal(current.character, 6); - - var pos = Cursor.wordRight(); - assert.equal(pos.line, 0); - assert.equal(pos.character, 8); + let cursor = new Cursor(0, 6).wordRight(); + assert.equal(cursor.position.line, 0); + assert.equal(cursor.position.character, 8); }); test("wordRight on end of line should move to next word on next line", () => { - Cursor.move(new vscode.Position(0, 8)); - - let current = Cursor.currentPosition(); - assert.equal(current.line, 0); - assert.equal(current.character, 8); - - var pos = Cursor.wordRight(); - assert.equal(pos.line, 1); - assert.equal(pos.character, 0); + let cursor = new Cursor(0, 8).wordRight(); + assert.equal(cursor.position.line, 1); + assert.equal(cursor.position.character, 0); }); test("wordLeft on first word should move to previous line of end of line", () => { - Cursor.move(new vscode.Position(2, 0)); - - let current = Cursor.currentPosition(); - assert.equal(current.line, 2); - assert.equal(current.character, 0); - - var pos = Cursor.wordLeft(); - assert.equal(pos.line, 1); - assert.equal(pos.character, 1); + let cursor = new Cursor(2, 0).wordLeft(); + assert.equal(cursor.position.line, 1); + assert.equal(cursor.position.character, 1); }); - test("get first line begin cursor on first non-blank character", () => { - let cursor = Cursor.firstLineNonBlankChar(); - - assert.equal(cursor.line, 0); - assert.equal(cursor.character, 0); - + test("get first line begin cursor on first non-blank character", (done) => { TextEditor.insert(" ", new vscode.Position(0, 0)).then(() => { - assert.equal(cursor.line, 0); - assert.equal(cursor.character, 2); - }); - }); - - test("get last line begin cursor on first non-blank character", () => { - let cursor = Cursor.lastLineNonBlankChar(); - - assert.equal(cursor.line, 2); - assert.equal(cursor.character, 0); - - let line = Cursor.documentEnd().line; - TextEditor.insert(" ", new vscode.Position(line, 0)).then(() => { - assert.equal(cursor.line, 2); - assert.equal(cursor.character, 2); - }); + let cursor = new Cursor(0, 0).firstLineNonBlankChar(); + assert.equal(cursor.position.line, 0); + assert.equal(cursor.position.character, 2); + }).then(done, done); + }); + + test("get last line begin cursor on first non-blank character", (done) => { + let lastLine = new Cursor().documentEnd().position.line; + TextEditor.insert(" ", new vscode.Position(lastLine, 0)).then(() => { + let cursor = new Cursor(0, 0).lastLineNonBlankChar(); + assert.equal(cursor.position.line, lastLine); + assert.equal(cursor.position.character, 2); + }).then(done, done); }); }); diff --git a/test/mode/modeInsert.test.ts b/test/mode/modeInsert.test.ts index 6b0d84660fd..01b5591e5a8 100644 --- a/test/mode/modeInsert.test.ts +++ b/test/mode/modeInsert.test.ts @@ -2,28 +2,21 @@ import * as assert from 'assert'; import ModeInsert from '../../src/mode/modeInsert'; import {ModeName} from '../../src/mode/mode'; -import Cursor from '../../src/cursor/cursor'; +import {Cursor} from '../../src/motion/motion'; import TextEditor from '../../src/textEditor'; - import * as testUtils from '../testUtils'; -import * as vscode from 'vscode'; - let modeHandler: ModeInsert = null; suite("Mode Insert", () => { setup((done) => { modeHandler = new ModeInsert(); - - testUtils.clearTextEditor() - .then(done); + TextEditor.delete().then(() => done()); }); teardown((done) => { modeHandler = null; - - testUtils.clearTextEditor() - .then(done); + TextEditor.delete().then(() => done()); }); test("can be activated", () => { @@ -41,7 +34,7 @@ suite("Mode Insert", () => { modeHandler.HandleKeyEvent("!") .then(() => { return testUtils.assertTextEditorText(expected); - }).then(done); + }).then(done, done); }); test("Can handle 'o'", (done) => { @@ -52,7 +45,7 @@ suite("Mode Insert", () => { return modeHandler.HandleActivation("o"); }).then(() => { return testUtils.assertTextEditorText(expected); - }).then(done); + }).then(done, done); }); test("Can handle 'O'", (done) => { @@ -63,7 +56,7 @@ suite("Mode Insert", () => { return modeHandler.HandleActivation("O"); }).then(() => { return testUtils.assertTextEditorText(expected); - }).then(done); + }).then(done, done); }); test("Can handle 'i'", (done) => { @@ -71,14 +64,14 @@ suite("Mode Insert", () => { TextEditor.insert("texttext") .then(() => { - Cursor.move(new vscode.Position(0, 4)); + new Cursor(0, 4).move(); }).then(() => { return modeHandler.HandleActivation("i"); }).then(() => { return modeHandler.HandleKeyEvent("!"); }).then(() => { return testUtils.assertTextEditorText(expected); - }).then(done); + }).then(done, done); }); test("Can handle 'I'", (done) => { @@ -86,14 +79,14 @@ suite("Mode Insert", () => { TextEditor.insert("text") .then(() => { - Cursor.move(new vscode.Position(0, 4)); + new Cursor(0, 4).move(); }).then(() => { return modeHandler.HandleActivation("I"); }).then(() => { return modeHandler.HandleKeyEvent("!"); }).then(() => { return testUtils.assertTextEditorText(expected); - }).then(done); + }).then(done, done); }); test("Can handle 'a'", (done) => { @@ -101,14 +94,14 @@ suite("Mode Insert", () => { TextEditor.insert("texttext") .then(() => { - Cursor.move(new vscode.Position(0, 4)); + new Cursor(0, 4).move(); }).then(() => { return modeHandler.HandleActivation("a"); }).then(() => { return modeHandler.HandleKeyEvent("!"); }).then(() => { return testUtils.assertTextEditorText(expected); - }).then(done); + }).then(done, done); }); test("Can handle 'A'", (done) => { @@ -116,13 +109,13 @@ suite("Mode Insert", () => { TextEditor.insert("text") .then(() => { - Cursor.move(new vscode.Position(0, 0)); + new Cursor(0, 0).move(); }).then(() => { return modeHandler.HandleActivation("A"); }).then(() => { return modeHandler.HandleKeyEvent("!"); }).then(() => { return testUtils.assertTextEditorText(expected); - }).then(done); + }).then(done, done); }); }); diff --git a/test/testUtils.ts b/test/testUtils.ts index 155e63944a7..da82d6fe826 100644 --- a/test/testUtils.ts +++ b/test/testUtils.ts @@ -1,15 +1,6 @@ -import * as vscode from 'vscode'; import TextEditor from '../src/textEditor'; -import Cursor from '../src/cursor/cursor'; import * as assert from 'assert'; -export function clearTextEditor(): Thenable { - let range = new vscode.Range(Cursor.documentBegin(), Cursor.documentEnd()); - return TextEditor.delete(range).then(() => { - return; - }); -} - export function assertTextEditorText(expected: string, lineNo?: number) { let actual: string; if (isNaN(lineNo) || typeof lineNo === 'undefined') { diff --git a/test/textEditor.test.ts b/test/textEditor.test.ts index fcdcc2fda9c..81112ba959b 100644 --- a/test/textEditor.test.ts +++ b/test/textEditor.test.ts @@ -1,19 +1,14 @@ import * as assert from 'assert'; import * as vscode from 'vscode'; import TextEditor from './../src/textEditor'; -import Cursor from './../src/cursor/cursor'; - -import * as testUtils from './testUtils'; suite("text editor", () => { suiteSetup(done => { - testUtils.clearTextEditor() - .then(done); + TextEditor.delete().then(() => done()); }); suiteTeardown(done => { - testUtils.clearTextEditor() - .then(done); + TextEditor.delete().then(() => done()); }); test("insert 'Hello World'", done => { @@ -44,7 +39,7 @@ suite("text editor", () => { assert.equal(vscode.window.activeTextEditor.document.lineCount, 1); var end = new vscode.Position(0, 5); - var range = new vscode.Range(Cursor.documentBegin(), end); + var range = new vscode.Range(new vscode.Position(0, 0), end); TextEditor.delete(range).then( x => { let actualText = TextEditor.readLine(0);