From 2947f3b79e8b8ce20a86241866cb5a2280b2d898 Mon Sep 17 00:00:00 2001 From: aioute Gao Date: Tue, 27 Sep 2016 14:41:54 +0900 Subject: [PATCH 1/4] Rename method. --- src/Actions/Delete.ts | 2 +- src/Modes/Normal.ts | 2 +- src/Modes/Visual.ts | 8 ++++---- src/Modes/VisualLine.ts | 20 ++++++++++---------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Actions/Delete.ts b/src/Actions/Delete.ts index 0f8799de..89529c2d 100644 --- a/src/Actions/Delete.ts +++ b/src/Actions/Delete.ts @@ -218,7 +218,7 @@ export class ActionDelete { } @PrototypeReflect.metadata(SymbolMetadata.Action.isChange, true) - static line(args: { + static byLines(args: { shouldYank?: boolean }): Thenable { args.shouldYank = args.shouldYank === undefined ? false : args.shouldYank; diff --git a/src/Modes/Normal.ts b/src/Modes/Normal.ts index 473bcb89..b86468d3 100644 --- a/src/Modes/Normal.ts +++ b/src/Modes/Normal.ts @@ -77,7 +77,7 @@ export class ModeNormal extends Mode { ], args: { shouldYank: true } }, - { keys: 'd d', actions: [ActionDelete.line], args: {shouldYank: true} }, + { keys: 'd d', actions: [ActionDelete.byLines], args: {shouldYank: true} }, { keys: 'D', actions: [ ActionDelete.byMotions, ActionSelection.validateSelections, diff --git a/src/Modes/Visual.ts b/src/Modes/Visual.ts index c147550a..96cd139b 100644 --- a/src/Modes/Visual.ts +++ b/src/Modes/Visual.ts @@ -40,15 +40,15 @@ export class ModeVisual extends Mode { { keys: 'backspace', actions: [ActionDelete.selectionsOrRight], args: {shouldYank: true} }, { keys: 'delete', actions: [ActionDelete.selectionsOrRight], args: {shouldYank: true} }, { keys: 'x', actions: [ActionDelete.selectionsOrRight], args: {shouldYank: true} }, - { keys: 'X', actions: [ActionDelete.line], args: {shouldYank: true} }, + { keys: 'X', actions: [ActionDelete.byLines], args: {shouldYank: true} }, { keys: 'd', actions: [ActionDelete.selectionsOrRight], args: {shouldYank: true} }, - { keys: 'D', actions: [ActionDelete.line], args: {shouldYank: true} }, + { keys: 'D', actions: [ActionDelete.byLines], args: {shouldYank: true} }, { keys: 'c', actions: [ ActionDelete.selectionsOrRight, ActionMode.toInsert, ], args: {shouldYank: true} }, { keys: 'C', actions: [ - ActionDelete.line, + ActionDelete.byLines, ActionInsert.newLineBefore, ActionMode.toInsert, ], args: {shouldYank: true} }, @@ -57,7 +57,7 @@ export class ModeVisual extends Mode { ActionMode.toInsert, ], args: {shouldYank: true} }, { keys: 'S', actions: [ - ActionDelete.line, + ActionDelete.byLines, ActionInsert.newLineBefore, ActionMode.toInsert, ], args: {shouldYank: true} }, diff --git a/src/Modes/VisualLine.ts b/src/Modes/VisualLine.ts index e075f081..2512b603 100644 --- a/src/Modes/VisualLine.ts +++ b/src/Modes/VisualLine.ts @@ -36,29 +36,29 @@ export class ModeVisualLine extends Mode { ActionMode.toInsert ] }, - { keys: 'backspace', actions: [ActionDelete.line], args: {shouldYank: true} }, - { keys: 'delete', actions: [ActionDelete.line], args: {shouldYank: true} }, - { keys: 'x', actions: [ActionDelete.line], args: {shouldYank: true} }, - { keys: 'X', actions: [ActionDelete.line], args: {shouldYank: true} }, - { keys: 'd', actions: [ActionDelete.line], args: {shouldYank: true} }, - { keys: 'D', actions: [ActionDelete.line], args: {shouldYank: true} }, + { keys: 'backspace', actions: [ActionDelete.byLines], args: {shouldYank: true} }, + { keys: 'delete', actions: [ActionDelete.byLines], args: {shouldYank: true} }, + { keys: 'x', actions: [ActionDelete.byLines], args: {shouldYank: true} }, + { keys: 'X', actions: [ActionDelete.byLines], args: {shouldYank: true} }, + { keys: 'd', actions: [ActionDelete.byLines], args: {shouldYank: true} }, + { keys: 'D', actions: [ActionDelete.byLines], args: {shouldYank: true} }, { keys: 'c', actions: [ - ActionDelete.line, + ActionDelete.byLines, ActionInsert.newLineBefore, ActionMode.toInsert, ], args: {shouldYank: true} }, { keys: 'C', actions: [ - ActionDelete.line, + ActionDelete.byLines, ActionInsert.newLineBefore, ActionMode.toInsert, ], args: {shouldYank: true} }, { keys: 's', actions: [ - ActionDelete.line, + ActionDelete.byLines, ActionInsert.newLineBefore, ActionMode.toInsert, ], args: {shouldYank: true} }, { keys: 'S', actions: [ - ActionDelete.line, + ActionDelete.byLines, ActionInsert.newLineBefore, ActionMode.toInsert, ], args: {shouldYank: true} }, From 85fe79d7939ed6a07e486da3de53e516613d4535 Mon Sep 17 00:00:00 2001 From: aioute Gao Date: Tue, 27 Sep 2016 14:42:16 +0900 Subject: [PATCH 2/4] Document aware toLinewise util. --- src/Utils/Range.ts | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Utils/Range.ts b/src/Utils/Range.ts index ea8a79df..a28e5e61 100644 --- a/src/Utils/Range.ts +++ b/src/Utils/Range.ts @@ -22,11 +22,23 @@ export class UtilRange { return to; } - static toLinewise(from: Range): Range { - return new Range( - from.start.line, 0, + static toLinewise(from: Range, document: TextDocument): Range { + let startLine: number; + let startCharacter: number; + + if (from.start.line !== 0 && from.end.line === document.lineCount - 1) { + startLine = from.start.line - 1; + startCharacter = Infinity; + } + else { + startLine = from.start.line; + startCharacter = 0; + } + + return document.validateRange(new Range( + startLine, startCharacter, from.end.line + 1, 0 - ); + )); } } From 451c7f6e854144077533e1eb8b62182a4df7518a Mon Sep 17 00:00:00 2001 From: aioute Gao Date: Tue, 27 Sep 2016 14:43:26 +0900 Subject: [PATCH 3/4] Replace usage of toLinewise. --- src/Actions/Delete.ts | 9 ++------- src/Actions/Register.ts | 8 ++++---- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/Actions/Delete.ts b/src/Actions/Delete.ts index 89529c2d..cfaa7fa8 100644 --- a/src/Actions/Delete.ts +++ b/src/Actions/Delete.ts @@ -39,7 +39,7 @@ export class ActionDelete { }); if (args.motions.some(motion => motion.isLinewise)) { - ranges = ranges.map(range => document.validateRange(UtilRange.toLinewise(range))); + ranges = ranges.map(range => UtilRange.toLinewise(range, document)); } ranges = UtilRange.unionOverlaps(ranges); @@ -231,12 +231,7 @@ export class ActionDelete { const document = activeTextEditor.document; - let ranges = activeTextEditor.selections.map(selection => document.validateRange( - new Range( - selection.start.line, 0, - selection.end.line + 1, 0 - ) - )); + let ranges = activeTextEditor.selections.map(selection => UtilRange.toLinewise(selection, document)); ranges = UtilRange.unionOverlaps(ranges); diff --git a/src/Actions/Register.ts b/src/Actions/Register.ts index b4a0294b..3aff3afe 100644 --- a/src/Actions/Register.ts +++ b/src/Actions/Register.ts @@ -53,7 +53,7 @@ export class ActionRegister { }); if (args.motions.some(motion => motion.isLinewise)) { - ranges = ranges.map(range => document.validateRange(UtilRange.toLinewise(range))); + ranges = ranges.map(range => UtilRange.toLinewise(range, document)); } ranges = UtilRange.unionOverlaps(ranges); @@ -99,9 +99,9 @@ export class ActionRegister { return Promise.resolve(false); } - let ranges = activeTextEditor.selections.map(selection => { - return UtilRange.toLinewise(selection); - }); + const document = activeTextEditor.document; + + let ranges = activeTextEditor.selections.map(selection => UtilRange.toLinewise(selection, document)); ranges = UtilRange.unionOverlaps(ranges); From 71f2a47cfe59b586e4af7b60c36252663ac863ec Mon Sep 17 00:00:00 2001 From: aioute Gao Date: Tue, 27 Sep 2016 14:54:30 +0900 Subject: [PATCH 4/4] Add tests. --- test/Actions/Delete.test.ts | 59 ++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/test/Actions/Delete.test.ts b/test/Actions/Delete.test.ts index fe542680..787ae4b9 100644 --- a/test/Actions/Delete.test.ts +++ b/test/Actions/Delete.test.ts @@ -5,6 +5,7 @@ import {window, Selection} from 'vscode'; import {Configuration} from '../../src/Configuration'; import {ActionDelete} from '../../src/Actions/Delete'; import {MotionWord} from '../../src/Motions/Word'; +import {MotionCharacter} from '../../src/Motions/Character'; export function run() { @@ -26,7 +27,21 @@ export function run() { in: 'Foo end\nBar end', selection: new Selection(1, 0, 1, 0), out: 'Foo end\nBar end', - } + }, + { + message: 'MotionCharacter.up at first line', + motions: [MotionCharacter.up()], + in: 'Foo end\nBar end', + selection: new Selection(0, 2, 0, 2), + out: 'Bar end', + }, + { + message: 'MotionCharacter.down at last line', + motions: [MotionCharacter.down()], + in: 'Foo end\nBar end', + selection: new Selection(1, 0, 1, 0), + out: 'Foo end', + }, ]; let promise = Promise.resolve(); @@ -55,4 +70,46 @@ export function run() { }); }); + + test('ActionDelete.byLines', (done) => { + + const testCases = [ + { + message: 'Selection at first line', + in: 'Foo end\nBar end', + selection: new Selection(0, 2, 0, 2), + out: 'Bar end', + }, + { + message: 'Selection at last line', + in: 'Foo end\nBar end', + selection: new Selection(1, 0, 1, 0), + out: 'Foo end', + }, + ]; + + let promise = Promise.resolve(); + + while (testCases.length > 0) { + const testCase = testCases.shift(); + promise = promise.then(() => { + + return TestUtil.createTempDocument(testCase.in).then(() => { + TestUtil.setSelection(testCase.selection); + + return ActionDelete.byLines({}).then(() => { + assert.equal(TestUtil.getDocument().getText(), testCase.out, testCase.message); + }); + }); + + }); + } + + promise.then(() => { + done(); + }, (error) => { + done(error); + }); + + }); };