diff --git a/vim-sample/src/controller.ts b/vim-sample/src/controller.ts index 5ffac135..2ef81cd2 100644 --- a/vim-sample/src/controller.ts +++ b/vim-sample/src/controller.ts @@ -203,7 +203,7 @@ export class Controller implements IController { }; } - let motionCommand = Mappings.findMotionCommand(this._currentInput); + let motionCommand = Mappings.findMotionCommand(this._currentInput, this._isVisual); if (motionCommand) { this._currentInput = ''; return { diff --git a/vim-sample/src/mappings.ts b/vim-sample/src/mappings.ts index 593c1607..70bb7012 100644 --- a/vim-sample/src/mappings.ts +++ b/vim-sample/src/mappings.ts @@ -21,23 +21,33 @@ function defineMotionCommand(char: string, motionCommand: MotionCommand): void { }; // Left-right motions -defineMotion('h', Motions.Left); -defineMotion('l', Motions.Right); +defineMotionCommand('h', Motions.Left); +defineMotionCommand('l', Motions.Right); defineMotion('0', Motions.StartOfLine); defineMotion('$', Motions.EndOfLine); -defineMotionCommand('g0', Motions.LineStart); -defineMotionCommand('g^', Motions.LineFirstNonWhiteSpaceCharacter); -defineMotionCommand('gm', Motions.LineColumnCenter); -defineMotionCommand('g$', Motions.LineEnd); +defineMotionCommand('g0', Motions.WrappedLineStart); +defineMotionCommand('g^', Motions.WrappedLineFirstNonWhiteSpaceCharacter); +defineMotionCommand('gm', Motions.WrappedLineColumnCenter); +defineMotionCommand('g$', Motions.WrappedLineEnd); + +// Scroll motions +defineMotionCommand('zh', Motions.ScrollLeft); +defineMotionCommand('zl', Motions.ScrollRight); +defineMotionCommand('zH', Motions.ScrollLeftByHalfLine); +defineMotionCommand('zL', Motions.ScrollRightByHalfLine); // Up-down motions defineMotion('j', Motions.Down); defineMotion('k', Motions.Up); -defineMotionCommand('gj', Motions.ViewLineDown); -defineMotionCommand('gk', Motions.ViewLineUp); +defineMotionCommand('gj', Motions.WrappedLineDown); +defineMotionCommand('gk', Motions.WrappedLineUp); defineMotion('G', Motions.GoToLine); defineMotion('gg', Motions.GoToFirstLine); +defineMotionCommand('H', Motions.ViewPortTop); +defineMotionCommand('M', Motions.ViewPortCenter); +defineMotionCommand('L', Motions.ViewPortBottom); + // Word motions defineMotion('w', Motions.NextWordStart); defineMotion('e', Motions.NextWordEnd); @@ -84,7 +94,7 @@ export class Mappings { return motion.repeat(parsed.hasRepeatCount, parsed.repeatCount); } - public static findMotionCommand(input: string): Command { + public static findMotionCommand(input: string, isVisual: boolean = false): Command { let parsed = _parseNumberAndString(input); let motionCommand = CHAR_TO_MOTION_COMMAND[parsed.input.substr(0, 1)]; if (!motionCommand) { @@ -96,7 +106,7 @@ export class Mappings { if (!motionCommand) { motionCommand = CHAR_TO_MOTION_COMMAND[parsed.input.substr(1, 3)]; } - return motionCommand ? motionCommand.command(parsed.repeatCount) : null; + return motionCommand ? motionCommand.command({ isVisual: isVisual, repeat: parsed.repeatCount }) : null; } public static findOperator(input: string): IFoundOperator { @@ -124,10 +134,10 @@ export class Mappings { if (input.length === 0) { return true; } - if (input === 'g') { + if (input === 'g' || input === 'v' || input === 'z') { return true; } - return /^[1-9]\d*g?$/.test(input); + return /^[1-9]\d*v?g?z?$/.test(input); } } diff --git a/vim-sample/src/motions.ts b/vim-sample/src/motions.ts index e7d15e90..69409b6c 100644 --- a/vim-sample/src/motions.ts +++ b/vim-sample/src/motions.ts @@ -24,7 +24,7 @@ export class MotionState { export abstract class MotionCommand { - public abstract command(args?: any): Command; + public abstract command(args: any): Command; } @@ -250,9 +250,9 @@ class GoToLineDefinedMotion extends GoToLineMotion { } } -abstract class CursorMoveCommand extends MotionCommand { +class CursorMoveCommand extends MotionCommand { - constructor(private to: string) { + constructor(private to: string, private by?: string) { super(); } @@ -264,65 +264,35 @@ abstract class CursorMoveCommand extends MotionCommand { }; } - protected addArgs(cursorMoveArgs: any, count?: number): any { + protected addArgs(cursorMoveArgs: any, args: any): any { + cursorMoveArgs.select = !!args.isVisual; + if (this.by) { + cursorMoveArgs.by = this.by; + } return cursorMoveArgs; } } -class LineStartMotionCommand extends CursorMoveCommand { - constructor() { - super('lineStart'); - } -} +class RepeatCursorMoveCommand extends CursorMoveCommand { -class LineFirstNonWhiteSpaceCharacterMotionCommand extends CursorMoveCommand { - constructor() { - super('lineFirstNonWhitespaceCharacter'); - } -} - -class LineColumnCenterMotionCommand extends CursorMoveCommand { - constructor() { - super('lineColumnCenter'); - } -} - -class LineEndMotionCommand extends CursorMoveCommand { - constructor() { - super('lineEnd'); - } -} - - -class ViewLineUpMotionCommand extends CursorMoveCommand { - constructor() { - super('lineUp'); + protected addArgs(cursorMoveArgs: any, args: any): any { + cursorMoveArgs.amount = args.repeat || 1; + return super.addArgs(cursorMoveArgs, args); } - protected addArgs(cursorMoveArgs: any, count?: number): any { - cursorMoveArgs.noOfLines= count || 1; - return super.addArgs(cursorMoveArgs); - } -} - -class ViewLineDownMotionCommand extends CursorMoveCommand { - constructor() { - super('lineDown'); - } - - protected addArgs(cursorMoveArgs: any, count?: number): any { - cursorMoveArgs.noOfLines= count || 1; - return super.addArgs(cursorMoveArgs); - } } export const Motions = { + RightMotion: new RightMotion(), + NextCharacter: new NextCharacterMotion(), - Left: new LeftMotion(), + + Left: new RepeatCursorMoveCommand('left'), + Right: new RepeatCursorMoveCommand('right'), Down: new DownMotion(), Up: new UpMotion(), - Right: new RightMotion(), + EndOfLine: new EndOfLineMotion(), StartOfLine: new StartOfLineMotion(), NextWordStart: new NextWordStartMotion(), @@ -331,10 +301,20 @@ export const Motions = { GoToFirstLine: new GoToFirstLineMotion(), GoToLastLine: new GoToLastLineMotion(), - LineStart: new LineStartMotionCommand(), - LineFirstNonWhiteSpaceCharacter: new LineFirstNonWhiteSpaceCharacterMotionCommand(), - LineColumnCenter: new LineColumnCenterMotionCommand(), - LineEnd: new LineEndMotionCommand(), - ViewLineUp: new ViewLineUpMotionCommand(), - ViewLineDown: new ViewLineDownMotionCommand(), + ScrollLeft: new RepeatCursorMoveCommand('left'), + ScrollRight: new RepeatCursorMoveCommand('right'), + ScrollLeftByHalfLine: new RepeatCursorMoveCommand('left', 'halfLine'), + ScrollRightByHalfLine: new RepeatCursorMoveCommand('right', 'halfLine'), + + WrappedLineUp: new RepeatCursorMoveCommand('up', 'wrappedLine'), + WrappedLineDown: new RepeatCursorMoveCommand('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'), + ViewPortCenter: new CursorMoveCommand('viewPortCenter'), }; diff --git a/vim-sample/src/operators.ts b/vim-sample/src/operators.ts index a2f2a9e1..716a30ef 100644 --- a/vim-sample/src/operators.ts +++ b/vim-sample/src/operators.ts @@ -58,7 +58,7 @@ class InsertOperator extends OperatorWithNoArgs { class AppendOperator extends OperatorWithNoArgs { protected _run(ctrl: IController, ed:TextEditor): void { - let newPos = Motions.Right.run(this.doc(ed), this.pos(ed), ctrl.motionState); + let newPos = Motions.RightMotion.run(this.doc(ed), this.pos(ed), ctrl.motionState); this.setPosReveal(ed, newPos.line, newPos.character); ctrl.setMode(Mode.INSERT); }