From 2984752b8d145e4405ca0485f3bf88ef21cbecc9 Mon Sep 17 00:00:00 2001 From: johnfn Date: Sat, 6 Feb 2016 22:37:46 -0800 Subject: [PATCH] Convert to ES6, Promises, async and await. --- .vscode/launch.json | 2 + extension.ts | 8 +- src/action/deleteAction.ts | 18 ++-- src/cmd_line/commands/quit.ts | 4 +- src/cmd_line/commands/write.ts | 4 +- src/cmd_line/lexer.ts | 2 + src/cmd_line/main.ts | 15 ++- src/cmd_line/node.ts | 2 + src/cmd_line/parser.ts | 2 + src/cmd_line/scanner.ts | 5 +- src/cmd_line/subparser.ts | 2 + src/cmd_line/subparsers/quit.ts | 4 +- src/cmd_line/subparsers/write.ts | 6 +- src/cmd_line/token.ts | 2 + src/configuration.ts | 4 +- src/error.ts | 2 + src/keyboard.ts | 2 + src/mode/mode.ts | 22 +++-- src/mode/modeHandler.ts | 45 +++++---- src/mode/modeInsert.ts | 50 +++++----- src/mode/modeNormal.ts | 93 +++++++++--------- src/motion/motion.ts | 14 ++- src/motion/position.ts | 15 +-- src/textEditor.ts | 51 ++++++---- src/util.ts | 6 +- test/cmd_line/lexer.test.ts | 2 + test/cmd_line/parser.test.ts | 2 + test/cmd_line/scanner.test.ts | 6 +- test/cmd_line/subparser.quit.test.ts | 2 + test/cmd_line/subparser.test.ts | 2 + test/error.test.ts | 2 + test/extension.test.ts | 22 ++--- test/index.ts | 2 + test/keyboard.test.ts | 2 + test/mode/modeHandler.test.ts | 12 ++- test/mode/modeInsert.test.ts | 142 +++++++++++---------------- test/mode/modeNormal.test.ts | 10 +- test/motion.test.ts | 79 +++++++-------- test/testUtils.ts | 44 ++++----- test/textEditor.test.ts | 55 +++++------ tsconfig.json | 2 +- 41 files changed, 414 insertions(+), 352 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 08869ac8b5d..213356475a9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,6 +8,7 @@ "request": "launch", "runtimeExecutable": "${execPath}", "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], + // "runtimeArgs": ["--harmony-default-parameters", "--harmony-rest-parameters"], "stopOnEntry": false, "sourceMaps": true, "outDir": "out/src", @@ -19,6 +20,7 @@ "request": "launch", "runtimeExecutable": "${execPath}", "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ], + // "runtimeArgs": ["--js-flags=\"--harmony --harmony-default-parameters\""], "stopOnEntry": false, "sourceMaps": true, "outDir": "out/test", diff --git a/extension.ts b/extension.ts index 9182fe834ad..2d905e56337 100644 --- a/extension.ts +++ b/extension.ts @@ -1,10 +1,12 @@ +"use strict" + // The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below import * as vscode from 'vscode'; import {showCmdLine} from './src/cmd_line/main'; import * as cc from './src/cmd_line/lexer'; -import ModeHandler from "./src/mode/modeHandler"; +import {ModeHandler} from "./src/mode/modeHandler"; import {ModeName} from "./src/mode/mode"; var modeHandler : ModeHandler; @@ -15,7 +17,7 @@ export function activate(context: vscode.ExtensionContext) { extensionContext = context; - registerCommand(context, 'extension.showCmdLine', () => showCmdLine()); + registerCommand(context, 'extension.showCmdLine', () => showCmdLine("")); registerCommand(context, 'extension.vim_esc', () => handleKeyEvent("esc")); registerCommand(context, 'extension.vim_colon', () => handleKeyEvent(":")); @@ -107,7 +109,7 @@ export function activate(context: vscode.ExtensionContext) { } function registerCommand(context: vscode.ExtensionContext, command: string, callback: (...args: any[]) => any) { - let disposable = vscode.commands.registerCommand(command, callback); + let disposable = vscode.commands.registerCommand(command, callback); context.subscriptions.push(disposable); } diff --git a/src/action/deleteAction.ts b/src/action/deleteAction.ts index 68f3ea92713..20bf02d7b8c 100644 --- a/src/action/deleteAction.ts +++ b/src/action/deleteAction.ts @@ -1,17 +1,19 @@ +"use strict"; + import * as vscode from 'vscode'; -import TextEditor from './../textEditor'; +import {TextEditor} from './../textEditor'; import {Motion} from './../motion/motion'; export class DeleteAction { - public static Character(motion : Motion) : Thenable { + public static async Character(motion : Motion): Promise { let start = motion.position; - let end = start.translate(0, 1); + let end = start.translate(0, 1); let range = new vscode.Range(start, end); - return TextEditor.delete(range).then(() => { - if (motion.position.isLineEnd()) { - return motion.left().move(); - } - }); + await TextEditor.delete(range); + + if (motion.position.isLineEnd()) { + return motion.left().move(); + } } } \ No newline at end of file diff --git a/src/cmd_line/commands/quit.ts b/src/cmd_line/commands/quit.ts index 2328f107684..151b3507e92 100644 --- a/src/cmd_line/commands/quit.ts +++ b/src/cmd_line/commands/quit.ts @@ -1,3 +1,5 @@ +"use strict"; + import vscode = require('vscode'); import node = require('../node'); @@ -15,7 +17,7 @@ export interface QuitCommandArguments extends node.CommandArgs { export class QuitCommand extends node.CommandBase { protected _arguments : QuitCommandArguments; - constructor(args : QuitCommandArguments = {}) { + constructor(args : QuitCommandArguments) { super(); this._name = 'quit'; this._shortName = 'q'; diff --git a/src/cmd_line/commands/write.ts b/src/cmd_line/commands/write.ts index 5f2d4ed1252..971b1f2c826 100644 --- a/src/cmd_line/commands/write.ts +++ b/src/cmd_line/commands/write.ts @@ -1,3 +1,5 @@ +"use strict"; + // XXX: use graceful-fs ?? import fs = require('fs'); @@ -22,7 +24,7 @@ export interface WriteCommandArguments extends node.CommandArgs { export class WriteCommand extends node.CommandBase { protected _arguments : WriteCommandArguments; - constructor(args : WriteCommandArguments = {}) { + constructor(args : WriteCommandArguments) { super(); this._name = 'write'; this._shortName = 'w'; diff --git a/src/cmd_line/lexer.ts b/src/cmd_line/lexer.ts index 896063c722d..9ba02c2ecaf 100644 --- a/src/cmd_line/lexer.ts +++ b/src/cmd_line/lexer.ts @@ -1,3 +1,5 @@ +"use strict"; + import {Scanner} from "./scanner"; import {Token, TokenType} from "./token"; diff --git a/src/cmd_line/main.ts b/src/cmd_line/main.ts index 77beed40dae..3b6e8e458be 100644 --- a/src/cmd_line/main.ts +++ b/src/cmd_line/main.ts @@ -1,9 +1,11 @@ +"use strict"; + import * as vscode from "vscode"; import * as parser from "./parser"; import * as util from "../util"; // Shows the vim command line. -export function showCmdLine(initialText = "") : Thenable<{}> { +export async function showCmdLine(initialText: string): Promise<{}> { if (!vscode.window.activeTextEditor) { return util.showInfo("No active document."); } @@ -13,10 +15,13 @@ export function showCmdLine(initialText = "") : Thenable<{}> { value: initialText }; - return vscode.window.showInputBox(options).then( - runCmdLine, - vscode.window.showErrorMessage - ); + try { + runCmdLine(await vscode.window.showInputBox(options)); + } catch (e) { + vscode.window.showErrorMessage(e.toString()); + + return; + } } function runCmdLine(s : string) : void { diff --git a/src/cmd_line/node.ts b/src/cmd_line/node.ts index f3ac0b17f40..0f5e6807ebc 100644 --- a/src/cmd_line/node.ts +++ b/src/cmd_line/node.ts @@ -1,3 +1,5 @@ +"use strict"; + import * as vscode from "vscode"; import * as token from "./token"; diff --git a/src/cmd_line/parser.ts b/src/cmd_line/parser.ts index d765072cada..708b1070559 100644 --- a/src/cmd_line/parser.ts +++ b/src/cmd_line/parser.ts @@ -1,3 +1,5 @@ +"use strict"; + import * as token from './token'; import * as node from './node'; import * as lexer from './lexer'; diff --git a/src/cmd_line/scanner.ts b/src/cmd_line/scanner.ts index 76e24654919..cea8d109d3d 100644 --- a/src/cmd_line/scanner.ts +++ b/src/cmd_line/scanner.ts @@ -1,3 +1,4 @@ +"use strict"; // Provides state and behavior to scan an input string character by character. export class Scanner { @@ -59,7 +60,7 @@ export class Scanner { } // skips text while any of chars matches and ignores the text span - skipRun(...chars : string[]) : void { + skipRun(chars : string[]) : void { if (this.isAtEof) { return; } @@ -98,7 +99,7 @@ export class Scanner { this.pos += value.length; } - expectOneOf(...values : string[]) : void { + expectOneOf(values : string[]) : void { let match = values.filter(s => this.input.substr(this.pos).startsWith(s)); if (match.length !== 1) { if (match.length > 1) { diff --git a/src/cmd_line/subparser.ts b/src/cmd_line/subparser.ts index aee6923c5e8..e14a95b85b5 100644 --- a/src/cmd_line/subparser.ts +++ b/src/cmd_line/subparser.ts @@ -1,3 +1,5 @@ +"use strict"; + import {parseQuitCommandArgs} from './subparsers/quit'; import {parseWriteCommandArgs} from './subparsers/write'; diff --git a/src/cmd_line/subparsers/quit.ts b/src/cmd_line/subparsers/quit.ts index 81c1a6b3e93..e12b67ef169 100644 --- a/src/cmd_line/subparsers/quit.ts +++ b/src/cmd_line/subparsers/quit.ts @@ -1,10 +1,12 @@ +"use strict"; + import * as node from "../commands/quit"; import {Scanner} from '../scanner'; import {VimError, ErrorCode} from '../../error'; export function parseQuitCommandArgs(args : string) : node.QuitCommand { if (!args) { - return new node.QuitCommand(); + return new node.QuitCommand({}); } var scannedArgs : node.QuitCommandArguments = {}; var scanner = new Scanner(args); diff --git a/src/cmd_line/subparsers/write.ts b/src/cmd_line/subparsers/write.ts index 8da2686f0c7..b40c1502c77 100644 --- a/src/cmd_line/subparsers/write.ts +++ b/src/cmd_line/subparsers/write.ts @@ -1,9 +1,11 @@ +"use strict"; + import {WriteCommand, WriteCommandArguments} from '../commands/write'; import {Scanner} from '../scanner'; export function parseWriteCommandArgs(args : string) : WriteCommand { if (!args) { - return new WriteCommand(); + return new WriteCommand({}); } var scannedArgs : WriteCommandArguments = {}; var scanner = new Scanner(args); @@ -33,7 +35,7 @@ export function parseWriteCommandArgs(args : string) : WriteCommand { // :write ++opt=value scanner.expect('+'); scanner.ignore(); - scanner.expectOneOf('bin', 'nobin', 'ff', 'enc'); + scanner.expectOneOf(['bin', 'nobin', 'ff', 'enc']); scannedArgs.opt = scanner.emit(); scanner.expect('='); scanner.ignore(); diff --git a/src/cmd_line/token.ts b/src/cmd_line/token.ts index 6df351fe9d9..d1f1e1bc395 100644 --- a/src/cmd_line/token.ts +++ b/src/cmd_line/token.ts @@ -1,3 +1,5 @@ +"use strict"; + // Tokens for the Vim command line. export enum TokenType { diff --git a/src/configuration.ts b/src/configuration.ts index 15d371206cc..38c75501f9f 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -1,6 +1,8 @@ +"use strict"; + import {KeyboardLayout} from "./keyboard"; -export default class Configuration { +export class Configuration { keyboardLayout : KeyboardLayout; diff --git a/src/error.ts b/src/error.ts index d4a3daf3afa..2fb868dd000 100644 --- a/src/error.ts +++ b/src/error.ts @@ -1,3 +1,5 @@ +"use strict"; + import * as util from "./util"; interface VimErrors { diff --git a/src/keyboard.ts b/src/keyboard.ts index 62cb7f47bff..5fb9c5a2061 100644 --- a/src/keyboard.ts +++ b/src/keyboard.ts @@ -1,3 +1,5 @@ +"use strict"; + import * as vscode from "vscode"; export class KeyboardLayout { diff --git a/src/mode/mode.ts b/src/mode/mode.ts index 98003ca3aef..4e06b5b2a8d 100644 --- a/src/mode/mode.ts +++ b/src/mode/mode.ts @@ -1,3 +1,5 @@ +"use strict"; + import {Motion} from './../motion/motion'; export enum ModeName { @@ -12,40 +14,40 @@ export abstract class Mode { private _motion : Motion; protected keyHistory : string[]; - constructor(name: ModeName, motion : Motion) { + constructor(name: ModeName, motion: Motion) { this._name = name; this._motion = motion; this._isActive = false; this.keyHistory = []; } - get Name(): ModeName { + get name(): ModeName { return this._name; } - get Motion() : Motion { + get motion() : Motion { return this._motion; } - set Motion(val : Motion) { + set motion(val : Motion) { this._motion = val; } - get IsActive() : boolean { + get isActive() : boolean { return this._isActive; } - set IsActive(val : boolean) { + set isActive(val : boolean) { this._isActive = val; } - public HandleDeactivation() : void { + public handleDeactivation() : void { this.keyHistory = []; } - abstract ShouldBeActivated(key : string, currentMode : ModeName) : boolean; + abstract shouldBeActivated(key : string, currentMode : ModeName) : boolean; - abstract HandleActivation(key : string) : Thenable<{}>; + abstract handleActivation(key : string) : Promise<{}>; - abstract HandleKeyEvent(key : string) : Thenable<{}>; + abstract handleKeyEvent(key : string) : Promise<{}>; } \ No newline at end of file diff --git a/src/mode/modeHandler.ts b/src/mode/modeHandler.ts index 50245667726..3dc19d42e07 100644 --- a/src/mode/modeHandler.ts +++ b/src/mode/modeHandler.ts @@ -1,13 +1,15 @@ +"use strict"; + import * as _ from 'lodash'; 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 Configuration from '../configuration'; +import {NormalMode} from './modeNormal'; +import {InsertMode} from './modeInsert'; +import {Configuration} from '../configuration'; -export default class ModeHandler implements vscode.Disposable { +export class ModeHandler implements vscode.Disposable { private _motion : Motion; private _modes : Mode[]; private _statusBarItem : vscode.StatusBarItem; @@ -16,7 +18,7 @@ export default class ModeHandler implements vscode.Disposable { constructor() { this._configuration = Configuration.fromUserFile(); - this._motion = new Motion(); + this._motion = new Motion(null); this._modes = [ new NormalMode(this._motion), new InsertMode(this._motion), @@ -27,7 +29,7 @@ export default class ModeHandler implements vscode.Disposable { get currentMode() : Mode { let currentMode = this._modes.find((mode, index) => { - return mode.IsActive; + return mode.isActive; }); return currentMode; @@ -35,7 +37,7 @@ export default class ModeHandler implements vscode.Disposable { setCurrentModeByName(modeName : ModeName) { this._modes.forEach(mode => { - mode.IsActive = (mode.Name === modeName); + mode.isActive = (mode.name === modeName); }); switch (modeName) { @@ -48,7 +50,7 @@ export default class ModeHandler implements vscode.Disposable { break; } - let statusBarText = (this.currentMode.Name === ModeName.Normal) ? '' : ModeName[modeName]; + const statusBarText = (this.currentMode.name === ModeName.Normal) ? '' : ModeName[modeName]; this.setupStatusBarItem(statusBarText.toUpperCase()); } @@ -58,24 +60,27 @@ export default class ModeHandler implements vscode.Disposable { // https://github.com/Microsoft/vscode/issues/713 key = this._configuration.keyboardLayout.translate(key); - let currentModeName = this.currentMode.Name; + let currentModeName = this.currentMode.name; let nextMode : Mode; - let inactiveModes = _.filter(this._modes, (m) => !m.IsActive); + let inactiveModes = _.filter(this._modes, (m) => !m.isActive); - _.forEach(inactiveModes, (m, i) => { - if (m.ShouldBeActivated(key, currentModeName)) { - nextMode = m; + for (let mode of inactiveModes) { + if (mode.shouldBeActivated(key, currentModeName)) { + if (nextMode) { + console.error("More that one mode matched in handleKeyEvent!"); } - }); - if (nextMode) { - this.currentMode.HandleDeactivation(); - this.setCurrentModeByName(nextMode.Name); - nextMode.HandleActivation(key); - return; + nextMode = mode; + } } - this.currentMode.HandleKeyEvent(key); + if (nextMode) { + this.currentMode.handleDeactivation(); + this.setCurrentModeByName(nextMode.name); + nextMode.handleActivation(key); + } else { + this.currentMode.handleKeyEvent(key); + } } private setupStatusBarItem(text : string) : void { diff --git a/src/mode/modeInsert.ts b/src/mode/modeInsert.ts index e12edb98723..5aefd59c18f 100644 --- a/src/mode/modeInsert.ts +++ b/src/mode/modeInsert.ts @@ -1,34 +1,36 @@ +"use strict"; + import * as vscode from 'vscode'; import {ModeName, Mode} from './mode'; -import TextEditor from './../textEditor'; +import {TextEditor} from './../textEditor'; import {Motion} from './../motion/motion'; -export default class InsertMode extends Mode { - private activationKeyHandler : { [ key : string] : (motion : Motion) => Thenable<{}> } = { - "i" : () => { +export class InsertMode extends Mode { + private activationKeyHandler : { [ key : string] : (motion : Motion) => Promise<{}> } = { + "i" : async () => { // insert at cursor - return Promise.resolve({}); + return {}; }, - "I" : c => { + "I" : async (c) => { // insert at line beginning - return Promise.resolve(c.lineBegin().move()); + return c.lineBegin().move(); }, - "a" : c => { + "a" : async (c) => { // append after the cursor - return Promise.resolve(c.right().move()); + return c.right().move(); }, - "A" : c => { + "A" : async (c) => { // append at the end of the line - return Promise.resolve(c.lineEnd().move()); + return c.lineEnd().move(); }, - "o" : () => { + "o" : async () => { // open blank line below current line - return vscode.commands.executeCommand("editor.action.insertLineAfter"); + return await vscode.commands.executeCommand("editor.action.insertLineAfter"); }, - "O" : () => { + "O" : async () => { // open blank line above current line - return vscode.commands.executeCommand("editor.action.insertLineBefore"); + return await vscode.commands.executeCommand("editor.action.insertLineBefore"); } }; @@ -36,27 +38,25 @@ export default class InsertMode extends Mode { super(ModeName.Insert, motion); } - ShouldBeActivated(key : string, currentMode : ModeName) : boolean { + shouldBeActivated(key : string, currentMode : ModeName) : boolean { return key in this.activationKeyHandler; } - HandleActivation(key : string) : Thenable<{}> { - return this.activationKeyHandler[key](this.Motion); + handleActivation(key : string) : Promise<{}> { + return this.activationKeyHandler[key](this.motion); } - HandleKeyEvent(key : string) : Thenable<{}> { + async handleKeyEvent(key : string) : Promise<{}> { this.keyHistory.push(key); - return TextEditor - .insert(this.ResolveKeyValue(key)) - .then(() => { - return vscode.commands.executeCommand("editor.action.triggerSuggest"); - }); + await TextEditor.insert(this.resolveKeyValue(key)); + + return vscode.commands.executeCommand("editor.action.triggerSuggest"); } // Some keys have names that are different to their value. // TODO: we probably need to put this somewhere else. - private ResolveKeyValue(key : string) : string { + private resolveKeyValue(key : string) : string { switch (key) { case 'space': return ' '; diff --git a/src/mode/modeNormal.ts b/src/mode/modeNormal.ts index 2f855589685..34f9678f265 100644 --- a/src/mode/modeNormal.ts +++ b/src/mode/modeNormal.ts @@ -1,3 +1,5 @@ +"use strict"; + import * as _ from 'lodash'; import * as vscode from 'vscode'; @@ -6,68 +8,65 @@ import {showCmdLine} from './../cmd_line/main'; import {Motion} from './../motion/motion'; import {DeleteAction} from './../action/deleteAction'; -export default class NormalMode extends Mode { - private keyHandler : { [key : string] : (motion : Motion) => Thenable<{}>; } = { - ":" : () => { return showCmdLine(); }, - "u" : () => { return vscode.commands.executeCommand("undo"); }, - "ctrl+r" : () => { return vscode.commands.executeCommand("redo"); }, - "h" : c => { return Promise.resolve(c.left().move()); }, - "j" : c => { return Promise.resolve(c.down().move()); }, - "k" : c => { return Promise.resolve(c.up().move()); }, - "l" : c => { return Promise.resolve(c.right().move()); }, - "$" : c => { return Promise.resolve(c.lineEnd().move()); }, - "0" : c => { return Promise.resolve(c.lineBegin().move()); }, - "^" : () => { return vscode.commands.executeCommand("cursorHome"); }, - "gg" : c => { return Promise.resolve(c.firstLineNonBlankChar().move()); }, - "G" : c => { return Promise.resolve(c.lastLineNonBlankChar().move()); }, - "w" : c => { return Promise.resolve(c.wordRight().move()); }, - "e" : c => { return Promise.resolve(c.goToEndOfCurrentWord().move()); }, - "b" : c => { return Promise.resolve(c.wordLeft().move()); }, - "}" : c => { return Promise.resolve(c.goToEndOfCurrentParagraph().move()); }, - "{" : c => { return Promise.resolve(c.goToBeginningOfCurrentParagraph().move()); }, - ">>" : () => { return vscode.commands.executeCommand("editor.action.indentLines"); }, - "<<" : () => { return vscode.commands.executeCommand("editor.action.outdentLines"); }, - "dd" : () => { return vscode.commands.executeCommand("editor.action.deleteLines"); }, - "dw" : () => { return vscode.commands.executeCommand("deleteWordRight"); }, - "db" : () => { return vscode.commands.executeCommand("deleteWordLeft"); }, - "x" : m => { return DeleteAction.Character(m); }, - "esc": () => { return vscode.commands.executeCommand("workbench.action.closeMessages"); } +export class NormalMode extends Mode { + private keyHandler : { [key : string] : (motion : Motion) => Promise<{}>; } = { + ":" : async () => { return showCmdLine(""); }, + "u" : async () => { return vscode.commands.executeCommand("undo"); }, + "ctrl+r" : async () => { return vscode.commands.executeCommand("redo"); }, + "h" : async (c) => { return c.left().move(); }, + "j" : async (c) => { return c.down().move(); }, + "k" : async (c) => { return c.up().move(); }, + "l" : async (c) => { return c.right().move(); }, + "$" : async (c) => { return c.lineEnd().move(); }, + "0" : async (c) => { return c.lineBegin().move(); }, + "^" : async () => { return vscode.commands.executeCommand("cursorHome"); }, + "gg" : async (c) => { return c.firstLineNonBlankChar().move(); }, + "G" : async (c) => { return c.lastLineNonBlankChar().move(); }, + "w" : async (c) => { return c.wordRight().move(); }, + "e" : async (c) => { return c.goToEndOfCurrentWord().move(); }, + "b" : async (c) => { return c.wordLeft().move(); }, + "}" : async (c) => { return c.goToEndOfCurrentParagraph().move(); }, + "{" : async (c) => { return c.goToBeginningOfCurrentParagraph().move(); }, + ">>" : async () => { return vscode.commands.executeCommand("editor.action.indentLines"); }, + "<<" : async () => { return vscode.commands.executeCommand("editor.action.outdentLines"); }, + "dd" : async () => { return vscode.commands.executeCommand("editor.action.deleteLines"); }, + "dw" : async () => { return vscode.commands.executeCommand("deleteWordRight"); }, + "db" : async () => { return vscode.commands.executeCommand("deleteWordLeft"); }, + "x" : async (m) => { return DeleteAction.Character(m); }, + "esc": async () => { return vscode.commands.executeCommand("workbench.action.closeMessages"); } }; constructor(motion : Motion) { super(ModeName.Normal, motion); } - ShouldBeActivated(key : string, currentMode : ModeName) : boolean { + shouldBeActivated(key : string, currentMode : ModeName) : boolean { return (key === 'esc' || key === 'ctrl+[' || key === "ctrl+c"); } - HandleActivation(key : string) : Thenable<{}> { - this.Motion.left().move(); - return Promise.resolve(this.Motion); + async handleActivation(key : string): Promise<{}> { + this.motion.left().move(); + + return this.motion; } - HandleKeyEvent(key : string) : Thenable<{}> { + async handleKeyEvent(key : string): Promise<{}> { this.keyHistory.push(key); - return new Promise(resolve => { - let keyHandled = false; - let keysPressed : string; - - for (let window = this.keyHistory.length; window > 0; window--) { - keysPressed = _.takeRight(this.keyHistory, window).join(''); - if (this.keyHandler[keysPressed] !== undefined) { - keyHandled = true; - break; - } - } + let keyHandled = false; + let keysPressed : string; - if (keyHandled) { - this.keyHistory = []; - return this.keyHandler[keysPressed](this.Motion); + for (let window = this.keyHistory.length; window > 0; window--) { + keysPressed = _.takeRight(this.keyHistory, window).join(''); + if (this.keyHandler[keysPressed] !== undefined) { + keyHandled = true; + break; } + } - resolve(); - }); + if (keyHandled) { + this.keyHistory = []; + return this.keyHandler[keysPressed](this.motion); + } } } diff --git a/src/motion/motion.ts b/src/motion/motion.ts index fffd57a0372..adef7bfda12 100644 --- a/src/motion/motion.ts +++ b/src/motion/motion.ts @@ -1,3 +1,5 @@ +"use strict"; + import * as vscode from "vscode"; import {Position, PositionOptions} from './position'; @@ -35,10 +37,10 @@ export class Motion implements vscode.Disposable { return this._position; } - public constructor(mode : MotionMode = null) { + public constructor(mode: MotionMode) { // initialize to current position let currentPosition = vscode.window.activeTextEditor.selection.active; - this._position = new Position(currentPosition.line, currentPosition.character); + this._position = new Position(currentPosition.line, currentPosition.character, null); this._desiredColumn = this._position.character; if (mode !== null) { @@ -55,7 +57,7 @@ export class Motion implements vscode.Disposable { if (this.position.line !== line || this.position.character !== char) { - this._position = new Position(line, char); + this._position = new Position(line, char, null); this._desiredColumn = this._position.character; this.changeMode(this._motionMode); } @@ -81,7 +83,11 @@ export class Motion implements vscode.Disposable { return this; } - public move(line : number = null, character : number = null) : Motion { + 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); this._desiredColumn = this._position.character; diff --git a/src/motion/position.ts b/src/motion/position.ts index ac7d28cff7f..e8e6168d470 100644 --- a/src/motion/position.ts +++ b/src/motion/position.ts @@ -1,6 +1,8 @@ +"use strict"; + import * as _ from "lodash"; import * as vscode from "vscode"; -import TextEditor from "./../textEditor"; +import {TextEditor} from "./../textEditor"; export enum PositionOptions { CharacterWiseInclusive, @@ -16,7 +18,7 @@ export class Position extends vscode.Position { public positionOptions: PositionOptions = null; - constructor(line: number, character: number, options : PositionOptions = null) { + constructor(line: number, character: number, options: PositionOptions) { super(line, character); let segments = ["(^[\t ]*$)"]; @@ -227,6 +229,7 @@ export class Position extends vscode.Position { let lineCount = TextEditor.getLineCount(); let line = lineCount > 0 ? lineCount - 1 : 0; let char = Position.getLineLength(line, this.positionOptions); + return new Position(line, char, this.positionOptions); } @@ -266,18 +269,18 @@ export class Position extends vscode.Position { } public static getFirstNonBlankCharAtLine(line: number): number { - return TextEditor.readLine(line).match(/^\s*/)[0].length; + return TextEditor.readLineAt(line).match(/^\s*/)[0].length; } - private static getLineLength(line : number, options : PositionOptions) : number { + private static getLineLength(line: number, options: PositionOptions) : number { switch (options) { case PositionOptions.CharacterWiseExclusive: // Valid Positions for Caret: [0, eol) - var len = TextEditor.readLine(line).length; + var len = TextEditor.readLineAt(line).length; return len > 0 ? len - 1 : len; case PositionOptions.CharacterWiseInclusive: // Valid Positions for Caret: [0, eol] - return TextEditor.readLine(line).length; + return TextEditor.readLineAt(line).length; default: throw new Error("Unhandled PositionOptions: " + options); diff --git a/src/textEditor.ts b/src/textEditor.ts index 9ccbcc34b02..bf3e39df1f1 100644 --- a/src/textEditor.ts +++ b/src/textEditor.ts @@ -1,32 +1,41 @@ +"use strict"; + import * as vscode from "vscode"; -export default class TextEditor { - static insert(text: string, position: vscode.Position = null) : Thenable { - if (position === null) { - position = vscode.window.activeTextEditor.selection.active; - } +export class TextEditor { + static async insert(text: string): Promise { + return vscode.window.activeTextEditor.edit(editBuilder => { + editBuilder.insert(vscode.window.activeTextEditor.selection.active, text); + }); + } + static async insertAt(text: string, position: vscode.Position): Promise { return vscode.window.activeTextEditor.edit(editBuilder => { editBuilder.insert(position, text); }); } - static delete(range: vscode.Range = null) : Thenable { - if (range === null) { - // delete entire document - 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); - } + static async delete(range: vscode.Range): Promise { return vscode.window.activeTextEditor.edit(editBuilder => { editBuilder.delete(range); }); } + /** + * Delete the entire document. + */ + static async deleteDocument(): Promise { + const start = new vscode.Position(0, 0); + const lastLine = vscode.window.activeTextEditor.document.lineCount - 1; + const end = vscode.window.activeTextEditor.document.lineAt(lastLine).range.end; + const range = new vscode.Range(start, end); + + return vscode.window.activeTextEditor.edit(editBuilder => { + editBuilder.delete(range); + }); + } - static replace(range: vscode.Range, text: string) : Thenable { + static async replace(range: vscode.Range, text: string): Promise { return vscode.window.activeTextEditor.edit(editBuilder => { editBuilder.replace(range, text); }); @@ -36,7 +45,13 @@ export default class TextEditor { return vscode.window.activeTextEditor.document.getText(); } - static readLine(lineNo: number = null): string { + static readLine(): string { + const lineNo = vscode.window.activeTextEditor.selection.active.line; + + return vscode.window.activeTextEditor.document.lineAt(lineNo).text; + } + + static readLineAt(lineNo: number): string { if (lineNo === null) { lineNo = vscode.window.activeTextEditor.selection.active.line; } @@ -48,7 +63,7 @@ export default class TextEditor { return vscode.window.activeTextEditor.document.lineAt(lineNo).text; } - static getLineCount() { + static getLineCount(): number { return vscode.window.activeTextEditor.document.lineCount; } @@ -56,7 +71,7 @@ export default class TextEditor { return vscode.window.activeTextEditor.document.lineAt(position); } - static isFirstLine(position : vscode.Position) : boolean { + static isFirstLine(position : vscode.Position): boolean { return position.line === 0; } diff --git a/src/util.ts b/src/util.ts index b5c518b7209..1a216f46991 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,9 +1,11 @@ +"use strict"; + import * as vscode from 'vscode'; -export function showInfo(message : string) : Thenable<{}> { +export async function showInfo(message : string): Promise<{}> { return vscode.window.showInformationMessage("Vim: " + message); } -export function showError(message : string) : Thenable<{}> { +export async function showError(message : string): Promise<{}> { return vscode.window.showErrorMessage("Vim: " + message); } diff --git a/test/cmd_line/lexer.test.ts b/test/cmd_line/lexer.test.ts index 8794e8cc2fa..80e58d03bdc 100644 --- a/test/cmd_line/lexer.test.ts +++ b/test/cmd_line/lexer.test.ts @@ -1,3 +1,5 @@ +"use strict"; + // The module 'assert' provides assertion methods from node import * as assert from 'assert'; import * as lexer from '../../src/cmd_line/lexer'; diff --git a/test/cmd_line/parser.test.ts b/test/cmd_line/parser.test.ts index 27cbda698ff..6323e2f99c0 100644 --- a/test/cmd_line/parser.test.ts +++ b/test/cmd_line/parser.test.ts @@ -1,3 +1,5 @@ +"use strict"; + import * as assert from 'assert'; import * as parser from '../../src/cmd_line/parser'; import * as node from '../../src/cmd_line/node'; diff --git a/test/cmd_line/scanner.test.ts b/test/cmd_line/scanner.test.ts index 3223abb51a8..1610e608679 100644 --- a/test/cmd_line/scanner.test.ts +++ b/test/cmd_line/scanner.test.ts @@ -1,3 +1,5 @@ +"use strict"; + import * as assert from 'assert'; import {Scanner} from '../../src/cmd_line/scanner'; @@ -86,11 +88,11 @@ suite("command line scanner", () => { test("can expect one of a set", () => { var state = new Scanner("dog cat"); - state.expectOneOf("dog", "mule", "monkey"); + state.expectOneOf(["dog", "mule", "monkey"]); }); test("can expect only one of a set", () => { var state = new Scanner("dog cat"); - assert.throws(() => state.expectOneOf("mule", "monkey")); + assert.throws(() => state.expectOneOf(["mule", "monkey"])); }); }); diff --git a/test/cmd_line/subparser.quit.test.ts b/test/cmd_line/subparser.quit.test.ts index b919f65c682..51c7164c17f 100644 --- a/test/cmd_line/subparser.quit.test.ts +++ b/test/cmd_line/subparser.quit.test.ts @@ -1,3 +1,5 @@ +"use strict"; + // The module 'assert' provides assertion methods from node import * as assert from 'assert'; diff --git a/test/cmd_line/subparser.test.ts b/test/cmd_line/subparser.test.ts index 9230fa054af..f30348209d7 100644 --- a/test/cmd_line/subparser.test.ts +++ b/test/cmd_line/subparser.test.ts @@ -1,3 +1,5 @@ +"use strict"; + // The module 'assert' provides assertion methods from node import * as assert from 'assert'; diff --git a/test/error.test.ts b/test/error.test.ts index 36eda6c40af..4e8888312f3 100644 --- a/test/error.test.ts +++ b/test/error.test.ts @@ -1,3 +1,5 @@ +"use strict"; + // The module 'assert' provides assertion methods from node import * as assert from 'assert'; import {VimError, ErrorCode} from '../src/error'; diff --git a/test/extension.test.ts b/test/extension.test.ts index 83b732cc0e7..97153df8709 100644 --- a/test/extension.test.ts +++ b/test/extension.test.ts @@ -1,24 +1,24 @@ +"use strict"; + import * as assert from 'assert'; import * as vscode from 'vscode'; import * as _ from 'lodash'; suite("setup", () => { - test("all keys have handlers", () => { + test("all keys have handlers", async () => { let pkg = require(__dirname + '/../../package.json'); assert.ok(pkg); - return vscode.commands.getCommands() - .then(registeredCommands => { - let keybindings = pkg.contributes.keybindings; - assert.ok(pkg); + let registeredCommands = await vscode.commands.getCommands(); + let keybindings = pkg.contributes.keybindings; + assert.ok(pkg); - for (let i = 0; i < keybindings.length; i++) { - let keybinding = keybindings[i]; + for (let i = 0; i < keybindings.length; i++) { + let keybinding = keybindings[i]; - var found = registeredCommands.indexOf(keybinding.command) >= -1; - assert.ok(found, "Missing handler for key=" + keybinding.key + ". Expected handler=" + keybinding.command); - } - }); + var found = registeredCommands.indexOf(keybinding.command) >= -1; + assert.ok(found, "Missing handler for key=" + keybinding.key + ". Expected handler=" + keybinding.command); + } }); test("duplicate keybindings", () => { diff --git a/test/index.ts b/test/index.ts index 3d736905c36..940fab2d0a4 100644 --- a/test/index.ts +++ b/test/index.ts @@ -1,3 +1,5 @@ +"use strict"; + // // PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING // diff --git a/test/keyboard.test.ts b/test/keyboard.test.ts index e4988437925..f4a5754afb4 100644 --- a/test/keyboard.test.ts +++ b/test/keyboard.test.ts @@ -1,3 +1,5 @@ +"use strict"; + // The module 'assert' provides assertion methods from node import * as assert from 'assert'; import {KeyboardLayout, KeyMapper} from '../src/keyboard'; diff --git a/test/mode/modeHandler.test.ts b/test/mode/modeHandler.test.ts index 6fba970142d..c9ea770cb42 100644 --- a/test/mode/modeHandler.test.ts +++ b/test/mode/modeHandler.test.ts @@ -1,7 +1,9 @@ +"use strict"; + import * as assert from 'assert'; import {setupWorkspace, cleanUpWorkspace} from './../testUtils'; import {ModeName} from '../../src/mode/mode'; -import ModeHandler from '../../src/mode/modeHandler'; +import {ModeHandler} from '../../src/mode/modeHandler'; suite("Mode Handler", () => { @@ -12,18 +14,18 @@ suite("Mode Handler", () => { test("ctor", () => { var modeHandler = new ModeHandler(); - assert.equal(modeHandler.currentMode.Name, ModeName.Normal); - assert.equal(modeHandler.currentMode.IsActive, true); + assert.equal(modeHandler.currentMode.name, ModeName.Normal); + assert.equal(modeHandler.currentMode.isActive, true); }); test("can set current mode", () => { var modeHandler = new ModeHandler(); modeHandler.setCurrentModeByName(ModeName.Normal); - assert.equal(modeHandler.currentMode.Name, ModeName.Normal); + assert.equal(modeHandler.currentMode.name, ModeName.Normal); modeHandler.setCurrentModeByName(ModeName.Insert); - assert.equal(modeHandler.currentMode.Name, ModeName.Insert); + assert.equal(modeHandler.currentMode.name, ModeName.Insert); /* modeHandler.setCurrentModeByName(ModeName.Visual); diff --git a/test/mode/modeInsert.test.ts b/test/mode/modeInsert.test.ts index 04eb897b354..a5f0bf3d7c8 100644 --- a/test/mode/modeInsert.test.ts +++ b/test/mode/modeInsert.test.ts @@ -1,20 +1,22 @@ +"use strict"; + import * as assert from 'assert'; import {setupWorkspace, cleanUpWorkspace, assertEqualLines} from './../testUtils'; -import ModeInsert from '../../src/mode/modeInsert'; +import {InsertMode} from '../../src/mode/modeInsert'; import {ModeName} from '../../src/mode/mode'; import {Motion, MotionMode} from '../../src/motion/motion'; -import TextEditor from '../../src/textEditor'; +import {TextEditor} from '../../src/textEditor'; suite("Mode Insert", () => { - let motion : Motion; - let modeInsert : ModeInsert; + let motion: Motion; + let modeInsert: InsertMode; + + setup(async () => { + await setupWorkspace(); - setup(() => { - return setupWorkspace().then(() => { - motion = new Motion(MotionMode.Cursor); - modeInsert = new ModeInsert(motion); - }); + motion = new Motion(MotionMode.Cursor); + modeInsert = new InsertMode(motion); }); teardown(cleanUpWorkspace); @@ -22,94 +24,68 @@ suite("Mode Insert", () => { test("can be activated", () => { let activationKeys = ['i', 'I', 'o', 'O', 'a', 'A']; - for (let i = 0; i < activationKeys.length; i++) { - let key = activationKeys[i]; - assert.equal(modeInsert.ShouldBeActivated(key, ModeName.Insert), true, key); + for (let key of activationKeys) { + assert.equal(modeInsert.shouldBeActivated(key, ModeName.Insert), true, key); } }); - test("can handle key events", () => { - return modeInsert.HandleKeyEvent("!") - .then(() => { - return assertEqualLines(["!"]); - }); + test("can handle key events", async () => { + await modeInsert.handleKeyEvent("!"); + + return assertEqualLines(["!"]); }); - test("Can handle 'o'", () => { - return TextEditor.insert("text") - .then(() => { - return modeInsert.HandleActivation("o"); - }) - .then(() => { - return assertEqualLines(["text", ""]); - }); + test("Can handle 'o'", async () => { + await TextEditor.insert("text"); + await modeInsert.handleActivation("o"); + + return assertEqualLines(["text", ""]); }); - test("Can handle 'O'", () => { - return TextEditor.insert("text") - .then(() => { - return modeInsert.HandleActivation("O"); - }) - .then(() => { - return assertEqualLines(["", "text"]); - }); + test("Can handle 'O'", async () => { + await TextEditor.insert("text"); + await modeInsert.handleActivation("O"); + + return assertEqualLines(["", "text"]); }); - test("Can handle 'i'", () => { - return TextEditor.insert("texttext") - .then(() => { - motion = motion.move(0, 4); - }) - .then(() => { - return modeInsert.HandleActivation("i"); - }) - .then(() => { - return modeInsert.HandleKeyEvent("!"); - }) - .then(() => { - return assertEqualLines(["text!text"]); - }); + test("Can handle 'i'", async () => { + await TextEditor.insert("texttext"); + + motion = motion.moveTo(0, 4); + await modeInsert.handleActivation("i"); + await modeInsert.handleKeyEvent("!"); + + assertEqualLines(["text!text"]); }); - test("Can handle 'I'", () => { - return TextEditor.insert("text") - .then(() => { - motion = motion.move(0, 3); - }) - .then(() => { - return modeInsert.HandleActivation("I"); - }) - .then(() => { - return modeInsert.HandleKeyEvent("!"); - }) - .then(() => { - return assertEqualLines(["!text"]); - }); + test("Can handle 'I'", async () => { + await TextEditor.insert("text"); + motion = motion.moveTo(0, 3); + + await modeInsert.handleActivation("I"); + await modeInsert.handleKeyEvent("!"); + + assertEqualLines(["!text"]); }); - test("Can handle 'a'", () => { - return TextEditor.insert("texttext") - .then(() => { - motion = motion.move(0, 4); - }).then(() => { - return modeInsert.HandleActivation("a"); - }).then(() => { - return modeInsert.HandleKeyEvent("!"); - }).then(() => { - return assertEqualLines(["textt!ext"]); - }); + test("Can handle 'a'", async () => { + await TextEditor.insert("texttext"); + + motion = motion.moveTo(0, 4); + await modeInsert.handleActivation("a"); + await modeInsert.handleKeyEvent("!"); + + assertEqualLines(["textt!ext"]); }); - test("Can handle 'A'", () => { - return TextEditor.insert("text") - .then(() => { - motion = motion.move(0, 0); - }).then(() => { - return modeInsert.HandleActivation("A"); - }).then(() => { - return modeInsert.HandleKeyEvent("!"); - }).then(() => { - return assertEqualLines(["text!"]); - }); + test("Can handle 'A'", async () => { + await TextEditor.insert("text"); + + motion = motion.moveTo(0, 0); + await modeInsert.handleActivation("A"); + await modeInsert.handleKeyEvent("!"); + + assertEqualLines(["text!"]); }); }); diff --git a/test/mode/modeNormal.test.ts b/test/mode/modeNormal.test.ts index d02e5b17424..7bf989e54b6 100644 --- a/test/mode/modeNormal.test.ts +++ b/test/mode/modeNormal.test.ts @@ -1,6 +1,8 @@ +"use strict"; + import * as assert from 'assert'; import {setupWorkspace, cleanUpWorkspace} from './../testUtils'; -import ModeNormal from '../../src/mode/modeNormal'; +import {NormalMode} from '../../src/mode/modeNormal'; import {ModeName} from '../../src/mode/mode'; import {Motion} from '../../src/motion/motion'; @@ -12,12 +14,12 @@ suite("Mode Normal", () => { test("can be activated", () => { let activationKeys = ['esc', 'ctrl+[', 'ctrl+c']; - let motion = new Motion(); - let modeHandler = new ModeNormal(motion); + let motion = new Motion(null); + let modeHandler = new NormalMode(motion); for (let i = 0; i < activationKeys.length; i++) { let key = activationKeys[i]; - assert.equal(modeHandler.ShouldBeActivated(key, ModeName.Insert), true, key); + assert.equal(modeHandler.shouldBeActivated(key, ModeName.Insert), true, key); } }); }); diff --git a/test/motion.test.ts b/test/motion.test.ts index 72393e8a1aa..6b687b07935 100644 --- a/test/motion.test.ts +++ b/test/motion.test.ts @@ -1,6 +1,8 @@ +"use strict"; + import * as assert from 'assert'; import * as vscode from "vscode"; -import TextEditor from './../src/textEditor'; +import {TextEditor} from './../src/textEditor'; import {Motion, MotionMode} from './../src/motion/motion'; import {setupWorkspace, cleanUpWorkspace} from './testUtils'; @@ -13,17 +15,16 @@ suite("motion", () => { " whose fleece was " ]; - suiteSetup(() => { - return setupWorkspace().then(() => { - return TextEditor.insert(text.join('\n')); - }); + suiteSetup(async () => { + await setupWorkspace(); + await TextEditor.insert(text.join('\n')); }); suiteTeardown(cleanUpWorkspace); test("char right: should move one column right", () => { - motionModes.forEach(o => { - let motion = new Motion(o).move(0, 0); + 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); @@ -34,20 +35,20 @@ suite("motion", () => { let curPos = vscode.window.activeTextEditor.selection.active; assert.equal(next.position.line, curPos.line); assert.equal(next.position.character, curPos.character); - }); + }; }); test("char right: caret", () => { let motion = new Motion(MotionMode.Caret); - motion = motion.move(0, 7).right(); + motion = motion.moveTo(0, 7).right(); assert.equal(motion.position.line, 0); assert.equal(motion.position.character, 7); }); test("char right: cursor", () => { let motion = new Motion(MotionMode.Cursor); - motion = motion.move(0, 8).right(); + motion = motion.moveTo(0, 8).right(); assert.equal(motion.position.line, 0); assert.equal(motion.position.character, 8); @@ -55,7 +56,7 @@ suite("motion", () => { test("char left: should move cursor one column left", () => { motionModes.forEach(o => { - let motion = new Motion(o).move(0, 5); + let motion = new Motion(o).moveTo(0, 5); assert.equal(motion.position.line, 0); assert.equal(motion.position.character, 5); @@ -71,7 +72,7 @@ suite("motion", () => { test("char left: left-most column should stay at the same location", () => { motionModes.forEach(o => { - let motion = new Motion(o).move(0, 0); + let motion = new Motion(o).moveTo(0, 0); assert.equal(motion.position.line, 0); assert.equal(motion.position.character, 0); @@ -87,7 +88,7 @@ suite("motion", () => { test("line down: should move cursor one line down", () => { motionModes.forEach(o => { - let motion = new Motion(o).move(1, 0); + let motion = new Motion(o).moveTo(1, 0); assert.equal(motion.position.line, 1); assert.equal(motion.position.character, 0); @@ -103,7 +104,7 @@ suite("motion", () => { test("line down: bottom-most line should stay at the same location", () => { motionModes.forEach(o => { - let motion = new Motion(o).move(3, 0); + let motion = new Motion(o).moveTo(3, 0); assert.equal(motion.position.line, 3); assert.equal(motion.position.character, 0); @@ -120,7 +121,7 @@ suite("motion", () => { suite("line up", () => { motionModes.forEach(o => { test("should move cursor one line up", () => { - let motion = new Motion(o).move(1, 0); + let motion = new Motion(o).moveTo(1, 0); assert.equal(motion.position.line, 1); assert.equal(motion.position.character, 0); @@ -134,7 +135,7 @@ suite("motion", () => { }); test("top-most line should stay at the same location", () => { - let motion = new Motion(o).move(0, 1); + let motion = new Motion(o).moveTo(0, 1); assert.equal(motion.position.line, 0); assert.equal(motion.position.character, 1); @@ -150,7 +151,7 @@ suite("motion", () => { }); test("keep same column as up/down", () => { - let motion = new Motion(MotionMode.Caret).move(0, 2); + let motion = new Motion(MotionMode.Caret).moveTo(0, 2); motion = motion.down(); assert.equal(motion.position.line, 1); @@ -163,44 +164,44 @@ suite("motion", () => { test("line begin", () => { motionModes.forEach(o => { - let motion = new Motion(o).move(0, 3).lineBegin(); + let motion = new Motion(o).moveTo(0, 3).lineBegin(); assert.equal(motion.position.line, 0); assert.equal(motion.position.character, 0); }); }); test("line end", () => { - let motion = new Motion(MotionMode.Cursor).move(0, 0).lineEnd(); + let motion = new Motion(MotionMode.Cursor).moveTo(0, 0).lineEnd(); assert.equal(motion.position.line, 0); assert.equal(motion.position.character, text[0].length); - motion = motion.move(2, 0).lineEnd(); + motion = motion.moveTo(2, 0).lineEnd(); assert.equal(motion.position.line, 2); assert.equal(motion.position.character, text[2].length); }); test("document begin", () => { motionModes.forEach(o => { - let motion = new Motion(o).move(1, 0).documentBegin(); + let motion = new Motion(o).moveTo(1, 0).documentBegin(); assert.equal(motion.position.line, 0); assert.equal(motion.position.character, 0); }); }); test("document end", () => { - let motion = new Motion(MotionMode.Cursor).move(0, 0).documentEnd(); + 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); }); test("line begin cursor on first non-blank character", () => { - let motion = new Motion(MotionMode.Caret).move(3, 3).firstLineNonBlankChar(); + let motion = new Motion(MotionMode.Caret).moveTo(3, 3).firstLineNonBlankChar(); assert.equal(motion.position.line, 0); assert.equal(motion.position.character, 0); }); test("last line begin cursor on first non-blank character", () => { - let motion = new Motion(MotionMode.Caret).move(0, 0).lastLineNonBlankChar(); + let motion = new Motion(MotionMode.Caret).moveTo(0, 0).lastLineNonBlankChar(); assert.equal(motion.position.line, 3); assert.equal(motion.position.character, 1); }); @@ -224,25 +225,25 @@ suite("word motion", () => { suite("word right", () => { test("move to word right", () => { - let motion = new Motion(MotionMode.Caret).move(0, 0).wordRight(); + let motion = new Motion(MotionMode.Caret).moveTo(0, 0).wordRight(); assert.equal(motion.position.line, 0); assert.equal(motion.position.character, 5); }); test("last word should move to next line", () => { - let motion = new Motion(MotionMode.Caret).move(0, 6).wordRight(); + let motion = new Motion(MotionMode.Caret).moveTo(0, 6).wordRight(); assert.equal(motion.position.line, 1); assert.equal(motion.position.character, 0); }); test("last word on last line should go to end of document (special case!)", () => { - let motion = new Motion(MotionMode.Caret).move(3, 14).wordRight(); + let motion = new Motion(MotionMode.Caret).moveTo(3, 14).wordRight(); assert.equal(motion.position.line, 3); assert.equal(motion.position.character, 18); }); test("end of line should move to next word on next line", () => { - let motion = new Motion(MotionMode.Caret).move(0, 7).wordRight(); + let motion = new Motion(MotionMode.Caret).moveTo(0, 7).wordRight(); assert.equal(motion.position.line, 1); assert.equal(motion.position.character, 0); }); @@ -250,26 +251,26 @@ suite("word motion", () => { suite("word left", () => { test("move cursor word left", () => { - let motion = new Motion(MotionMode.Caret).move(0, 3).wordLeft(); + let motion = new Motion(MotionMode.Caret).moveTo(0, 3).wordLeft(); assert.equal(motion.position.line, 0); assert.equal(motion.position.character, 0); }); test("first word should move to previous line of end of line", () => { - let motion = new Motion(MotionMode.Caret).move(2, 0).wordLeft(); + let motion = new Motion(MotionMode.Caret).moveTo(2, 0).wordLeft(); assert.equal(motion.position.line, 1); assert.equal(motion.position.character, 0); }); }); test("line begin cursor on first non-blank character", () => { - let motion = new Motion(MotionMode.Caret).move(3, 3).firstLineNonBlankChar(); + let motion = new Motion(MotionMode.Caret).moveTo(3, 3).firstLineNonBlankChar(); assert.equal(motion.position.line, 0); assert.equal(motion.position.character, 0); }); test("last line begin cursor on first non-blank character", () => { - let motion = new Motion(MotionMode.Caret).move(0, 0).lastLineNonBlankChar(); + let motion = new Motion(MotionMode.Caret).moveTo(0, 0).lastLineNonBlankChar(); assert.equal(motion.position.line, 3); assert.equal(motion.position.character, 1); }); @@ -299,25 +300,25 @@ suite("paragraph motion", () => { suite("paragraph down", () => { test("move down normally", () => { - let motion = new Motion(MotionMode.Caret).move(0, 0).goToEndOfCurrentParagraph(); + let motion = new Motion(MotionMode.Caret).moveTo(0, 0).goToEndOfCurrentParagraph(); assert.equal(motion.position.line, 1); assert.equal(motion.position.character, 0); }); test("move down longer paragraph", () => { - let motion = new Motion(MotionMode.Caret).move(2, 0).goToEndOfCurrentParagraph(); + let motion = new Motion(MotionMode.Caret).moveTo(2, 0).goToEndOfCurrentParagraph(); assert.equal(motion.position.line, 4); assert.equal(motion.position.character, 0); }); test("move down starting inside empty line", () => { - let motion = new Motion(MotionMode.Caret).move(4, 0).goToEndOfCurrentParagraph(); + let motion = new Motion(MotionMode.Caret).moveTo(4, 0).goToEndOfCurrentParagraph(); assert.equal(motion.position.line, 7); assert.equal(motion.position.character, 0); }); test("paragraph at end of document", () => { - let motion = new Motion(MotionMode.Caret).move(7, 0).goToEndOfCurrentParagraph(); + let motion = new Motion(MotionMode.Caret).moveTo(7, 0).goToEndOfCurrentParagraph(); assert.equal(motion.position.line, 8); assert.equal(motion.position.character, 2); }); @@ -325,19 +326,19 @@ suite("paragraph motion", () => { suite("paragraph up", () => { test("move up short paragraph", () => { - let motion = new Motion(MotionMode.Caret).move(1, 0).goToBeginningOfCurrentParagraph(); + let motion = new Motion(MotionMode.Caret).moveTo(1, 0).goToBeginningOfCurrentParagraph(); assert.equal(motion.position.line, 0); assert.equal(motion.position.character, 0); }); test("move up longer paragraph", () => { - let motion = new Motion(MotionMode.Caret).move(3, 0).goToBeginningOfCurrentParagraph(); + let motion = new Motion(MotionMode.Caret).moveTo(3, 0).goToBeginningOfCurrentParagraph(); assert.equal(motion.position.line, 1); assert.equal(motion.position.character, 0); }); test("move up starting inside empty line", () => { - let motion = new Motion(MotionMode.Caret).move(5, 0).goToBeginningOfCurrentParagraph(); + let motion = new Motion(MotionMode.Caret).moveTo(5, 0).goToBeginningOfCurrentParagraph(); assert.equal(motion.position.line, 1); assert.equal(motion.position.character, 0); }); diff --git a/test/testUtils.ts b/test/testUtils.ts index 74120878eb5..3c2e592d099 100644 --- a/test/testUtils.ts +++ b/test/testUtils.ts @@ -1,4 +1,6 @@ -import TextEditor from '../src/textEditor'; +"use strict"; + +import {TextEditor} from '../src/textEditor'; import * as vscode from "vscode"; import * as assert from 'assert'; import {join} from 'path'; @@ -9,40 +11,36 @@ function rndName() { return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10); } -function createRandomFile(contents = ''): Thenable { - return new Promise((resolve, reject) => { - const tmpFile = join(os.tmpdir(), rndName()); - fs.writeFile(tmpFile, contents, (error) => { - if (error) { - return reject(error); - } +async function createRandomFile(contents: string): Promise { + const tmpFile = join(os.tmpdir(), rndName()); - resolve(vscode.Uri.file(tmpFile)); - }); - }); + try { + await fs.writeFile(tmpFile, contents); + } catch (error) { + throw error; + } + + return vscode.Uri.file(tmpFile); } -export function assertEqualLines(expectedLines : string[]) { +export function assertEqualLines(expectedLines: string[]) { assert.equal(TextEditor.getLineCount(), expectedLines.length); for (let i = 0; i < expectedLines.length; i++) { - assert.equal(TextEditor.readLine(i), expectedLines[i]); + assert.equal(TextEditor.readLineAt(i), expectedLines[i]); } } +export async function setupWorkspace(): Promise { + const file = await createRandomFile(""); + const doc = await vscode.workspace.openTextDocument(file); -export function setupWorkspace() : Thenable { - return createRandomFile().then(file => { - return vscode.workspace.openTextDocument(file).then(doc => { - return vscode.window.showTextDocument(doc).then(editor => { - const active = vscode.window.activeTextEditor; - assert.ok(active); - }); - }); - }); + await vscode.window.showTextDocument(doc); + + assert.ok(vscode.window.activeTextEditor); } -export function cleanUpWorkspace(): Thenable { +export function cleanUpWorkspace(): Promise { // https://github.com/Microsoft/vscode/blob/master/extensions/vscode-api-tests/src/utils.ts return new Promise((c, e) => { if (vscode.window.visibleTextEditors.length === 0) { diff --git a/test/textEditor.test.ts b/test/textEditor.test.ts index 8fe15b9ca20..6cab76fa09f 100644 --- a/test/textEditor.test.ts +++ b/test/textEditor.test.ts @@ -1,6 +1,8 @@ +"use strict"; + import * as assert from 'assert'; import * as vscode from 'vscode'; -import TextEditor from './../src/textEditor'; +import {TextEditor} from './../src/textEditor'; import {setupWorkspace, cleanUpWorkspace} from './testUtils'; suite("text editor", () => { @@ -8,56 +10,53 @@ suite("text editor", () => { suiteTeardown(cleanUpWorkspace); - test("insert 'Hello World'", () => { + test("insert 'Hello World'", async () => { let expectedText = "Hello World"; - return TextEditor.insert(expectedText).then(x => { - assert.equal(vscode.window.activeTextEditor.document.lineCount, 1); - let actualText = TextEditor.readLine(0); - assert.equal(actualText, expectedText); - }); + await TextEditor.insert(expectedText); + + assert.equal(vscode.window.activeTextEditor.document.lineCount, 1); + let actualText = TextEditor.readLineAt(0); + assert.equal(actualText, expectedText); }); - test("replace 'World' with 'Foo Bar'", () => { + test("replace 'World' with 'Foo Bar'", async () => { let newText = "Foo Bar"; let start = new vscode.Position(0, 6); let end = new vscode.Position(0, 11); let range : vscode.Range = new vscode.Range(start, end); - return TextEditor.replace(range, newText).then( x => { - assert.equal(vscode.window.activeTextEditor.document.lineCount, 1); + await TextEditor.replace(range, newText); + assert.equal(vscode.window.activeTextEditor.document.lineCount, 1); - let actualText = TextEditor.readLine(0); - assert.equal(actualText, "Hello Foo Bar"); - }); + let actualText = TextEditor.readLineAt(0); + assert.equal(actualText, "Hello Foo Bar"); }); - test("delete `Hello`", () => { + test("delete `Hello`", async () => { assert.equal(vscode.window.activeTextEditor.document.lineCount, 1); - var end = new vscode.Position(0, 5); - var range = new vscode.Range(new vscode.Position(0, 0), end); + let end = new vscode.Position(0, 5); + let range = new vscode.Range(new vscode.Position(0, 0), end); - return TextEditor.delete(range).then( x => { - let actualText = TextEditor.readLine(0); - assert.equal(actualText, " Foo Bar"); - }); + await TextEditor.delete(range); + let actualText = TextEditor.readLineAt(0); + assert.equal(actualText, " Foo Bar"); }); - test("delete the whole line", () => { + test("delete the whole line", async () => { assert.equal(vscode.window.activeTextEditor.document.lineCount, 1); - var range = vscode.window.activeTextEditor.document.lineAt(0).range; + let range = vscode.window.activeTextEditor.document.lineAt(0).range; - return TextEditor.delete(range).then(x => { - let actualText = TextEditor.readLine(0); - assert.equal(actualText, ""); - }); + await TextEditor.delete(range); + let actualText = TextEditor.readLineAt(0); + assert.equal(actualText, ""); }); test("try to read lines that don't exist", () => { assert.equal(vscode.window.activeTextEditor.document.lineCount, 1); - assert.throws(() => TextEditor.readLine(1), RangeError); - assert.throws(() => TextEditor.readLine(2), RangeError); + assert.throws(() => TextEditor.readLineAt(1), RangeError); + assert.throws(() => TextEditor.readLineAt(2), RangeError); }); }); diff --git a/tsconfig.json b/tsconfig.json index 5a3f2462d64..12788d6bdac 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "module": "commonjs", - "target": "es5", + "target": "es6", "outDir": "out", "noLib": true, "sourceMap": true