diff --git a/src/cmd_line/main.ts b/src/cmd_line/main.ts index 13969869c..4535ad498 100644 --- a/src/cmd_line/main.ts +++ b/src/cmd_line/main.ts @@ -3,17 +3,17 @@ import * as parser from "./parser"; import * as util from "../util"; // Shows the vim command line. -export function showCmdLine(initialText = "") { +export function showCmdLine(initialText = "") : Thenable<{}> { if (!vscode.window.activeTextEditor) { - util.showInfo("No active document."); - return; + return util.showInfo("No active document."); } const options : vscode.InputBoxOptions = { prompt: "Vim command line", value: initialText }; - vscode.window.showInputBox(options).then( + + return vscode.window.showInputBox(options).then( runCmdLine, vscode.window.showErrorMessage ); diff --git a/src/mode/mode.ts b/src/mode/mode.ts index 470397535..c39d75c48 100644 --- a/src/mode/mode.ts +++ b/src/mode/mode.ts @@ -33,7 +33,7 @@ export abstract class Mode { abstract ShouldBeActivated(key : string, currentMode : ModeName) : boolean; - abstract HandleActivation(key : string) : Thenable | void; + abstract HandleActivation(key : string) : Thenable<{}>; - abstract HandleKeyEvent(key : string) : void; + abstract HandleKeyEvent(key : string) : Thenable<{}>; } \ No newline at end of file diff --git a/src/mode/modeInsert.ts b/src/mode/modeInsert.ts index 69626ef99..b0d918ccf 100644 --- a/src/mode/modeInsert.ts +++ b/src/mode/modeInsert.ts @@ -4,56 +4,56 @@ import TextEditor from './../textEditor'; import {Cursor} from './../motion/motion'; export default class InsertMode extends Mode { - - private activationKeyHandler : { [ key : string] : (cursor : Cursor) => Thenable | void; }; - private cursor : Cursor = new Cursor(); + private cursor : Cursor; + private activationKeyHandler : { [ key : string] : (cursor : Cursor) => Thenable<{}> } = { + "i" : () => { + // insert at cursor + return Promise.resolve({}); + }, + "I" : c => { + // insert at line beginning + return Promise.resolve(c.lineBegin().move()); + }, + "a" : c => { + // append after the cursor + return Promise.resolve(c.right().move()); + }, + "A" : c => { + // append at the end of the line + return Promise.resolve(c.lineEnd().move()); + }, + "o" : () => { + // open blank line below current line + return vscode.commands.executeCommand("editor.action.insertLineAfter"); + }, + "O" : () => { + // open blank line above current line + return vscode.commands.executeCommand("editor.action.insertLineBefore"); + } + }; constructor() { super(ModeName.Insert); - - this.activationKeyHandler = { - // insert at cursor - "i" : (cursor) => { - // nothing - }, - - // insert at the beginning of the line - "I" : (cursor) => { cursor.lineBegin().move(); }, - - // append after the cursor - "a" : (cursor) => { cursor.right().move(); }, - - // append at the end of the line - "A" : (cursor) => { cursor.lineEnd().move(); }, - - // open blank line below current line - "o" : () => { - return vscode.commands.executeCommand("editor.action.insertLineAfter"); - }, - - // open blank line above current line - "O" : () => { - return vscode.commands.executeCommand("editor.action.insertLineBefore"); - } - }; + this.cursor = new Cursor(); } ShouldBeActivated(key : string, currentMode : ModeName) : boolean { return key in this.activationKeyHandler; } - HandleActivation(key : string) : Thenable | void { + HandleActivation(key : string) : Thenable<{}> { this.cursor.reset(); return this.activationKeyHandler[key](this.cursor); } - HandleKeyEvent(key : string) : Thenable { + HandleKeyEvent(key : string) : Thenable<{}> { this.keyHistory.push(key); - var thenable = TextEditor.insert(this.ResolveKeyValue(key)); - vscode.commands.executeCommand("editor.action.triggerSuggest"); - - return thenable; + return TextEditor + .insert(this.ResolveKeyValue(key)) + .then(() => { + return vscode.commands.executeCommand("editor.action.triggerSuggest"); + }); } // Some keys have names that are different to their value. @@ -66,4 +66,4 @@ export default class InsertMode extends Mode { return key; } } -} \ No newline at end of file +} diff --git a/src/mode/modeNormal.ts b/src/mode/modeNormal.ts index 22c0fdbd2..4807ca2ec 100644 --- a/src/mode/modeNormal.ts +++ b/src/mode/modeNormal.ts @@ -4,62 +4,66 @@ import {ModeName, Mode} from './mode'; import {showCmdLine} from './../cmd_line/main'; import {Caret} from './../motion/motion'; -export default class CommandMode extends Mode { - private keyHandler : { [key : string] : () => void; } = {}; - private caret : Caret = new Caret(); +export default class NormalMode extends Mode { + private caret : Caret; + private keyHandler : { [key : string] : (caret : Caret) => 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()); }, + "^" : c => { return Promise.resolve(c.lineBegin().move()); }, + "gg" : c => {return Promise.resolve(c.firstLineNonBlankChar().move()); }, + "G" : c => { return Promise.resolve(c.lastLineNonBlankChar().move()); }, + "w" : c => { return Promise.resolve(c.wordRight().move()); }, + "b" : c => { return Promise.resolve(c.wordLeft().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" : () => { this.CommandDelete(1); } + "esc": () => { return vscode.commands.executeCommand("workbench.action.closeMessages"); } + }; constructor() { super(ModeName.Normal); - - this.keyHandler = { - ":" : () => { showCmdLine(); }, - "u" : () => { vscode.commands.executeCommand("undo"); }, - "ctrl+r" : () => { vscode.commands.executeCommand("redo"); }, - "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"); }, - // "x" : () => { this.CommandDelete(1); } - "esc": () => { vscode.commands.executeCommand("workbench.action.closeMessages"); } - }; + this.caret = new Caret(); } ShouldBeActivated(key : string, currentMode : ModeName) : boolean { return (key === 'esc' || key === 'ctrl+['); } - HandleActivation(key : string) : void { - this.caret.reset().left().move(); + HandleActivation(key : string) : Thenable<{}> { + return Promise.resolve(this.caret.reset().left().move()); } - HandleKeyEvent(key : string) : void { + HandleKeyEvent(key : string) : Thenable<{}> { this.keyHistory.push(key); - let keyHandled = false; + return new Promise(resolve => { + let keyHandled = false; + let keysPressed : string; - for (let window = this.keyHistory.length; window > 0; window--) { - let keysPressed = _.takeRight(this.keyHistory, window).join(''); - if (this.keyHandler[keysPressed] !== undefined) { - keyHandled = true; - this.keyHandler[keysPressed](); - break; + for (let window = this.keyHistory.length; window > 0; window--) { + keysPressed = _.takeRight(this.keyHistory, window).join(''); + if (this.keyHandler[keysPressed] !== undefined) { + keyHandled = true; + break; + } } - } - if (keyHandled) { - this.keyHistory = []; - } + if (keyHandled) { + this.keyHistory = []; + return this.keyHandler[keysPressed](this.caret); + } + + resolve(); + }); } /* diff --git a/src/mode/modeVisual.ts b/src/mode/modeVisual.ts index 01291e801..9647ce2c0 100644 --- a/src/mode/modeVisual.ts +++ b/src/mode/modeVisual.ts @@ -10,11 +10,12 @@ export default class VisualMode extends Mode { return (key === "v" || key === "V") && (currentMode === ModeName.Normal); } - HandleActivation(key : string) : void { - // do nothing + HandleActivation(key : string) : Thenable<{}> { + return Promise.resolve({}); } - HandleKeyEvent(key : string) : void { + HandleKeyEvent(key : string) : Thenable<{}> { this.keyHistory.push(key); + return Promise.resolve({}); } } \ No newline at end of file diff --git a/src/motion/motion.ts b/src/motion/motion.ts index d5f85c187..3b61d4056 100644 --- a/src/motion/motion.ts +++ b/src/motion/motion.ts @@ -19,6 +19,7 @@ abstract class Motion> { line = currentPosition.line; character = currentPosition.character; } + this.prevColumn = character; this.position = new vscode.Position(line, character); } diff --git a/src/textEditor.ts b/src/textEditor.ts index 52c7f4cc2..83a108591 100644 --- a/src/textEditor.ts +++ b/src/textEditor.ts @@ -6,27 +6,28 @@ export default class TextEditor { position = vscode.window.activeTextEditor.selection.active; } - return vscode.window.activeTextEditor.edit((editBuilder) => { + 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); } - return vscode.window.activeTextEditor.edit((editBuilder) => { + return vscode.window.activeTextEditor.edit(editBuilder => { editBuilder.delete(range); }); } static replace(range: vscode.Range, text: string) : Thenable { - return vscode.window.activeTextEditor.edit((editBuilder) => { + return vscode.window.activeTextEditor.edit(editBuilder => { editBuilder.replace(range, text); }); } diff --git a/src/util.ts b/src/util.ts index f5a554a29..b5c518b72 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,9 +1,9 @@ import * as vscode from 'vscode'; -export function showInfo(message : string) : void { - vscode.window.showInformationMessage("Vim: " + message); +export function showInfo(message : string) : Thenable<{}> { + return vscode.window.showInformationMessage("Vim: " + message); } -export function showError(message : string) : void { - vscode.window.showErrorMessage("Vim: " + message); +export function showError(message : string) : Thenable<{}> { + return vscode.window.showErrorMessage("Vim: " + message); }