Implement move active tab

This commit is contained in:
Sandeep Somavarapu
2016-07-25 16:59:01 +02:00
parent 985a394b59
commit 435d503317
5 changed files with 142 additions and 70 deletions

View File

@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as vscode from 'vscode';
import {MotionState, Motion} from './motions';
export enum Mode {
@ -34,7 +35,13 @@ export interface IController {
getDeleteRegister(): DeleteRegister;
}
export abstract class AbstractCommandDescriptor {
public abstract createCommand(args?: any): Command;
}
export interface Command {
commandId: string,
args?: any
args?: any[]
}

View File

@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as vscode from 'vscode';
import {
TextEditorCursorStyle,
Position,
@ -135,12 +136,12 @@ export class Controller implements IController {
return `VIM:> ${label}` + (this._currentInput ? ` >${this._currentInput}` : ``);
}
public type(editor: TextEditor, text: string): ITypeResult {
public type(editor: TextEditor, text: string): Thenable<ITypeResult> {
if (this._currentMode !== Mode.NORMAL && this._currentMode !== Mode.REPLACE) {
return {
return Promise.resolve({
hasConsumedInput: false,
executeEditorCommand: null
};
});
}
if (this._currentMode === Mode.REPLACE) {
let pos = editor.selection.active;
@ -150,10 +151,10 @@ export class Controller implements IController {
setPositionAndReveal(editor, pos.line, pos.character + 1);
});
return {
return Promise.resolve({
hasConsumedInput: true,
executeEditorCommand: null
};
});
}
this._currentInput += text;
return this._interpretNormalModeInput(editor);
@ -175,8 +176,31 @@ export class Controller implements IController {
return true;
}
private _interpretNormalModeInput(editor: TextEditor): ITypeResult {
let command = Mappings.findCommand(this._currentInput);
private _interpretNormalModeInput(editor: TextEditor): Thenable<ITypeResult> {
if (this._currentInput.startsWith(':')) {
return vscode.window.showInputBox({value: 'tabm'}).then((value) => {
let motionCommand = value ? Mappings.findMotionCommand(value) : null;
this._currentInput = '';
return {
hasConsumedInput: true,
executeEditorCommand: motionCommand
};
});
}
let result = this._findMapping(this._currentInput, editor);
if (!result) {
// INVALID INPUT - beep!!
this._currentInput = '';
result = {
hasConsumedInput: true,
executeEditorCommand: null
};
}
return Promise.resolve(result);
}
private _findMapping(input: string, editor: TextEditor): ITypeResult {
let command = Mappings.findCommand(input);
if (command) {
this._currentInput = '';
return {
@ -185,7 +209,7 @@ export class Controller implements IController {
};
}
let operator = Mappings.findOperator(this._currentInput);
let operator = Mappings.findOperator(input);
if (operator) {
if (this._isVisual) {
if (operator.runVisual(this, editor)) {
@ -203,7 +227,7 @@ export class Controller implements IController {
};
}
let motionCommand = Mappings.findMotionCommand(this._currentInput, this._isVisual);
let motionCommand = Mappings.findMotionCommand(input, this._isVisual);
if (motionCommand) {
this._currentInput = '';
return {
@ -212,7 +236,7 @@ export class Controller implements IController {
};
}
let motion = Mappings.findMotion(this._currentInput);
let motion = Mappings.findMotion(input);
if (motion) {
let newPos = motion.run(editor.document, editor.selection.active, this._motionState);
if (this._isVisual) {
@ -229,20 +253,14 @@ export class Controller implements IController {
}
// is it motion building
if (this.isMotionPrefix(this._currentInput)) {
if (this.isMotionPrefix(input)) {
return {
hasConsumedInput: true,
executeEditorCommand: null
};
}
// INVALID INPUT - beep!!
this._currentInput = '';
return {
hasConsumedInput: true,
executeEditorCommand: null
};
return null;
}
}

View File

@ -127,17 +127,22 @@ class VimExt {
}
public type(text: string): void {
let r = this._controller.type(vscode.window.activeTextEditor, text);
if (r.hasConsumedInput) {
this._ensureState();
if (r.executeEditorCommand) {
vscode.commands.executeCommand(r.executeEditorCommand.commandId, r.executeEditorCommand.args);
let r = this._controller.type(vscode.window.activeTextEditor, text).then(
(r) => {
if (r.hasConsumedInput) {
this._ensureState();
if (r.executeEditorCommand) {
let args = [r.executeEditorCommand.commandId];
args = args.concat(r.executeEditorCommand.args);
vscode.commands.executeCommand.apply(this, args);
}
return;
}
vscode.commands.executeCommand('default:type', {
text: text
});
}
return;
}
vscode.commands.executeCommand('default:type', {
text: text
});
);
}
public replacePrevChar(text: string, replaceCharCnt: number): void {

View File

@ -5,9 +5,9 @@
'use strict';
import {TextEditor} from 'vscode';
import {Motion, Motions, MotionCommand} from './motions';
import {Motion, Motions} from './motions';
import {Operator, Operators} from './operators';
import {IController, Command} from './common';
import {IController, Command, AbstractCommandDescriptor} from './common';
const CHAR_TO_MOTION: { [char: string]: Motion; } = {};
@ -15,8 +15,8 @@ function defineMotion(char: string, motion: Motion): void {
CHAR_TO_MOTION[char] = motion;
};
const CHAR_TO_MOTION_COMMAND: { [char: string]: MotionCommand; } = {};
function defineMotionCommand(char: string, motionCommand: MotionCommand): void {
const CHAR_TO_MOTION_COMMAND: { [char: string]: AbstractCommandDescriptor; } = {};
function defineMotionCommand(char: string, motionCommand: AbstractCommandDescriptor): void {
CHAR_TO_MOTION_COMMAND[char] = motionCommand;
};
@ -52,6 +52,13 @@ defineMotionCommand('L', Motions.ViewPortBottom);
defineMotion('w', Motions.NextWordStart);
defineMotion('e', Motions.NextWordEnd);
// Window motions
defineMotionCommand('tabm', Motions.MoveActiveEditor);
defineMotionCommand('tabm<', Motions.MoveActiveEditorLeft);
defineMotionCommand('tabm>', Motions.MoveActiveEditorRight);
defineMotionCommand('tabm<<', Motions.MoveActiveEditorFirst);
defineMotionCommand('tabm>>', Motions.MoveActiveEditorLast);
defineMotionCommand('tabm.', Motions.MoveActiveEditorCenter);
const CHAR_TO_OPERATOR: { [char: string]: Operator; } = {};
function defineOperator(char: string, operator: Operator): void {
@ -106,7 +113,10 @@ export class Mappings {
if (!motionCommand) {
motionCommand = CHAR_TO_MOTION_COMMAND[parsed.input.substr(1, 3)];
}
return motionCommand ? motionCommand.command({ isVisual: isVisual, repeat: parsed.repeatCount }) : null;
if (!motionCommand) {
motionCommand = CHAR_TO_MOTION_COMMAND[parsed.input];
}
return motionCommand ? motionCommand.createCommand({ isVisual: isVisual, repeat: parsed.hasRepeatCount ? parsed.repeatCount : undefined}) : null;
}
public static findOperator(input: string): IFoundOperator {
@ -117,10 +127,10 @@ export class Mappings {
}
let operatorArgs = parsed.input.substr(1);
return {
runNormal: (controller: IController, editor:TextEditor) => {
runNormal: (controller: IController, editor: TextEditor) => {
return operator.runNormalMode(controller, editor, parsed.repeatCount, operatorArgs);
},
runVisual: (controller: IController, editor:TextEditor) => {
runVisual: (controller: IController, editor: TextEditor) => {
return operator.runVisualMode(controller, editor, operatorArgs);
}
};
@ -150,6 +160,14 @@ function _parseNumberAndString(input: string): INumberAndString {
input: input.substr(repeatCountMatch[0].length)
};
}
repeatCountMatch = input.match(/(\d+)$/);
if (repeatCountMatch) {
return {
hasRepeatCount: true,
repeatCount: parseInt(repeatCountMatch[1], 10),
input: input.substr(0, input.length - repeatCountMatch[1].length)
};
}
return {
hasRepeatCount: false,
repeatCount: 1,

View File

@ -6,7 +6,7 @@
import {Position, TextDocument} from 'vscode';
import {Words, WordCharacters} from './words';
import {Command} from './common';
import {Command, AbstractCommandDescriptor} from './common';
export class MotionState {
@ -22,12 +22,6 @@ export class MotionState {
}
export abstract class MotionCommand {
public abstract command(args: any): Command;
}
export abstract class Motion {
public abstract run(doc: TextDocument, pos: Position, state: MotionState): Position;
@ -250,37 +244,60 @@ class GoToLineDefinedMotion extends GoToLineMotion {
}
}
class CursorMoveCommand extends MotionCommand {
class CursorMoveCommand extends AbstractCommandDescriptor {
constructor(private to: string, private by?: string) {
super();
}
public command(count?: number): Command {
let cursorMoveArgs= { to: this.to }
public createCommand(args?: any): Command {
let cursorMoveArgs: any = {
to: this.to,
by: this.by,
value: args.repeat || 1,
select: !!args.isVisual
}
return {
commandId: 'cursorMove',
args: this.addArgs(cursorMoveArgs, count)
args: cursorMoveArgs
};
}
protected addArgs(cursorMoveArgs: any, args: any): any {
cursorMoveArgs.select = !!args.isVisual;
if (this.by) {
cursorMoveArgs.by = this.by;
}
return cursorMoveArgs;
}
}
class RepeatCursorMoveCommand extends CursorMoveCommand {
class MoveActiveEditorCommandByPosition extends AbstractCommandDescriptor {
protected addArgs(cursorMoveArgs: any, args: any): any {
cursorMoveArgs.amount = args.repeat || 1;
return super.addArgs(cursorMoveArgs, args);
constructor() {
super();
}
public createCommand(args?: any): Command {
let moveActiveEditorArgs: any = {
to: args.repeat === void 0 ? 'last' : 'position',
value: args.repeat !== void 0 ? args.repeat + 1 : undefined
}
return {
commandId: 'moveActiveEditor',
args: moveActiveEditorArgs
};
}
}
class MoveActiveEditorCommand extends AbstractCommandDescriptor {
constructor(private to: string) {
super();
}
public createCommand(args?: any): Command {
let moveActiveEditorArgs: any = {
to: this.to,
value: args.repeat ? args.repeat : 1
}
return {
commandId: 'moveActiveEditor',
args: moveActiveEditorArgs
};
}
}
export const Motions = {
@ -288,8 +305,8 @@ export const Motions = {
NextCharacter: new NextCharacterMotion(),
Left: new RepeatCursorMoveCommand('left'),
Right: new RepeatCursorMoveCommand('right'),
Left: new CursorMoveCommand('left'),
Right: new CursorMoveCommand('right'),
Down: new DownMotion(),
Up: new UpMotion(),
@ -301,20 +318,27 @@ export const Motions = {
GoToFirstLine: new GoToFirstLineMotion(),
GoToLastLine: new GoToLastLineMotion(),
ScrollLeft: new RepeatCursorMoveCommand('left'),
ScrollRight: new RepeatCursorMoveCommand('right'),
ScrollLeftByHalfLine: new RepeatCursorMoveCommand('left', 'halfLine'),
ScrollRightByHalfLine: new RepeatCursorMoveCommand('right', 'halfLine'),
ScrollLeft: new CursorMoveCommand('left'),
ScrollRight: new CursorMoveCommand('right'),
ScrollLeftByHalfLine: new CursorMoveCommand('left', 'halfLine'),
ScrollRightByHalfLine: new CursorMoveCommand('right', 'halfLine'),
WrappedLineUp: new RepeatCursorMoveCommand('up', 'wrappedLine'),
WrappedLineDown: new RepeatCursorMoveCommand('down', 'wrappedLine'),
WrappedLineUp: new CursorMoveCommand('up', 'wrappedLine'),
WrappedLineDown: new CursorMoveCommand('down', 'wrappedLine'),
WrappedLineStart: new CursorMoveCommand('wrappedLineStart'),
WrappedLineFirstNonWhiteSpaceCharacter: new CursorMoveCommand('wrappedLineFirstNonWhitespaceCharacter'),
WrappedLineColumnCenter: new CursorMoveCommand('wrappedLineColumnCenter'),
WrappedLineEnd: new CursorMoveCommand('wrappedLineEnd'),
ViewPortTop: new RepeatCursorMoveCommand('viewPortTop'),
ViewPortBottom: new RepeatCursorMoveCommand('viewPortBottom'),
ViewPortTop: new CursorMoveCommand('viewPortTop'),
ViewPortBottom: new CursorMoveCommand('viewPortBottom'),
ViewPortCenter: new CursorMoveCommand('viewPortCenter'),
MoveActiveEditor: new MoveActiveEditorCommandByPosition(),
MoveActiveEditorLeft: new MoveActiveEditorCommand('left'),
MoveActiveEditorRight: new MoveActiveEditorCommand('right'),
MoveActiveEditorFirst: new MoveActiveEditorCommand('first'),
MoveActiveEditorLast: new MoveActiveEditorCommand('last'),
MoveActiveEditorCenter: new MoveActiveEditorCommand('center')
};