diff --git a/src/vs/editor/contrib/linesOperations/linesOperations.ts b/src/vs/editor/contrib/linesOperations/linesOperations.ts index 0e2e13b66b6e1..d6d79bee280b2 100644 --- a/src/vs/editor/contrib/linesOperations/linesOperations.ts +++ b/src/vs/editor/contrib/linesOperations/linesOperations.ts @@ -408,8 +408,8 @@ export abstract class AbstractDeleteAllToBoundaryAction extends EditorAction { effectiveRanges.push(rangesToDelete[rangesToDelete.length - 1]); let endCursorState = this._getEndCursorState(primaryCursor, effectiveRanges); + let edits: IIdentifiedSingleEditOperation[] = effectiveRanges.map(range => { - endCursorState.push(new Selection(range.startLineNumber, range.startColumn, range.startLineNumber, range.startColumn)); return EditOperation.replace(range, ''); }); @@ -444,17 +444,25 @@ export class DeleteAllLeftAction extends AbstractDeleteAllToBoundaryAction { _getEndCursorState(primaryCursor: Range, rangesToDelete: Range[]): Selection[] { let endPrimaryCursor: Selection; let endCursorState: Selection[] = []; + let deletedLines = 0; - for (let i = 0, len = rangesToDelete.length; i < len; i++) { - let range = rangesToDelete[i]; - let endCursor = new Selection(rangesToDelete[i].startLineNumber, rangesToDelete[i].startColumn, rangesToDelete[i].startLineNumber, rangesToDelete[i].startColumn); + rangesToDelete.forEach(range => { + let endCursor; + if (range.endColumn === 1 && deletedLines > 0) { + let newStartLine = range.startLineNumber - deletedLines; + endCursor = new Selection(newStartLine, range.startColumn, newStartLine, range.startColumn); + } else { + endCursor = new Selection(range.startLineNumber, range.startColumn, range.startLineNumber, range.startColumn); + } + + deletedLines += range.endLineNumber - range.startLineNumber; if (range.intersectRanges(primaryCursor)) { endPrimaryCursor = endCursor; } else { endCursorState.push(endCursor); } - } + }); if (endPrimaryCursor) { endCursorState.unshift(endPrimaryCursor); @@ -465,11 +473,18 @@ export class DeleteAllLeftAction extends AbstractDeleteAllToBoundaryAction { _getRangesToDelete(editor: ICodeEditor): Range[] { let rangesToDelete: Range[] = editor.getSelections(); + let model = editor.getModel(); rangesToDelete.sort(Range.compareRangesUsingStarts); rangesToDelete = rangesToDelete.map(selection => { if (selection.isEmpty()) { - return new Range(selection.startLineNumber, 1, selection.startLineNumber, selection.startColumn); + if (selection.startColumn === 1) { + let deleteFromLine = Math.max(1, selection.startLineNumber - 1); + let deleteFromColumn = selection.startLineNumber === 1 ? 1 : model.getLineContent(deleteFromLine).length + 1; + return new Range(deleteFromLine, deleteFromColumn, selection.startLineNumber, 1); + } else { + return new Range(selection.startLineNumber, 1, selection.startLineNumber, selection.startColumn); + } } else { return selection; } diff --git a/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts b/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts index ae01a2682eb91..31963d459865d 100644 --- a/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts +++ b/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts @@ -155,6 +155,101 @@ suite('Editor Contrib - Line Operations', () => { }); }); + test('should jump to the previous line when on first column', function () { + withTestCodeEditor( + [ + 'one', + 'two', + 'three' + ], {}, (editor, cursor) => { + let model = editor.getModel(); + let deleteAllLeftAction = new DeleteAllLeftAction(); + + editor.setSelection(new Selection(2, 1, 2, 1)); + deleteAllLeftAction.run(null, editor); + assert.equal(model.getLineContent(1), 'onetwo', '001'); + + editor.setSelections([new Selection(1, 1, 1, 1), new Selection(2, 1, 2, 1)]); + deleteAllLeftAction.run(null, editor); + assert.equal(model.getLinesContent()[0], 'onetwothree'); + assert.equal(model.getLinesContent().length, 1); + + editor.setSelection(new Selection(1, 1, 1, 1)); + deleteAllLeftAction.run(null, editor); + assert.equal(model.getLinesContent()[0], 'onetwothree'); + }); + }); + + test('should keep deleting lines in multi cursor mode', function () { + withTestCodeEditor( + [ + 'hi my name is Carlos Matos', + 'BCC', + 'waso waso waso', + 'my wife doesnt believe in me', + 'nonononono', + 'bitconneeeect' + ], {}, (editor, cursor) => { + let model = editor.getModel(); + let deleteAllLeftAction = new DeleteAllLeftAction(); + + const beforeSecondWasoSelection = new Selection(3, 5, 3, 5); + const endOfBCCSelection = new Selection(2, 4, 2, 4); + const endOfNonono = new Selection(5, 11, 5, 11); + + editor.setSelections([beforeSecondWasoSelection, endOfBCCSelection, endOfNonono]); + let selections; + + deleteAllLeftAction.run(null, editor); + selections = editor.getSelections(); + + assert.equal(model.getLineContent(2), ''); + assert.equal(model.getLineContent(3), ' waso waso'); + assert.equal(model.getLineContent(5), ''); + + assert.deepEqual([ + selections[0].startLineNumber, + selections[0].startColumn, + selections[0].endLineNumber, + selections[0].endColumn + ], [3, 1, 3, 1]); + + assert.deepEqual([ + selections[1].startLineNumber, + selections[1].startColumn, + selections[1].endLineNumber, + selections[1].endColumn + ], [2, 1, 2, 1]); + + assert.deepEqual([ + selections[2].startLineNumber, + selections[2].startColumn, + selections[2].endLineNumber, + selections[2].endColumn + ], [5, 1, 5, 1]); + + deleteAllLeftAction.run(null, editor); + selections = editor.getSelections(); + + assert.equal(model.getLineContent(1), 'hi my name is Carlos Matos waso waso'); + assert.equal(selections.length, 2); + + assert.deepEqual([ + selections[0].startLineNumber, + selections[0].startColumn, + selections[0].endLineNumber, + selections[0].endColumn + ], [1, 27, 1, 27]); + + assert.deepEqual([ + selections[1].startLineNumber, + selections[1].startColumn, + selections[1].endLineNumber, + selections[1].endColumn + ], [2, 29, 2, 29]); + }); + }); + test('should work in multi cursor mode', function () { withTestCodeEditor( [