Update Mode abstract class to properly return promises when calling HandleActivation and HandleKeyEvent

This commit is contained in:
Jason Poon 2015-12-04 08:53:10 -08:00
parent 9a834918c5
commit f74e887d4d
8 changed files with 99 additions and 92 deletions

View File

@ -3,17 +3,17 @@ import * as parser from "./parser";
import * as util from "../util"; import * as util from "../util";
// Shows the vim command line. // Shows the vim command line.
export function showCmdLine(initialText = "") { export function showCmdLine(initialText = "") : Thenable<{}> {
if (!vscode.window.activeTextEditor) { if (!vscode.window.activeTextEditor) {
util.showInfo("No active document."); return util.showInfo("No active document.");
return;
} }
const options : vscode.InputBoxOptions = { const options : vscode.InputBoxOptions = {
prompt: "Vim command line", prompt: "Vim command line",
value: initialText value: initialText
}; };
vscode.window.showInputBox(options).then(
return vscode.window.showInputBox(options).then(
runCmdLine, runCmdLine,
vscode.window.showErrorMessage vscode.window.showErrorMessage
); );

View File

@ -33,7 +33,7 @@ export abstract class Mode {
abstract ShouldBeActivated(key : string, currentMode : ModeName) : boolean; abstract ShouldBeActivated(key : string, currentMode : ModeName) : boolean;
abstract HandleActivation(key : string) : Thenable<void> | void; abstract HandleActivation(key : string) : Thenable<{}>;
abstract HandleKeyEvent(key : string) : void; abstract HandleKeyEvent(key : string) : Thenable<{}>;
} }

View File

@ -4,56 +4,56 @@ import TextEditor from './../textEditor';
import {Cursor} from './../motion/motion'; import {Cursor} from './../motion/motion';
export default class InsertMode extends Mode { export default class InsertMode extends Mode {
private cursor : Cursor;
private activationKeyHandler : { [ key : string] : (cursor : Cursor) => Thenable<void> | void; }; private activationKeyHandler : { [ key : string] : (cursor : Cursor) => Thenable<{}> } = {
private cursor : Cursor = new Cursor(); "i" : () => {
constructor() {
super(ModeName.Insert);
this.activationKeyHandler = {
// insert at cursor // insert at cursor
"i" : (cursor) => { return Promise.resolve({});
// nothing
}, },
"I" : c => {
// insert at the beginning of the line // insert at line beginning
"I" : (cursor) => { cursor.lineBegin().move(); }, return Promise.resolve(c.lineBegin().move());
},
"a" : c => {
// append after the cursor // append after the cursor
"a" : (cursor) => { cursor.right().move(); }, return Promise.resolve(c.right().move());
},
"A" : c => {
// append at the end of the line // append at the end of the line
"A" : (cursor) => { cursor.lineEnd().move(); }, return Promise.resolve(c.lineEnd().move());
},
// open blank line below current line
"o" : () => { "o" : () => {
// open blank line below current line
return vscode.commands.executeCommand("editor.action.insertLineAfter"); return vscode.commands.executeCommand("editor.action.insertLineAfter");
}, },
// open blank line above current line
"O" : () => { "O" : () => {
// open blank line above current line
return vscode.commands.executeCommand("editor.action.insertLineBefore"); return vscode.commands.executeCommand("editor.action.insertLineBefore");
} }
}; };
constructor() {
super(ModeName.Insert);
this.cursor = new Cursor();
} }
ShouldBeActivated(key : string, currentMode : ModeName) : boolean { ShouldBeActivated(key : string, currentMode : ModeName) : boolean {
return key in this.activationKeyHandler; return key in this.activationKeyHandler;
} }
HandleActivation(key : string) : Thenable<void> | void { HandleActivation(key : string) : Thenable<{}> {
this.cursor.reset(); this.cursor.reset();
return this.activationKeyHandler[key](this.cursor); return this.activationKeyHandler[key](this.cursor);
} }
HandleKeyEvent(key : string) : Thenable<boolean> { HandleKeyEvent(key : string) : Thenable<{}> {
this.keyHistory.push(key); this.keyHistory.push(key);
var thenable = TextEditor.insert(this.ResolveKeyValue(key));
vscode.commands.executeCommand("editor.action.triggerSuggest"); return TextEditor
.insert(this.ResolveKeyValue(key))
return thenable; .then(() => {
return vscode.commands.executeCommand("editor.action.triggerSuggest");
});
} }
// Some keys have names that are different to their value. // Some keys have names that are different to their value.

View File

@ -4,62 +4,66 @@ import {ModeName, Mode} from './mode';
import {showCmdLine} from './../cmd_line/main'; import {showCmdLine} from './../cmd_line/main';
import {Caret} from './../motion/motion'; import {Caret} from './../motion/motion';
export default class CommandMode extends Mode { export default class NormalMode extends Mode {
private keyHandler : { [key : string] : () => void; } = {}; private caret : Caret;
private caret : Caret = new 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() { constructor() {
super(ModeName.Normal); super(ModeName.Normal);
this.caret = new Caret();
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"); }
};
} }
ShouldBeActivated(key : string, currentMode : ModeName) : boolean { ShouldBeActivated(key : string, currentMode : ModeName) : boolean {
return (key === 'esc' || key === 'ctrl+['); return (key === 'esc' || key === 'ctrl+[');
} }
HandleActivation(key : string) : void { HandleActivation(key : string) : Thenable<{}> {
this.caret.reset().left().move(); return Promise.resolve(this.caret.reset().left().move());
} }
HandleKeyEvent(key : string) : void { HandleKeyEvent(key : string) : Thenable<{}> {
this.keyHistory.push(key); this.keyHistory.push(key);
return new Promise(resolve => {
let keyHandled = false; let keyHandled = false;
let keysPressed : string;
for (let window = this.keyHistory.length; window > 0; window--) { for (let window = this.keyHistory.length; window > 0; window--) {
let keysPressed = _.takeRight(this.keyHistory, window).join(''); keysPressed = _.takeRight(this.keyHistory, window).join('');
if (this.keyHandler[keysPressed] !== undefined) { if (this.keyHandler[keysPressed] !== undefined) {
keyHandled = true; keyHandled = true;
this.keyHandler[keysPressed]();
break; break;
} }
} }
if (keyHandled) { if (keyHandled) {
this.keyHistory = []; this.keyHistory = [];
return this.keyHandler[keysPressed](this.caret);
} }
resolve();
});
} }
/* /*

View File

@ -10,11 +10,12 @@ export default class VisualMode extends Mode {
return (key === "v" || key === "V") && (currentMode === ModeName.Normal); return (key === "v" || key === "V") && (currentMode === ModeName.Normal);
} }
HandleActivation(key : string) : void { HandleActivation(key : string) : Thenable<{}> {
// do nothing return Promise.resolve({});
} }
HandleKeyEvent(key : string) : void { HandleKeyEvent(key : string) : Thenable<{}> {
this.keyHistory.push(key); this.keyHistory.push(key);
return Promise.resolve({});
} }
} }

View File

@ -19,6 +19,7 @@ abstract class Motion<T extends Motion<any>> {
line = currentPosition.line; line = currentPosition.line;
character = currentPosition.character; character = currentPosition.character;
} }
this.prevColumn = character; this.prevColumn = character;
this.position = new vscode.Position(line, character); this.position = new vscode.Position(line, character);
} }

View File

@ -6,27 +6,28 @@ export default class TextEditor {
position = vscode.window.activeTextEditor.selection.active; position = vscode.window.activeTextEditor.selection.active;
} }
return vscode.window.activeTextEditor.edit((editBuilder) => { return vscode.window.activeTextEditor.edit(editBuilder => {
editBuilder.insert(position, text); editBuilder.insert(position, text);
}); });
} }
static delete(range: vscode.Range = null) : Thenable<boolean> { static delete(range: vscode.Range = null) : Thenable<boolean> {
if (range === null) { if (range === null) {
// delete entire document
let start = new vscode.Position(0, 0); let start = new vscode.Position(0, 0);
let lastLine = vscode.window.activeTextEditor.document.lineCount - 1; let lastLine = vscode.window.activeTextEditor.document.lineCount - 1;
let end = vscode.window.activeTextEditor.document.lineAt(lastLine).range.end; let end = vscode.window.activeTextEditor.document.lineAt(lastLine).range.end;
range = new vscode.Range(start, end); range = new vscode.Range(start, end);
} }
return vscode.window.activeTextEditor.edit((editBuilder) => { return vscode.window.activeTextEditor.edit(editBuilder => {
editBuilder.delete(range); editBuilder.delete(range);
}); });
} }
static replace(range: vscode.Range, text: string) : Thenable<boolean> { static replace(range: vscode.Range, text: string) : Thenable<boolean> {
return vscode.window.activeTextEditor.edit((editBuilder) => { return vscode.window.activeTextEditor.edit(editBuilder => {
editBuilder.replace(range, text); editBuilder.replace(range, text);
}); });
} }

View File

@ -1,9 +1,9 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
export function showInfo(message : string) : void { export function showInfo(message : string) : Thenable<{}> {
vscode.window.showInformationMessage("Vim: " + message); return vscode.window.showInformationMessage("Vim: " + message);
} }
export function showError(message : string) : void { export function showError(message : string) : Thenable<{}> {
vscode.window.showErrorMessage("Vim: " + message); return vscode.window.showErrorMessage("Vim: " + message);
} }