From 8cfd819dadfebd3de3baa41fd77d9fcb5bf317af Mon Sep 17 00:00:00 2001 From: amin roosta Date: Tue, 30 Aug 2016 17:21:42 +0430 Subject: [PATCH 1/7] Implement ; and , --- ROADMAP.md | 4 +- src/actions/actions.ts | 90 ++++++++++++++++++++++-- src/mode/modeHandler.ts | 4 +- test/register/repeatableMovement.test.ts | 49 +++++++++++++ 4 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 test/register/repeatableMovement.test.ts diff --git a/ROADMAP.md b/ROADMAP.md index 61a24264bd0..e71fd385a30 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -54,8 +54,8 @@ Status | Command | Description :white_check_mark: |:1234: F{char} | to the Nth occurrence of {char} to the left :white_check_mark: |:1234: t{char} | till before the Nth occurrence of {char} to the right :white_check_mark: |:1234: T{char} | till before the Nth occurrence of {char} to the left - |:1234: ; | repeat the last "f", "F", "t", or "T" N times - |:1234: , | repeat the last "f", "F", "t", or "T" N times in opposite direction +:white_check_mark: |:1234: ; | repeat the last "f", "F", "t", or "T" N times +:white_check_mark: |:1234: , | repeat the last "f", "F", "t", or "T" N times in opposite direction ## Up-down motions diff --git a/src/actions/actions.ts b/src/actions/actions.ts index 683dd5dc552..42706b371d6 100644 --- a/src/actions/actions.ts +++ b/src/actions/actions.ts @@ -237,6 +237,16 @@ export abstract class BaseMovement extends BaseAction { } } +/** + * Movements that are repeatable by ; and , + */ +export abstract class BaseRepeatableMovement extends BaseMovement { + /** + * Get the reverse of the this movement. f => F + */ + public abstract reverse(): BaseRepeatableMovement; +} + /** * A command is something like , :, v, i, etc. */ @@ -1976,7 +1986,47 @@ class MoveToColumn extends BaseMovement { } @RegisterAction -class MoveFindForward extends BaseMovement { +class MoveRepeat extends BaseMovement { + keys = [";"]; + + public async execActionWithCount(position: Position, vimState: VimState, count: number): Promise { + const movement = VimState.lastRepeatableMovement; + if (movement) { + const result = await movement.execActionWithCount(position,vimState, count); + /** + * For t and T commands vim executes ; as 2; + * This way the cursor will get to the next instance of + */ + if (result instanceof Position && position.isEqual(result) && count <= 1) { + return await movement.execActionWithCount(position,vimState, 2); + } + return result; + } + return position; + } +} + +@RegisterAction +class MoveRepeatReversed extends BaseMovement { + keys = [","]; + + public async execActionWithCount(position: Position, vimState: VimState, count: number): Promise { + const movement = VimState.lastRepeatableMovement; + if (movement) { + let result = await movement.reverse().execActionWithCount(position,vimState, count); + // For t and T commands vim executes ; as 2; + if (result instanceof Position && position.isEqual(result) && count <= 1) { + result = await movement.reverse().execActionWithCount(position,vimState, 2); + } + VimState.lastRepeatableMovement = movement; + return result; + } + return position; + } +} + +@RegisterAction +class MoveFindForward extends BaseRepeatableMovement { keys = ["f", ""]; public async execActionWithCount(position: Position, vimState: VimState, count: number): Promise { @@ -1990,14 +2040,22 @@ class MoveFindForward extends BaseMovement { if (vimState.recordedState.operator) { result = result.getRight(); + } else { + VimState.lastRepeatableMovement = this; } return result; } + + public reverse() : BaseRepeatableMovement { + let reverse = new MoveFindBackward(); + reverse.keysPressed = ['F', this.keysPressed[1]]; + return reverse; + } } @RegisterAction -class MoveFindBackward extends BaseMovement { +class MoveFindBackward extends BaseRepeatableMovement { keys = ["F", ""]; public async execActionWithCount(position: Position, vimState: VimState, count: number): Promise { @@ -2007,15 +2065,23 @@ class MoveFindBackward extends BaseMovement { if (!result) { return { start: position, stop: position, failed: true }; + } else { + VimState.lastRepeatableMovement = this; } return result; } + + public reverse() : BaseRepeatableMovement { + let reverse = new MoveFindForward(); + reverse.keysPressed = ['f', this.keysPressed[1]]; + return reverse; + } } @RegisterAction -class MoveTilForward extends BaseMovement { +class MoveTilForward extends BaseRepeatableMovement { keys = ["t", ""]; public async execActionWithCount(position: Position, vimState: VimState, count: number): Promise { @@ -2029,14 +2095,22 @@ class MoveTilForward extends BaseMovement { if (vimState.recordedState.operator) { result = result.getRight(); + } else { + VimState.lastRepeatableMovement = this; } return result; } + + public reverse() : BaseRepeatableMovement { + let reverse = new MoveTilBackward(); + reverse.keysPressed = ['T', this.keysPressed[1]]; + return reverse; + } } @RegisterAction -class MoveTilBackward extends BaseMovement { +class MoveTilBackward extends BaseRepeatableMovement { keys = ["T", ""]; public async execActionWithCount(position: Position, vimState: VimState, count: number): Promise { @@ -2046,10 +2120,18 @@ class MoveTilBackward extends BaseMovement { if (!result) { return { start: position, stop: position, failed: true }; + } else { + VimState.lastRepeatableMovement = this; } return result; } + + public reverse() : BaseRepeatableMovement { + let reverse = new MoveTilForward(); + reverse.keysPressed = ['t', this.keysPressed[1]]; + return reverse; + } } @RegisterAction diff --git a/src/mode/modeHandler.ts b/src/mode/modeHandler.ts index 838cc01a120..7ce5517b0de 100644 --- a/src/mode/modeHandler.ts +++ b/src/mode/modeHandler.ts @@ -18,7 +18,7 @@ import { VisualLineMode } from './modeVisualLine'; import { HistoryTracker } from './../history/historyTracker'; import { BaseMovement, BaseCommand, Actions, BaseAction, - BaseOperator, isIMovement, + BaseOperator, isIMovement, BaseRepeatableMovement, KeypressState } from './../actions/actions'; import { Position } from './../motion/position'; import { RegisterMode } from './../register/register'; @@ -54,6 +54,8 @@ export class VimState { public historyTracker: HistoryTracker; + public static lastRepeatableMovement : BaseRepeatableMovement | undefined = undefined; + /** * The keystroke sequence that made up our last complete action (that can be * repeated with '.'). diff --git a/test/register/repeatableMovement.test.ts b/test/register/repeatableMovement.test.ts new file mode 100644 index 00000000000..0ac8a07eba3 --- /dev/null +++ b/test/register/repeatableMovement.test.ts @@ -0,0 +1,49 @@ +"use strict"; + +import { ModeHandler } from "../../src/mode/modeHandler"; +import { setupWorkspace, cleanUpWorkspace, assertEqualLines } from '../testUtils'; +import { getTestingFunctions } from '../testSimplifier'; + +suite("register", () => { + let modeHandler: ModeHandler = new ModeHandler(); + + let { + newTest, + newTestOnly, + } = getTestingFunctions(modeHandler); + + setup(async () => { + await setupWorkspace(); + }); + + suiteTeardown(cleanUpWorkspace); + + newTest({ + title: "Can repeat f", + start: ['|abc abc abc'], + keysPressed: 'fa;', + end: ['abc abc |abc'], + }); + + newTest({ + title: "Can repeat reversed F", + start: ['|abc abc abc'], + keysPressed: 'fa$,', + end: ['abc abc |abc'], + }); + + newTest({ + title: "Can repeat t", + start: ['|abc abc abc'], + keysPressed: 'tc;', + end: ['abc a|bc abc'], + }); + + newTest({ + title: "Can repeat N times reversed t", + start: ['|abc abc abc abc'], + keysPressed: 'tc$3,', + end: ['abc| abc abc abc'], + }); + +}); \ No newline at end of file From 287c2efb4fe7ac4cbd4d56d1799cc17db72d18a5 Mon Sep 17 00:00:00 2001 From: amin roosta Date: Tue, 30 Aug 2016 17:43:34 +0430 Subject: [PATCH 2/7] Trying to fix travis ci agent (which does not handle clipboard tests well) --- test/register/register.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/register/register.test.ts b/test/register/register.test.ts index 3e1ada972ec..6f67906566d 100644 --- a/test/register/register.test.ts +++ b/test/register/register.test.ts @@ -44,7 +44,7 @@ suite("register", () => { newTest({ title: "Can use two registers together", start: ['|one', "two"], - keysPressed: '"*yyjyy"*pp', + keysPressed: '"ayyj"byy"ap"bp', end: ["one", "two", "one", "|two"], }); From 87296c3fccf9e4ffd9707b6f0be29a3f95fecfd2 Mon Sep 17 00:00:00 2001 From: amin roosta Date: Tue, 30 Aug 2016 17:50:45 +0430 Subject: [PATCH 3/7] fix tslint errors --- src/actions/actions.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/actions/actions.ts b/src/actions/actions.ts index 42706b371d6..58d857471e4 100644 --- a/src/actions/actions.ts +++ b/src/actions/actions.ts @@ -1992,13 +1992,13 @@ class MoveRepeat extends BaseMovement { public async execActionWithCount(position: Position, vimState: VimState, count: number): Promise { const movement = VimState.lastRepeatableMovement; if (movement) { - const result = await movement.execActionWithCount(position,vimState, count); + const result = await movement.execActionWithCount(position, vimState, count); /** * For t and T commands vim executes ; as 2; * This way the cursor will get to the next instance of */ if (result instanceof Position && position.isEqual(result) && count <= 1) { - return await movement.execActionWithCount(position,vimState, 2); + return await movement.execActionWithCount(position, vimState, 2); } return result; } @@ -2013,10 +2013,10 @@ class MoveRepeatReversed extends BaseMovement { public async execActionWithCount(position: Position, vimState: VimState, count: number): Promise { const movement = VimState.lastRepeatableMovement; if (movement) { - let result = await movement.reverse().execActionWithCount(position,vimState, count); + let result = await movement.reverse().execActionWithCount(position, vimState, count); // For t and T commands vim executes ; as 2; if (result instanceof Position && position.isEqual(result) && count <= 1) { - result = await movement.reverse().execActionWithCount(position,vimState, 2); + result = await movement.reverse().execActionWithCount(position, vimState, 2); } VimState.lastRepeatableMovement = movement; return result; From 2a2a76368bc4ad0fab7a34f9219b02914cfafa4b Mon Sep 17 00:00:00 2001 From: amin roosta Date: Tue, 30 Aug 2016 23:06:53 +0430 Subject: [PATCH 4/7] cleanup --- src/actions/actions.ts | 128 ++++++++++++++++------------------------ src/mode/modeHandler.ts | 4 +- 2 files changed, 54 insertions(+), 78 deletions(-) diff --git a/src/actions/actions.ts b/src/actions/actions.ts index 58d857471e4..33114dbc73a 100644 --- a/src/actions/actions.ts +++ b/src/actions/actions.ts @@ -237,16 +237,6 @@ export abstract class BaseMovement extends BaseAction { } } -/** - * Movements that are repeatable by ; and , - */ -export abstract class BaseRepeatableMovement extends BaseMovement { - /** - * Get the reverse of the this movement. f => F - */ - public abstract reverse(): BaseRepeatableMovement; -} - /** * A command is something like , :, v, i, etc. */ @@ -1986,47 +1976,7 @@ class MoveToColumn extends BaseMovement { } @RegisterAction -class MoveRepeat extends BaseMovement { - keys = [";"]; - - public async execActionWithCount(position: Position, vimState: VimState, count: number): Promise { - const movement = VimState.lastRepeatableMovement; - if (movement) { - const result = await movement.execActionWithCount(position, vimState, count); - /** - * For t and T commands vim executes ; as 2; - * This way the cursor will get to the next instance of - */ - if (result instanceof Position && position.isEqual(result) && count <= 1) { - return await movement.execActionWithCount(position, vimState, 2); - } - return result; - } - return position; - } -} - -@RegisterAction -class MoveRepeatReversed extends BaseMovement { - keys = [","]; - - public async execActionWithCount(position: Position, vimState: VimState, count: number): Promise { - const movement = VimState.lastRepeatableMovement; - if (movement) { - let result = await movement.reverse().execActionWithCount(position, vimState, count); - // For t and T commands vim executes ; as 2; - if (result instanceof Position && position.isEqual(result) && count <= 1) { - result = await movement.reverse().execActionWithCount(position, vimState, 2); - } - VimState.lastRepeatableMovement = movement; - return result; - } - return position; - } -} - -@RegisterAction -class MoveFindForward extends BaseRepeatableMovement { +class MoveFindForward extends BaseMovement { keys = ["f", ""]; public async execActionWithCount(position: Position, vimState: VimState, count: number): Promise { @@ -2046,16 +1996,10 @@ class MoveFindForward extends BaseRepeatableMovement { return result; } - - public reverse() : BaseRepeatableMovement { - let reverse = new MoveFindBackward(); - reverse.keysPressed = ['F', this.keysPressed[1]]; - return reverse; - } } @RegisterAction -class MoveFindBackward extends BaseRepeatableMovement { +class MoveFindBackward extends BaseMovement { keys = ["F", ""]; public async execActionWithCount(position: Position, vimState: VimState, count: number): Promise { @@ -2071,17 +2015,11 @@ class MoveFindBackward extends BaseRepeatableMovement { return result; } - - public reverse() : BaseRepeatableMovement { - let reverse = new MoveFindForward(); - reverse.keysPressed = ['f', this.keysPressed[1]]; - return reverse; - } } @RegisterAction -class MoveTilForward extends BaseRepeatableMovement { +class MoveTilForward extends BaseMovement { keys = ["t", ""]; public async execActionWithCount(position: Position, vimState: VimState, count: number): Promise { @@ -2101,16 +2039,10 @@ class MoveTilForward extends BaseRepeatableMovement { return result; } - - public reverse() : BaseRepeatableMovement { - let reverse = new MoveTilBackward(); - reverse.keysPressed = ['T', this.keysPressed[1]]; - return reverse; - } } @RegisterAction -class MoveTilBackward extends BaseRepeatableMovement { +class MoveTilBackward extends BaseMovement { keys = ["T", ""]; public async execActionWithCount(position: Position, vimState: VimState, count: number): Promise { @@ -2126,11 +2058,55 @@ class MoveTilBackward extends BaseRepeatableMovement { return result; } +} + +@RegisterAction +class MoveRepeat extends BaseMovement { + keys = [";"]; + + public async execActionWithCount(position: Position, vimState: VimState, count: number): Promise { + const movement = VimState.lastRepeatableMovement; + if (movement) { + const result = await movement.execActionWithCount(position, vimState, count); + /** + * For t and T commands vim executes ; as 2; + * This way the cursor will get to the next instance of + */ + if (result instanceof Position && position.isEqual(result) && count <= 1) { + return await movement.execActionWithCount(position, vimState, 2); + } + return result; + } + return position; + } +} + + +@RegisterAction +class MoveRepeatReversed extends BaseMovement { + keys = [","]; + static reverseMotionMapping : Map BaseMovement> = new Map([ + [MoveFindForward, () => new MoveFindBackward()], + [MoveFindBackward, () => new MoveFindForward()], + [MoveTilForward, () => new MoveTilBackward()], + [MoveTilBackward, () => new MoveTilForward()] + ]); - public reverse() : BaseRepeatableMovement { - let reverse = new MoveTilForward(); - reverse.keysPressed = ['t', this.keysPressed[1]]; - return reverse; + public async execActionWithCount(position: Position, vimState: VimState, count: number): Promise { + const movement = VimState.lastRepeatableMovement; + if (movement) { + const reverse = MoveRepeatReversed.reverseMotionMapping.get(movement.constructor)(); + reverse.keysPressed = [reverse.keys[0], movement.keysPressed[1]]; + + let result = await reverse.execActionWithCount(position, vimState, count); + // For t and T commands vim executes ; as 2; + if (result instanceof Position && position.isEqual(result) && count <= 1) { + result = await reverse.execActionWithCount(position, vimState, 2); + } + VimState.lastRepeatableMovement = movement; + return result; + } + return position; } } diff --git a/src/mode/modeHandler.ts b/src/mode/modeHandler.ts index 7ce5517b0de..472151f62fd 100644 --- a/src/mode/modeHandler.ts +++ b/src/mode/modeHandler.ts @@ -18,7 +18,7 @@ import { VisualLineMode } from './modeVisualLine'; import { HistoryTracker } from './../history/historyTracker'; import { BaseMovement, BaseCommand, Actions, BaseAction, - BaseOperator, isIMovement, BaseRepeatableMovement, + BaseOperator, isIMovement, KeypressState } from './../actions/actions'; import { Position } from './../motion/position'; import { RegisterMode } from './../register/register'; @@ -54,7 +54,7 @@ export class VimState { public historyTracker: HistoryTracker; - public static lastRepeatableMovement : BaseRepeatableMovement | undefined = undefined; + public static lastRepeatableMovement : BaseMovement | undefined = undefined; /** * The keystroke sequence that made up our last complete action (that can be From 7cbfdc56f0c0cf7b595bb5f826fc45baa9c7a9e0 Mon Sep 17 00:00:00 2001 From: amin roosta Date: Wed, 31 Aug 2016 14:30:26 +0430 Subject: [PATCH 5/7] more cleanup --- src/actions/actions.ts | 14 +++++++++----- src/mode/modeHandler.ts | 4 ++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/actions/actions.ts b/src/actions/actions.ts index 33114dbc73a..7caef54c4e0 100644 --- a/src/actions/actions.ts +++ b/src/actions/actions.ts @@ -156,6 +156,11 @@ export abstract class BaseMovement extends BaseAction { canBePrefixedWithCount = false; + /** + * Whether we should change lastRepeatableMovement in VimState. + */ + public repeatableWithSemicolonOrComma = false; + /** * Whether we should change desiredColumn in VimState. */ @@ -1991,7 +1996,7 @@ class MoveFindForward extends BaseMovement { if (vimState.recordedState.operator) { result = result.getRight(); } else { - VimState.lastRepeatableMovement = this; + this.repeatableWithSemicolonOrComma = true; } return result; @@ -2010,7 +2015,7 @@ class MoveFindBackward extends BaseMovement { if (!result) { return { start: position, stop: position, failed: true }; } else { - VimState.lastRepeatableMovement = this; + this.repeatableWithSemicolonOrComma = true; } return result; @@ -2034,7 +2039,7 @@ class MoveTilForward extends BaseMovement { if (vimState.recordedState.operator) { result = result.getRight(); } else { - VimState.lastRepeatableMovement = this; + this.repeatableWithSemicolonOrComma = true; } return result; @@ -2053,7 +2058,7 @@ class MoveTilBackward extends BaseMovement { if (!result) { return { start: position, stop: position, failed: true }; } else { - VimState.lastRepeatableMovement = this; + this.repeatableWithSemicolonOrComma = true; } return result; @@ -2103,7 +2108,6 @@ class MoveRepeatReversed extends BaseMovement { if (result instanceof Position && position.isEqual(result) && count <= 1) { result = await reverse.execActionWithCount(position, vimState, 2); } - VimState.lastRepeatableMovement = movement; return result; } return position; diff --git a/src/mode/modeHandler.ts b/src/mode/modeHandler.ts index 472151f62fd..fc03b434f0a 100644 --- a/src/mode/modeHandler.ts +++ b/src/mode/modeHandler.ts @@ -864,6 +864,10 @@ export class ModeHandler implements vscode.Disposable { } } + if (movement.repeatableWithSemicolonOrComma) { + VimState.lastRepeatableMovement = movement; + } + vimState.recordedState.count = 0; let stop = vimState.cursorPosition; From e87d11030d4ec89107eb001d7a5e6b784bebb0fc Mon Sep 17 00:00:00 2001 From: amin roosta Date: Thu, 1 Sep 2016 05:32:16 +0430 Subject: [PATCH 6/7] even more cleanup --- src/actions/actions.ts | 40 +++++++++++++++++++++++++++++++--------- src/mode/modeHandler.ts | 2 +- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/actions/actions.ts b/src/actions/actions.ts index 7caef54c4e0..e34d636c618 100644 --- a/src/actions/actions.ts +++ b/src/actions/actions.ts @@ -159,7 +159,9 @@ export abstract class BaseMovement extends BaseAction { /** * Whether we should change lastRepeatableMovement in VimState. */ - public repeatableWithSemicolonOrComma = false; + public canBeRepeatedWithSemicolon(vimState: VimState, result: Position | IMovement) { + return false; + } /** * Whether we should change desiredColumn in VimState. @@ -1995,12 +1997,17 @@ class MoveFindForward extends BaseMovement { if (vimState.recordedState.operator) { result = result.getRight(); - } else { - this.repeatableWithSemicolonOrComma = true; } return result; } + + public canBeRepeatedWithSemicolon(vimState: VimState, result: Position | IMovement) { + if (vimState.recordedState.operator) { + return false; + } + return !isIMovement(result) || !result.failed; + } } @RegisterAction @@ -2014,12 +2021,17 @@ class MoveFindBackward extends BaseMovement { if (!result) { return { start: position, stop: position, failed: true }; - } else { - this.repeatableWithSemicolonOrComma = true; } return result; } + + public canBeRepeatedWithSemicolon(vimState: VimState, result: Position | IMovement) { + if (vimState.recordedState.operator) { + return false; + } + return !isIMovement(result) || !result.failed; + } } @@ -2038,12 +2050,17 @@ class MoveTilForward extends BaseMovement { if (vimState.recordedState.operator) { result = result.getRight(); - } else { - this.repeatableWithSemicolonOrComma = true; } return result; } + + public canBeRepeatedWithSemicolon(vimState: VimState, result: Position | IMovement) { + if (vimState.recordedState.operator) { + return false; + } + return !isIMovement(result) || !result.failed; + } } @RegisterAction @@ -2057,12 +2074,17 @@ class MoveTilBackward extends BaseMovement { if (!result) { return { start: position, stop: position, failed: true }; - } else { - this.repeatableWithSemicolonOrComma = true; } return result; } + + public canBeRepeatedWithSemicolon(vimState: VimState, result: Position | IMovement) { + if (vimState.recordedState.operator) { + return false; + } + return !isIMovement(result) || !result.failed; + } } @RegisterAction diff --git a/src/mode/modeHandler.ts b/src/mode/modeHandler.ts index fc03b434f0a..cb720b8dd19 100644 --- a/src/mode/modeHandler.ts +++ b/src/mode/modeHandler.ts @@ -864,7 +864,7 @@ export class ModeHandler implements vscode.Disposable { } } - if (movement.repeatableWithSemicolonOrComma) { + if (movement.canBeRepeatedWithSemicolon(vimState, result)) { VimState.lastRepeatableMovement = movement; } From 564ecd75fc18e11ded0c9217237ee8a8fdae3fe0 Mon Sep 17 00:00:00 2001 From: amin roosta Date: Sat, 3 Sep 2016 01:52:36 +0430 Subject: [PATCH 7/7] and more cleanup --- src/actions/actions.ts | 20 ++++---------------- test/index.ts | 2 +- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/src/actions/actions.ts b/src/actions/actions.ts index e34d636c618..de43b22fcbc 100644 --- a/src/actions/actions.ts +++ b/src/actions/actions.ts @@ -2003,10 +2003,7 @@ class MoveFindForward extends BaseMovement { } public canBeRepeatedWithSemicolon(vimState: VimState, result: Position | IMovement) { - if (vimState.recordedState.operator) { - return false; - } - return !isIMovement(result) || !result.failed; + return !vimState.recordedState.operator || !(isIMovement(result) && result.failed); } } @@ -2027,10 +2024,7 @@ class MoveFindBackward extends BaseMovement { } public canBeRepeatedWithSemicolon(vimState: VimState, result: Position | IMovement) { - if (vimState.recordedState.operator) { - return false; - } - return !isIMovement(result) || !result.failed; + return !vimState.recordedState.operator || !(isIMovement(result) && result.failed); } } @@ -2056,10 +2050,7 @@ class MoveTilForward extends BaseMovement { } public canBeRepeatedWithSemicolon(vimState: VimState, result: Position | IMovement) { - if (vimState.recordedState.operator) { - return false; - } - return !isIMovement(result) || !result.failed; + return !vimState.recordedState.operator || !(isIMovement(result) && result.failed); } } @@ -2080,10 +2071,7 @@ class MoveTilBackward extends BaseMovement { } public canBeRepeatedWithSemicolon(vimState: VimState, result: Position | IMovement) { - if (vimState.recordedState.operator) { - return false; - } - return !isIMovement(result) || !result.failed; + return !vimState.recordedState.operator || !(isIMovement(result) && result.failed); } } diff --git a/test/index.ts b/test/index.ts index 94753f3d397..0a53dcb3423 100644 --- a/test/index.ts +++ b/test/index.ts @@ -23,7 +23,7 @@ Globals.isTesting = true; testRunner.configure({ ui: 'tdd', useColors: true, - timeout: 2500, + timeout: 4000, }); module.exports = testRunner;