From 67cde5765ed4121c3c66e4a8cf87819f61c02cb4 Mon Sep 17 00:00:00 2001 From: berknam Date: Tue, 12 May 2020 23:30:00 +0000 Subject: [PATCH] Fix bugs with a remapped in insert mode (#4829) - Fix DotCommand deleting extra character when used after a remapped in insert mode Fixes #4817 Fixes #4814 - Fix remapped leaving trailing character when used with multiple cursors Fixes #4811 Co-authored-by: Jason Fields --- src/history/historyTracker.ts | 29 +++++++++++++------- test/mode/normalModeTests/dot.test.ts | 39 +++++++++++++++++++++++++++ test/multicursor.test.ts | 27 +++++++++++++++++++ 3 files changed, 85 insertions(+), 10 deletions(-) diff --git a/src/history/historyTracker.ts b/src/history/historyTracker.ts index d3bacef445a..d6a93171991 100644 --- a/src/history/historyTracker.ts +++ b/src/history/historyTracker.ts @@ -609,16 +609,25 @@ export class HistoryTracker { this.currentContentChanges.length - n, this.currentContentChanges.length ); - const firstRemovedChange = removedChanges[0]; - - // Remove the characters from the editor. - await vscode.window.activeTextEditor?.edit((edit) => - edit.delete( - new vscode.Range( - firstRemovedChange!.range.start, - firstRemovedChange!.range.end.translate(0, n) - ) - ) + + // Remove the characters from the editor in reverse order otherwise the characters + // position would change. + await vscode.window.activeTextEditor?.edit((edit) => { + for (const removedChange of removedChanges.reverse()) { + edit.delete( + new vscode.Range( + removedChange.range.start, + removedChange.range.end.translate({ characterDelta: 1 }) + ) + ); + } + }); + + // Remove the previous deletions from currentContentChanges otherwise the DotCommand + // or a recorded macro will be deleting a character that wasn't typed. + this.currentContentChanges.splice( + this.currentContentChanges.length - removedChanges.length, + removedChanges.length ); // We can't ignore the change, because that would mean that addChange() doesn't run. diff --git a/test/mode/normalModeTests/dot.test.ts b/test/mode/normalModeTests/dot.test.ts index 26f6bbf4b83..ed586dbe07d 100644 --- a/test/mode/normalModeTests/dot.test.ts +++ b/test/mode/normalModeTests/dot.test.ts @@ -113,3 +113,42 @@ suite('Repeat content change', () => { end: ['\tonecb', 'tw|co'], }); }); + +suite('Dot Operator repeat with remap', () => { + const { newTest, newTestOnly } = getTestingFunctions(); + + setup(async () => { + const configuration = new Configuration(); + configuration.insertModeKeyBindings = [ + { + before: ['j', 'j', 'k'], + after: [''], + }, + ]; + configuration.normalModeKeyBindings = [ + { + before: ['', 'w'], + after: ['d', 'w'], + }, + ]; + configuration.leader = ' '; + + await setupWorkspace(configuration); + }); + + teardown(cleanUpWorkspace); + + newTest({ + title: "Can repeat content change using 'jjk' mapped to '' without trailing characters", + start: ['on|e', 'two'], + keysPressed: 'ciwfoojjkj.', + end: ['foo', 'fo|o'], + }); + + newTest({ + title: "Can repeat 'w' when mapped to 'dw'", + start: ['|one two three'], + keysPressed: ' w.', + end: ['|three'], + }); +}); \ No newline at end of file diff --git a/test/multicursor.test.ts b/test/multicursor.test.ts index f34b8df5bd4..ca702fa784d 100644 --- a/test/multicursor.test.ts +++ b/test/multicursor.test.ts @@ -2,6 +2,8 @@ import * as assert from 'assert'; import { getAndUpdateModeHandler } from '../extension'; import { ModeHandler } from '../src/mode/modeHandler'; import { assertEqualLines, cleanUpWorkspace, setupWorkspace } from './testUtils'; +import { getTestingFunctions } from './testSimplifier'; +import { Configuration } from './testConfiguration'; suite('Multicursor', () => { let modeHandler: ModeHandler; @@ -103,3 +105,28 @@ suite('Multicursor', () => { assert.strictEqual(modeHandler.vimState.cursors.length, 2); }); }); + +suite('Multicursor with remaps', () => { + const { newTest, newTestOnly } = getTestingFunctions(); + + setup(async () => { + const configuration = new Configuration(); + configuration.insertModeKeyBindings = [ + { + before: ['j', 'j', 'k'], + after: [''], + }, + ]; + + await setupWorkspace(configuration); + }); + + teardown(cleanUpWorkspace); + + newTest({ + title: "Using 'jjk' mapped to '' doesn't leave trailing characters", + start: ['o|ne', 'two'], + keysPressed: 'jAfoojjk', + end: ['onfo|oe', 'twfooo'], + }); +}); \ No newline at end of file